1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/control.cpp 
   3 // Purpose:     wxControl class 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  29 #include "wx/control.h" 
  32     #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly" 
  35     #include "wx/dcclient.h" 
  37     #include "wx/settings.h" 
  41     #include "wx/listctrl.h" 
  42 #endif // wxUSE_LISTCTRL 
  45     #include "wx/treectrl.h" 
  46 #endif // wxUSE_TREECTRL 
  48 #include "wx/msw/private.h" 
  49 #include "wx/msw/uxtheme.h" 
  51 // ---------------------------------------------------------------------------- 
  53 // ---------------------------------------------------------------------------- 
  55 IMPLEMENT_ABSTRACT_CLASS(wxControl
, wxWindow
) 
  57 // ============================================================================ 
  58 // wxControl implementation 
  59 // ============================================================================ 
  61 // ---------------------------------------------------------------------------- 
  62 // wxControl ctor/dtor 
  63 // ---------------------------------------------------------------------------- 
  65 wxControl::~wxControl() 
  67     m_isBeingDeleted 
= true; 
  70 // ---------------------------------------------------------------------------- 
  71 // control window creation 
  72 // ---------------------------------------------------------------------------- 
  74 bool wxControl::Create(wxWindow 
*parent
, 
  79                        const wxValidator
& wxVALIDATOR_PARAM(validator
), 
  82     if ( !wxWindow::Create(parent
, id
, pos
, size
, style
, name
) ) 
  86     SetValidator(validator
); 
  92 bool wxControl::MSWCreateControl(const wxChar 
*classname
, 
  93                                  const wxString
& label
, 
  98     WXDWORD msStyle 
= MSWGetStyle(GetWindowStyle(), &exstyle
); 
 100     return MSWCreateControl(classname
, msStyle
, pos
, size
, label
, exstyle
); 
 103 bool wxControl::MSWCreateControl(const wxChar 
*classname
, 
 107                                  const wxString
& label
, 
 110     // if no extended style given, determine it ourselves 
 111     if ( exstyle 
== (WXDWORD
)-1 ) 
 114         (void) MSWGetStyle(GetWindowStyle(), &exstyle
); 
 117     // all controls should have this style 
 120     // create the control visible if it's currently shown for wxWidgets 
 126     // choose the position for the control: we have a problem with default size 
 127     // here as we can't calculate the best size before the control exists 
 128     // (DoGetBestSize() may need to use m_hWnd), so just choose the minimal 
 129     // possible but non 0 size because 0 window width/height result in problems 
 131     int x 
= pos
.x 
== wxDefaultCoord 
? 0 : pos
.x
, 
 132         y 
= pos
.y 
== wxDefaultCoord 
? 0 : pos
.y
, 
 133         w 
= size
.x 
== wxDefaultCoord 
? 1 : size
.x
, 
 134         h 
= size
.y 
== wxDefaultCoord 
? 1 : size
.y
; 
 136     // ... and adjust it to account for a possible parent frames toolbar 
 137     AdjustForParentClientOrigin(x
, y
); 
 139     m_hWnd 
= (WXHWND
)::CreateWindowEx
 
 141                         exstyle
,            // extended style 
 142                         classname
,          // the kind of control to create 
 143                         label
,              // the window name 
 144                         style
,              // the window style 
 145                         x
, y
, w
, h
,         // the window position and size 
 146                         GetHwndOf(GetParent()),  // parent 
 147                         (HMENU
)GetId(),     // child id 
 148                         wxGetInstance(),    // app instance 
 149                         NULL                
// creation parameters 
 155         wxFAIL_MSG(wxString::Format
 
 157                     _T("CreateWindowEx(\"%s\", flags=%08x, ex=%08x) failed"), 
 158                     classname
, (unsigned int)style
, (unsigned int)exstyle
 
 160 #endif // __WXDEBUG__ 
 165     // install wxWidgets window proc for this window 
 168     // set up fonts and colours 
 172 #if wxUSE_LISTCTRL || wxUSE_TREECTRL 
 173         // if we set a font for {list,tree}ctrls and the font size is changed in 
 174         // the display properties then the font size for these controls doesn't 
 175         // automatically adjust when they receive WM_SETTINGCHANGE 
 176         if ( wxDynamicCastThis(wxListCtrl
) || wxDynamicCastThis(wxTreeCtrl
) ) 
 178             // not sure if we need to explicitly set the font here for Win95/NT4 
 179             // but we definitely can't do it for any newer version 
 180             // see wxGetCCDefaultFont() in src/msw/settings.cpp for explanation 
 181             // of why this test works 
 183             // TODO: test Win95/NT4 to see if this is needed or breaks the 
 184             // font resizing as it does on newer versions 
 185             wxFont font 
= GetDefaultAttributes().font
; 
 186             if ( font 
== wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
) ) 
 192 #endif // wxUSE_LISTCTRL || wxUSE_TREECTRL 
 194             SetFont(GetDefaultAttributes().font
); 
 198     // set the size now if no initial size specified 
 199     SetInitialBestSize(size
); 
 204 // ---------------------------------------------------------------------------- 
 206 // ---------------------------------------------------------------------------- 
 208 wxBorder 
wxControl::GetDefaultBorder() const 
 210     // we want to automatically give controls a sunken style (confusingly, 
 211     // it may not really mean sunken at all as we map it to WS_EX_CLIENTEDGE 
 212     // which is not sunken at all under Windows XP -- rather, just the default) 
 213 #if defined(__POCKETPC__) || defined(__SMARTPHONE__) 
 214     return wxBORDER_SIMPLE
; 
 216     return wxBORDER_SUNKEN
; 
 220 WXDWORD 
wxControl::MSWGetStyle(long style
, WXDWORD 
*exstyle
) const 
 222     long msStyle 
= wxWindow::MSWGetStyle(style
, exstyle
); 
 224     if ( AcceptsFocus() ) 
 226         msStyle 
|= WS_TABSTOP
; 
 232 wxSize 
wxControl::DoGetBestSize() const 
 234     return wxSize(DEFAULT_ITEM_WIDTH
, DEFAULT_ITEM_HEIGHT
); 
 237 // This is a helper for all wxControls made with UPDOWN native control. 
 238 // In wxMSW it was only wxSpinCtrl derived from wxSpinButton but in 
 239 // WinCE of Smartphones this happens also for native wxTextCtrl, 
 240 // wxChoice and others. 
 241 wxSize 
wxControl::GetBestSpinnerSize(const bool is_vertical
) const 
 243     // take size according to layout 
 245 #if defined(__SMARTPHONE__) && defined(__WXWINCE__) 
 248                     ::GetSystemMetrics(is_vertical 
? SM_CXVSCROLL 
: SM_CXHSCROLL
), 
 249                     ::GetSystemMetrics(is_vertical 
? SM_CYVSCROLL 
: SM_CYHSCROLL
) 
 253     // correct size as for undocumented MSW variants cases (WinCE and perhaps others) 
 255         bestSize
.x 
= bestSize
.y
; 
 257         bestSize
.y 
= bestSize
.x
; 
 259     // double size according to layout 
 268 /* static */ wxVisualAttributes
 
 269 wxControl::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 271     wxVisualAttributes attrs
; 
 273     // old school (i.e. not "common") controls use the standard dialog font 
 275     attrs
.font 
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 277     // most, or at least many, of the controls use the same colours as the 
 278     // buttons -- others will have to override this (and possibly simply call 
 279     // GetCompositeControlsDefaultAttributes() from their versions) 
 280     attrs
.colFg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
); 
 281     attrs
.colBg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
); 
 286 // another version for the "composite", i.e. non simple controls 
 287 /* static */ wxVisualAttributes
 
 288 wxControl::GetCompositeControlsDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 290     wxVisualAttributes attrs
; 
 291     attrs
.font 
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 292     attrs
.colFg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
); 
 293     attrs
.colBg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
); 
 298 // ---------------------------------------------------------------------------- 
 300 // ---------------------------------------------------------------------------- 
 302 bool wxControl::ProcessCommand(wxCommandEvent
& event
) 
 304     return GetEventHandler()->ProcessEvent(event
); 
 307 bool wxControl::MSWOnNotify(int idCtrl
, 
 311     wxEventType eventType 
wxDUMMY_INITIALIZE(wxEVT_NULL
); 
 313     NMHDR 
*hdr 
= (NMHDR
*) lParam
; 
 317             eventType 
= wxEVT_COMMAND_LEFT_CLICK
; 
 321             eventType 
= wxEVT_COMMAND_LEFT_DCLICK
; 
 325             eventType 
= wxEVT_COMMAND_RIGHT_CLICK
; 
 329             eventType 
= wxEVT_COMMAND_RIGHT_DCLICK
; 
 333             eventType 
= wxEVT_COMMAND_SET_FOCUS
; 
 337             eventType 
= wxEVT_COMMAND_KILL_FOCUS
; 
 341             eventType 
= wxEVT_COMMAND_ENTER
; 
 345             return wxWindow::MSWOnNotify(idCtrl
, lParam
, result
); 
 348     wxCommandEvent 
event(wxEVT_NULL
, m_windowId
); 
 349     event
.SetEventType(eventType
); 
 350     event
.SetEventObject(this); 
 352     return GetEventHandler()->ProcessEvent(event
); 
 355 WXHBRUSH 
wxControl::DoMSWControlColor(WXHDC pDC
, wxColour colBg
, WXHWND hWnd
) 
 360         ::SetTextColor(hdc
, wxColourToRGB(GetForegroundColour())); 
 366         hbr 
= MSWGetBgBrush(pDC
, hWnd
); 
 368         // if the control doesn't have any bg colour, foreground colour will be 
 369         // ignored as the return value would be 0 -- so forcefully give it a 
 370         // non default background brush in this case 
 371         if ( !hbr 
&& m_hasFgCol 
) 
 372             colBg 
= GetBackgroundColour(); 
 375     // use the background colour override if a valid colour is given 
 378         ::SetBkColor(hdc
, wxColourToRGB(colBg
)); 
 380         // draw children with the same colour as the parent 
 381         wxBrush 
*brush 
= wxTheBrushList
->FindOrCreateBrush(colBg
, wxSOLID
); 
 383         hbr 
= (WXHBRUSH
)brush
->GetResourceHandle(); 
 387     // if we use custom background, we should set foreground ourselves too 
 388     if ( hbr 
&& !m_hasFgCol 
) 
 390         ::SetTextColor(hdc
, ::GetSysColor(COLOR_WINDOWTEXT
)); 
 392     //else: already set above 
 397 WXHBRUSH 
wxControl::MSWControlColor(WXHDC pDC
, WXHWND hWnd
) 
 401     if ( HasTransparentBackground() ) 
 402         ::SetBkMode((HDC
)pDC
, TRANSPARENT
); 
 403     else // if the control is opaque it shouldn't use the parents background 
 404         colBg 
= GetBackgroundColour(); 
 406     return DoMSWControlColor(pDC
, colBg
, hWnd
); 
 409 WXHBRUSH 
wxControl::MSWControlColorDisabled(WXHDC pDC
) 
 411     return DoMSWControlColor(pDC
, 
 412                              wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
), 
 416 // --------------------------------------------------------------------------- 
 418 // --------------------------------------------------------------------------- 
 420 // this is used in radiobox.cpp and slider95.cpp and should be removed as soon 
 421 // as it is not needed there any more! 
 423 // Call this repeatedly for several wnds to find the overall size 
 425 // Call it initially with wxDefaultCoord for all values in rect. 
 426 // Keep calling for other widgets, and rect will be modified 
 427 // to calculate largest bounding rectangle. 
 428 void wxFindMaxSize(WXHWND wnd
, RECT 
*rect
) 
 430     int left 
= rect
->left
; 
 431     int right 
= rect
->right
; 
 433     int bottom 
= rect
->bottom
; 
 435     GetWindowRect((HWND
) wnd
, rect
); 
 440     if (left 
< rect
->left
) 
 443     if (right 
> rect
->right
) 
 449     if (bottom 
> rect
->bottom
) 
 450         rect
->bottom 
= bottom
; 
 453 #endif // wxUSE_CONTROLS