1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/window.cpp 
   3 // Purpose:     wxWindowMSW 
   4 // Author:      Julian Smart 
   5 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation 
   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" 
  27 #include "wx/window.h" 
  30     #include "wx/msw/wrapwin.h" 
  34     #include "wx/dcclient.h" 
  35     #include "wx/dcmemory.h" 
  38     #include "wx/layout.h" 
  39     #include "wx/dialog.h" 
  41     #include "wx/listbox.h" 
  42     #include "wx/button.h" 
  43     #include "wx/msgdlg.h" 
  44     #include "wx/settings.h" 
  45     #include "wx/statbox.h" 
  49     #include "wx/textctrl.h" 
  50     #include "wx/menuitem.h" 
  53 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__) 
  54     #include "wx/ownerdrw.h" 
  57 #include "wx/evtloop.h" 
  58 #include "wx/module.h" 
  60 #include "wx/sysopt.h" 
  62 #if wxUSE_DRAG_AND_DROP 
  66 #if wxUSE_ACCESSIBILITY 
  67     #include "wx/access.h" 
  71         #define WM_GETOBJECT 0x003D 
  74         #define OBJID_CLIENT 0xFFFFFFFC 
  78 #include "wx/msw/private.h" 
  81     #include "wx/tooltip.h" 
  89     #include "wx/spinctrl.h" 
  90 #endif // wxUSE_SPINCTRL 
  92 #include "wx/notebook.h" 
  93 #include "wx/listctrl.h" 
  97 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) 
 103     #include <windowsx.h> 
 106 // include <commctrl.h> "properly" 
 107 #include "wx/msw/wrapcctl.h" 
 113 #include "wx/msw/missing.h" 
 115 #if defined(__WXWINCE__) 
 116     #include "wx/msw/wince/missing.h" 
 119     #include <shellapi.h> 
 121     #include <aygshell.h> 
 125 #if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) 
 126     #define HAVE_TRACKMOUSEEVENT 
 127 #endif // everything needed for TrackMouseEvent() 
 129 // if this is set to 1, we use deferred window sizing to reduce flicker when 
 130 // resizing complicated window hierarchies, but this can in theory result in 
 131 // different behaviour than the old code so we keep the possibility to use it 
 132 // by setting this to 0 (in the future this should be removed completely) 
 134 #define USE_DEFERRED_SIZING 0 
 136 #define USE_DEFERRED_SIZING 1 
 139 // set this to 1 to filter out duplicate mouse events, e.g. mouse move events 
 140 // when mouse position didnd't change 
 142     #define wxUSE_MOUSEEVENT_HACK 0 
 144     #define wxUSE_MOUSEEVENT_HACK 1 
 147 // --------------------------------------------------------------------------- 
 149 // --------------------------------------------------------------------------- 
 151 #if wxUSE_MENUS_NATIVE 
 152 wxMenu 
*wxCurrentPopupMenu 
= NULL
; 
 153 #endif // wxUSE_MENUS_NATIVE 
 156 extern       wxChar 
*wxCanvasClassName
; 
 158 extern const wxChar 
*wxCanvasClassName
; 
 161 // true if we had already created the std colour map, used by 
 162 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT) 
 163 static bool gs_hasStdCmap 
= false; 
 165 // last mouse event information we need to filter out the duplicates 
 166 #if wxUSE_MOUSEEVENT_HACK 
 167 static struct MouseEventInfoDummy
 
 169     // mouse position (in screen coordinates) 
 172     // last mouse event type 
 175 #endif // wxUSE_MOUSEEVENT_HACK 
 177 // --------------------------------------------------------------------------- 
 179 // --------------------------------------------------------------------------- 
 181 // the window proc for all our windows 
 182 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
 183                                    WPARAM wParam
, LPARAM lParam
); 
 187     const wxChar 
*wxGetMessageName(int message
); 
 190 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 191 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 192 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
); 
 194 // get the text metrics for the current font 
 195 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
); 
 198 // find the window for the mouse event at the specified position 
 199 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
); 
 200 #endif // __WXWINCE__ 
 202 // wrapper around BringWindowToTop() API 
 203 static inline void wxBringWindowToTop(HWND hwnd
) 
 205 #ifdef __WXMICROWIN__ 
 206     // It seems that MicroWindows brings the _parent_ of the window to the top, 
 207     // which can be the wrong one. 
 209     // activate (set focus to) specified window 
 213     // raise top level parent to top of z order 
 214     if (!::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE 
| SWP_NOSIZE
)) 
 216         wxLogLastError(_T("SetWindowPos")); 
 222 // ensure that all our parent windows have WS_EX_CONTROLPARENT style 
 223 static void EnsureParentHasControlParentStyle(wxWindow 
*parent
) 
 226        If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our 
 227        parent as well as otherwise several Win32 functions using 
 228        GetNextDlgTabItem() to iterate over all controls such as 
 229        IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, 
 230        all of them iterate over all the controls starting from the currently 
 231        focused one and stop iterating when they get back to the focus but 
 232        unless all parents have WS_EX_CONTROLPARENT bit set, they would never 
 233        get back to the initial (focused) window: as we do have this style, 
 234        GetNextDlgTabItem() will leave this window and continue in its parent, 
 235        but if the parent doesn't have it, it wouldn't recurse inside it later 
 236        on and so wouldn't have a chance of getting back to this window either. 
 238     while ( parent 
&& !parent
->IsTopLevel() ) 
 240         LONG exStyle 
= ::GetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
); 
 241         if ( !(exStyle 
& WS_EX_CONTROLPARENT
) ) 
 243             // force the parent to have this style 
 244             ::SetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
, 
 245                             exStyle 
| WS_EX_CONTROLPARENT
); 
 248         parent 
= parent
->GetParent(); 
 252 #endif // !__WXWINCE__ 
 255 // On Windows CE, GetCursorPos can return an error, so use this function 
 257 bool GetCursorPosWinCE(POINT
* pt
) 
 259     if (!GetCursorPos(pt
)) 
 261         DWORD pos 
= GetMessagePos(); 
 269 // --------------------------------------------------------------------------- 
 271 // --------------------------------------------------------------------------- 
 273 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
 275 #ifdef __WXUNIVERSAL__ 
 276     IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
) 
 278 #if wxUSE_EXTENDED_RTTI 
 280 // windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls 
 281 // must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as 
 282 // windows with negative ids never can be recreated anyway 
 284 bool wxWindowStreamingCallback( const wxObject 
*object
, wxWriter 
* , wxPersister 
* , wxxVariantArray 
& ) 
 286     const wxWindow 
* win 
= dynamic_cast<const wxWindow
*>(object
) ; 
 287     if ( win 
&& win
->GetId() < 0 ) 
 292 IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow
, wxWindowBase
,"wx/window.h", wxWindowStreamingCallback
) 
 294 // make wxWindowList known before the property is used 
 296 wxCOLLECTION_TYPE_INFO( wxWindow
* , wxWindowList 
) ; 
 298 template<> void wxCollectionToVariantArray( wxWindowList 
const &theList
, wxxVariantArray 
&value
) 
 300     wxListCollectionToVariantArray
<wxWindowList::compatibility_iterator
>( theList 
, value 
) ; 
 303 WX_DEFINE_FLAGS( wxWindowStyle 
) 
 305 wxBEGIN_FLAGS( wxWindowStyle 
) 
 306     // new style border flags, we put them first to 
 307     // use them for streaming out 
 309     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
 310     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
 311     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
 312     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
 313     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
 314     wxFLAGS_MEMBER(wxBORDER_NONE
) 
 316     // old style border flags 
 317     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
 318     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
 319     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
 320     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
 321     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
 322     wxFLAGS_MEMBER(wxBORDER
) 
 324     // standard window styles 
 325     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
 326     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
 327     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
 328     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
 329     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
 330     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
 331     wxFLAGS_MEMBER(wxVSCROLL
) 
 332     wxFLAGS_MEMBER(wxHSCROLL
) 
 334 wxEND_FLAGS( wxWindowStyle 
) 
 336 wxBEGIN_PROPERTIES_TABLE(wxWindow
) 
 337     wxEVENT_PROPERTY( Close 
, wxEVT_CLOSE_WINDOW 
, wxCloseEvent
) 
 338     wxEVENT_PROPERTY( Create 
, wxEVT_CREATE 
, wxWindowCreateEvent 
) 
 339     wxEVENT_PROPERTY( Destroy 
, wxEVT_DESTROY 
, wxWindowDestroyEvent 
) 
 340     // Always constructor Properties first 
 342     wxREADONLY_PROPERTY( Parent
,wxWindow
*, GetParent
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 343     wxPROPERTY( Id
,wxWindowID
, SetId
, GetId
, -1 /*wxID_ANY*/ , 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
 344     wxPROPERTY( Position
,wxPoint
, SetPosition 
, GetPosition
, wxDefaultPosition 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos 
 345     wxPROPERTY( Size
,wxSize
, SetSize
, GetSize
, wxDefaultSize 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size 
 346     wxPROPERTY( WindowStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
 348     // Then all relations of the object graph 
 350     wxREADONLY_PROPERTY_COLLECTION( Children 
, wxWindowList 
, wxWindowBase
* , GetWindowChildren 
, wxPROP_OBJECT_GRAPH 
/*flags*/ , wxT("Helpstring") , wxT("group")) 
 352    // and finally all other properties 
 354     wxPROPERTY( ExtraStyle 
, long , SetExtraStyle 
, GetExtraStyle 
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle 
 355     wxPROPERTY( BackgroundColour 
, wxColour 
, SetBackgroundColour 
, GetBackgroundColour 
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg 
 356     wxPROPERTY( ForegroundColour 
, wxColour 
, SetForegroundColour 
, GetForegroundColour 
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg 
 357     wxPROPERTY( Enabled 
, bool , Enable 
, IsEnabled 
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 358     wxPROPERTY( Shown 
, bool , Show 
, IsShown 
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 360     // possible property candidates (not in xrc) or not valid in all subclasses 
 361     wxPROPERTY( Title
,wxString
, SetTitle
, GetTitle
, wxEmptyString 
) 
 362     wxPROPERTY( Font 
, wxFont 
, SetFont 
, GetWindowFont  
, ) 
 363     wxPROPERTY( Label
,wxString
, SetLabel
, GetLabel
, wxEmptyString 
) 
 364     // MaxHeight, Width , MinHeight , Width 
 365     // TODO switch label to control and title to toplevels 
 367     wxPROPERTY( ThemeEnabled 
, bool , SetThemeEnabled 
, GetThemeEnabled 
, ) 
 368     //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , ) 
 369     // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , ) 
 370     wxPROPERTY( AutoLayout 
, bool , SetAutoLayout 
, GetAutoLayout 
, ) 
 375 wxEND_PROPERTIES_TABLE() 
 377 wxBEGIN_HANDLERS_TABLE(wxWindow
) 
 378 wxEND_HANDLERS_TABLE() 
 380 wxCONSTRUCTOR_DUMMY(wxWindow
) 
 383     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
 385 #endif // __WXUNIVERSAL__/__WXMSW__ 
 387 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
) 
 388     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
) 
 389     EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
) 
 391     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
) 
 395 // =========================================================================== 
 397 // =========================================================================== 
 399 // --------------------------------------------------------------------------- 
 400 // wxWindow utility functions 
 401 // --------------------------------------------------------------------------- 
 403 // Find an item given the MS Windows id 
 404 wxWindow 
*wxWindowMSW::FindItem(long id
) const 
 407     wxControl 
*item 
= wxDynamicCastThis(wxControl
); 
 410         // is it us or one of our "internal" children? 
 411         if ( item
->GetId() == id
 
 412 #ifndef __WXUNIVERSAL__ 
 413                 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
) 
 414 #endif // __WXUNIVERSAL__ 
 420 #endif // wxUSE_CONTROLS 
 422     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 425         wxWindow 
*childWin 
= current
->GetData(); 
 427         wxWindow 
*wnd 
= childWin
->FindItem(id
); 
 431         current 
= current
->GetNext(); 
 437 // Find an item given the MS Windows handle 
 438 wxWindow 
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const 
 440     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 443         wxWindow 
*parent 
= current
->GetData(); 
 445         // Do a recursive search. 
 446         wxWindow 
*wnd 
= parent
->FindItemByHWND(hWnd
); 
 452                 || parent
->IsKindOf(CLASSINFO(wxControl
)) 
 453 #endif // wxUSE_CONTROLS 
 456             wxWindow 
*item 
= current
->GetData(); 
 457             if ( item
->GetHWND() == hWnd 
) 
 461                 if ( item
->ContainsHWND(hWnd
) ) 
 466         current 
= current
->GetNext(); 
 471 // Default command handler 
 472 bool wxWindowMSW::MSWCommand(WXUINT 
WXUNUSED(param
), WXWORD 
WXUNUSED(id
)) 
 477 // ---------------------------------------------------------------------------- 
 478 // constructors and such 
 479 // ---------------------------------------------------------------------------- 
 481 void wxWindowMSW::Init() 
 484     m_isBeingDeleted 
= false; 
 486     m_mouseInWindow 
= false; 
 487     m_lastKeydownProcessed 
= false; 
 489     m_childrenDisabled 
= NULL
; 
 498     m_pendingPosition 
= wxDefaultPosition
; 
 499     m_pendingSize 
= wxDefaultSize
; 
 502     m_contextMenuEnabled 
= false; 
 507 wxWindowMSW::~wxWindowMSW() 
 509     m_isBeingDeleted 
= true; 
 511 #ifndef __WXUNIVERSAL__ 
 512     // VS: make sure there's no wxFrame with last focus set to us: 
 513     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
 515         wxTopLevelWindow 
*frame 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 518             if ( frame
->GetLastFocus() == this ) 
 520                 frame
->SetLastFocus(NULL
); 
 523             // apparently sometimes we can end up with our grand parent 
 524             // pointing to us as well: this is surely a bug in focus handling 
 525             // code but it's not clear where it happens so for now just try to 
 526             // fix it here by not breaking out of the loop 
 530 #endif // __WXUNIVERSAL__ 
 532     // VS: destroy children first and _then_ detach *this from its parent. 
 533     //     If we did it the other way around, children wouldn't be able 
 534     //     find their parent frame (see above). 
 539         // VZ: test temp removed to understand what really happens here 
 540         //if (::IsWindow(GetHwnd())) 
 542             if ( !::DestroyWindow(GetHwnd()) ) 
 543                 wxLogLastError(wxT("DestroyWindow")); 
 546         // remove hWnd <-> wxWindow association 
 547         wxRemoveHandleAssociation(this); 
 550     delete m_childrenDisabled
; 
 554 // real construction (Init() must have been called before!) 
 555 bool wxWindowMSW::Create(wxWindow 
*parent
, 
 560                          const wxString
& name
) 
 562     wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") ); 
 564     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 567     parent
->AddChild(this); 
 570     DWORD msflags 
= MSWGetCreateWindowFlags(&exstyle
); 
 572 #ifdef __WXUNIVERSAL__ 
 573     // no borders, we draw them ourselves 
 574     exstyle 
&= ~(WS_EX_DLGMODALFRAME 
| 
 578     msflags 
&= ~WS_BORDER
; 
 579 #endif // wxUniversal 
 583         msflags 
|= WS_VISIBLE
; 
 586     if ( !MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
) ) 
 594 // --------------------------------------------------------------------------- 
 596 // --------------------------------------------------------------------------- 
 598 void wxWindowMSW::SetFocus() 
 600     HWND hWnd 
= GetHwnd(); 
 601     wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") ); 
 603 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
 607     if ( !::SetFocus(hWnd
) ) 
 609 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__) 
 610         // was there really an error? 
 611         DWORD dwRes 
= ::GetLastError(); 
 614             HWND hwndFocus 
= ::GetFocus(); 
 615             if ( hwndFocus 
!= hWnd 
) 
 617                 wxLogApiError(_T("SetFocus"), dwRes
); 
 624 void wxWindowMSW::SetFocusFromKbd() 
 626     // when the focus is given to the control with DLGC_HASSETSEL style from 
 627     // keyboard its contents should be entirely selected: this is what 
 628     // ::IsDialogMessage() does and so we should do it as well to provide the 
 629     // same LNF as the native programs 
 630     if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL 
) 
 632         ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1); 
 635     // do this after (maybe) setting the selection as like this when 
 636     // wxEVT_SET_FOCUS handler is called, the selection would have been already 
 637     // set correctly -- this may be important 
 638     wxWindowBase::SetFocusFromKbd(); 
 641 // Get the window with the focus 
 642 wxWindow 
*wxWindowBase::DoFindFocus() 
 644     HWND hWnd 
= ::GetFocus(); 
 647         return wxGetWindowFromHWND((WXHWND
)hWnd
); 
 653 bool wxWindowMSW::Enable(bool enable
) 
 655     if ( !wxWindowBase::Enable(enable
) ) 
 658     HWND hWnd 
= GetHwnd(); 
 660         ::EnableWindow(hWnd
, (BOOL
)enable
); 
 662     // the logic below doesn't apply to the top level windows -- otherwise 
 663     // showing a modal dialog would result in total greying out (and ungreying 
 664     // out later) of everything which would be really ugly 
 668     // when the parent is disabled, all of its children should be disabled as 
 669     // well but when it is enabled back, only those of the children which 
 670     // hadn't been already disabled in the beginning should be enabled again, 
 671     // so we have to keep the list of those children 
 672     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
 674           node 
= node
->GetNext() ) 
 676         wxWindow 
*child 
= node
->GetData(); 
 677         if ( child
->IsTopLevel() ) 
 679             // the logic below doesn't apply to top level children 
 685             // re-enable the child unless it had been disabled before us 
 686             if ( !m_childrenDisabled 
|| !m_childrenDisabled
->Find(child
) ) 
 689         else // we're being disabled 
 691             if ( child
->IsEnabled() ) 
 693                 // disable it as children shouldn't stay enabled while the 
 697             else // child already disabled, remember it 
 699                 // have we created the list of disabled children already? 
 700                 if ( !m_childrenDisabled 
) 
 701                     m_childrenDisabled 
= new wxWindowList
; 
 703                 m_childrenDisabled
->Append(child
); 
 708     if ( enable 
&& m_childrenDisabled 
) 
 710         // we don't need this list any more, don't keep unused memory 
 711         delete m_childrenDisabled
; 
 712         m_childrenDisabled 
= NULL
; 
 718 bool wxWindowMSW::Show(bool show
) 
 720     if ( !wxWindowBase::Show(show
) ) 
 723     HWND hWnd 
= GetHwnd(); 
 725     // we could be called before the underlying window is created (this is 
 726     // actually useful to prevent it from being initially shown), e.g. 
 728     //      wxFoo *foo = new wxFoo; 
 730     //      foo->Create(parent, ...); 
 732     // should work without errors 
 735         ::ShowWindow(hWnd
, show 
? SW_SHOW 
: SW_HIDE
); 
 741 // Raise the window to the top of the Z order 
 742 void wxWindowMSW::Raise() 
 744     wxBringWindowToTop(GetHwnd()); 
 747 // Lower the window to the bottom of the Z order 
 748 void wxWindowMSW::Lower() 
 750     ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0, 
 751                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
 754 void wxWindowMSW::DoCaptureMouse() 
 756     HWND hWnd 
= GetHwnd(); 
 763 void wxWindowMSW::DoReleaseMouse() 
 765     if ( !::ReleaseCapture() ) 
 767         wxLogLastError(_T("ReleaseCapture")); 
 771 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 773     HWND hwnd 
= ::GetCapture(); 
 774     return hwnd 
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow 
*)NULL
; 
 777 bool wxWindowMSW::SetFont(const wxFont
& font
) 
 779     if ( !wxWindowBase::SetFont(font
) ) 
 785     HWND hWnd 
= GetHwnd(); 
 788         WXHANDLE hFont 
= m_font
.GetResourceHandle(); 
 790         wxASSERT_MSG( hFont
, wxT("should have valid font") ); 
 792         ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0)); 
 797 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
) 
 799     if ( !wxWindowBase::SetCursor(cursor
) ) 
 805     // don't "overwrite" busy cursor 
 806     if ( m_cursor
.Ok() && !wxIsBusy() ) 
 808         ::SetCursor(GetHcursorOf(m_cursor
)); 
 814 void wxWindowMSW::WarpPointer(int x
, int y
) 
 816     ClientToScreen(&x
, &y
); 
 818     if ( !::SetCursorPos(x
, y
) ) 
 820         wxLogLastError(_T("SetCursorPos")); 
 824 void wxWindowMSW::MSWUpdateUIState(int action
, int state
) 
 826     // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good 
 827     // to use it on older systems -- and could possibly do some harm 
 828     static int s_needToUpdate 
= -1; 
 829     if ( s_needToUpdate 
== -1 ) 
 832         s_needToUpdate 
= wxGetOsVersion(&verMaj
, &verMin
) == wxWINDOWS_NT 
&& 
 836     if ( s_needToUpdate 
) 
 838         // we send WM_CHANGEUISTATE so if nothing needs changing then the system 
 839         // won't send WM_UPDATEUISTATE 
 840         ::SendMessage(GetHwnd(), WM_CHANGEUISTATE
, MAKEWPARAM(action
, state
), 0); 
 844 // --------------------------------------------------------------------------- 
 846 // --------------------------------------------------------------------------- 
 848 inline int GetScrollPosition(HWND hWnd
, int wOrient
) 
 850 #ifdef __WXMICROWIN__ 
 851     return ::GetScrollPosWX(hWnd
, wOrient
); 
 853     WinStruct
<SCROLLINFO
> scrollInfo
; 
 854     scrollInfo
.cbSize 
= sizeof(SCROLLINFO
); 
 855     scrollInfo
.fMask 
= SIF_POS
; 
 856     ::GetScrollInfo(hWnd
, wOrient
, &scrollInfo 
); 
 858     return scrollInfo
.nPos
; 
 863 int wxWindowMSW::GetScrollPos(int orient
) const 
 865     HWND hWnd 
= GetHwnd(); 
 866     wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") ); 
 868     return GetScrollPosition(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
); 
 871 // This now returns the whole range, not just the number 
 872 // of positions that we can scroll. 
 873 int wxWindowMSW::GetScrollRange(int orient
) const 
 876     HWND hWnd 
= GetHwnd(); 
 880     ::GetScrollRange(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 883     WinStruct
<SCROLLINFO
> scrollInfo
; 
 884     scrollInfo
.fMask 
= SIF_RANGE
; 
 885     if ( !::GetScrollInfo(hWnd
, 
 886                           orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 889         // Most of the time this is not really an error, since the return 
 890         // value can also be zero when there is no scrollbar yet. 
 891         // wxLogLastError(_T("GetScrollInfo")); 
 893     maxPos 
= scrollInfo
.nMax
; 
 895     // undo "range - 1" done in SetScrollbar() 
 899 int wxWindowMSW::GetScrollThumb(int orient
) const 
 901     return orient 
== wxHORIZONTAL 
? m_xThumbSize 
: m_yThumbSize
; 
 904 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
) 
 906     HWND hWnd 
= GetHwnd(); 
 907     wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") ); 
 909     WinStruct
<SCROLLINFO
> info
; 
 913     info
.fMask 
= SIF_POS
; 
 914     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 916         // disable scrollbar instead of removing it then 
 917         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 920     ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 924 // New function that will replace some of the above. 
 925 void wxWindowMSW::SetScrollbar(int orient
, 
 931     WinStruct
<SCROLLINFO
> info
; 
 932     info
.nPage 
= pageSize
; 
 933     info
.nMin 
= 0;              // range is nMax - nMin + 1 
 934     info
.nMax 
= range 
- 1;      //  as both nMax and nMax are inclusive 
 936     info
.fMask 
= SIF_RANGE 
| SIF_PAGE 
| SIF_POS
; 
 937     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 939         // disable scrollbar instead of removing it then 
 940         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 943     HWND hWnd 
= GetHwnd(); 
 946         // We have to set the variables here to make them valid in events 
 947         // triggered by ::SetScrollInfo() 
 948         *(orient 
== wxHORIZONTAL 
? &m_xThumbSize 
: &m_yThumbSize
) = pageSize
; 
 950         ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 955 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect 
*prect
) 
 961         rect
.left 
= prect
->x
; 
 963         rect
.right 
= prect
->x 
+ prect
->width
; 
 964         rect
.bottom 
= prect
->y 
+ prect
->height
; 
 974     // FIXME: is this the exact equivalent of the line below? 
 975     ::ScrollWindowEx(GetHwnd(), dx
, dy
, pr
, pr
, 0, 0, SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
); 
 977     ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
); 
 981 static bool ScrollVertically(HWND hwnd
, int kind
, int count
) 
 983     int posStart 
= GetScrollPosition(hwnd
, SB_VERT
); 
 986     for ( int n 
= 0; n 
< count
; n
++ ) 
 988         ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0); 
 990         int posNew 
= GetScrollPosition(hwnd
, SB_VERT
); 
 993             // don't bother to continue, we're already at top/bottom 
1000     return pos 
!= posStart
; 
1003 bool wxWindowMSW::ScrollLines(int lines
) 
1005     bool down 
= lines 
> 0; 
1007     return ScrollVertically(GetHwnd(), 
1008                             down 
? SB_LINEDOWN 
: SB_LINEUP
, 
1009                             down 
? lines 
: -lines
); 
1012 bool wxWindowMSW::ScrollPages(int pages
) 
1014     bool down 
= pages 
> 0; 
1016     return ScrollVertically(GetHwnd(), 
1017                             down 
? SB_PAGEDOWN 
: SB_PAGEUP
, 
1018                             down 
? pages 
: -pages
); 
1021 // --------------------------------------------------------------------------- 
1023 // --------------------------------------------------------------------------- 
1025 void wxWindowMSW::SubclassWin(WXHWND hWnd
) 
1027     wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") ); 
1029     HWND hwnd 
= (HWND
)hWnd
; 
1030     wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") ); 
1032     wxAssociateWinWithHandle(hwnd
, this); 
1034     m_oldWndProc 
= (WXFARPROC
)wxGetWindowProc((HWND
)hWnd
); 
1036     // we don't need to subclass the window of our own class (in the Windows 
1037     // sense of the word) 
1038     if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) ) 
1040         wxSetWindowProc(hwnd
, wxWndProc
); 
1044         // don't bother restoring it either: this also makes it easy to 
1045         // implement IsOfStandardClass() method which returns true for the 
1046         // standard controls and false for the wxWidgets own windows as it can 
1047         // simply check m_oldWndProc 
1048         m_oldWndProc 
= NULL
; 
1051     // we're officially created now, send the event 
1052     wxWindowCreateEvent 
event((wxWindow 
*)this); 
1053     (void)GetEventHandler()->ProcessEvent(event
); 
1056 void wxWindowMSW::UnsubclassWin() 
1058     wxRemoveHandleAssociation(this); 
1060     // Restore old Window proc 
1061     HWND hwnd 
= GetHwnd(); 
1066         wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") ); 
1070             if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) ) 
1072                 wxSetWindowProc(hwnd
, (WNDPROC
)m_oldWndProc
); 
1075             m_oldWndProc 
= NULL
; 
1080 void wxWindowMSW::AssociateHandle(WXWidget handle
) 
1084       if ( !::DestroyWindow(GetHwnd()) ) 
1085         wxLogLastError(wxT("DestroyWindow")); 
1088     WXHWND wxhwnd 
= (WXHWND
)handle
; 
1091     SubclassWin(wxhwnd
); 
1094 void wxWindowMSW::DissociateHandle() 
1096     // this also calls SetHWND(0) for us 
1101 bool wxCheckWindowWndProc(WXHWND hWnd
, 
1102                           WXFARPROC 
WXUNUSED(wndProc
)) 
1104 // TODO: This list of window class names should be factored out so they can be 
1105 // managed in one place and then accessed from here and other places, such as 
1106 // wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses() 
1109     extern       wxChar 
*wxCanvasClassName
; 
1110     extern       wxChar 
*wxCanvasClassNameNR
; 
1112     extern const wxChar 
*wxCanvasClassName
; 
1113     extern const wxChar 
*wxCanvasClassNameNR
; 
1115     extern const wxChar 
*wxMDIFrameClassName
; 
1116     extern const wxChar 
*wxMDIFrameClassNameNoRedraw
; 
1117     extern const wxChar 
*wxMDIChildFrameClassName
; 
1118     extern const wxChar 
*wxMDIChildFrameClassNameNoRedraw
; 
1119     wxString 
str(wxGetWindowClass(hWnd
)); 
1120     if (str 
== wxCanvasClassName 
|| 
1121         str 
== wxCanvasClassNameNR 
|| 
1123         str 
== _T("wxGLCanvasClass") || 
1124         str 
== _T("wxGLCanvasClassNR") || 
1125 #endif // wxUSE_GLCANVAS 
1126         str 
== wxMDIFrameClassName 
|| 
1127         str 
== wxMDIFrameClassNameNoRedraw 
|| 
1128         str 
== wxMDIChildFrameClassName 
|| 
1129         str 
== wxMDIChildFrameClassNameNoRedraw 
|| 
1130         str 
== _T("wxTLWHiddenParent")) 
1131         return true; // Effectively means don't subclass 
1136 // ---------------------------------------------------------------------------- 
1138 // ---------------------------------------------------------------------------- 
1140 void wxWindowMSW::SetWindowStyleFlag(long flags
) 
1142     long flagsOld 
= GetWindowStyleFlag(); 
1143     if ( flags 
== flagsOld 
) 
1146     // update the internal variable 
1147     wxWindowBase::SetWindowStyleFlag(flags
); 
1149     // and the real window flags 
1150     MSWUpdateStyle(flagsOld
, GetExtraStyle()); 
1153 void wxWindowMSW::SetExtraStyle(long exflags
) 
1155     long exflagsOld 
= GetExtraStyle(); 
1156     if ( exflags 
== exflagsOld 
) 
1159     // update the internal variable 
1160     wxWindowBase::SetExtraStyle(exflags
); 
1162     // and the real window flags 
1163     MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld
); 
1166 void wxWindowMSW::MSWUpdateStyle(long flagsOld
, long exflagsOld
) 
1168     // now update the Windows style as well if needed - and if the window had 
1169     // been already created 
1173     // we may need to call SetWindowPos() when we change some styles 
1174     bool callSWP 
= false; 
1177     long style 
= MSWGetStyle(GetWindowStyleFlag(), &exstyle
); 
1179     // this is quite a horrible hack but we need it because MSWGetStyle() 
1180     // doesn't take exflags as parameter but uses GetExtraStyle() internally 
1181     // and so we have to modify the window exflags temporarily to get the 
1182     // correct exstyleOld 
1183     long exflagsNew 
= GetExtraStyle(); 
1184     wxWindowBase::SetExtraStyle(exflagsOld
); 
1187     long styleOld 
= MSWGetStyle(flagsOld
, &exstyleOld
); 
1189     wxWindowBase::SetExtraStyle(exflagsNew
); 
1192     if ( style 
!= styleOld 
) 
1194         // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by 
1195         // this function so instead of simply setting the style to the new 
1196         // value we clear the bits which were set in styleOld but are set in 
1197         // the new one and set the ones which were not set before 
1198         long styleReal 
= ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
1199         styleReal 
&= ~styleOld
; 
1202         ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
); 
1204         // we need to call SetWindowPos() if any of the styles affecting the 
1205         // frame appearance have changed 
1206         callSWP 
= ((styleOld 
^ style 
) & (WS_BORDER 
| 
1215     // and the extended style 
1216     long exstyleReal 
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1218     if ( exstyle 
!= exstyleOld 
) 
1220         exstyleReal 
&= ~exstyleOld
; 
1221         exstyleReal 
|= exstyle
; 
1223         ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
); 
1225         // ex style changes don't take effect without calling SetWindowPos 
1231         // we must call SetWindowPos() to flush the cached extended style and 
1232         // also to make the change to wxSTAY_ON_TOP style take effect: just 
1233         // setting the style simply doesn't work 
1234         if ( !::SetWindowPos(GetHwnd(), 
1235                              exstyleReal 
& WS_EX_TOPMOST 
? HWND_TOPMOST
 
1238                              SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_FRAMECHANGED
) ) 
1240             wxLogLastError(_T("SetWindowPos")); 
1245 WXDWORD 
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD 
*exstyle
) const 
1247     // translate common wxWidgets styles to Windows ones 
1249     // most of windows are child ones, those which are not (such as 
1250     // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle() 
1251     WXDWORD style 
= WS_CHILD
; 
1253     // using this flag results in very significant reduction in flicker, 
1254     // especially with controls inside the static boxes (as the interior of the 
1255     // box is not redrawn twice), but sometimes results in redraw problems, so 
1256     // optionally allow the old code to continue to use it provided a special 
1257     // system option is turned on 
1258     if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) 
1259             || (flags 
& wxCLIP_CHILDREN
) ) 
1260         style 
|= WS_CLIPCHILDREN
; 
1262     // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially 
1263     // don't support overlapping windows and it only makes sense for them and, 
1264     // presumably, gives the system some extra work (to manage more clipping 
1265     // regions), so avoid it alltogether 
1268     if ( flags 
& wxVSCROLL 
) 
1269         style 
|= WS_VSCROLL
; 
1271     if ( flags 
& wxHSCROLL 
) 
1272         style 
|= WS_HSCROLL
; 
1274     const wxBorder border 
= GetBorder(flags
); 
1276     // WS_BORDER is only required for wxBORDER_SIMPLE 
1277     if ( border 
== wxBORDER_SIMPLE 
) 
1280     // now deal with ext style if the caller wants it 
1286         if ( flags 
& wxTRANSPARENT_WINDOW 
) 
1287             *exstyle 
|= WS_EX_TRANSPARENT
; 
1293             case wxBORDER_DEFAULT
: 
1294                 wxFAIL_MSG( _T("unknown border style") ); 
1298             case wxBORDER_SIMPLE
: 
1301             case wxBORDER_STATIC
: 
1302                 *exstyle 
|= WS_EX_STATICEDGE
; 
1305             case wxBORDER_RAISED
: 
1306                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1309             case wxBORDER_SUNKEN
: 
1310                 *exstyle 
|= WS_EX_CLIENTEDGE
; 
1311                 style 
&= ~WS_BORDER
; 
1314             case wxBORDER_DOUBLE
: 
1315                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1319         // wxUniv doesn't use Windows dialog navigation functions at all 
1320 #if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__) 
1321         // to make the dialog navigation work with the nested panels we must 
1322         // use this style (top level windows such as dialogs don't need it) 
1323         if ( (flags 
& wxTAB_TRAVERSAL
) && !IsTopLevel() ) 
1325             *exstyle 
|= WS_EX_CONTROLPARENT
; 
1327 #endif // __WXUNIVERSAL__ 
1333 // Setup background and foreground colours correctly 
1334 void wxWindowMSW::SetupColours() 
1337         SetBackgroundColour(GetParent()->GetBackgroundColour()); 
1340 bool wxWindowMSW::IsMouseInWindow() const 
1342     // get the mouse position 
1345     ::GetCursorPosWinCE(&pt
); 
1347     ::GetCursorPos(&pt
); 
1350     // find the window which currently has the cursor and go up the window 
1351     // chain until we find this window - or exhaust it 
1352     HWND hwnd 
= ::WindowFromPoint(pt
); 
1353     while ( hwnd 
&& (hwnd 
!= GetHwnd()) ) 
1354         hwnd 
= ::GetParent(hwnd
); 
1356     return hwnd 
!= NULL
; 
1359 void wxWindowMSW::OnInternalIdle() 
1361 #ifndef HAVE_TRACKMOUSEEVENT 
1362     // Check if we need to send a LEAVE event 
1363     if ( m_mouseInWindow 
) 
1365         // note that we should generate the leave event whether the window has 
1366         // or doesn't have mouse capture 
1367         if ( !IsMouseInWindow() ) 
1369             GenerateMouseLeave(); 
1372 #endif // !HAVE_TRACKMOUSEEVENT 
1374     if (wxUpdateUIEvent::CanUpdate(this)) 
1375         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
1378 // Set this window to be the child of 'parent'. 
1379 bool wxWindowMSW::Reparent(wxWindowBase 
*parent
) 
1381     if ( !wxWindowBase::Reparent(parent
) ) 
1384     HWND hWndChild 
= GetHwnd(); 
1385     HWND hWndParent 
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0; 
1387     ::SetParent(hWndChild
, hWndParent
); 
1390     if ( ::GetWindowLong(hWndChild
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
1392         EnsureParentHasControlParentStyle(GetParent()); 
1394 #endif // !__WXWINCE__ 
1399 static inline void SendSetRedraw(HWND hwnd
, bool on
) 
1401 #ifndef __WXMICROWIN__ 
1402     ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0); 
1406 void wxWindowMSW::Freeze() 
1408     if ( !m_frozenness
++ ) 
1411             SendSetRedraw(GetHwnd(), false); 
1415 void wxWindowMSW::Thaw() 
1417     wxASSERT_MSG( m_frozenness 
> 0, _T("Thaw() without matching Freeze()") ); 
1419     if ( --m_frozenness 
== 0 ) 
1423             SendSetRedraw(GetHwnd(), true); 
1425             // we need to refresh everything or otherwise the invalidated area 
1426             // is not going to be repainted 
1432 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1434     HWND hWnd 
= GetHwnd(); 
1441             mswRect
.left 
= rect
->x
; 
1442             mswRect
.top 
= rect
->y
; 
1443             mswRect
.right 
= rect
->x 
+ rect
->width
; 
1444             mswRect
.bottom 
= rect
->y 
+ rect
->height
; 
1453         // RedrawWindow not available on SmartPhone or eVC++ 3 
1454 #if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400) 
1455         UINT flags 
= RDW_INVALIDATE 
| RDW_ALLCHILDREN
; 
1459         ::RedrawWindow(hWnd
, pRect
, NULL
, flags
); 
1461         ::InvalidateRect(hWnd
, pRect
, eraseBack
); 
1466 void wxWindowMSW::Update() 
1468     if ( !::UpdateWindow(GetHwnd()) ) 
1470         wxLogLastError(_T("UpdateWindow")); 
1473 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
1474     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT 
1475     // handler needs to be really drawn right now 
1480 // --------------------------------------------------------------------------- 
1482 // --------------------------------------------------------------------------- 
1484 // we need to lower the sibling static boxes so controls contained within can be 
1486 static inline void AdjustStaticBoxZOrder(wxWindow 
*parent
) 
1488     // no sibling static boxes if we have no parent (ie TLW) 
1492     for ( wxWindowList::compatibility_iterator node 
= parent
->GetChildren().GetFirst(); 
1494           node 
= node
->GetNext() ) 
1496         wxStaticBox 
*statbox 
= wxDynamicCast(node
->GetData(), wxStaticBox
); 
1499             ::SetWindowPos(GetHwndOf(statbox
), HWND_BOTTOM
, 0, 0, 0, 0, 
1500                            SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
1505 #if wxUSE_DRAG_AND_DROP 
1506 void wxWindowMSW::SetDropTarget(wxDropTarget 
*pDropTarget
) 
1508     if ( m_dropTarget 
!= 0 ) { 
1509         m_dropTarget
->Revoke(m_hWnd
); 
1510         delete m_dropTarget
; 
1513     m_dropTarget 
= pDropTarget
; 
1514     if ( m_dropTarget 
!= 0 ) 
1516         AdjustStaticBoxZOrder(GetParent()); 
1517         m_dropTarget
->Register(m_hWnd
); 
1520 #endif // wxUSE_DRAG_AND_DROP 
1522 // old-style file manager drag&drop support: we retain the old-style 
1523 // DragAcceptFiles in parallel with SetDropTarget. 
1524 void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept
)) 
1527     HWND hWnd 
= GetHwnd(); 
1530         AdjustStaticBoxZOrder(GetParent()); 
1531         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
1536 // ---------------------------------------------------------------------------- 
1538 // ---------------------------------------------------------------------------- 
1542 void wxWindowMSW::DoSetToolTip(wxToolTip 
*tooltip
) 
1544     wxWindowBase::DoSetToolTip(tooltip
); 
1547         m_tooltip
->SetWindow((wxWindow 
*)this); 
1550 #endif // wxUSE_TOOLTIPS 
1552 // --------------------------------------------------------------------------- 
1553 // moving and resizing 
1554 // --------------------------------------------------------------------------- 
1556 bool wxWindowMSW::IsSizeDeferred() const 
1558 #if USE_DEFERRED_SIZING 
1559     if ( m_pendingPosition 
!= wxDefaultPosition 
|| 
1560          m_pendingSize     
!= wxDefaultSize 
) 
1562 #endif // USE_DEFERRED_SIZING 
1568 void wxWindowMSW::DoGetSize(int *x
, int *y
) const 
1570     // if SetSize() had been called at wx level but not realized at Windows 
1571     // level yet (i.e. EndDeferWindowPos() not called), we still should return 
1572     // the new and not the old position to the other wx code 
1573     if ( m_pendingSize 
!= wxDefaultSize 
) 
1576             *x 
= m_pendingSize
.x
; 
1578             *y 
= m_pendingSize
.y
; 
1580     else // use current size 
1582         RECT rect 
= wxGetWindowRect(GetHwnd()); 
1585             *x 
= rect
.right 
- rect
.left
; 
1587             *y 
= rect
.bottom 
- rect
.top
; 
1591 // Get size *available for subwindows* i.e. excluding menu bar etc. 
1592 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const 
1594 #if USE_DEFERRED_SIZING 
1595     if ( IsTopLevel() || m_pendingSize 
== wxDefaultSize 
) 
1597     {        // top level windows resizing is never deferred, so we can safely use 
1598         // the current size here 
1599         RECT rect 
= wxGetClientRect(GetHwnd()); 
1606 #if USE_DEFERRED_SIZING 
1607     else // non top level and using deferred sizing 
1609         // we need to calculate the *pending* client size here 
1611         rect
.left 
= m_pendingPosition
.x
; 
1612         rect
.top 
= m_pendingPosition
.y
; 
1613         rect
.right 
= rect
.left 
+ m_pendingSize
.x
; 
1614         rect
.bottom 
= rect
.top 
+ m_pendingSize
.y
; 
1616         ::SendMessage(GetHwnd(), WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
); 
1619             *x 
= rect
.right 
- rect
.left
; 
1621             *y 
= rect
.bottom 
- rect
.top
; 
1626 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const 
1628     wxWindow 
* const parent 
= GetParent(); 
1631     if ( m_pendingPosition 
!= wxDefaultPosition 
) 
1633         pos 
= m_pendingPosition
; 
1635     else // use current position 
1637         RECT rect 
= wxGetWindowRect(GetHwnd()); 
1640         point
.x 
= rect
.left
; 
1643         // we do the adjustments with respect to the parent only for the "real" 
1644         // children, not for the dialogs/frames 
1645         if ( !IsTopLevel() ) 
1647             // Since we now have the absolute screen coords, if there's a 
1648             // parent we must subtract its top left corner 
1651                 ::ScreenToClient(GetHwndOf(parent
), &point
); 
1659     // we also must adjust by the client area offset: a control which is just 
1660     // under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx 
1661     if ( parent 
&& !IsTopLevel() ) 
1663         const wxPoint 
pt(parent
->GetClientAreaOrigin()); 
1674 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const 
1682     ::ScreenToClient(GetHwnd(), &pt
); 
1690 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const 
1698     ::ClientToScreen(GetHwnd(), &pt
); 
1707 wxWindowMSW::DoMoveSibling(WXHWND hwnd
, int x
, int y
, int width
, int height
) 
1709 #if USE_DEFERRED_SIZING 
1710     // if our parent had prepared a defer window handle for us, use it (unless 
1711     // we are a top level window) 
1712     wxWindowMSW 
* const parent 
= IsTopLevel() ? NULL 
: GetParent(); 
1714     HDWP hdwp 
= parent 
? (HDWP
)parent
->m_hDWP 
: NULL
; 
1717         hdwp 
= ::DeferWindowPos(hdwp
, (HWND
)hwnd
, NULL
, x
, y
, width
, height
, 
1718                                 SWP_NOZORDER 
| SWP_NOOWNERZORDER 
| SWP_NOACTIVATE
); 
1721             wxLogLastError(_T("DeferWindowPos")); 
1727         // hdwp must be updated as it may have been changed 
1728         parent
->m_hDWP 
= (WXHANDLE
)hdwp
; 
1733         // did deferred move, remember new coordinates of the window as they're 
1734         // different from what Windows would return for it 
1738     // otherwise (or if deferring failed) move the window in place immediately 
1739 #endif // USE_DEFERRED_SIZING 
1740     if ( !::MoveWindow((HWND
)hwnd
, x
, y
, width
, height
, IsShown()) ) 
1742         wxLogLastError(wxT("MoveWindow")); 
1745     // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move, 
1746     // ignored otherwise 
1750 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
) 
1752     // TODO: is this consistent with other platforms? 
1753     // Still, negative width or height shouldn't be allowed 
1759     if ( DoMoveSibling(m_hWnd
, x
, y
, width
, height
) ) 
1761 #if USE_DEFERRED_SIZING 
1762         m_pendingPosition 
= wxPoint(x
, y
); 
1763         m_pendingSize 
= wxSize(width
, height
); 
1764 #endif // USE_DEFERRED_SIZING 
1768 // set the size of the window: if the dimensions are positive, just use them, 
1769 // but if any of them is equal to -1, it means that we must find the value for 
1770 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
1771 // which case -1 is a valid value for x and y) 
1773 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
1774 // the width/height to best suit our contents, otherwise we reuse the current 
1776 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
1778     // get the current size and position... 
1779     int currentX
, currentY
; 
1780     int currentW
, currentH
; 
1782     GetPosition(¤tX
, ¤tY
); 
1783     GetSize(¤tW
, ¤tH
); 
1785     // ... and don't do anything (avoiding flicker) if it's already ok unless 
1786     // we're forced to resize the window 
1787     if ( x 
== currentX 
&& y 
== currentY 
&& 
1788          width 
== currentW 
&& height 
== currentH 
&& 
1789             !(sizeFlags 
& wxSIZE_FORCE
) ) 
1794     if ( x 
== wxDefaultCoord 
&& !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1796     if ( y 
== wxDefaultCoord 
&& !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1799     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
1801     wxSize size 
= wxDefaultSize
; 
1802     if ( width 
== wxDefaultCoord 
) 
1804         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
1806             size 
= DoGetBestSize(); 
1811             // just take the current one 
1816     if ( height 
== wxDefaultCoord 
) 
1818         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
1820             if ( size
.x 
== wxDefaultCoord 
) 
1822                 size 
= DoGetBestSize(); 
1824             //else: already called DoGetBestSize() above 
1830             // just take the current one 
1835     DoMoveWindow(x
, y
, width
, height
); 
1838 void wxWindowMSW::DoSetClientSize(int width
, int height
) 
1840     // setting the client size is less obvious than it could have been 
1841     // because in the result of changing the total size the window scrollbar 
1842     // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect() 
1843     // doesn't take neither into account) and so the client size will not be 
1844     // correct as the difference between the total and client size changes -- 
1845     // so we keep changing it until we get it right 
1847     // normally this loop shouldn't take more than 3 iterations (usually 1 but 
1848     // if scrollbars [dis]appear as the result of the first call, then 2 and it 
1849     // may become 3 if the window had 0 size originally and so we didn't 
1850     // calculate the scrollbar correction correctly during the first iteration) 
1851     // but just to be on the safe side we check for it instead of making it an 
1852     // "infinite" loop (i.e. leaving break inside as the only way to get out) 
1853     for ( int i 
= 0; i 
< 4; i
++ ) 
1856         ::GetClientRect(GetHwnd(), &rectClient
); 
1858         // if the size is already ok, stop here (NB: rectClient.left = top = 0) 
1859         if ( (rectClient
.right 
== width 
|| width 
== wxDefaultCoord
) && 
1860              (rectClient
.bottom 
== height 
|| height 
== wxDefaultCoord
) ) 
1865         // Find the difference between the entire window (title bar and all) 
1866         // and the client area; add this to the new client size to move the 
1869         ::GetWindowRect(GetHwnd(), &rectWin
); 
1871         const int widthWin 
= rectWin
.right 
- rectWin
.left
, 
1872                   heightWin 
= rectWin
.bottom 
- rectWin
.top
; 
1874         // MoveWindow positions the child windows relative to the parent, so 
1875         // adjust if necessary 
1876         if ( !IsTopLevel() ) 
1878             wxWindow 
*parent 
= GetParent(); 
1881                 ::ScreenToClient(GetHwndOf(parent
), (POINT 
*)&rectWin
); 
1885         // don't call DoMoveWindow() because we want to move window immediately 
1886         // and not defer it here as otherwise the value returned by 
1887         // GetClient/WindowRect() wouldn't change as the window wouldn't be 
1889         if ( !::MoveWindow(GetHwnd(), 
1892                            width 
+ widthWin 
- rectClient
.right
, 
1893                            height 
+ heightWin 
- rectClient
.bottom
, 
1896             wxLogLastError(_T("MoveWindow")); 
1901 // --------------------------------------------------------------------------- 
1903 // --------------------------------------------------------------------------- 
1905 int wxWindowMSW::GetCharHeight() const 
1907     return wxGetTextMetrics(this).tmHeight
; 
1910 int wxWindowMSW::GetCharWidth() const 
1912     // +1 is needed because Windows apparently adds it when calculating the 
1913     // dialog units size in pixels 
1914 #if wxDIALOG_UNIT_COMPATIBILITY 
1915     return wxGetTextMetrics(this).tmAveCharWidth
; 
1917     return wxGetTextMetrics(this).tmAveCharWidth 
+ 1; 
1921 void wxWindowMSW::GetTextExtent(const wxString
& string
, 
1923                              int *descent
, int *externalLeading
, 
1924                              const wxFont 
*theFont
) const 
1926     wxASSERT_MSG( !theFont 
|| theFont
->Ok(), 
1927                     _T("invalid font in GetTextExtent()") ); 
1931         fontToUse 
= *theFont
; 
1933         fontToUse 
= GetFont(); 
1935     WindowHDC 
hdc(GetHwnd()); 
1936     SelectInHDC 
selectFont(hdc
, GetHfontOf(fontToUse
)); 
1940     ::GetTextExtentPoint32(hdc
, string
, string
.length(), &sizeRect
); 
1941     GetTextMetrics(hdc
, &tm
); 
1948         *descent 
= tm
.tmDescent
; 
1949     if ( externalLeading 
) 
1950         *externalLeading 
= tm
.tmExternalLeading
; 
1953 // --------------------------------------------------------------------------- 
1955 // --------------------------------------------------------------------------- 
1957 #if wxUSE_MENUS_NATIVE 
1959 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue 
1960 // immediately, without waiting for the next event loop iteration 
1962 // NB: this function should probably be made public later as it can almost 
1963 //     surely replace wxYield() elsewhere as well 
1964 static void wxYieldForCommandsOnly() 
1966     // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't 
1967     // want to process it here) 
1969     while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) ) 
1971         if ( msg
.message 
== WM_QUIT 
) 
1973             // if we retrieved a WM_QUIT, insert back into the message queue. 
1974             ::PostQuitMessage(0); 
1978         // luckily (as we don't have access to wxEventLoopImpl method from here 
1979         // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it 
1981         ::TranslateMessage(&msg
); 
1982         ::DispatchMessage(&msg
); 
1986 bool wxWindowMSW::DoPopupMenu(wxMenu 
*menu
, int x
, int y
) 
1988     menu
->SetInvokingWindow(this); 
1991     if ( x 
== wxDefaultCoord 
&& y 
== wxDefaultCoord 
) 
1993         wxPoint mouse 
= ScreenToClient(wxGetMousePosition()); 
1994         x 
= mouse
.x
; y 
= mouse
.y
; 
1997     HWND hWnd 
= GetHwnd(); 
1998     HMENU hMenu 
= GetHmenuOf(menu
); 
2002     ::ClientToScreen(hWnd
, &point
); 
2003     wxCurrentPopupMenu 
= menu
; 
2004 #if defined(__WXWINCE__) 
2007     UINT flags 
= TPM_RIGHTBUTTON 
| TPM_RECURSE
; 
2009     ::TrackPopupMenu(hMenu
, flags
, point
.x
, point
.y
, 0, hWnd
, NULL
); 
2011     // we need to do it right now as otherwise the events are never going to be 
2012     // sent to wxCurrentPopupMenu from HandleCommand() 
2014     // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't 
2015     // help and we'd still need wxYieldForCommandsOnly() as the menu may be 
2016     // destroyed as soon as we return (it can be a local variable in the caller 
2017     // for example) and so we do need to process the event immediately 
2018     wxYieldForCommandsOnly(); 
2020     wxCurrentPopupMenu 
= NULL
; 
2022     menu
->SetInvokingWindow(NULL
); 
2027 #endif // wxUSE_MENUS_NATIVE 
2029 // =========================================================================== 
2030 // pre/post message processing 
2031 // =========================================================================== 
2033 WXLRESULT 
wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
2036         return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
2038         return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
); 
2041 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
) 
2043     // wxUniversal implements tab traversal itself 
2044 #ifndef __WXUNIVERSAL__ 
2045     if ( m_hWnd 
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) ) 
2047         // intercept dialog navigation keys 
2048         MSG 
*msg 
= (MSG 
*)pMsg
; 
2050         // here we try to do all the job which ::IsDialogMessage() usually does 
2052         if ( msg
->message 
== WM_KEYDOWN 
) 
2054             bool bCtrlDown 
= wxIsCtrlDown(); 
2055             bool bShiftDown 
= wxIsShiftDown(); 
2057             // WM_GETDLGCODE: ask the control if it wants the key for itself, 
2058             // don't process it if it's the case (except for Ctrl-Tab/Enter 
2059             // combinations which are always processed) 
2060             LONG lDlgCode 
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0); 
2062             // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the 
2063             // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, 
2064             // it, of course, implies them 
2065             if ( lDlgCode 
& DLGC_WANTALLKEYS 
) 
2067                 lDlgCode 
|= DLGC_WANTTAB 
| DLGC_WANTARROWS
; 
2070             bool bForward 
= true, 
2071                  bWindowChange 
= false, 
2074             // should we process this message specially? 
2075             bool bProcess 
= true; 
2076             switch ( msg
->wParam 
) 
2079                     if ( lDlgCode 
& DLGC_WANTTAB 
) { 
2083                         // Ctrl-Tab cycles thru notebook pages 
2084                         bWindowChange 
= bCtrlDown
; 
2085                         bForward 
= !bShiftDown
; 
2092                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
2100                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
2109                     // we treat PageUp/Dn as arrows because chances are that 
2110                     // a control which needs arrows also needs them for 
2111                     // navigation (e.g. wxTextCtrl, wxListCtrl, ...) 
2112                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || !bCtrlDown 
) 
2115                         bWindowChange 
= true; 
2120                         if ( (lDlgCode 
& DLGC_WANTMESSAGE
) && !bCtrlDown 
) 
2122                             // control wants to process Enter itself, don't 
2123                             // call IsDialogMessage() which would interpret 
2128                         // currently active button should get enter press even 
2129                         // if there is a default button elsewhere 
2130                         if ( lDlgCode 
& DLGC_DEFPUSHBUTTON 
) 
2132                             // let IsDialogMessage() handle this for all 
2133                             // buttons except the owner-drawn ones which it 
2134                             // just seems to ignore 
2135                             long style 
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
); 
2136                             if ( (style 
& BS_OWNERDRAW
) == BS_OWNERDRAW 
) 
2138                                 // emulate the button click 
2140                                     btn 
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
); 
2142                                     btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
2147                         else // not a button itself 
2150                             wxButton 
*btn 
= wxDynamicCast(GetDefaultItem(), 
2152                             if ( btn 
&& btn
->IsEnabled() ) 
2154                                 // if we do have a default button, do press it 
2155                                 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
2159                             else // no default button 
2160 #endif // wxUSE_BUTTON 
2163                                 wxJoystickEvent 
event(wxEVT_JOY_BUTTON_DOWN
); 
2164                                 event
.SetEventObject(this); 
2165                                 if(GetEventHandler()->ProcessEvent(event
)) 
2168                                 // this is a quick and dirty test for a text 
2170                                 if ( !(lDlgCode 
& DLGC_HASSETSEL
) ) 
2172                                     // don't process Enter, the control might 
2173                                     // need it for itself and don't let 
2174                                     // ::IsDialogMessage() have it as it can 
2175                                     // eat the Enter events sometimes 
2178                                 else if (!IsTopLevel()) 
2180                                     // if not a top level window, let parent 
2184                                 //else: treat Enter as TAB: pass to the next 
2185                                 //      control as this is the best thing to do 
2186                                 //      if the text doesn't handle Enter itself 
2198                 wxNavigationKeyEvent event
; 
2199                 event
.SetDirection(bForward
); 
2200                 event
.SetWindowChange(bWindowChange
); 
2201                 event
.SetFromTab(bFromTab
); 
2202                 event
.SetEventObject(this); 
2204                 if ( GetEventHandler()->ProcessEvent(event
) ) 
2206                     // as we don't call IsDialogMessage(), which would take of 
2207                     // this by default, we need to manually send this message 
2208                     // so that controls can change their UI state if needed 
2209                     MSWUpdateUIState(UIS_CLEAR
, UISF_HIDEFOCUS
); 
2216         // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the 
2217         // message even when there is no cancel button and when the message is 
2218         // needed by the control itself: in particular, it prevents the tree in 
2219         // place edit control from being closed with Escape in a dialog 
2220         if ( msg
->message 
!= WM_KEYDOWN 
|| msg
->wParam 
!= VK_ESCAPE 
) 
2222             // ::IsDialogMessage() is broken and may sometimes hang the 
2223             // application by going into an infinite loop, so we try to detect 
2224             // [some of] the situations when this may happen and not call it 
2227             // assume we can call it by default 
2228             bool canSafelyCallIsDlgMsg 
= true; 
2230             HWND hwndFocus 
= ::GetFocus(); 
2232             // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter 
2233             // an infinite loop, because it will recursively check the child 
2234             // windows but not the window itself and so if none of the children 
2235             // accepts focus it loops forever (as it only stops when it gets 
2236             // back to the window it started from) 
2238             // while it is very unusual that a window with WS_EX_CONTROLPARENT 
2239             // style has the focus, it can happen. One such possibility is if 
2240             // all windows are either toplevel, wxDialog, wxPanel or static 
2241             // controls and no window can actually accept keyboard input. 
2242 #if !defined(__WXWINCE__) 
2243             if ( ::GetWindowLong(hwndFocus
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
2245                 // pessimistic by default 
2246                 canSafelyCallIsDlgMsg 
= false; 
2247                 for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
2249                       node 
= node
->GetNext() ) 
2251                     wxWindow 
* const win 
= node
->GetData(); 
2252                     if ( win
->AcceptsFocus() && 
2253                             !(::GetWindowLong(GetHwndOf(win
), GWL_EXSTYLE
) & 
2254                                 WS_EX_CONTROLPARENT
) ) 
2256                         // it shouldn't hang... 
2257                         canSafelyCallIsDlgMsg 
= true; 
2263 #endif // !__WXWINCE__ 
2265             if ( canSafelyCallIsDlgMsg 
) 
2267                 // ::IsDialogMessage() can enter in an infinite loop when the 
2268                 // currently focused window is disabled or hidden and its 
2269                 // parent has WS_EX_CONTROLPARENT style, so don't call it in 
2273                     if ( !::IsWindowEnabled(hwndFocus
) || 
2274                             !::IsWindowVisible(hwndFocus
) ) 
2276                         // it would enter an infinite loop if we do this! 
2277                         canSafelyCallIsDlgMsg 
= false; 
2282                     if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) ) 
2284                         // it's a top level window, don't go further -- e.g. even 
2285                         // if the parent of a dialog is disabled, this doesn't 
2286                         // break navigation inside the dialog 
2290                     hwndFocus 
= ::GetParent(hwndFocus
); 
2294             // let IsDialogMessage() have the message if it's safe to call it 
2295             if ( canSafelyCallIsDlgMsg 
&& ::IsDialogMessage(GetHwnd(), msg
) ) 
2297                 // IsDialogMessage() did something... 
2302 #endif // __WXUNIVERSAL__ 
2307         // relay mouse move events to the tooltip control 
2308         MSG 
*msg 
= (MSG 
*)pMsg
; 
2309         if ( msg
->message 
== WM_MOUSEMOVE 
) 
2310             wxToolTip::RelayEvent(pMsg
); 
2312 #endif // wxUSE_TOOLTIPS 
2317 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
) 
2319 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__) 
2320     return m_acceleratorTable
.Translate(this, pMsg
); 
2324 #endif // wxUSE_ACCEL 
2327 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
)) 
2329     // preprocess all messages by default 
2333 // --------------------------------------------------------------------------- 
2334 // message params unpackers 
2335 // --------------------------------------------------------------------------- 
2337 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2338                              WORD 
*id
, WXHWND 
*hwnd
, WORD 
*cmd
) 
2340     *id 
= LOWORD(wParam
); 
2341     *hwnd 
= (WXHWND
)lParam
; 
2342     *cmd 
= HIWORD(wParam
); 
2345 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2346                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2348     *state 
= LOWORD(wParam
); 
2349     *minimized 
= HIWORD(wParam
); 
2350     *hwnd 
= (WXHWND
)lParam
; 
2353 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2354                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2356     *code 
= LOWORD(wParam
); 
2357     *pos 
= HIWORD(wParam
); 
2358     *hwnd 
= (WXHWND
)lParam
; 
2361 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2362                                  WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2364     *hwnd 
= (WXHWND
)lParam
; 
2365     *hdc 
= (WXHDC
)wParam
; 
2368 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2369                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2371     *item 
= (WXWORD
)wParam
; 
2372     *flags 
= HIWORD(wParam
); 
2373     *hmenu 
= (WXHMENU
)lParam
; 
2376 // --------------------------------------------------------------------------- 
2377 // Main wxWidgets window proc and the window proc for wxWindow 
2378 // --------------------------------------------------------------------------- 
2380 // Hook for new window just as it's being created, when the window isn't yet 
2381 // associated with the handle 
2382 static wxWindowMSW 
*gs_winBeingCreated 
= NULL
; 
2384 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the 
2385 // window being created and insures that it's always unset back later 
2386 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW 
*winBeingCreated
) 
2388     gs_winBeingCreated 
= winBeingCreated
; 
2391 wxWindowCreationHook::~wxWindowCreationHook() 
2393     gs_winBeingCreated 
= NULL
; 
2397 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) 
2399     // trace all messages - useful for the debugging 
2401     wxLogTrace(wxTraceMessages
, 
2402                wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"), 
2403                wxGetMessageName(message
), (long)hWnd
, (long)wParam
, lParam
); 
2404 #endif // __WXDEBUG__ 
2406     wxWindowMSW 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2408     // when we get the first message for the HWND we just created, we associate 
2409     // it with wxWindow stored in gs_winBeingCreated 
2410     if ( !wnd 
&& gs_winBeingCreated 
) 
2412         wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
); 
2413         wnd 
= gs_winBeingCreated
; 
2414         gs_winBeingCreated 
= NULL
; 
2415         wnd
->SetHWND((WXHWND
)hWnd
); 
2420     if ( wnd 
&& wxEventLoop::AllowProcessing(wnd
) ) 
2421         rc 
= wnd
->MSWWindowProc(message
, wParam
, lParam
); 
2423         rc 
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
); 
2428 WXLRESULT 
wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
2430     // did we process the message? 
2431     bool processed 
= false; 
2441     // for most messages we should return 0 when we do process the message 
2449                 processed 
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
); 
2452                     // return 0 to allow window creation 
2453                     rc
.result 
= mayCreate 
? 0 : -1; 
2459             // never set processed to true and *always* pass WM_DESTROY to 
2460             // DefWindowProc() as Windows may do some internal cleanup when 
2461             // processing it and failing to pass the message along may cause 
2462             // memory and resource leaks! 
2463             (void)HandleDestroy(); 
2467             processed 
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), wParam
); 
2471             processed 
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2474 #if !defined(__WXWINCE__) 
2477                 LPRECT pRect 
= (LPRECT
)lParam
; 
2479                 rc
.SetLeft(pRect
->left
); 
2480                 rc
.SetTop(pRect
->top
); 
2481                 rc
.SetRight(pRect
->right
); 
2482                 rc
.SetBottom(pRect
->bottom
); 
2483                 processed 
= HandleMoving(rc
); 
2485                     pRect
->left 
= rc
.GetLeft(); 
2486                     pRect
->top 
= rc
.GetTop(); 
2487                     pRect
->right 
= rc
.GetRight(); 
2488                     pRect
->bottom 
= rc
.GetBottom(); 
2495                 LPRECT pRect 
= (LPRECT
)lParam
; 
2497                 rc
.SetLeft(pRect
->left
); 
2498                 rc
.SetTop(pRect
->top
); 
2499                 rc
.SetRight(pRect
->right
); 
2500                 rc
.SetBottom(pRect
->bottom
); 
2501                 processed 
= HandleSizing(rc
); 
2503                     pRect
->left 
= rc
.GetLeft(); 
2504                     pRect
->top 
= rc
.GetTop(); 
2505                     pRect
->right 
= rc
.GetRight(); 
2506                     pRect
->bottom 
= rc
.GetBottom(); 
2510 #endif // !__WXWINCE__ 
2512 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
2513         case WM_ACTIVATEAPP
: 
2514             // This implicitly sends a wxEVT_ACTIVATE_APP event 
2515             wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
2521                 WXWORD state
, minimized
; 
2523                 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
); 
2525                 processed 
= HandleActivate(state
, minimized 
!= 0, (WXHWND
)hwnd
); 
2530             processed 
= HandleSetFocus((WXHWND
)(HWND
)wParam
); 
2534             processed 
= HandleKillFocus((WXHWND
)(HWND
)wParam
); 
2537         case WM_PRINTCLIENT
: 
2538             processed 
= HandlePrintClient((WXHDC
)wParam
); 
2544                 wxPaintDCEx 
dc((wxWindow 
*)this, (WXHDC
)wParam
); 
2546                 processed 
= HandlePaint(); 
2550                 processed 
= HandlePaint(); 
2555 #ifdef __WXUNIVERSAL__ 
2556             // Universal uses its own wxFrame/wxDialog, so we don't receive 
2557             // close events unless we have this. 
2559 #endif // __WXUNIVERSAL__ 
2561             // don't let the DefWindowProc() destroy our window - we'll do it 
2562             // ourselves in ~wxWindow 
2568             processed 
= HandleShow(wParam 
!= 0, (int)lParam
); 
2572             processed 
= HandleMouseMove(GET_X_LPARAM(lParam
), 
2573                                         GET_Y_LPARAM(lParam
), 
2577 #ifdef HAVE_TRACKMOUSEEVENT 
2579             // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least) 
2580             if ( m_mouseInWindow 
) 
2582                 GenerateMouseLeave(); 
2585             // always pass processed back as false, this allows the window 
2586             // manager to process the message too.  This is needed to 
2587             // ensure windows XP themes work properly as the mouse moves 
2588             // over widgets like buttons. So don't set processed to true here. 
2590 #endif // HAVE_TRACKMOUSEEVENT 
2592 #if wxUSE_MOUSEWHEEL 
2594             processed 
= HandleMouseWheel(wParam
, lParam
); 
2598         case WM_LBUTTONDOWN
: 
2600         case WM_LBUTTONDBLCLK
: 
2601         case WM_RBUTTONDOWN
: 
2603         case WM_RBUTTONDBLCLK
: 
2604         case WM_MBUTTONDOWN
: 
2606         case WM_MBUTTONDBLCLK
: 
2608 #ifdef __WXMICROWIN__ 
2609                 // MicroWindows seems to ignore the fact that a window is 
2610                 // disabled. So catch mouse events and throw them away if 
2612                 wxWindowMSW
* win 
= this; 
2615                     if (!win
->IsEnabled()) 
2621                     win 
= win
->GetParent(); 
2622                     if ( !win 
|| win
->IsTopLevel() ) 
2629 #endif // __WXMICROWIN__ 
2630                 int x 
= GET_X_LPARAM(lParam
), 
2631                     y 
= GET_Y_LPARAM(lParam
); 
2634                 // redirect the event to a static control if necessary by 
2635                 // finding one under mouse because under CE the static controls 
2636                 // don't generate mouse events (even with SS_NOTIFY) 
2638                 if ( GetCapture() == this ) 
2640                     // but don't do it if the mouse is captured by this window 
2641                     // because then it should really get this event itself 
2646                     win 
= FindWindowForMouseEvent(this, &x
, &y
); 
2648                     // this should never happen 
2649                     wxCHECK_MSG( win
, 0, 
2650                                  _T("FindWindowForMouseEvent() returned NULL") ); 
2653                 if (IsContextMenuEnabled() && message 
== WM_LBUTTONDOWN
) 
2655                     SHRGINFO shrgi 
= {0}; 
2657                     shrgi
.cbSize 
= sizeof(SHRGINFO
); 
2658                     shrgi
.hwndClient 
= (HWND
) GetHWND(); 
2662                     shrgi
.dwFlags 
= SHRG_RETURNCMD
; 
2663                     // shrgi.dwFlags = SHRG_NOTIFYPARENT; 
2665                     if (GN_CONTEXTMENU 
== ::SHRecognizeGesture(&shrgi
)) 
2668                         pt 
= ClientToScreen(pt
); 
2670                         wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
2672                         evtCtx
.SetEventObject(this); 
2673                         if (GetEventHandler()->ProcessEvent(evtCtx
)) 
2682 #else // !__WXWINCE__ 
2683                 wxWindowMSW 
*win 
= this; 
2684 #endif // __WXWINCE__/!__WXWINCE__ 
2686                 processed 
= win
->HandleMouseEvent(message
, x
, y
, wParam
); 
2688                 // if the app didn't eat the event, handle it in the default 
2689                 // way, that is by giving this window the focus 
2692                     // for the standard classes their WndProc sets the focus to 
2693                     // them anyhow and doing it from here results in some weird 
2694                     // problems, so don't do it for them (unnecessary anyhow) 
2695                     if ( !win
->IsOfStandardClass() ) 
2697                         if ( message 
== WM_LBUTTONDOWN 
&& win
->AcceptsFocus() ) 
2709         case MM_JOY1BUTTONDOWN
: 
2710         case MM_JOY2BUTTONDOWN
: 
2711         case MM_JOY1BUTTONUP
: 
2712         case MM_JOY2BUTTONUP
: 
2713             processed 
= HandleJoystickEvent(message
, 
2714                                             GET_X_LPARAM(lParam
), 
2715                                             GET_Y_LPARAM(lParam
), 
2718 #endif // __WXMICROWIN__ 
2724                 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
); 
2726                 processed 
= HandleCommand(id
, cmd
, hwnd
); 
2731             processed 
= HandleNotify((int)wParam
, lParam
, &rc
.result
); 
2734         // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU, 
2735         // otherwise DefWindowProc() does it perfectly fine for us, but MSLU 
2736         // apparently doesn't always behave properly and needs some help 
2737 #if wxUSE_UNICODE_MSLU && defined(NF_QUERY) 
2738         case WM_NOTIFYFORMAT
: 
2739             if ( lParam 
== NF_QUERY 
) 
2742                 rc
.result 
= NFR_UNICODE
; 
2745 #endif // wxUSE_UNICODE_MSLU 
2747             // for these messages we must return true if process the message 
2750         case WM_MEASUREITEM
: 
2752                 int idCtrl 
= (UINT
)wParam
; 
2753                 if ( message 
== WM_DRAWITEM 
) 
2755                     processed 
= MSWOnDrawItem(idCtrl
, 
2756                                               (WXDRAWITEMSTRUCT 
*)lParam
); 
2760                     processed 
= MSWOnMeasureItem(idCtrl
, 
2761                                                  (WXMEASUREITEMSTRUCT 
*)lParam
); 
2768 #endif // defined(WM_DRAWITEM) 
2771             if ( !IsOfStandardClass() ) 
2773                 // we always want to get the char events 
2774                 rc
.result 
= DLGC_WANTCHARS
; 
2776                 if ( GetWindowStyleFlag() & wxWANTS_CHARS 
) 
2778                     // in fact, we want everything 
2779                     rc
.result 
|= DLGC_WANTARROWS 
| 
2786             //else: get the dlg code from the DefWindowProc() 
2791             // If this has been processed by an event handler, return 0 now 
2792             // (we've handled it). 
2793             m_lastKeydownProcessed 
= HandleKeyDown((WORD
) wParam
, lParam
); 
2794             if ( m_lastKeydownProcessed 
) 
2803                     // we consider these messages "not interesting" to OnChar, so 
2804                     // just don't do anything more with them 
2814                     // avoid duplicate messages to OnChar for these ASCII keys: 
2815                     // they will be translated by TranslateMessage() and received 
2847                         // but set processed to false, not true to still pass them 
2848                         // to the control's default window proc - otherwise 
2849                         // built-in keyboard handling won't work 
2854                     // special case of VK_APPS: treat it the same as right mouse 
2855                     // click because both usually pop up a context menu 
2857                         processed 
= HandleMouseEvent(WM_RBUTTONDOWN
, -1, -1, 0); 
2862                         // do generate a CHAR event 
2863                         processed 
= HandleChar((WORD
)wParam
, lParam
); 
2866             if (message 
== WM_SYSKEYDOWN
)  // Let Windows still handle the SYSKEYs 
2873             // special case of VK_APPS: treat it the same as right mouse button 
2874             if ( wParam 
== VK_APPS 
) 
2876                 processed 
= HandleMouseEvent(WM_RBUTTONUP
, -1, -1, 0); 
2881                 processed 
= HandleKeyUp((WORD
) wParam
, lParam
); 
2886         case WM_CHAR
: // Always an ASCII character 
2887             if ( m_lastKeydownProcessed 
) 
2889                 // The key was handled in the EVT_KEY_DOWN and handling 
2890                 // a key in an EVT_KEY_DOWN handler is meant, by 
2891                 // design, to prevent EVT_CHARs from happening 
2892                 m_lastKeydownProcessed 
= false; 
2897                 processed 
= HandleChar((WORD
)wParam
, lParam
, true); 
2903             processed 
= HandleHotKey((WORD
)wParam
, lParam
); 
2905 #endif // wxUSE_HOTKEY 
2912                 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
); 
2914                 processed 
= MSWOnScroll(message 
== WM_HSCROLL 
? wxHORIZONTAL
 
2920         // CTLCOLOR messages are sent by children to query the parent for their 
2922 #ifndef __WXMICROWIN__ 
2923         case WM_CTLCOLORMSGBOX
: 
2924         case WM_CTLCOLOREDIT
: 
2925         case WM_CTLCOLORLISTBOX
: 
2926         case WM_CTLCOLORBTN
: 
2927         case WM_CTLCOLORDLG
: 
2928         case WM_CTLCOLORSCROLLBAR
: 
2929         case WM_CTLCOLORSTATIC
: 
2933                 UnpackCtlColor(wParam
, lParam
, &hdc
, &hwnd
); 
2935                 processed 
= HandleCtlColor(&rc
.hBrush
, (WXHDC
)hdc
, (WXHWND
)hwnd
); 
2938 #endif // !__WXMICROWIN__ 
2940         case WM_SYSCOLORCHANGE
: 
2941             // the return value for this message is ignored 
2942             processed 
= HandleSysColorChange(); 
2945 #if !defined(__WXWINCE__) 
2946         case WM_DISPLAYCHANGE
: 
2947             processed 
= HandleDisplayChange(); 
2951         case WM_PALETTECHANGED
: 
2952             processed 
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
); 
2955         case WM_CAPTURECHANGED
: 
2956             processed 
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
); 
2959         case WM_SETTINGCHANGE
: 
2960             processed 
= HandleSettingChange(wParam
, lParam
); 
2963         case WM_QUERYNEWPALETTE
: 
2964             processed 
= HandleQueryNewPalette(); 
2968             processed 
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
2971                 // we processed the message, i.e. erased the background 
2976 #if !defined(__WXWINCE__) 
2978             processed 
= HandleDropFiles(wParam
); 
2983             processed 
= HandleInitDialog((WXHWND
)(HWND
)wParam
); 
2987                 // we never set focus from here 
2992 #if !defined(__WXWINCE__) 
2993         case WM_QUERYENDSESSION
: 
2994             processed 
= HandleQueryEndSession(lParam
, &rc
.allow
); 
2998             processed 
= HandleEndSession(wParam 
!= 0, lParam
); 
3001         case WM_GETMINMAXINFO
: 
3002             processed 
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
); 
3007             processed 
= HandleSetCursor((WXHWND
)(HWND
)wParam
, 
3008                                         LOWORD(lParam
),     // hit test 
3009                                         HIWORD(lParam
));    // mouse msg 
3013                 // returning TRUE stops the DefWindowProc() from further 
3014                 // processing this message - exactly what we need because we've 
3015                 // just set the cursor. 
3020 #if wxUSE_ACCESSIBILITY 
3023                 //WPARAM dwFlags = (WPARAM) (DWORD) wParam; 
3024                 LPARAM dwObjId 
= (LPARAM
) (DWORD
) lParam
; 
3026                 if (dwObjId 
== (LPARAM
)OBJID_CLIENT 
&& GetOrCreateAccessible()) 
3028                     return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible()); 
3034 #if defined(WM_HELP) 
3037                 // by default, WM_HELP is propagated by DefWindowProc() upwards 
3038                 // to the window parent but as we do it ourselves already 
3039                 // (wxHelpEvent is derived from wxCommandEvent), we don't want 
3040                 // to get the other events if we process this message at all 
3043                 // WM_HELP doesn't use lParam under CE 
3045                 HELPINFO
* info 
= (HELPINFO
*) lParam
; 
3046                 if ( info
->iContextType 
== HELPINFO_WINDOW 
) 
3048 #endif // !__WXWINCE__ 
3049                     wxHelpEvent helpEvent
 
3054                                     wxGetMousePosition() // what else? 
3056                                     wxPoint(info
->MousePos
.x
, info
->MousePos
.y
) 
3060                     helpEvent
.SetEventObject(this); 
3061                     GetEventHandler()->ProcessEvent(helpEvent
); 
3064                 else if ( info
->iContextType 
== HELPINFO_MENUITEM 
) 
3066                     wxHelpEvent 
helpEvent(wxEVT_HELP
, info
->iCtrlId
); 
3067                     helpEvent
.SetEventObject(this); 
3068                     GetEventHandler()->ProcessEvent(helpEvent
); 
3071                 else // unknown help event? 
3075 #endif // !__WXWINCE__ 
3080 #if !defined(__WXWINCE__) 
3081         case WM_CONTEXTMENU
: 
3083                 // we don't convert from screen to client coordinates as 
3084                 // the event may be handled by a parent window 
3085                 wxPoint 
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
3087                 wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
3089                 // we could have got an event from our child, reflect it back 
3090                 // to it if this is the case 
3091                 wxWindowMSW 
*win 
= NULL
; 
3092                 if ( (WXHWND
)wParam 
!= m_hWnd 
) 
3094                     win 
= FindItemByHWND((WXHWND
)wParam
); 
3100                 evtCtx
.SetEventObject(win
); 
3101                 processed 
= win
->GetEventHandler()->ProcessEvent(evtCtx
); 
3107             // we're only interested in our own menus, not MF_SYSMENU 
3108             if ( HIWORD(wParam
) == MF_POPUP 
) 
3110                 // handle menu chars for ownerdrawn menu items 
3111                 int i 
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
); 
3112                 if ( i 
!= wxNOT_FOUND 
) 
3114                     rc
.result 
= MAKELRESULT(i
, MNC_EXECUTE
); 
3121         case WM_POWERBROADCAST
: 
3124                 processed 
= HandlePower(wParam
, lParam
, &vetoed
); 
3125                 rc
.result 
= processed 
&& vetoed 
? BROADCAST_QUERY_DENY 
: TRUE
; 
3128 #endif // __WXWINCE__ 
3134         wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."), 
3135                    wxGetMessageName(message
)); 
3136 #endif // __WXDEBUG__ 
3137         rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
3143 // ---------------------------------------------------------------------------- 
3144 // wxWindow <-> HWND map 
3145 // ---------------------------------------------------------------------------- 
3147 wxWinHashTable 
*wxWinHandleHash 
= NULL
; 
3149 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
) 
3151     return (wxWindow
*)wxWinHandleHash
->Get((long)hWnd
); 
3154 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
) 
3156     // adding NULL hWnd is (first) surely a result of an error and 
3157     // (secondly) breaks menu command processing 
3158     wxCHECK_RET( hWnd 
!= (HWND
)NULL
, 
3159                  wxT("attempt to add a NULL hWnd to window list ignored") ); 
3161     wxWindow 
*oldWin 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
3163     if ( oldWin 
&& (oldWin 
!= win
) ) 
3165         wxLogDebug(wxT("HWND %X already associated with another window (%s)"), 
3166                    (int) hWnd
, win
->GetClassInfo()->GetClassName()); 
3169 #endif // __WXDEBUG__ 
3172         wxWinHandleHash
->Put((long)hWnd
, (wxWindow 
*)win
); 
3176 void wxRemoveHandleAssociation(wxWindowMSW 
*win
) 
3178     wxWinHandleHash
->Delete((long)win
->GetHWND()); 
3181 // ---------------------------------------------------------------------------- 
3182 // various MSW speciic class dependent functions 
3183 // ---------------------------------------------------------------------------- 
3185 // Default destroyer - override if you destroy it in some other way 
3186 // (e.g. with MDI child windows) 
3187 void wxWindowMSW::MSWDestroyWindow() 
3191 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
, 
3194                                            int& w
, int& h
) const 
3196     // yes, those are just some arbitrary hardcoded numbers 
3197     static const int DEFAULT_Y 
= 200; 
3199     bool nonDefault 
= false; 
3201     if ( pos
.x 
== wxDefaultCoord 
) 
3203         // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we 
3204         // can just as well set it to CW_USEDEFAULT as well 
3210         // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it 
3211         // neither because it is not handled as a special value by Windows then 
3212         // and so we have to choose some default value for it 
3214         y 
= pos
.y 
== wxDefaultCoord 
? DEFAULT_Y 
: pos
.y
; 
3220       NB: there used to be some code here which set the initial size of the 
3221           window to the client size of the parent if no explicit size was 
3222           specified. This was wrong because wxWidgets programs often assume 
3223           that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke 
3224           it. To see why, you should understand that Windows sends WM_SIZE from 
3225           inside ::CreateWindow() anyhow. However, ::CreateWindow() is called 
3226           from some base class ctor and so this WM_SIZE is not processed in the 
3227           real class' OnSize() (because it's not fully constructed yet and the 
3228           event goes to some base class OnSize() instead). So the WM_SIZE we 
3229           rely on is the one sent when the parent frame resizes its children 
3230           but here is the problem: if the child already has just the right 
3231           size, nothing will happen as both wxWidgets and Windows check for 
3232           this and ignore any attempts to change the window size to the size it 
3233           already has - so no WM_SIZE would be sent. 
3237     // we don't use CW_USEDEFAULT here for several reasons: 
3239     //  1. it results in huge frames on modern screens (1000*800 is not 
3240     //     uncommon on my 1280*1024 screen) which is way too big for a half 
3241     //     empty frame of most of wxWidgets samples for example) 
3243     //  2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which 
3244     //     the default is for whatever reason 8*8 which breaks client <-> 
3245     //     window size calculations (it would be nice if it didn't, but it 
3246     //     does and the simplest way to fix it seemed to change the broken 
3247     //     default size anyhow) 
3249     //  3. there is just no advantage in doing it: with x and y it is 
3250     //     possible that [future versions of] Windows position the new top 
3251     //     level window in some smart way which we can't do, but we can 
3252     //     guess a reasonably good size for a new window just as well 
3255     // However, on PocketPC devices, we must use the default 
3256     // size if possible. 
3258     if (size
.x 
== wxDefaultCoord
) 
3262     if (size
.y 
== wxDefaultCoord
) 
3267     if ( size
.x 
== wxDefaultCoord 
|| size
.y 
== wxDefaultCoord
) 
3271     w 
= WidthDefault(size
.x
); 
3272     h 
= HeightDefault(size
.y
); 
3275     AdjustForParentClientOrigin(x
, y
); 
3280 WXHWND 
wxWindowMSW::MSWGetParent() const 
3282     return m_parent 
? m_parent
->GetHWND() : WXHWND(NULL
); 
3285 bool wxWindowMSW::MSWCreate(const wxChar 
*wclass
, 
3286                             const wxChar 
*title
, 
3290                             WXDWORD extendedStyle
) 
3292     // choose the position/size for the new window 
3294     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
3296     // controlId is menu handle for the top level windows, so set it to 0 
3297     // unless we're creating a child window 
3298     int controlId 
= style 
& WS_CHILD 
? GetId() : 0; 
3300     // for each class "Foo" we have we also have "FooNR" ("no repaint") class 
3301     // which is the same but without CS_[HV]REDRAW class styles so using it 
3302     // ensures that the window is not fully repainted on each resize 
3303     wxString 
className(wclass
); 
3304     if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE
) ) 
3306         className 
+= wxT("NR"); 
3309     // do create the window 
3310     wxWindowCreationHook 
hook(this); 
3312     m_hWnd 
= (WXHWND
)::CreateWindowEx
 
3316                         title 
? title 
: m_windowName
.c_str(), 
3319                         (HWND
)MSWGetParent(), 
3322                         NULL                        
// no extra data 
3327         wxLogSysError(_("Can't create window of class %s"), className
.c_str()); 
3332     SubclassWin(m_hWnd
); 
3337 // =========================================================================== 
3338 // MSW message handlers 
3339 // =========================================================================== 
3341 // --------------------------------------------------------------------------- 
3343 // --------------------------------------------------------------------------- 
3345 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
3347 #ifndef __WXMICROWIN__ 
3348     LPNMHDR hdr 
= (LPNMHDR
)lParam
; 
3349     HWND hWnd 
= hdr
->hwndFrom
; 
3350     wxWindow 
*win 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
3352     // if the control is one of our windows, let it handle the message itself 
3355         return win
->MSWOnNotify(idCtrl
, lParam
, result
); 
3358     // VZ: why did we do it? normally this is unnecessary and, besides, it 
3359     //     breaks the message processing for the toolbars because the tooltip 
3360     //     notifications were being forwarded to the toolbar child controls 
3361     //     (if it had any) before being passed to the toolbar itself, so in my 
3362     //     example the tooltip for the combobox was always shown instead of the 
3363     //     correct button tooltips 
3365     // try all our children 
3366     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3369         wxWindow 
*child 
= node
->GetData(); 
3370         if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) ) 
3375         node 
= node
->GetNext(); 
3379     // by default, handle it ourselves 
3380     return MSWOnNotify(idCtrl
, lParam
, result
); 
3381 #else // __WXMICROWIN__ 
3388 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
, 
3390                                       const wxString
& ttip
) 
3392     // I don't know why it happens, but the versions of comctl32.dll starting 
3393     // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally, 
3394     // this message is supposed to be sent to Unicode programs only) -- hence 
3395     // we need to handle it as well, otherwise no tooltips will be shown in 
3398     if ( !(code 
== (WXUINT
) TTN_NEEDTEXTA 
|| code 
== (WXUINT
) TTN_NEEDTEXTW
) 
3401         // not a tooltip message or no tooltip to show anyhow 
3406     LPTOOLTIPTEXT ttText 
= (LPTOOLTIPTEXT
)lParam
; 
3408     // We don't want to use the szText buffer because it has a limit of 80 
3409     // bytes and this is not enough, especially for Unicode build where it 
3410     // limits the tooltip string length to only 40 characters 
3412     // The best would be, of course, to not impose any length limitations at 
3413     // all but then the buffer would have to be dynamic and someone would have 
3414     // to free it and we don't have the tooltip owner object here any more, so 
3415     // for now use our own static buffer with a higher fixed max length. 
3417     // Note that using a static buffer should not be a problem as only a single 
3418     // tooltip can be shown at the same time anyhow. 
3420     if ( code 
== (WXUINT
) TTN_NEEDTEXTW 
) 
3422         // We need to convert tooltip from multi byte to Unicode on the fly. 
3423         static wchar_t buf
[513]; 
3425         // Truncate tooltip length if needed as otherwise we might not have 
3426         // enough space for it in the buffer and MultiByteToWideChar() would 
3428         size_t tipLength 
= wxMin(ttip
.length(), WXSIZEOF(buf
) - 1); 
3430         // Convert to WideChar without adding the NULL character. The NULL 
3431         // character is added afterwards (this is more efficient). 
3432         int len 
= ::MultiByteToWideChar
 
3444             wxLogLastError(_T("MultiByteToWideChar()")); 
3448         ttText
->lpszText 
= (LPSTR
) buf
; 
3450     else // TTN_NEEDTEXTA 
3451 #endif // !wxUSE_UNICODE 
3453         // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or 
3454         // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have 
3455         // to copy the string we have into the buffer 
3456         static wxChar buf
[513]; 
3457         wxStrncpy(buf
, ttip
.c_str(), WXSIZEOF(buf
) - 1); 
3458         buf
[WXSIZEOF(buf
) - 1] = _T('\0'); 
3459         ttText
->lpszText 
= buf
; 
3465 #endif // wxUSE_TOOLTIPS 
3467 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
), 
3469                               WXLPARAM
* WXUNUSED(result
)) 
3474         NMHDR
* hdr 
= (NMHDR 
*)lParam
; 
3475         if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip())) 
3482     wxUnusedVar(lParam
); 
3483 #endif // wxUSE_TOOLTIPS 
3488 // --------------------------------------------------------------------------- 
3489 // end session messages 
3490 // --------------------------------------------------------------------------- 
3492 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
) 
3494 #ifdef ENDSESSION_LOGOFF 
3495     wxCloseEvent 
event(wxEVT_QUERY_END_SESSION
, wxID_ANY
); 
3496     event
.SetEventObject(wxTheApp
); 
3497     event
.SetCanVeto(true); 
3498     event
.SetLoggingOff(logOff 
== (long)ENDSESSION_LOGOFF
); 
3500     bool rc 
= wxTheApp
->ProcessEvent(event
); 
3504         // we may end only if the app didn't veto session closing (double 
3506         *mayEnd 
= !event
.GetVeto(); 
3511     wxUnusedVar(logOff
); 
3512     wxUnusedVar(mayEnd
); 
3517 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
) 
3519 #ifdef ENDSESSION_LOGOFF 
3520     // do nothing if the session isn't ending 
3525     if ( (this != wxTheApp
->GetTopWindow()) ) 
3528     wxCloseEvent 
event(wxEVT_END_SESSION
, wxID_ANY
); 
3529     event
.SetEventObject(wxTheApp
); 
3530     event
.SetCanVeto(false); 
3531     event
.SetLoggingOff( (logOff 
== (long)ENDSESSION_LOGOFF
) ); 
3533     return wxTheApp
->ProcessEvent(event
); 
3535     wxUnusedVar(endSession
); 
3536     wxUnusedVar(logOff
); 
3541 // --------------------------------------------------------------------------- 
3542 // window creation/destruction 
3543 // --------------------------------------------------------------------------- 
3545 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT 
WXUNUSED_IN_WINCE(cs
), 
3548     // VZ: why is this commented out for WinCE? If it doesn't support 
3549     //     WS_EX_CONTROLPARENT at all it should be somehow handled globally, 
3550     //     not with multiple #ifdef's! 
3552     if ( ((CREATESTRUCT 
*)cs
)->dwExStyle 
& WS_EX_CONTROLPARENT 
) 
3553         EnsureParentHasControlParentStyle(GetParent()); 
3554 #endif // !__WXWINCE__ 
3561 bool wxWindowMSW::HandleDestroy() 
3565     // delete our drop target if we've got one 
3566 #if wxUSE_DRAG_AND_DROP 
3567     if ( m_dropTarget 
!= NULL 
) 
3569         m_dropTarget
->Revoke(m_hWnd
); 
3571         delete m_dropTarget
; 
3572         m_dropTarget 
= NULL
; 
3574 #endif // wxUSE_DRAG_AND_DROP 
3576     // WM_DESTROY handled 
3580 // --------------------------------------------------------------------------- 
3582 // --------------------------------------------------------------------------- 
3584 bool wxWindowMSW::HandleActivate(int state
, 
3585                               bool WXUNUSED(minimized
), 
3586                               WXHWND 
WXUNUSED(activate
)) 
3588     wxActivateEvent 
event(wxEVT_ACTIVATE
, 
3589                           (state 
== WA_ACTIVE
) || (state 
== WA_CLICKACTIVE
), 
3591     event
.SetEventObject(this); 
3593     return GetEventHandler()->ProcessEvent(event
); 
3596 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
) 
3598     // Strangly enough, some controls get set focus events when they are being 
3599     // deleted, even if they already had focus before. 
3600     if ( m_isBeingDeleted 
) 
3605     // notify the parent keeping track of focus for the kbd navigation 
3606     // purposes that we got it 
3607     wxChildFocusEvent 
eventFocus((wxWindow 
*)this); 
3608     (void)GetEventHandler()->ProcessEvent(eventFocus
); 
3614         m_caret
->OnSetFocus(); 
3616 #endif // wxUSE_CARET 
3619     // If it's a wxTextCtrl don't send the event as it will be done 
3620     // after the control gets to process it from EN_FOCUS handler 
3621     if ( wxDynamicCastThis(wxTextCtrl
) ) 
3625 #endif // wxUSE_TEXTCTRL 
3627     wxFocusEvent 
event(wxEVT_SET_FOCUS
, m_windowId
); 
3628     event
.SetEventObject(this); 
3630     // wxFindWinFromHandle() may return NULL, it is ok 
3631     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3633     return GetEventHandler()->ProcessEvent(event
); 
3636 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
) 
3642         m_caret
->OnKillFocus(); 
3644 #endif // wxUSE_CARET 
3647     // If it's a wxTextCtrl don't send the event as it will be done 
3648     // after the control gets to process it. 
3649     wxTextCtrl 
*ctrl 
= wxDynamicCastThis(wxTextCtrl
); 
3656     // Don't send the event when in the process of being deleted.  This can 
3657     // only cause problems if the event handler tries to access the object. 
3658     if ( m_isBeingDeleted 
) 
3663     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, m_windowId
); 
3664     event
.SetEventObject(this); 
3666     // wxFindWinFromHandle() may return NULL, it is ok 
3667     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3669     return GetEventHandler()->ProcessEvent(event
); 
3672 // --------------------------------------------------------------------------- 
3674 // --------------------------------------------------------------------------- 
3676 void wxWindowMSW::SetLabel( const wxString
& label
) 
3678     SetWindowText(GetHwnd(), label
.c_str()); 
3681 wxString 
wxWindowMSW::GetLabel() const 
3683     return wxGetWindowText(GetHWND()); 
3686 // --------------------------------------------------------------------------- 
3688 // --------------------------------------------------------------------------- 
3690 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
)) 
3692     wxShowEvent 
event(GetId(), show
); 
3693     event
.SetEventObject(this); 
3695     return GetEventHandler()->ProcessEvent(event
); 
3698 bool wxWindowMSW::HandleInitDialog(WXHWND 
WXUNUSED(hWndFocus
)) 
3700     wxInitDialogEvent 
event(GetId()); 
3701     event
.SetEventObject(this); 
3703     return GetEventHandler()->ProcessEvent(event
); 
3706 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
) 
3708 #if defined (__WXMICROWIN__) || defined(__WXWINCE__) 
3709     wxUnusedVar(wParam
); 
3711 #else // __WXMICROWIN__ 
3712     HDROP hFilesInfo 
= (HDROP
) wParam
; 
3714     // Get the total number of files dropped 
3715     UINT gwFilesDropped 
= ::DragQueryFile
 
3723     wxString 
*files 
= new wxString
[gwFilesDropped
]; 
3724     for ( UINT wIndex 
= 0; wIndex 
< gwFilesDropped
; wIndex
++ ) 
3726         // first get the needed buffer length (+1 for terminating NUL) 
3727         size_t len 
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1; 
3729         // and now get the file name 
3730         ::DragQueryFile(hFilesInfo
, wIndex
, 
3731                         wxStringBuffer(files
[wIndex
], len
), len
); 
3733     DragFinish (hFilesInfo
); 
3735     wxDropFilesEvent 
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
); 
3736     event
.SetEventObject(this); 
3739     DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
); 
3740     event
.m_pos
.x 
= dropPoint
.x
; 
3741     event
.m_pos
.y 
= dropPoint
.y
; 
3743     return GetEventHandler()->ProcessEvent(event
); 
3748 bool wxWindowMSW::HandleSetCursor(WXHWND 
WXUNUSED(hWnd
), 
3750                                   int WXUNUSED(mouseMsg
)) 
3752 #ifndef __WXMICROWIN__ 
3753     // the logic is as follows: 
3754     // -1. don't set cursor for non client area, including but not limited to 
3755     //     the title bar, scrollbars, &c 
3756     //  0. allow the user to override default behaviour by using EVT_SET_CURSOR 
3757     //  1. if we have the cursor set it unless wxIsBusy() 
3758     //  2. if we're a top level window, set some cursor anyhow 
3759     //  3. if wxIsBusy(), set the busy cursor, otherwise the global one 
3761     if ( nHitTest 
!= HTCLIENT 
) 
3766     HCURSOR hcursor 
= 0; 
3768     // first ask the user code - it may wish to set the cursor in some very 
3769     // specific way (for example, depending on the current position) 
3772     if ( !::GetCursorPosWinCE(&pt
)) 
3774     if ( !::GetCursorPos(&pt
) ) 
3777         wxLogLastError(wxT("GetCursorPos")); 
3782     ScreenToClient(&x
, &y
); 
3783     wxSetCursorEvent 
event(x
, y
); 
3785     bool processedEvtSetCursor 
= GetEventHandler()->ProcessEvent(event
); 
3786     if ( processedEvtSetCursor 
&& event
.HasCursor() ) 
3788         hcursor 
= GetHcursorOf(event
.GetCursor()); 
3793         bool isBusy 
= wxIsBusy(); 
3795         // the test for processedEvtSetCursor is here to prevent using m_cursor 
3796         // if the user code caught EVT_SET_CURSOR() and returned nothing from 
3797         // it - this is a way to say that our cursor shouldn't be used for this 
3799         if ( !processedEvtSetCursor 
&& m_cursor
.Ok() ) 
3801             hcursor 
= GetHcursorOf(m_cursor
); 
3808                 hcursor 
= wxGetCurrentBusyCursor(); 
3810             else if ( !hcursor 
) 
3812                 const wxCursor 
*cursor 
= wxGetGlobalCursor(); 
3813                 if ( cursor 
&& cursor
->Ok() ) 
3815                     hcursor 
= GetHcursorOf(*cursor
); 
3823 //        wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor); 
3825         ::SetCursor(hcursor
); 
3827         // cursor set, stop here 
3830 #endif // __WXMICROWIN__ 
3832     // pass up the window chain 
3836 bool wxWindowMSW::HandlePower(WXWPARAM 
WXUNUSED_IN_WINCE(wParam
), 
3837                               WXLPARAM 
WXUNUSED(lParam
), 
3838                               bool *WXUNUSED_IN_WINCE(vetoed
)) 
3844     wxEventType evtType
; 
3847         case PBT_APMQUERYSUSPEND
: 
3848             evtType 
= wxEVT_POWER_SUSPENDING
; 
3851         case PBT_APMQUERYSUSPENDFAILED
: 
3852             evtType 
= wxEVT_POWER_SUSPEND_CANCEL
; 
3855         case PBT_APMSUSPEND
: 
3856             evtType 
= wxEVT_POWER_SUSPENDED
; 
3859         case PBT_APMRESUMESUSPEND
: 
3860 #ifdef PBT_APMRESUMEAUTOMATIC 
3861         case PBT_APMRESUMEAUTOMATIC
: 
3863             evtType 
= wxEVT_POWER_RESUME
; 
3867             wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam
); 
3870         // these messages are currently not mapped to wx events 
3871         case PBT_APMQUERYSTANDBY
: 
3872         case PBT_APMQUERYSTANDBYFAILED
: 
3873         case PBT_APMSTANDBY
: 
3874         case PBT_APMRESUMESTANDBY
: 
3875         case PBT_APMBATTERYLOW
: 
3876         case PBT_APMPOWERSTATUSCHANGE
: 
3877         case PBT_APMOEMEVENT
: 
3878         case PBT_APMRESUMECRITICAL
: 
3879             evtType 
= wxEVT_NULL
; 
3883     // don't handle unknown messages 
3884     if ( evtType 
== wxEVT_NULL 
) 
3887     // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events? 
3889     wxPowerEvent 
event(evtType
); 
3890     if ( !GetEventHandler()->ProcessEvent(event
) ) 
3893     *vetoed 
= event
.IsVetoed(); 
3899 // --------------------------------------------------------------------------- 
3900 // owner drawn stuff 
3901 // --------------------------------------------------------------------------- 
3903 #if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \ 
3904         (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)) 
3905     #define WXUNUSED_UNLESS_ODRAWN(param) param 
3907     #define WXUNUSED_UNLESS_ODRAWN(param) 
3911 wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id
), 
3912                            WXDRAWITEMSTRUCT 
* WXUNUSED_UNLESS_ODRAWN(itemStruct
)) 
3914 #if wxUSE_OWNER_DRAWN 
3916 #if wxUSE_MENUS_NATIVE 
3917     // is it a menu item? 
3918     DRAWITEMSTRUCT 
*pDrawStruct 
= (DRAWITEMSTRUCT 
*)itemStruct
; 
3919     if ( id 
== 0 && pDrawStruct
->CtlType 
== ODT_MENU 
) 
3921         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pDrawStruct
->itemData
); 
3923         // see comment before the same test in MSWOnMeasureItem() below 
3927         wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
), 
3928                          false, _T("MSWOnDrawItem: bad wxMenuItem pointer") ); 
3930         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent 
3931         // the DC from being released 
3932         wxDCTemp 
dc((WXHDC
)pDrawStruct
->hDC
); 
3933         wxRect 
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
, 
3934                     pDrawStruct
->rcItem
.right 
- pDrawStruct
->rcItem
.left
, 
3935                     pDrawStruct
->rcItem
.bottom 
- pDrawStruct
->rcItem
.top
); 
3937         return pMenuItem
->OnDrawItem
 
3941                 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
, 
3942                 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
 
3945 #endif // wxUSE_MENUS_NATIVE 
3947 #endif // USE_OWNER_DRAWN 
3949 #if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) 
3951 #if wxUSE_OWNER_DRAWN 
3952     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
3953 #else // !wxUSE_OWNER_DRAWN 
3954     // we may still have owner-drawn buttons internally because we have to make 
3955     // them owner-drawn to support colour change 
3958                          wxDynamicCast(FindItem(id
), wxButton
) 
3963 #endif // USE_OWNER_DRAWN 
3967         return item
->MSWOnDraw(itemStruct
); 
3970 #endif // wxUSE_CONTROLS 
3976 wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT 
*itemStruct
) 
3978 #if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE 
3979     // is it a menu item? 
3980     MEASUREITEMSTRUCT 
*pMeasureStruct 
= (MEASUREITEMSTRUCT 
*)itemStruct
; 
3981     if ( id 
== 0 && pMeasureStruct
->CtlType 
== ODT_MENU 
) 
3983         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pMeasureStruct
->itemData
); 
3985         // according to Carsten Fuchs the pointer may be NULL under XP if an 
3986         // MDI child frame is initially maximized, see this for more info: 
3987         // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745 
3989         // so silently ignore it instead of asserting 
3993         wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
), 
3994                         false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") ); 
3997         bool rc 
= pMenuItem
->OnMeasureItem(&w
, &h
); 
3999         pMeasureStruct
->itemWidth 
= w
; 
4000         pMeasureStruct
->itemHeight 
= h
; 
4005     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
4008         return item
->MSWOnMeasure(itemStruct
); 
4012     wxUnusedVar(itemStruct
); 
4013 #endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE 
4018 // --------------------------------------------------------------------------- 
4019 // colours and palettes 
4020 // --------------------------------------------------------------------------- 
4022 bool wxWindowMSW::HandleSysColorChange() 
4024     wxSysColourChangedEvent event
; 
4025     event
.SetEventObject(this); 
4027     (void)GetEventHandler()->ProcessEvent(event
); 
4029     // always let the system carry on the default processing to allow the 
4030     // native controls to react to the colours update 
4034 bool wxWindowMSW::HandleDisplayChange() 
4036     wxDisplayChangedEvent event
; 
4037     event
.SetEventObject(this); 
4039     return GetEventHandler()->ProcessEvent(event
); 
4042 #ifndef __WXMICROWIN__ 
4044 bool wxWindowMSW::HandleCtlColor(WXHBRUSH 
*brush
, WXHDC hDC
, WXHWND hWnd
) 
4046 #if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__) 
4050     wxControl 
*item 
= wxDynamicCast(FindItemByHWND(hWnd
, true), wxControl
); 
4053         *brush 
= item
->MSWControlColor(hDC
, hWnd
); 
4055 #endif // wxUSE_CONTROLS 
4058     return *brush 
!= NULL
; 
4061 #endif // __WXMICROWIN__ 
4063 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
) 
4066     // same as below except we don't respond to our own messages 
4067     if ( hWndPalChange 
!= GetHWND() ) 
4069         // check to see if we our our parents have a custom palette 
4070         wxWindowMSW 
*win 
= this; 
4071         while ( win 
&& !win
->HasCustomPalette() ) 
4073             win 
= win
->GetParent(); 
4076         if ( win 
&& win
->HasCustomPalette() ) 
4078             // realize the palette to see whether redrawing is needed 
4079             HDC hdc 
= ::GetDC((HWND
) hWndPalChange
); 
4080             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
4081                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
4083             int result 
= ::RealizePalette(hdc
); 
4085             // restore the palette (before releasing the DC) 
4086             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
4087                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
4088             ::RealizePalette(hdc
); 
4089             ::ReleaseDC((HWND
) hWndPalChange
, hdc
); 
4091             // now check for the need to redraw 
4093                 ::InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
); 
4097 #endif // wxUSE_PALETTE 
4099     wxPaletteChangedEvent 
event(GetId()); 
4100     event
.SetEventObject(this); 
4101     event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
)); 
4103     return GetEventHandler()->ProcessEvent(event
); 
4106 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
) 
4108     wxMouseCaptureChangedEvent 
event(GetId(), wxFindWinFromHandle(hWndGainedCapture
)); 
4109     event
.SetEventObject(this); 
4111     return GetEventHandler()->ProcessEvent(event
); 
4114 bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam
, WXLPARAM lParam
) 
4116     // despite MSDN saying "(This message cannot be sent directly to a window.)" 
4117     // we need to send this to child windows (it is only sent to top-level 
4118     // windows) so {list,tree}ctrls can adjust their font size if necessary 
4119     // this is exactly how explorer does it to enable the font size changes 
4121     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4124         // top-level windows already get this message from the system 
4125         wxWindow 
*win 
= node
->GetData(); 
4126         if ( !win
->IsTopLevel() ) 
4128             ::SendMessage(GetHwndOf(win
), WM_SETTINGCHANGE
, wParam
, lParam
); 
4131         node 
= node
->GetNext(); 
4134     // let the system handle it 
4138 bool wxWindowMSW::HandleQueryNewPalette() 
4142     // check to see if we our our parents have a custom palette 
4143     wxWindowMSW 
*win 
= this; 
4144     while (!win
->HasCustomPalette() && win
->GetParent()) win 
= win
->GetParent(); 
4145     if (win
->HasCustomPalette()) { 
4146         /* realize the palette to see whether redrawing is needed */ 
4147         HDC hdc 
= ::GetDC((HWND
) GetHWND()); 
4148         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
4149              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) ); 
4151         int result 
= ::RealizePalette(hdc
); 
4152         /* restore the palette (before releasing the DC) */ 
4153         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
4154              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) ); 
4155         ::RealizePalette(hdc
); 
4156         ::ReleaseDC((HWND
) GetHWND(), hdc
); 
4157         /* now check for the need to redraw */ 
4159             ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
); 
4161 #endif // wxUSE_PALETTE 
4163     wxQueryNewPaletteEvent 
event(GetId()); 
4164     event
.SetEventObject(this); 
4166     return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized(); 
4169 // Responds to colour changes: passes event on to children. 
4170 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
4172     // the top level window also reset the standard colour map as it might have 
4173     // changed (there is no need to do it for the non top level windows as we 
4174     // only have to do it once) 
4178         gs_hasStdCmap 
= false; 
4180     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4183         // Only propagate to non-top-level windows because Windows already 
4184         // sends this event to all top-level ones 
4185         wxWindow 
*win 
= node
->GetData(); 
4186         if ( !win
->IsTopLevel() ) 
4188             // we need to send the real WM_SYSCOLORCHANGE and not just trigger 
4189             // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for 
4190             // the standard controls 
4191             ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0); 
4194         node 
= node
->GetNext(); 
4198 extern wxCOLORMAP 
*wxGetStdColourMap() 
4200     static COLORREF s_stdColours
[wxSTD_COL_MAX
]; 
4201     static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
]; 
4203     if ( !gs_hasStdCmap 
) 
4205         static bool s_coloursInit 
= false; 
4207         if ( !s_coloursInit 
) 
4209             // When a bitmap is loaded, the RGB values can change (apparently 
4210             // because Windows adjusts them to care for the old programs always 
4211             // using 0xc0c0c0 while the transparent colour for the new Windows 
4212             // versions is different). But we do this adjustment ourselves so 
4213             // we want to avoid Windows' "help" and for this we need to have a 
4214             // reference bitmap which can tell us what the RGB values change 
4216             wxLogNull logNo
; // suppress error if we couldn't load the bitmap 
4217             wxBitmap 
stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); 
4218             if ( stdColourBitmap
.Ok() ) 
4220                 // the pixels in the bitmap must correspond to wxSTD_COL_XXX! 
4221                 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
, 
4222                               _T("forgot to update wxBITMAP_STD_COLOURS!") ); 
4225                 memDC
.SelectObject(stdColourBitmap
); 
4228                 for ( size_t i 
= 0; i 
< WXSIZEOF(s_stdColours
); i
++ ) 
4230                     memDC
.GetPixel(i
, 0, &colour
); 
4231                     s_stdColours
[i
] = wxColourToRGB(colour
); 
4234             else // wxBITMAP_STD_COLOURS couldn't be loaded 
4236                 s_stdColours
[0] = RGB(000,000,000);     // black 
4237                 s_stdColours
[1] = RGB(128,128,128);     // dark grey 
4238                 s_stdColours
[2] = RGB(192,192,192);     // light grey 
4239                 s_stdColours
[3] = RGB(255,255,255);     // white 
4240                 //s_stdColours[4] = RGB(000,000,255);     // blue 
4241                 //s_stdColours[5] = RGB(255,000,255);     // magenta 
4244             s_coloursInit 
= true; 
4247         gs_hasStdCmap 
= true; 
4249         // create the colour map 
4250 #define INIT_CMAP_ENTRY(col) \ 
4251             s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \ 
4252             s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col) 
4254         INIT_CMAP_ENTRY(BTNTEXT
); 
4255         INIT_CMAP_ENTRY(BTNSHADOW
); 
4256         INIT_CMAP_ENTRY(BTNFACE
); 
4257         INIT_CMAP_ENTRY(BTNHIGHLIGHT
); 
4259 #undef INIT_CMAP_ENTRY 
4265 // --------------------------------------------------------------------------- 
4267 // --------------------------------------------------------------------------- 
4269 bool wxWindowMSW::HandlePaint() 
4271     HRGN hRegion 
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle 
4273         wxLogLastError(wxT("CreateRectRgn")); 
4274     if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR 
) 
4275         wxLogLastError(wxT("GetUpdateRgn")); 
4277     m_updateRegion 
= wxRegion((WXHRGN
) hRegion
); 
4279     wxPaintEvent 
event(m_windowId
); 
4280     event
.SetEventObject(this); 
4282     bool processed 
= GetEventHandler()->ProcessEvent(event
); 
4284     // note that we must generate NC event after the normal one as otherwise 
4285     // BeginPaint() will happily overwrite our decorations with the background 
4287     wxNcPaintEvent 
eventNc(m_windowId
); 
4288     eventNc
.SetEventObject(this); 
4289     GetEventHandler()->ProcessEvent(eventNc
); 
4294 // Can be called from an application's OnPaint handler 
4295 void wxWindowMSW::OnPaint(wxPaintEvent
& event
) 
4297 #ifdef __WXUNIVERSAL__ 
4300     HDC hDC 
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject()); 
4303         MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0); 
4308 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
) 
4313     dc
.SetWindow((wxWindow 
*)this); 
4315     wxEraseEvent 
event(m_windowId
, &dc
); 
4316     event
.SetEventObject(this); 
4317     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4319     // must be called manually as ~wxDC doesn't do anything for wxDCTemp 
4320     dc
.SelectOldObjects(hdc
); 
4325 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
) 
4327     // standard non top level controls (i.e. except the dialogs) always erase 
4328     // their background themselves in HandleCtlColor() or have some control- 
4329     // specific ways to set the colours (common controls) 
4330     if ( IsOfStandardClass() && !IsTopLevel() ) 
4336     if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM 
) 
4338         // don't skip the event here, custom background means that the app 
4339         // is drawing it itself in its OnPaint(), so don't draw it at all 
4340         // now to avoid flicker 
4345     // do default background painting 
4346     if ( !DoEraseBackground(GetHdcOf(*event
.GetDC())) ) 
4348         // let the system paint the background 
4353 bool wxWindowMSW::DoEraseBackground(WXHDC hDC
) 
4355     HBRUSH hbr 
= (HBRUSH
)MSWGetBgBrush(hDC
); 
4359     wxFillRect(GetHwnd(), (HDC
)hDC
, hbr
); 
4365 wxWindowMSW::MSWGetBgBrushForChild(WXHDC 
WXUNUSED(hDC
), WXHWND hWnd
) 
4369         // our background colour applies to: 
4370         //  1. this window itself, always 
4371         //  2. all children unless the colour is "not inheritable" 
4372         //  3. even if it is not inheritable, our immediate transparent 
4373         //     children should still inherit it -- but not any transparent 
4374         //     children because it would look wrong if a child of non 
4375         //     transparent child would show our bg colour when the child itself 
4377         wxWindow 
*win 
= wxFindWinFromHandle(hWnd
); 
4380                     (win 
&& win
->HasTransparentBackground() && 
4381                         win
->GetParent() == this) ) 
4383             // draw children with the same colour as the parent 
4385                 brush 
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour()); 
4387             return (WXHBRUSH
)GetHbrushOf(*brush
); 
4394 WXHBRUSH 
wxWindowMSW::MSWGetBgBrush(WXHDC hDC
, WXHWND hWndToPaint
) 
4397         hWndToPaint 
= GetHWND(); 
4399     for ( wxWindowMSW 
*win 
= this; win
; win 
= win
->GetParent() ) 
4401         WXHBRUSH hBrush 
= win
->MSWGetBgBrushForChild(hDC
, hWndToPaint
); 
4405         // background is not inherited beyond top level windows 
4406         if ( win
->IsTopLevel() ) 
4413 bool wxWindowMSW::HandlePrintClient(WXHDC hDC
) 
4415     // we receive this message when DrawThemeParentBackground() is 
4416     // called from def window proc of several controls under XP and we 
4417     // must draw properly themed background here 
4419     // note that naively I'd expect filling the client rect with the 
4420     // brush returned by MSWGetBgBrush() work -- but for some reason it 
4421     // doesn't and we have to call parents MSWPrintChild() which is 
4422     // supposed to call DrawThemeBackground() with appropriate params 
4424     // also note that in this case lParam == PRF_CLIENT but we're 
4425     // clearly expected to paint the background and nothing else! 
4427     if ( IsTopLevel() || InheritsBackgroundColour() ) 
4430     // sometimes we don't want the parent to handle it at all, instead 
4431     // return whatever value this window wants 
4432     if ( !MSWShouldPropagatePrintChild() ) 
4433         return MSWPrintChild(hDC
, (wxWindow 
*)this); 
4435     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
4437         if ( win
->MSWPrintChild(hDC
, (wxWindow 
*)this) ) 
4440         if ( win
->IsTopLevel() || win
->InheritsBackgroundColour() ) 
4447 // --------------------------------------------------------------------------- 
4448 // moving and resizing 
4449 // --------------------------------------------------------------------------- 
4451 bool wxWindowMSW::HandleMinimize() 
4453     wxIconizeEvent 
event(m_windowId
); 
4454     event
.SetEventObject(this); 
4456     return GetEventHandler()->ProcessEvent(event
); 
4459 bool wxWindowMSW::HandleMaximize() 
4461     wxMaximizeEvent 
event(m_windowId
); 
4462     event
.SetEventObject(this); 
4464     return GetEventHandler()->ProcessEvent(event
); 
4467 bool wxWindowMSW::HandleMove(int x
, int y
) 
4470     wxMoveEvent 
event(point
, m_windowId
); 
4471     event
.SetEventObject(this); 
4473     return GetEventHandler()->ProcessEvent(event
); 
4476 bool wxWindowMSW::HandleMoving(wxRect
& rect
) 
4478     wxMoveEvent 
event(rect
, m_windowId
); 
4479     event
.SetEventObject(this); 
4481     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4483         rect 
= event
.GetRect(); 
4487 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), WXUINT wParam
) 
4489 #if USE_DEFERRED_SIZING 
4490     // when we resize this window, its children are probably going to be 
4491     // repositioned as well, prepare to use DeferWindowPos() for them 
4492     int numChildren 
= 0; 
4493     for ( HWND child 
= ::GetWindow(GetHwndOf(this), GW_CHILD
); 
4495           child 
= ::GetWindow(child
, GW_HWNDNEXT
) ) 
4500     // Protect against valid m_hDWP being overwritten 
4501     bool useDefer 
= false; 
4503     if ( numChildren 
> 1 ) 
4507             m_hDWP 
= (WXHANDLE
)::BeginDeferWindowPos(numChildren
); 
4510                 wxLogLastError(_T("BeginDeferWindowPos")); 
4516 #endif // USE_DEFERRED_SIZING 
4518     // update this window size 
4519     bool processed 
= false; 
4523             wxFAIL_MSG( _T("unexpected WM_SIZE parameter") ); 
4524             // fall through nevertheless 
4528             // we're not interested in these messages at all 
4531         case SIZE_MINIMIZED
: 
4532             processed 
= HandleMinimize(); 
4535         case SIZE_MAXIMIZED
: 
4536             /* processed = */ HandleMaximize(); 
4537             // fall through to send a normal size event as well 
4540             // don't use w and h parameters as they specify the client size 
4541             // while according to the docs EVT_SIZE handler is supposed to 
4542             // receive the total size 
4543             wxSizeEvent 
event(GetSize(), m_windowId
); 
4544             event
.SetEventObject(this); 
4546             processed 
= GetEventHandler()->ProcessEvent(event
); 
4549 #if USE_DEFERRED_SIZING 
4550     // and finally change the positions of all child windows at once 
4551     if ( useDefer 
&& m_hDWP 
) 
4553         // reset m_hDWP to NULL so that child windows don't try to use our 
4554         // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't 
4555         // happen anyhow normally but who knows what weird flow of control we 
4556         // may have depending on what the users EVT_SIZE handler does...) 
4557         HDWP hDWP 
= (HDWP
)m_hDWP
; 
4560         // do put all child controls in place at once 
4561         if ( !::EndDeferWindowPos(hDWP
) ) 
4563             wxLogLastError(_T("EndDeferWindowPos")); 
4566         // Reset our children's pending pos/size values. 
4567         for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4569               node 
= node
->GetNext() ) 
4571             wxWindowMSW 
*child 
= node
->GetData(); 
4572             child
->m_pendingPosition 
= wxDefaultPosition
; 
4573             child
->m_pendingSize 
= wxDefaultSize
; 
4576 #endif // USE_DEFERRED_SIZING 
4581 bool wxWindowMSW::HandleSizing(wxRect
& rect
) 
4583     wxSizeEvent 
event(rect
, m_windowId
); 
4584     event
.SetEventObject(this); 
4586     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4588         rect 
= event
.GetRect(); 
4592 bool wxWindowMSW::HandleGetMinMaxInfo(void *WXUNUSED_IN_WINCE(mmInfo
)) 
4597     MINMAXINFO 
*info 
= (MINMAXINFO 
*)mmInfo
; 
4601     int minWidth 
= GetMinWidth(), 
4602         minHeight 
= GetMinHeight(), 
4603         maxWidth 
= GetMaxWidth(), 
4604         maxHeight 
= GetMaxHeight(); 
4606     if ( minWidth 
!= wxDefaultCoord 
) 
4608         info
->ptMinTrackSize
.x 
= minWidth
; 
4612     if ( minHeight 
!= wxDefaultCoord 
) 
4614         info
->ptMinTrackSize
.y 
= minHeight
; 
4618     if ( maxWidth 
!= wxDefaultCoord 
) 
4620         info
->ptMaxTrackSize
.x 
= maxWidth
; 
4624     if ( maxHeight 
!= wxDefaultCoord 
) 
4626         info
->ptMaxTrackSize
.y 
= maxHeight
; 
4634 // --------------------------------------------------------------------------- 
4636 // --------------------------------------------------------------------------- 
4638 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
) 
4640 #if wxUSE_MENUS_NATIVE 
4641     if ( !cmd 
&& wxCurrentPopupMenu 
) 
4643         wxMenu 
*popupMenu 
= wxCurrentPopupMenu
; 
4644         wxCurrentPopupMenu 
= NULL
; 
4646         return popupMenu
->MSWCommand(cmd
, id
); 
4648 #endif // wxUSE_MENUS_NATIVE 
4650     wxWindow 
*win 
= NULL
; 
4652     // first try to find it from HWND - this works even with the broken 
4653     // programs using the same ids for different controls 
4656         win 
= wxFindWinFromHandle(control
); 
4662         // must cast to a signed type before comparing with other ids! 
4663         win 
= FindItem((signed short)id
); 
4668         return win
->MSWCommand(cmd
, id
); 
4671     // the messages sent from the in-place edit control used by the treectrl 
4672     // for label editing have id == 0, but they should _not_ be treated as menu 
4673     // messages (they are EN_XXX ones, in fact) so don't translate anything 
4674     // coming from a control to wxEVT_COMMAND_MENU_SELECTED 
4677         // If no child window, it may be an accelerator, e.g. for a popup menu 
4680         wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
); 
4681         event
.SetEventObject(this); 
4685         return GetEventHandler()->ProcessEvent(event
); 
4689 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
4690         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND 
4691         // notifications to its parent which we want to reflect back to 
4693         wxSpinCtrl 
*spin 
= wxSpinCtrl::GetSpinForTextCtrl(control
); 
4694         if ( spin 
&& spin
->ProcessTextCommand(cmd
, id
) ) 
4696 #endif // wxUSE_SPINCTRL 
4698 #if wxUSE_CHOICE && defined(__SMARTPHONE__) 
4699         // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND 
4700         // notifications to its parent which we want to reflect back to 
4702         wxChoice 
*choice 
= wxChoice::GetChoiceForListBox(control
); 
4703         if ( choice 
&& choice
->MSWCommand(cmd
, id
) ) 
4711 // --------------------------------------------------------------------------- 
4713 // --------------------------------------------------------------------------- 
4715 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
, 
4719     // our client coords are not quite the same as Windows ones 
4720     wxPoint pt 
= GetClientAreaOrigin(); 
4721     event
.m_x 
= x 
- pt
.x
; 
4722     event
.m_y 
= y 
- pt
.y
; 
4724     event
.m_shiftDown 
= (flags 
& MK_SHIFT
) != 0; 
4725     event
.m_controlDown 
= (flags 
& MK_CONTROL
) != 0; 
4726     event
.m_leftDown 
= (flags 
& MK_LBUTTON
) != 0; 
4727     event
.m_middleDown 
= (flags 
& MK_MBUTTON
) != 0; 
4728     event
.m_rightDown 
= (flags 
& MK_RBUTTON
) != 0; 
4729     event
.m_altDown 
= ::GetKeyState(VK_MENU
) < 0; 
4732     event
.SetTimestamp(::GetMessageTime()); 
4735     event
.SetEventObject(this); 
4736     event
.SetId(GetId()); 
4738 #if wxUSE_MOUSEEVENT_HACK 
4739     gs_lastMouseEvent
.pos 
= ClientToScreen(wxPoint(x
, y
)); 
4740     gs_lastMouseEvent
.type 
= event
.GetEventType(); 
4741 #endif // wxUSE_MOUSEEVENT_HACK 
4745 // Windows doesn't send the mouse events to the static controls (which are 
4746 // transparent in the sense that their WM_NCHITTEST handler returns 
4747 // HTTRANSPARENT) at all but we want all controls to receive the mouse events 
4748 // and so we manually check if we don't have a child window under mouse and if 
4749 // we do, send the event to it instead of the window Windows had sent WM_XXX 
4752 // Notice that this is not done for the mouse move events because this could 
4753 // (would?) be too slow, but only for clicks which means that the static texts 
4754 // still don't get move, enter nor leave events. 
4755 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
) 
4757     wxCHECK_MSG( x 
&& y
, win
, _T("NULL pointer in FindWindowForMouseEvent") ); 
4759     // first try to find a non transparent child: this allows us to send events 
4760     // to a static text which is inside a static box, for example 
4761     POINT pt 
= { *x
, *y 
}; 
4762     HWND hwnd 
= GetHwndOf(win
), 
4766     hwndUnderMouse 
= ::ChildWindowFromPoint
 
4772     hwndUnderMouse 
= ::ChildWindowFromPointEx
 
4782     if ( !hwndUnderMouse 
|| hwndUnderMouse 
== hwnd 
) 
4784         // now try any child window at all 
4785         hwndUnderMouse 
= ::ChildWindowFromPoint(hwnd
, pt
); 
4788     // check that we have a child window which is susceptible to receive mouse 
4789     // events: for this it must be shown and enabled 
4790     if ( hwndUnderMouse 
&& 
4791             hwndUnderMouse 
!= hwnd 
&& 
4792                 ::IsWindowVisible(hwndUnderMouse
) && 
4793                     ::IsWindowEnabled(hwndUnderMouse
) ) 
4795         wxWindow 
*winUnderMouse 
= wxFindWinFromHandle((WXHWND
)hwndUnderMouse
); 
4796         if ( winUnderMouse 
) 
4798             // translate the mouse coords to the other window coords 
4799             win
->ClientToScreen(x
, y
); 
4800             winUnderMouse
->ScreenToClient(x
, y
); 
4802             win 
= winUnderMouse
; 
4808 #endif // __WXWINCE__ 
4810 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4812     // the mouse events take consecutive IDs from WM_MOUSEFIRST to 
4813     // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST 
4814     // from the message id and take the value in the table to get wxWin event 
4816     static const wxEventType eventsMouse
[] = 
4830     wxMouseEvent 
event(eventsMouse
[msg 
- WM_MOUSEMOVE
]); 
4831     InitMouseEvent(event
, x
, y
, flags
); 
4833     return GetEventHandler()->ProcessEvent(event
); 
4836 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
) 
4838     if ( !m_mouseInWindow 
) 
4840         // it would be wrong to assume that just because we get a mouse move 
4841         // event that the mouse is inside the window: although this is usually 
4842         // true, it is not if we had captured the mouse, so we need to check 
4843         // the mouse coordinates here 
4844         if ( !HasCapture() || IsMouseInWindow() ) 
4846             // Generate an ENTER event 
4847             m_mouseInWindow 
= true; 
4849 #ifdef HAVE_TRACKMOUSEEVENT 
4850             WinStruct
<TRACKMOUSEEVENT
> trackinfo
; 
4852             trackinfo
.dwFlags 
= TME_LEAVE
; 
4853             trackinfo
.hwndTrack 
= GetHwnd(); 
4855             // Use the commctrl.h _TrackMouseEvent(), which will call the real 
4856             // TrackMouseEvent() if available or emulate it 
4857             _TrackMouseEvent(&trackinfo
); 
4858 #endif // HAVE_TRACKMOUSEEVENT 
4860             wxMouseEvent 
event(wxEVT_ENTER_WINDOW
); 
4861             InitMouseEvent(event
, x
, y
, flags
); 
4863             (void)GetEventHandler()->ProcessEvent(event
); 
4866 #ifdef HAVE_TRACKMOUSEEVENT 
4869         // Check if we need to send a LEAVE event 
4870         // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so 
4871         // send it here if we are using native mouse leave tracking 
4872         if ( HasCapture() && !IsMouseInWindow() ) 
4874             GenerateMouseLeave(); 
4877 #endif // HAVE_TRACKMOUSEEVENT 
4879 #if wxUSE_MOUSEEVENT_HACK 
4880     // Windows often generates mouse events even if mouse position hasn't 
4881     // changed (http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/66576) 
4883     // Filter this out as it can result in unexpected behaviour compared to 
4885     if ( gs_lastMouseEvent
.type 
== wxEVT_RIGHT_DOWN 
|| 
4886          gs_lastMouseEvent
.type 
== wxEVT_LEFT_DOWN 
|| 
4887          gs_lastMouseEvent
.type 
== wxEVT_MIDDLE_DOWN 
|| 
4888          gs_lastMouseEvent
.type 
== wxEVT_MOTION 
) 
4890         if ( ClientToScreen(wxPoint(x
, y
)) == gs_lastMouseEvent
.pos 
) 
4892             gs_lastMouseEvent
.type 
= wxEVT_MOTION
; 
4897 #endif // wxUSE_MOUSEEVENT_HACK 
4899     return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
); 
4903 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
) 
4905 #if wxUSE_MOUSEWHEEL 
4906     // notice that WM_MOUSEWHEEL position is in screen coords (as it's 
4907     // forwarded up to the parent by DefWindowProc()) and not in the client 
4908     // ones as all the other messages, translate them to the client coords for 
4911         pt 
= ScreenToClient(wxPoint(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
))); 
4912     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
4913     InitMouseEvent(event
, pt
.x
, pt
.y
, LOWORD(wParam
)); 
4914     event
.m_wheelRotation 
= (short)HIWORD(wParam
); 
4915     event
.m_wheelDelta 
= WHEEL_DELTA
; 
4917     static int s_linesPerRotation 
= -1; 
4918     if ( s_linesPerRotation 
== -1 ) 
4920         if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, 
4921                                      &s_linesPerRotation
, 0)) 
4923             // this is not supposed to happen 
4924             wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)")); 
4926             // the default is 3, so use it if SystemParametersInfo() failed 
4927             s_linesPerRotation 
= 3; 
4931     event
.m_linesPerAction 
= s_linesPerRotation
; 
4932     return GetEventHandler()->ProcessEvent(event
); 
4934 #else // !wxUSE_MOUSEWHEEL 
4935     wxUnusedVar(wParam
); 
4936     wxUnusedVar(lParam
); 
4939 #endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL 
4942 void wxWindowMSW::GenerateMouseLeave() 
4944     m_mouseInWindow 
= false; 
4947     if ( wxIsShiftDown() ) 
4949     if ( wxIsCtrlDown() ) 
4950         state 
|= MK_CONTROL
; 
4952     // Only the high-order bit should be tested 
4953     if ( GetKeyState( VK_LBUTTON 
) & (1<<15) ) 
4954         state 
|= MK_LBUTTON
; 
4955     if ( GetKeyState( VK_MBUTTON 
) & (1<<15) ) 
4956         state 
|= MK_MBUTTON
; 
4957     if ( GetKeyState( VK_RBUTTON 
) & (1<<15) ) 
4958         state 
|= MK_RBUTTON
; 
4962     if ( !::GetCursorPosWinCE(&pt
) ) 
4964     if ( !::GetCursorPos(&pt
) ) 
4967         wxLogLastError(_T("GetCursorPos")); 
4970     // we need to have client coordinates here for symmetry with 
4971     // wxEVT_ENTER_WINDOW 
4972     RECT rect 
= wxGetWindowRect(GetHwnd()); 
4976     wxMouseEvent 
event(wxEVT_LEAVE_WINDOW
); 
4977     InitMouseEvent(event
, pt
.x
, pt
.y
, state
); 
4979     (void)GetEventHandler()->ProcessEvent(event
); 
4982 // --------------------------------------------------------------------------- 
4983 // keyboard handling 
4984 // --------------------------------------------------------------------------- 
4986 // create the key event of the given type for the given key - used by 
4987 // HandleChar and HandleKeyDown/Up 
4988 wxKeyEvent 
wxWindowMSW::CreateKeyEvent(wxEventType evType
, 
4991                                        WXWPARAM wParam
) const 
4993     wxKeyEvent 
event(evType
); 
4994     event
.SetId(GetId()); 
4995     event
.m_shiftDown 
= wxIsShiftDown(); 
4996     event
.m_controlDown 
= wxIsCtrlDown(); 
4997     event
.m_altDown 
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
; 
4999     event
.SetEventObject((wxWindow 
*)this); // const_cast 
5000     event
.m_keyCode 
= id
; 
5002     event
.m_uniChar 
= (wxChar
) wParam
; 
5004     event
.m_rawCode 
= (wxUint32
) wParam
; 
5005     event
.m_rawFlags 
= (wxUint32
) lParam
; 
5007     event
.SetTimestamp(::GetMessageTime()); 
5010     // translate the position to client coords 
5013     GetCursorPosWinCE(&pt
); 
5018     GetWindowRect(GetHwnd(),&rect
); 
5028 // isASCII is true only when we're called from WM_CHAR handler and not from 
5030 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
) 
5037     else // we're called from WM_KEYDOWN 
5039         // don't pass lParam to wxCharCodeMSWToWX() here because we don't want 
5040         // to get numpad key codes: CHAR events should use the logical keys 
5041         // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events 
5042         id 
= wxCharCodeMSWToWX(wParam
); 
5045             // it's ASCII and will be processed here only when called from 
5046             // WM_CHAR (i.e. when isASCII = true), don't process it now 
5051     wxKeyEvent 
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
)); 
5053     // the alphanumeric keys produced by pressing AltGr+something on European 
5054     // keyboards have both Ctrl and Alt modifiers which may confuse the user 
5055     // code as, normally, keys with Ctrl and/or Alt don't result in anything 
5056     // alphanumeric, so pretend that there are no modifiers at all (the 
5057     // KEY_DOWN event would still have the correct modifiers if they're really 
5059     if ( event
.m_controlDown 
&& event
.m_altDown 
&& 
5060             (id 
>= 32 && id 
< 256) ) 
5062         event
.m_controlDown 
= 
5063         event
.m_altDown 
= false; 
5066     return GetEventHandler()->ProcessEvent(event
); 
5069 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
) 
5071     int id 
= wxCharCodeMSWToWX(wParam
, lParam
); 
5075         // normal ASCII char 
5079     wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
)); 
5080     return GetEventHandler()->ProcessEvent(event
); 
5083 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
) 
5085     int id 
= wxCharCodeMSWToWX(wParam
, lParam
); 
5089         // normal ASCII char 
5093     wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
)); 
5094     return GetEventHandler()->ProcessEvent(event
); 
5097 int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel
), 
5098                                 WXLPARAM 
WXUNUSED_IN_WINCE(lParam
)) 
5100     // FIXME: implement GetMenuItemCount for WinCE, possibly 
5101     // in terms of GetMenuItemInfo 
5103     const HMENU hmenu 
= (HMENU
)lParam
; 
5107     mii
.cbSize 
= sizeof(MENUITEMINFO
); 
5109     // we could use MIIM_FTYPE here as we only need to know if the item is 
5110     // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but 
5111     // MIIM_FTYPE is not supported under Win95 
5112     mii
.fMask 
= MIIM_TYPE 
| MIIM_DATA
; 
5114     // find if we have this letter in any owner drawn item 
5115     const int count 
= ::GetMenuItemCount(hmenu
); 
5116     for ( int i 
= 0; i 
< count
; i
++ ) 
5118         // previous loop iteration could modify it, reset it back before 
5119         // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData 
5122         if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) ) 
5124             if ( mii
.fType 
== MFT_OWNERDRAW 
) 
5126                 //  dwItemData member of the MENUITEMINFO is a 
5127                 //  pointer to the associated wxMenuItem -- see the 
5128                 //  menu creation code 
5129                 wxMenuItem 
*item 
= (wxMenuItem
*)mii
.dwItemData
; 
5131                 const wxChar 
*p 
= wxStrchr(item
->GetText(), _T('&')); 
5134                     if ( *p 
== _T('&') ) 
5136                         // this is not the accel char, find the real one 
5137                         p 
= wxStrchr(p 
+ 1, _T('&')); 
5139                     else // got the accel char 
5141                         // FIXME-UNICODE: this comparison doesn't risk to work 
5142                         // for non ASCII accelerator characters I'm afraid, but 
5144                         if ( (wchar_t)wxToupper(*p
) == (wchar_t)chAccel 
) 
5150                             // this one doesn't match 
5157         else // failed to get the menu text? 
5159             // it's not fatal, so don't show error, but still log it 
5160             wxLogLastError(_T("GetMenuItemInfo")); 
5167 bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg 
) 
5169     const wxEventType type 
= ( nMsg 
== WM_CUT 
) ? wxEVT_COMMAND_TEXT_CUT 
: 
5170                              ( nMsg 
== WM_COPY 
) ? wxEVT_COMMAND_TEXT_COPY 
: 
5171                            /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE
; 
5172     wxClipboardTextEvent 
evt(type
, GetId()); 
5174     evt
.SetEventObject(this); 
5176     return GetEventHandler()->ProcessEvent(evt
); 
5179 // --------------------------------------------------------------------------- 
5181 // --------------------------------------------------------------------------- 
5183 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
5187     if ( flags 
& JOY_BUTTON1CHG 
) 
5188         change 
= wxJOY_BUTTON1
; 
5189     if ( flags 
& JOY_BUTTON2CHG 
) 
5190         change 
= wxJOY_BUTTON2
; 
5191     if ( flags 
& JOY_BUTTON3CHG 
) 
5192         change 
= wxJOY_BUTTON3
; 
5193     if ( flags 
& JOY_BUTTON4CHG 
) 
5194         change 
= wxJOY_BUTTON4
; 
5197     if ( flags 
& JOY_BUTTON1 
) 
5198         buttons 
|= wxJOY_BUTTON1
; 
5199     if ( flags 
& JOY_BUTTON2 
) 
5200         buttons 
|= wxJOY_BUTTON2
; 
5201     if ( flags 
& JOY_BUTTON3 
) 
5202         buttons 
|= wxJOY_BUTTON3
; 
5203     if ( flags 
& JOY_BUTTON4 
) 
5204         buttons 
|= wxJOY_BUTTON4
; 
5206     // the event ids aren't consecutive so we can't use table based lookup 
5208     wxEventType eventType
; 
5213             eventType 
= wxEVT_JOY_MOVE
; 
5218             eventType 
= wxEVT_JOY_MOVE
; 
5223             eventType 
= wxEVT_JOY_ZMOVE
; 
5228             eventType 
= wxEVT_JOY_ZMOVE
; 
5231         case MM_JOY1BUTTONDOWN
: 
5233             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
5236         case MM_JOY2BUTTONDOWN
: 
5238             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
5241         case MM_JOY1BUTTONUP
: 
5243             eventType 
= wxEVT_JOY_BUTTON_UP
; 
5246         case MM_JOY2BUTTONUP
: 
5248             eventType 
= wxEVT_JOY_BUTTON_UP
; 
5252             wxFAIL_MSG(wxT("no such joystick event")); 
5257     wxJoystickEvent 
event(eventType
, buttons
, joystick
, change
); 
5258     event
.SetPosition(wxPoint(x
, y
)); 
5259     event
.SetEventObject(this); 
5261     return GetEventHandler()->ProcessEvent(event
); 
5271 // --------------------------------------------------------------------------- 
5273 // --------------------------------------------------------------------------- 
5275 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
, 
5276                               WXWORD pos
, WXHWND control
) 
5278     if ( control 
&& control 
!= m_hWnd 
) // Prevent infinite recursion 
5280         wxWindow 
*child 
= wxFindWinFromHandle(control
); 
5282             return child
->MSWOnScroll(orientation
, wParam
, pos
, control
); 
5285     wxScrollWinEvent event
; 
5286     event
.SetPosition(pos
); 
5287     event
.SetOrientation(orientation
); 
5288     event
.SetEventObject(this); 
5293         event
.SetEventType(wxEVT_SCROLLWIN_TOP
); 
5297         event
.SetEventType(wxEVT_SCROLLWIN_BOTTOM
); 
5301         event
.SetEventType(wxEVT_SCROLLWIN_LINEUP
); 
5305         event
.SetEventType(wxEVT_SCROLLWIN_LINEDOWN
); 
5309         event
.SetEventType(wxEVT_SCROLLWIN_PAGEUP
); 
5313         event
.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN
); 
5316     case SB_THUMBPOSITION
: 
5318         // under Win32, the scrollbar range and position are 32 bit integers, 
5319         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must 
5320         // explicitly query the scrollbar for the correct position (this must 
5321         // be done only for these two SB_ events as they are the only one 
5322         // carrying the scrollbar position) 
5324             WinStruct
<SCROLLINFO
> scrollInfo
; 
5325             scrollInfo
.fMask 
= SIF_TRACKPOS
; 
5327             if ( !::GetScrollInfo(GetHwnd(), 
5328                                   orientation 
== wxHORIZONTAL 
? SB_HORZ
 
5332                 // Not necessarily an error, if there are no scrollbars yet. 
5333                 // wxLogLastError(_T("GetScrollInfo")); 
5336             event
.SetPosition(scrollInfo
.nTrackPos
); 
5339         event
.SetEventType( wParam 
== SB_THUMBPOSITION
 
5340                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
 
5341                                 : wxEVT_SCROLLWIN_THUMBTRACK 
); 
5348     return GetEventHandler()->ProcessEvent(event
); 
5351 // =========================================================================== 
5353 // =========================================================================== 
5355 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
& the_font
) 
5358     HDC dc 
= ::GetDC((HWND
) wnd
); 
5361     //    the_font.UseResource(); 
5362     //    the_font.RealizeResource(); 
5363     HFONT fnt 
= (HFONT
)the_font
.GetResourceHandle(); // const_cast 
5365         was 
= (HFONT
) SelectObject(dc
,fnt
); 
5367     GetTextMetrics(dc
, &tm
); 
5370         SelectObject(dc
,was
); 
5372     ReleaseDC((HWND
)wnd
, dc
); 
5375         *x 
= tm
.tmAveCharWidth
; 
5377         *y 
= tm
.tmHeight 
+ tm
.tmExternalLeading
; 
5379     //   the_font.ReleaseResource(); 
5382 // use the "extended" bit (24) of lParam to distinguish extended keys 
5383 // from normal keys as the same key is sent 
5385 int ChooseNormalOrExtended(int lParam
, int keyNormal
, int keyExtended
) 
5387     // except that if lParam is 0, it means we don't have real lParam from 
5388     // WM_KEYDOWN but are just translating just a VK constant (e.g. done from 
5389     // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a 
5390     // non-numpad (hence extended) key as this is a more common case 
5391     return !lParam 
|| (lParam 
& (1 << 24)) ? keyExtended 
: keyNormal
; 
5394 // this array contains the Windows virtual key codes which map one to one to 
5395 // WXK_xxx constants and is used in wxCharCodeMSWToWX/WXToMSW() below 
5397 // note that keys having a normal and numpad version (e.g. WXK_HOME and 
5398 // WXK_NUMPAD_HOME) are not included in this table as the mapping is not 1-to-1 
5399 static const struct wxKeyMapping
 
5403 } gs_specialKeys
[] = 
5405     { VK_CANCEL
,        WXK_CANCEL 
}, 
5406     { VK_BACK
,          WXK_BACK 
}, 
5407     { VK_TAB
,           WXK_TAB 
}, 
5408     { VK_CLEAR
,         WXK_CLEAR 
}, 
5409     { VK_SHIFT
,         WXK_SHIFT 
}, 
5410     { VK_CONTROL
,       WXK_CONTROL 
}, 
5411     { VK_MENU 
,         WXK_ALT 
}, 
5412     { VK_PAUSE
,         WXK_PAUSE 
}, 
5413     { VK_CAPITAL
,       WXK_CAPITAL 
}, 
5414     { VK_SPACE
,         WXK_SPACE 
}, 
5415     { VK_ESCAPE
,        WXK_ESCAPE 
}, 
5416     { VK_SELECT
,        WXK_SELECT 
}, 
5417     { VK_PRINT
,         WXK_PRINT 
}, 
5418     { VK_EXECUTE
,       WXK_EXECUTE 
}, 
5419     { VK_SNAPSHOT
,      WXK_SNAPSHOT 
}, 
5420     { VK_HELP
,          WXK_HELP 
}, 
5422     { VK_NUMPAD0
,       WXK_NUMPAD0 
}, 
5423     { VK_NUMPAD1
,       WXK_NUMPAD1 
}, 
5424     { VK_NUMPAD2
,       WXK_NUMPAD2 
}, 
5425     { VK_NUMPAD3
,       WXK_NUMPAD3 
}, 
5426     { VK_NUMPAD4
,       WXK_NUMPAD4 
}, 
5427     { VK_NUMPAD5
,       WXK_NUMPAD5 
}, 
5428     { VK_NUMPAD6
,       WXK_NUMPAD6 
}, 
5429     { VK_NUMPAD7
,       WXK_NUMPAD7 
}, 
5430     { VK_NUMPAD8
,       WXK_NUMPAD8 
}, 
5431     { VK_NUMPAD9
,       WXK_NUMPAD9 
}, 
5432     { VK_MULTIPLY
,      WXK_NUMPAD_MULTIPLY 
}, 
5433     { VK_ADD
,           WXK_NUMPAD_ADD 
}, 
5434     { VK_SUBTRACT
,      WXK_NUMPAD_SUBTRACT 
}, 
5435     { VK_DECIMAL
,       WXK_NUMPAD_DECIMAL 
}, 
5436     { VK_DIVIDE
,        WXK_NUMPAD_DIVIDE 
}, 
5447     { VK_F10
,           WXK_F10 
}, 
5448     { VK_F11
,           WXK_F11 
}, 
5449     { VK_F12
,           WXK_F12 
}, 
5450     { VK_F13
,           WXK_F13 
}, 
5451     { VK_F14
,           WXK_F14 
}, 
5452     { VK_F15
,           WXK_F15 
}, 
5453     { VK_F16
,           WXK_F16 
}, 
5454     { VK_F17
,           WXK_F17 
}, 
5455     { VK_F18
,           WXK_F18 
}, 
5456     { VK_F19
,           WXK_F19 
}, 
5457     { VK_F20
,           WXK_F20 
}, 
5458     { VK_F21
,           WXK_F21 
}, 
5459     { VK_F22
,           WXK_F22 
}, 
5460     { VK_F23
,           WXK_F23 
}, 
5461     { VK_F24
,           WXK_F24 
}, 
5463     { VK_NUMLOCK
,       WXK_NUMLOCK 
}, 
5464     { VK_SCROLL
,        WXK_SCROLL 
}, 
5467     { VK_LWIN
,          WXK_WINDOWS_LEFT 
}, 
5468     { VK_RWIN
,          WXK_WINDOWS_RIGHT 
}, 
5469     { VK_APPS
,          WXK_WINDOWS_MENU 
}, 
5470 #endif // VK_APPS defined 
5473 // Returns 0 if was a normal ASCII value, not a special key. This indicates that 
5474 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. 
5475 int wxCharCodeMSWToWX(int vk
, WXLPARAM lParam
) 
5477     // check the table first 
5478     for ( size_t n 
= 0; n 
< WXSIZEOF(gs_specialKeys
); n
++ ) 
5480         if ( gs_specialKeys
[n
].vk 
== vk 
) 
5481             return gs_specialKeys
[n
].wxk
; 
5484     // keys requiring special handling 
5488         // the mapping for these keys may be incorrect on non-US keyboards so 
5489         // maybe we shouldn't map them to ASCII values at all 
5490         case VK_OEM_1
:      wxk 
= ';'; break; 
5491         case VK_OEM_PLUS
:   wxk 
= '+'; break; 
5492         case VK_OEM_COMMA
:  wxk 
= ','; break; 
5493         case VK_OEM_MINUS
:  wxk 
= '-'; break; 
5494         case VK_OEM_PERIOD
: wxk 
= '.'; break; 
5495         case VK_OEM_2
:      wxk 
= '/'; break; 
5496         case VK_OEM_3
:      wxk 
= '~'; break; 
5497         case VK_OEM_4
:      wxk 
= '['; break; 
5498         case VK_OEM_5
:      wxk 
= '\\'; break; 
5499         case VK_OEM_6
:      wxk 
= ']'; break; 
5500         case VK_OEM_7
:      wxk 
= '\''; break; 
5502         // handle extended keys 
5504             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_PAGEUP
, WXK_PAGEUP
); 
5508             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_PAGEDOWN
, WXK_PAGEDOWN
); 
5512             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_END
, WXK_END
); 
5516             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_HOME
, WXK_HOME
); 
5520             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_LEFT
, WXK_LEFT
); 
5524             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_UP
, WXK_UP
); 
5528             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_RIGHT
, WXK_RIGHT
); 
5532             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_DOWN
, WXK_DOWN
); 
5536             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_INSERT
, WXK_INSERT
); 
5540             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_DELETE
, WXK_DELETE
); 
5544             // don't use ChooseNormalOrExtended() here as the keys are reversed 
5545             // here: numpad enter is the extended one 
5546             wxk 
= lParam 
&& (lParam 
& (1 << 24)) ? WXK_NUMPAD_ENTER 
: WXK_RETURN
; 
5556 WXWORD 
wxCharCodeWXToMSW(int wxk
, bool *isVirtual
) 
5561     // check the table first 
5562     for ( size_t n 
= 0; n 
< WXSIZEOF(gs_specialKeys
); n
++ ) 
5564         if ( gs_specialKeys
[n
].wxk 
== wxk 
) 
5565             return gs_specialKeys
[n
].vk
; 
5568     // and then check for special keys not included in the table 
5573         case WXK_NUMPAD_PAGEUP
: 
5578         case WXK_NUMPAD_PAGEDOWN
: 
5583         case WXK_NUMPAD_END
: 
5588         case WXK_NUMPAD_HOME
: 
5593         case WXK_NUMPAD_LEFT
: 
5603         case WXK_NUMPAD_RIGHT
: 
5608         case WXK_NUMPAD_DOWN
: 
5613         case WXK_NUMPAD_INSERT
: 
5618         case WXK_NUMPAD_DELETE
: 
5632 // small helper for wxGetKeyState() and wxGetMouseState() 
5633 static inline bool wxIsKeyDown(WXWORD vk
) 
5635     // the low order bit indicates whether the key was pressed since the last 
5636     // call and the high order one indicates whether it is down right now and 
5637     // we only want that one 
5638     return (::GetAsyncKeyState(vk
) & (1<<15)) != 0; 
5641 bool wxGetKeyState(wxKeyCode key
) 
5643     // although this does work under Windows, it is not supported under other 
5644     // platforms so don't allow it, you must use wxGetMouseState() instead 
5645     wxASSERT_MSG( key 
!= VK_LBUTTON 
&& 
5646                     key 
!= VK_RBUTTON 
&& 
5648                     wxT("can't use wxGetKeyState() for mouse buttons") ); 
5650     const WXWORD vk 
= wxCharCodeWXToMSW(key
); 
5652     // if the requested key is a LED key, return true if the led is pressed 
5653     if ( key 
== WXK_NUMLOCK 
|| key 
== WXK_CAPITAL 
|| key 
== WXK_SCROLL 
) 
5655         // low order bit means LED is highlighted and high order one means the 
5656         // key is down; for compatibility with the other ports return true if 
5657         // either one is set 
5658         return ::GetKeyState(vk
) != 0; 
5663         return wxIsKeyDown(vk
); 
5668 wxMouseState 
wxGetMouseState() 
5672     GetCursorPos( &pt 
); 
5676     ms
.SetLeftDown(wxIsKeyDown(VK_LBUTTON
)); 
5677     ms
.SetMiddleDown(wxIsKeyDown(VK_MBUTTON
)); 
5678     ms
.SetRightDown(wxIsKeyDown(VK_RBUTTON
)); 
5680     ms
.SetControlDown(wxIsKeyDown(VK_CONTROL
)); 
5681     ms
.SetShiftDown(wxIsKeyDown(VK_SHIFT
)); 
5682     ms
.SetAltDown(wxIsKeyDown(VK_MENU
)); 
5683 //    ms.SetMetaDown(); 
5689 wxWindow 
*wxGetActiveWindow() 
5691     HWND hWnd 
= GetActiveWindow(); 
5694         return wxFindWinFromHandle((WXHWND
) hWnd
); 
5699 extern wxWindow 
*wxGetWindowFromHWND(WXHWND hWnd
) 
5701     HWND hwnd 
= (HWND
)hWnd
; 
5703     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set 
5704     // by code in msw/radiobox.cpp), for all the others we just search up the 
5706     wxWindow 
*win 
= (wxWindow 
*)NULL
; 
5709         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
5713             // native radiobuttons return DLGC_RADIOBUTTON here and for any 
5714             // wxWindow class which overrides WM_GETDLGCODE processing to 
5715             // do it as well, win would be already non NULL 
5716             if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON 
) 
5718                 win 
= (wxWindow 
*)wxGetWindowUserData(hwnd
); 
5720             //else: it's a wxRadioButton, not a radiobutton from wxRadioBox 
5721 #endif // wxUSE_RADIOBOX 
5723             // spin control text buddy window should be mapped to spin ctrl 
5724             // itself so try it too 
5725 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
5728                 win 
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
); 
5730 #endif // wxUSE_SPINCTRL 
5734     while ( hwnd 
&& !win 
) 
5736         // this is a really ugly hack needed to avoid mistakenly returning the 
5737         // parent frame wxWindow for the find/replace modeless dialog HWND - 
5738         // this, in turn, is needed to call IsDialogMessage() from 
5739         // wxApp::ProcessMessage() as for this we must return NULL from here 
5741         // FIXME: this is clearly not the best way to do it but I think we'll 
5742         //        need to change HWND <-> wxWindow code more heavily than I can 
5743         //        do it now to fix it 
5744 #ifndef __WXMICROWIN__ 
5745         if ( ::GetWindow(hwnd
, GW_OWNER
) ) 
5747             // it's a dialog box, don't go upwards 
5752         hwnd 
= ::GetParent(hwnd
); 
5753         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
5759 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
5761 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE 
5762 // in active frames and dialogs, regardless of where the focus is. 
5763 static HHOOK wxTheKeyboardHook 
= 0; 
5764 static FARPROC wxTheKeyboardHookProc 
= 0; 
5765 int APIENTRY _EXPORT
 
5766 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
); 
5768 void wxSetKeyboardHook(bool doIt
) 
5772         wxTheKeyboardHookProc 
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance()); 
5773         wxTheKeyboardHook 
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(), 
5775             GetCurrentThreadId() 
5776         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? 
5781         UnhookWindowsHookEx(wxTheKeyboardHook
); 
5785 int APIENTRY _EXPORT
 
5786 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
) 
5788     DWORD hiWord 
= HIWORD(lParam
); 
5789     if ( nCode 
!= HC_NOREMOVE 
&& ((hiWord 
& KF_UP
) == 0) ) 
5791         int id 
= wxCharCodeMSWToWX(wParam
, lParam
); 
5794             wxKeyEvent 
event(wxEVT_CHAR_HOOK
); 
5795             if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
5796                 event
.m_altDown 
= true; 
5798             event
.SetEventObject(NULL
); 
5799             event
.m_keyCode 
= id
; 
5800             event
.m_shiftDown 
= wxIsShiftDown(); 
5801             event
.m_controlDown 
= wxIsCtrlDown(); 
5803             event
.SetTimestamp(::GetMessageTime()); 
5805             wxWindow 
*win 
= wxGetActiveWindow(); 
5806             wxEvtHandler 
*handler
; 
5809                 handler 
= win
->GetEventHandler(); 
5810                 event
.SetId(win
->GetId()); 
5815                 event
.SetId(wxID_ANY
); 
5818             if ( handler 
&& handler
->ProcessEvent(event
) ) 
5826     return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
); 
5829 #endif // !__WXMICROWIN__ 
5832 const wxChar 
*wxGetMessageName(int message
) 
5836         case 0x0000: return wxT("WM_NULL"); 
5837         case 0x0001: return wxT("WM_CREATE"); 
5838         case 0x0002: return wxT("WM_DESTROY"); 
5839         case 0x0003: return wxT("WM_MOVE"); 
5840         case 0x0005: return wxT("WM_SIZE"); 
5841         case 0x0006: return wxT("WM_ACTIVATE"); 
5842         case 0x0007: return wxT("WM_SETFOCUS"); 
5843         case 0x0008: return wxT("WM_KILLFOCUS"); 
5844         case 0x000A: return wxT("WM_ENABLE"); 
5845         case 0x000B: return wxT("WM_SETREDRAW"); 
5846         case 0x000C: return wxT("WM_SETTEXT"); 
5847         case 0x000D: return wxT("WM_GETTEXT"); 
5848         case 0x000E: return wxT("WM_GETTEXTLENGTH"); 
5849         case 0x000F: return wxT("WM_PAINT"); 
5850         case 0x0010: return wxT("WM_CLOSE"); 
5851         case 0x0011: return wxT("WM_QUERYENDSESSION"); 
5852         case 0x0012: return wxT("WM_QUIT"); 
5853         case 0x0013: return wxT("WM_QUERYOPEN"); 
5854         case 0x0014: return wxT("WM_ERASEBKGND"); 
5855         case 0x0015: return wxT("WM_SYSCOLORCHANGE"); 
5856         case 0x0016: return wxT("WM_ENDSESSION"); 
5857         case 0x0017: return wxT("WM_SYSTEMERROR"); 
5858         case 0x0018: return wxT("WM_SHOWWINDOW"); 
5859         case 0x0019: return wxT("WM_CTLCOLOR"); 
5860         case 0x001A: return wxT("WM_WININICHANGE"); 
5861         case 0x001B: return wxT("WM_DEVMODECHANGE"); 
5862         case 0x001C: return wxT("WM_ACTIVATEAPP"); 
5863         case 0x001D: return wxT("WM_FONTCHANGE"); 
5864         case 0x001E: return wxT("WM_TIMECHANGE"); 
5865         case 0x001F: return wxT("WM_CANCELMODE"); 
5866         case 0x0020: return wxT("WM_SETCURSOR"); 
5867         case 0x0021: return wxT("WM_MOUSEACTIVATE"); 
5868         case 0x0022: return wxT("WM_CHILDACTIVATE"); 
5869         case 0x0023: return wxT("WM_QUEUESYNC"); 
5870         case 0x0024: return wxT("WM_GETMINMAXINFO"); 
5871         case 0x0026: return wxT("WM_PAINTICON"); 
5872         case 0x0027: return wxT("WM_ICONERASEBKGND"); 
5873         case 0x0028: return wxT("WM_NEXTDLGCTL"); 
5874         case 0x002A: return wxT("WM_SPOOLERSTATUS"); 
5875         case 0x002B: return wxT("WM_DRAWITEM"); 
5876         case 0x002C: return wxT("WM_MEASUREITEM"); 
5877         case 0x002D: return wxT("WM_DELETEITEM"); 
5878         case 0x002E: return wxT("WM_VKEYTOITEM"); 
5879         case 0x002F: return wxT("WM_CHARTOITEM"); 
5880         case 0x0030: return wxT("WM_SETFONT"); 
5881         case 0x0031: return wxT("WM_GETFONT"); 
5882         case 0x0037: return wxT("WM_QUERYDRAGICON"); 
5883         case 0x0039: return wxT("WM_COMPAREITEM"); 
5884         case 0x0041: return wxT("WM_COMPACTING"); 
5885         case 0x0044: return wxT("WM_COMMNOTIFY"); 
5886         case 0x0046: return wxT("WM_WINDOWPOSCHANGING"); 
5887         case 0x0047: return wxT("WM_WINDOWPOSCHANGED"); 
5888         case 0x0048: return wxT("WM_POWER"); 
5890         case 0x004A: return wxT("WM_COPYDATA"); 
5891         case 0x004B: return wxT("WM_CANCELJOURNAL"); 
5892         case 0x004E: return wxT("WM_NOTIFY"); 
5893         case 0x0050: return wxT("WM_INPUTLANGCHANGEREQUEST"); 
5894         case 0x0051: return wxT("WM_INPUTLANGCHANGE"); 
5895         case 0x0052: return wxT("WM_TCARD"); 
5896         case 0x0053: return wxT("WM_HELP"); 
5897         case 0x0054: return wxT("WM_USERCHANGED"); 
5898         case 0x0055: return wxT("WM_NOTIFYFORMAT"); 
5899         case 0x007B: return wxT("WM_CONTEXTMENU"); 
5900         case 0x007C: return wxT("WM_STYLECHANGING"); 
5901         case 0x007D: return wxT("WM_STYLECHANGED"); 
5902         case 0x007E: return wxT("WM_DISPLAYCHANGE"); 
5903         case 0x007F: return wxT("WM_GETICON"); 
5904         case 0x0080: return wxT("WM_SETICON"); 
5906         case 0x0081: return wxT("WM_NCCREATE"); 
5907         case 0x0082: return wxT("WM_NCDESTROY"); 
5908         case 0x0083: return wxT("WM_NCCALCSIZE"); 
5909         case 0x0084: return wxT("WM_NCHITTEST"); 
5910         case 0x0085: return wxT("WM_NCPAINT"); 
5911         case 0x0086: return wxT("WM_NCACTIVATE"); 
5912         case 0x0087: return wxT("WM_GETDLGCODE"); 
5913         case 0x00A0: return wxT("WM_NCMOUSEMOVE"); 
5914         case 0x00A1: return wxT("WM_NCLBUTTONDOWN"); 
5915         case 0x00A2: return wxT("WM_NCLBUTTONUP"); 
5916         case 0x00A3: return wxT("WM_NCLBUTTONDBLCLK"); 
5917         case 0x00A4: return wxT("WM_NCRBUTTONDOWN"); 
5918         case 0x00A5: return wxT("WM_NCRBUTTONUP"); 
5919         case 0x00A6: return wxT("WM_NCRBUTTONDBLCLK"); 
5920         case 0x00A7: return wxT("WM_NCMBUTTONDOWN"); 
5921         case 0x00A8: return wxT("WM_NCMBUTTONUP"); 
5922         case 0x00A9: return wxT("WM_NCMBUTTONDBLCLK"); 
5923         case 0x0100: return wxT("WM_KEYDOWN"); 
5924         case 0x0101: return wxT("WM_KEYUP"); 
5925         case 0x0102: return wxT("WM_CHAR"); 
5926         case 0x0103: return wxT("WM_DEADCHAR"); 
5927         case 0x0104: return wxT("WM_SYSKEYDOWN"); 
5928         case 0x0105: return wxT("WM_SYSKEYUP"); 
5929         case 0x0106: return wxT("WM_SYSCHAR"); 
5930         case 0x0107: return wxT("WM_SYSDEADCHAR"); 
5931         case 0x0108: return wxT("WM_KEYLAST"); 
5933         case 0x010D: return wxT("WM_IME_STARTCOMPOSITION"); 
5934         case 0x010E: return wxT("WM_IME_ENDCOMPOSITION"); 
5935         case 0x010F: return wxT("WM_IME_COMPOSITION"); 
5937         case 0x0110: return wxT("WM_INITDIALOG"); 
5938         case 0x0111: return wxT("WM_COMMAND"); 
5939         case 0x0112: return wxT("WM_SYSCOMMAND"); 
5940         case 0x0113: return wxT("WM_TIMER"); 
5941         case 0x0114: return wxT("WM_HSCROLL"); 
5942         case 0x0115: return wxT("WM_VSCROLL"); 
5943         case 0x0116: return wxT("WM_INITMENU"); 
5944         case 0x0117: return wxT("WM_INITMENUPOPUP"); 
5945         case 0x011F: return wxT("WM_MENUSELECT"); 
5946         case 0x0120: return wxT("WM_MENUCHAR"); 
5947         case 0x0121: return wxT("WM_ENTERIDLE"); 
5948         case 0x0200: return wxT("WM_MOUSEMOVE"); 
5949         case 0x0201: return wxT("WM_LBUTTONDOWN"); 
5950         case 0x0202: return wxT("WM_LBUTTONUP"); 
5951         case 0x0203: return wxT("WM_LBUTTONDBLCLK"); 
5952         case 0x0204: return wxT("WM_RBUTTONDOWN"); 
5953         case 0x0205: return wxT("WM_RBUTTONUP"); 
5954         case 0x0206: return wxT("WM_RBUTTONDBLCLK"); 
5955         case 0x0207: return wxT("WM_MBUTTONDOWN"); 
5956         case 0x0208: return wxT("WM_MBUTTONUP"); 
5957         case 0x0209: return wxT("WM_MBUTTONDBLCLK"); 
5958         case 0x020A: return wxT("WM_MOUSEWHEEL"); 
5959         case 0x0210: return wxT("WM_PARENTNOTIFY"); 
5960         case 0x0211: return wxT("WM_ENTERMENULOOP"); 
5961         case 0x0212: return wxT("WM_EXITMENULOOP"); 
5963         case 0x0213: return wxT("WM_NEXTMENU"); 
5964         case 0x0214: return wxT("WM_SIZING"); 
5965         case 0x0215: return wxT("WM_CAPTURECHANGED"); 
5966         case 0x0216: return wxT("WM_MOVING"); 
5967         case 0x0218: return wxT("WM_POWERBROADCAST"); 
5968         case 0x0219: return wxT("WM_DEVICECHANGE"); 
5970         case 0x0220: return wxT("WM_MDICREATE"); 
5971         case 0x0221: return wxT("WM_MDIDESTROY"); 
5972         case 0x0222: return wxT("WM_MDIACTIVATE"); 
5973         case 0x0223: return wxT("WM_MDIRESTORE"); 
5974         case 0x0224: return wxT("WM_MDINEXT"); 
5975         case 0x0225: return wxT("WM_MDIMAXIMIZE"); 
5976         case 0x0226: return wxT("WM_MDITILE"); 
5977         case 0x0227: return wxT("WM_MDICASCADE"); 
5978         case 0x0228: return wxT("WM_MDIICONARRANGE"); 
5979         case 0x0229: return wxT("WM_MDIGETACTIVE"); 
5980         case 0x0230: return wxT("WM_MDISETMENU"); 
5981         case 0x0233: return wxT("WM_DROPFILES"); 
5983         case 0x0281: return wxT("WM_IME_SETCONTEXT"); 
5984         case 0x0282: return wxT("WM_IME_NOTIFY"); 
5985         case 0x0283: return wxT("WM_IME_CONTROL"); 
5986         case 0x0284: return wxT("WM_IME_COMPOSITIONFULL"); 
5987         case 0x0285: return wxT("WM_IME_SELECT"); 
5988         case 0x0286: return wxT("WM_IME_CHAR"); 
5989         case 0x0290: return wxT("WM_IME_KEYDOWN"); 
5990         case 0x0291: return wxT("WM_IME_KEYUP"); 
5992         case 0x0300: return wxT("WM_CUT"); 
5993         case 0x0301: return wxT("WM_COPY"); 
5994         case 0x0302: return wxT("WM_PASTE"); 
5995         case 0x0303: return wxT("WM_CLEAR"); 
5996         case 0x0304: return wxT("WM_UNDO"); 
5997         case 0x0305: return wxT("WM_RENDERFORMAT"); 
5998         case 0x0306: return wxT("WM_RENDERALLFORMATS"); 
5999         case 0x0307: return wxT("WM_DESTROYCLIPBOARD"); 
6000         case 0x0308: return wxT("WM_DRAWCLIPBOARD"); 
6001         case 0x0309: return wxT("WM_PAINTCLIPBOARD"); 
6002         case 0x030A: return wxT("WM_VSCROLLCLIPBOARD"); 
6003         case 0x030B: return wxT("WM_SIZECLIPBOARD"); 
6004         case 0x030C: return wxT("WM_ASKCBFORMATNAME"); 
6005         case 0x030D: return wxT("WM_CHANGECBCHAIN"); 
6006         case 0x030E: return wxT("WM_HSCROLLCLIPBOARD"); 
6007         case 0x030F: return wxT("WM_QUERYNEWPALETTE"); 
6008         case 0x0310: return wxT("WM_PALETTEISCHANGING"); 
6009         case 0x0311: return wxT("WM_PALETTECHANGED"); 
6011         case 0x0312: return wxT("WM_HOTKEY"); 
6014         // common controls messages - although they're not strictly speaking 
6015         // standard, it's nice to decode them nevertheless 
6018         case 0x1000 + 0: return wxT("LVM_GETBKCOLOR"); 
6019         case 0x1000 + 1: return wxT("LVM_SETBKCOLOR"); 
6020         case 0x1000 + 2: return wxT("LVM_GETIMAGELIST"); 
6021         case 0x1000 + 3: return wxT("LVM_SETIMAGELIST"); 
6022         case 0x1000 + 4: return wxT("LVM_GETITEMCOUNT"); 
6023         case 0x1000 + 5: return wxT("LVM_GETITEMA"); 
6024         case 0x1000 + 75: return wxT("LVM_GETITEMW"); 
6025         case 0x1000 + 6: return wxT("LVM_SETITEMA"); 
6026         case 0x1000 + 76: return wxT("LVM_SETITEMW"); 
6027         case 0x1000 + 7: return wxT("LVM_INSERTITEMA"); 
6028         case 0x1000 + 77: return wxT("LVM_INSERTITEMW"); 
6029         case 0x1000 + 8: return wxT("LVM_DELETEITEM"); 
6030         case 0x1000 + 9: return wxT("LVM_DELETEALLITEMS"); 
6031         case 0x1000 + 10: return wxT("LVM_GETCALLBACKMASK"); 
6032         case 0x1000 + 11: return wxT("LVM_SETCALLBACKMASK"); 
6033         case 0x1000 + 12: return wxT("LVM_GETNEXTITEM"); 
6034         case 0x1000 + 13: return wxT("LVM_FINDITEMA"); 
6035         case 0x1000 + 83: return wxT("LVM_FINDITEMW"); 
6036         case 0x1000 + 14: return wxT("LVM_GETITEMRECT"); 
6037         case 0x1000 + 15: return wxT("LVM_SETITEMPOSITION"); 
6038         case 0x1000 + 16: return wxT("LVM_GETITEMPOSITION"); 
6039         case 0x1000 + 17: return wxT("LVM_GETSTRINGWIDTHA"); 
6040         case 0x1000 + 87: return wxT("LVM_GETSTRINGWIDTHW"); 
6041         case 0x1000 + 18: return wxT("LVM_HITTEST"); 
6042         case 0x1000 + 19: return wxT("LVM_ENSUREVISIBLE"); 
6043         case 0x1000 + 20: return wxT("LVM_SCROLL"); 
6044         case 0x1000 + 21: return wxT("LVM_REDRAWITEMS"); 
6045         case 0x1000 + 22: return wxT("LVM_ARRANGE"); 
6046         case 0x1000 + 23: return wxT("LVM_EDITLABELA"); 
6047         case 0x1000 + 118: return wxT("LVM_EDITLABELW"); 
6048         case 0x1000 + 24: return wxT("LVM_GETEDITCONTROL"); 
6049         case 0x1000 + 25: return wxT("LVM_GETCOLUMNA"); 
6050         case 0x1000 + 95: return wxT("LVM_GETCOLUMNW"); 
6051         case 0x1000 + 26: return wxT("LVM_SETCOLUMNA"); 
6052         case 0x1000 + 96: return wxT("LVM_SETCOLUMNW"); 
6053         case 0x1000 + 27: return wxT("LVM_INSERTCOLUMNA"); 
6054         case 0x1000 + 97: return wxT("LVM_INSERTCOLUMNW"); 
6055         case 0x1000 + 28: return wxT("LVM_DELETECOLUMN"); 
6056         case 0x1000 + 29: return wxT("LVM_GETCOLUMNWIDTH"); 
6057         case 0x1000 + 30: return wxT("LVM_SETCOLUMNWIDTH"); 
6058         case 0x1000 + 31: return wxT("LVM_GETHEADER"); 
6059         case 0x1000 + 33: return wxT("LVM_CREATEDRAGIMAGE"); 
6060         case 0x1000 + 34: return wxT("LVM_GETVIEWRECT"); 
6061         case 0x1000 + 35: return wxT("LVM_GETTEXTCOLOR"); 
6062         case 0x1000 + 36: return wxT("LVM_SETTEXTCOLOR"); 
6063         case 0x1000 + 37: return wxT("LVM_GETTEXTBKCOLOR"); 
6064         case 0x1000 + 38: return wxT("LVM_SETTEXTBKCOLOR"); 
6065         case 0x1000 + 39: return wxT("LVM_GETTOPINDEX"); 
6066         case 0x1000 + 40: return wxT("LVM_GETCOUNTPERPAGE"); 
6067         case 0x1000 + 41: return wxT("LVM_GETORIGIN"); 
6068         case 0x1000 + 42: return wxT("LVM_UPDATE"); 
6069         case 0x1000 + 43: return wxT("LVM_SETITEMSTATE"); 
6070         case 0x1000 + 44: return wxT("LVM_GETITEMSTATE"); 
6071         case 0x1000 + 45: return wxT("LVM_GETITEMTEXTA"); 
6072         case 0x1000 + 115: return wxT("LVM_GETITEMTEXTW"); 
6073         case 0x1000 + 46: return wxT("LVM_SETITEMTEXTA"); 
6074         case 0x1000 + 116: return wxT("LVM_SETITEMTEXTW"); 
6075         case 0x1000 + 47: return wxT("LVM_SETITEMCOUNT"); 
6076         case 0x1000 + 48: return wxT("LVM_SORTITEMS"); 
6077         case 0x1000 + 49: return wxT("LVM_SETITEMPOSITION32"); 
6078         case 0x1000 + 50: return wxT("LVM_GETSELECTEDCOUNT"); 
6079         case 0x1000 + 51: return wxT("LVM_GETITEMSPACING"); 
6080         case 0x1000 + 52: return wxT("LVM_GETISEARCHSTRINGA"); 
6081         case 0x1000 + 117: return wxT("LVM_GETISEARCHSTRINGW"); 
6082         case 0x1000 + 53: return wxT("LVM_SETICONSPACING"); 
6083         case 0x1000 + 54: return wxT("LVM_SETEXTENDEDLISTVIEWSTYLE"); 
6084         case 0x1000 + 55: return wxT("LVM_GETEXTENDEDLISTVIEWSTYLE"); 
6085         case 0x1000 + 56: return wxT("LVM_GETSUBITEMRECT"); 
6086         case 0x1000 + 57: return wxT("LVM_SUBITEMHITTEST"); 
6087         case 0x1000 + 58: return wxT("LVM_SETCOLUMNORDERARRAY"); 
6088         case 0x1000 + 59: return wxT("LVM_GETCOLUMNORDERARRAY"); 
6089         case 0x1000 + 60: return wxT("LVM_SETHOTITEM"); 
6090         case 0x1000 + 61: return wxT("LVM_GETHOTITEM"); 
6091         case 0x1000 + 62: return wxT("LVM_SETHOTCURSOR"); 
6092         case 0x1000 + 63: return wxT("LVM_GETHOTCURSOR"); 
6093         case 0x1000 + 64: return wxT("LVM_APPROXIMATEVIEWRECT"); 
6094         case 0x1000 + 65: return wxT("LVM_SETWORKAREA"); 
6097         case 0x1100 + 0: return wxT("TVM_INSERTITEMA"); 
6098         case 0x1100 + 50: return wxT("TVM_INSERTITEMW"); 
6099         case 0x1100 + 1: return wxT("TVM_DELETEITEM"); 
6100         case 0x1100 + 2: return wxT("TVM_EXPAND"); 
6101         case 0x1100 + 4: return wxT("TVM_GETITEMRECT"); 
6102         case 0x1100 + 5: return wxT("TVM_GETCOUNT"); 
6103         case 0x1100 + 6: return wxT("TVM_GETINDENT"); 
6104         case 0x1100 + 7: return wxT("TVM_SETINDENT"); 
6105         case 0x1100 + 8: return wxT("TVM_GETIMAGELIST"); 
6106         case 0x1100 + 9: return wxT("TVM_SETIMAGELIST"); 
6107         case 0x1100 + 10: return wxT("TVM_GETNEXTITEM"); 
6108         case 0x1100 + 11: return wxT("TVM_SELECTITEM"); 
6109         case 0x1100 + 12: return wxT("TVM_GETITEMA"); 
6110         case 0x1100 + 62: return wxT("TVM_GETITEMW"); 
6111         case 0x1100 + 13: return wxT("TVM_SETITEMA"); 
6112         case 0x1100 + 63: return wxT("TVM_SETITEMW"); 
6113         case 0x1100 + 14: return wxT("TVM_EDITLABELA"); 
6114         case 0x1100 + 65: return wxT("TVM_EDITLABELW"); 
6115         case 0x1100 + 15: return wxT("TVM_GETEDITCONTROL"); 
6116         case 0x1100 + 16: return wxT("TVM_GETVISIBLECOUNT"); 
6117         case 0x1100 + 17: return wxT("TVM_HITTEST"); 
6118         case 0x1100 + 18: return wxT("TVM_CREATEDRAGIMAGE"); 
6119         case 0x1100 + 19: return wxT("TVM_SORTCHILDREN"); 
6120         case 0x1100 + 20: return wxT("TVM_ENSUREVISIBLE"); 
6121         case 0x1100 + 21: return wxT("TVM_SORTCHILDRENCB"); 
6122         case 0x1100 + 22: return wxT("TVM_ENDEDITLABELNOW"); 
6123         case 0x1100 + 23: return wxT("TVM_GETISEARCHSTRINGA"); 
6124         case 0x1100 + 64: return wxT("TVM_GETISEARCHSTRINGW"); 
6125         case 0x1100 + 24: return wxT("TVM_SETTOOLTIPS"); 
6126         case 0x1100 + 25: return wxT("TVM_GETTOOLTIPS"); 
6129         case 0x1200 + 0: return wxT("HDM_GETITEMCOUNT"); 
6130         case 0x1200 + 1: return wxT("HDM_INSERTITEMA"); 
6131         case 0x1200 + 10: return wxT("HDM_INSERTITEMW"); 
6132         case 0x1200 + 2: return wxT("HDM_DELETEITEM"); 
6133         case 0x1200 + 3: return wxT("HDM_GETITEMA"); 
6134         case 0x1200 + 11: return wxT("HDM_GETITEMW"); 
6135         case 0x1200 + 4: return wxT("HDM_SETITEMA"); 
6136         case 0x1200 + 12: return wxT("HDM_SETITEMW"); 
6137         case 0x1200 + 5: return wxT("HDM_LAYOUT"); 
6138         case 0x1200 + 6: return wxT("HDM_HITTEST"); 
6139         case 0x1200 + 7: return wxT("HDM_GETITEMRECT"); 
6140         case 0x1200 + 8: return wxT("HDM_SETIMAGELIST"); 
6141         case 0x1200 + 9: return wxT("HDM_GETIMAGELIST"); 
6142         case 0x1200 + 15: return wxT("HDM_ORDERTOINDEX"); 
6143         case 0x1200 + 16: return wxT("HDM_CREATEDRAGIMAGE"); 
6144         case 0x1200 + 17: return wxT("HDM_GETORDERARRAY"); 
6145         case 0x1200 + 18: return wxT("HDM_SETORDERARRAY"); 
6146         case 0x1200 + 19: return wxT("HDM_SETHOTDIVIDER"); 
6149         case 0x1300 + 2: return wxT("TCM_GETIMAGELIST"); 
6150         case 0x1300 + 3: return wxT("TCM_SETIMAGELIST"); 
6151         case 0x1300 + 4: return wxT("TCM_GETITEMCOUNT"); 
6152         case 0x1300 + 5: return wxT("TCM_GETITEMA"); 
6153         case 0x1300 + 60: return wxT("TCM_GETITEMW"); 
6154         case 0x1300 + 6: return wxT("TCM_SETITEMA"); 
6155         case 0x1300 + 61: return wxT("TCM_SETITEMW"); 
6156         case 0x1300 + 7: return wxT("TCM_INSERTITEMA"); 
6157         case 0x1300 + 62: return wxT("TCM_INSERTITEMW"); 
6158         case 0x1300 + 8: return wxT("TCM_DELETEITEM"); 
6159         case 0x1300 + 9: return wxT("TCM_DELETEALLITEMS"); 
6160         case 0x1300 + 10: return wxT("TCM_GETITEMRECT"); 
6161         case 0x1300 + 11: return wxT("TCM_GETCURSEL"); 
6162         case 0x1300 + 12: return wxT("TCM_SETCURSEL"); 
6163         case 0x1300 + 13: return wxT("TCM_HITTEST"); 
6164         case 0x1300 + 14: return wxT("TCM_SETITEMEXTRA"); 
6165         case 0x1300 + 40: return wxT("TCM_ADJUSTRECT"); 
6166         case 0x1300 + 41: return wxT("TCM_SETITEMSIZE"); 
6167         case 0x1300 + 42: return wxT("TCM_REMOVEIMAGE"); 
6168         case 0x1300 + 43: return wxT("TCM_SETPADDING"); 
6169         case 0x1300 + 44: return wxT("TCM_GETROWCOUNT"); 
6170         case 0x1300 + 45: return wxT("TCM_GETTOOLTIPS"); 
6171         case 0x1300 + 46: return wxT("TCM_SETTOOLTIPS"); 
6172         case 0x1300 + 47: return wxT("TCM_GETCURFOCUS"); 
6173         case 0x1300 + 48: return wxT("TCM_SETCURFOCUS"); 
6174         case 0x1300 + 49: return wxT("TCM_SETMINTABWIDTH"); 
6175         case 0x1300 + 50: return wxT("TCM_DESELECTALL"); 
6178         case WM_USER
+1: return wxT("TB_ENABLEBUTTON"); 
6179         case WM_USER
+2: return wxT("TB_CHECKBUTTON"); 
6180         case WM_USER
+3: return wxT("TB_PRESSBUTTON"); 
6181         case WM_USER
+4: return wxT("TB_HIDEBUTTON"); 
6182         case WM_USER
+5: return wxT("TB_INDETERMINATE"); 
6183         case WM_USER
+9: return wxT("TB_ISBUTTONENABLED"); 
6184         case WM_USER
+10: return wxT("TB_ISBUTTONCHECKED"); 
6185         case WM_USER
+11: return wxT("TB_ISBUTTONPRESSED"); 
6186         case WM_USER
+12: return wxT("TB_ISBUTTONHIDDEN"); 
6187         case WM_USER
+13: return wxT("TB_ISBUTTONINDETERMINATE"); 
6188         case WM_USER
+17: return wxT("TB_SETSTATE"); 
6189         case WM_USER
+18: return wxT("TB_GETSTATE"); 
6190         case WM_USER
+19: return wxT("TB_ADDBITMAP"); 
6191         case WM_USER
+20: return wxT("TB_ADDBUTTONS"); 
6192         case WM_USER
+21: return wxT("TB_INSERTBUTTON"); 
6193         case WM_USER
+22: return wxT("TB_DELETEBUTTON"); 
6194         case WM_USER
+23: return wxT("TB_GETBUTTON"); 
6195         case WM_USER
+24: return wxT("TB_BUTTONCOUNT"); 
6196         case WM_USER
+25: return wxT("TB_COMMANDTOINDEX"); 
6197         case WM_USER
+26: return wxT("TB_SAVERESTOREA"); 
6198         case WM_USER
+76: return wxT("TB_SAVERESTOREW"); 
6199         case WM_USER
+27: return wxT("TB_CUSTOMIZE"); 
6200         case WM_USER
+28: return wxT("TB_ADDSTRINGA"); 
6201         case WM_USER
+77: return wxT("TB_ADDSTRINGW"); 
6202         case WM_USER
+29: return wxT("TB_GETITEMRECT"); 
6203         case WM_USER
+30: return wxT("TB_BUTTONSTRUCTSIZE"); 
6204         case WM_USER
+31: return wxT("TB_SETBUTTONSIZE"); 
6205         case WM_USER
+32: return wxT("TB_SETBITMAPSIZE"); 
6206         case WM_USER
+33: return wxT("TB_AUTOSIZE"); 
6207         case WM_USER
+35: return wxT("TB_GETTOOLTIPS"); 
6208         case WM_USER
+36: return wxT("TB_SETTOOLTIPS"); 
6209         case WM_USER
+37: return wxT("TB_SETPARENT"); 
6210         case WM_USER
+39: return wxT("TB_SETROWS"); 
6211         case WM_USER
+40: return wxT("TB_GETROWS"); 
6212         case WM_USER
+42: return wxT("TB_SETCMDID"); 
6213         case WM_USER
+43: return wxT("TB_CHANGEBITMAP"); 
6214         case WM_USER
+44: return wxT("TB_GETBITMAP"); 
6215         case WM_USER
+45: return wxT("TB_GETBUTTONTEXTA"); 
6216         case WM_USER
+75: return wxT("TB_GETBUTTONTEXTW"); 
6217         case WM_USER
+46: return wxT("TB_REPLACEBITMAP"); 
6218         case WM_USER
+47: return wxT("TB_SETINDENT"); 
6219         case WM_USER
+48: return wxT("TB_SETIMAGELIST"); 
6220         case WM_USER
+49: return wxT("TB_GETIMAGELIST"); 
6221         case WM_USER
+50: return wxT("TB_LOADIMAGES"); 
6222         case WM_USER
+51: return wxT("TB_GETRECT"); 
6223         case WM_USER
+52: return wxT("TB_SETHOTIMAGELIST"); 
6224         case WM_USER
+53: return wxT("TB_GETHOTIMAGELIST"); 
6225         case WM_USER
+54: return wxT("TB_SETDISABLEDIMAGELIST"); 
6226         case WM_USER
+55: return wxT("TB_GETDISABLEDIMAGELIST"); 
6227         case WM_USER
+56: return wxT("TB_SETSTYLE"); 
6228         case WM_USER
+57: return wxT("TB_GETSTYLE"); 
6229         case WM_USER
+58: return wxT("TB_GETBUTTONSIZE"); 
6230         case WM_USER
+59: return wxT("TB_SETBUTTONWIDTH"); 
6231         case WM_USER
+60: return wxT("TB_SETMAXTEXTROWS"); 
6232         case WM_USER
+61: return wxT("TB_GETTEXTROWS"); 
6233         case WM_USER
+41: return wxT("TB_GETBITMAPFLAGS"); 
6236             static wxString s_szBuf
; 
6237             s_szBuf
.Printf(wxT("<unknown message = %d>"), message
); 
6238             return s_szBuf
.c_str(); 
6241 #endif //__WXDEBUG__ 
6243 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
) 
6247     HWND hwnd 
= GetHwndOf(win
); 
6248     HDC hdc 
= ::GetDC(hwnd
); 
6250 #if !wxDIALOG_UNIT_COMPATIBILITY 
6251     // and select the current font into it 
6252     HFONT hfont 
= GetHfontOf(win
->GetFont()); 
6255         hfont 
= (HFONT
)::SelectObject(hdc
, hfont
); 
6259     // finally retrieve the text metrics from it 
6260     GetTextMetrics(hdc
, &tm
); 
6262 #if !wxDIALOG_UNIT_COMPATIBILITY 
6266         (void)::SelectObject(hdc
, hfont
); 
6270     ::ReleaseDC(hwnd
, hdc
); 
6275 // Find the wxWindow at the current mouse position, returning the mouse 
6277 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
6279     pt 
= wxGetMousePosition(); 
6280     return wxFindWindowAtPoint(pt
); 
6283 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
6289     HWND hWnd 
= ::WindowFromPoint(pt2
); 
6291     return wxGetWindowFromHWND((WXHWND
)hWnd
); 
6294 // Get the current mouse position. 
6295 wxPoint 
wxGetMousePosition() 
6299     GetCursorPosWinCE(&pt
); 
6301     GetCursorPos( & pt 
); 
6304     return wxPoint(pt
.x
, pt
.y
); 
6309 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
6310 static void WinCEUnregisterHotKey(int modifiers
, int id
) 
6312     // Register hotkeys for the hardware buttons 
6314     typedef BOOL (WINAPI 
*UnregisterFunc1Proc
)(UINT
, UINT
); 
6316     UnregisterFunc1Proc procUnregisterFunc
; 
6317     hCoreDll 
= LoadLibrary(_T("coredll.dll")); 
6320         procUnregisterFunc 
= (UnregisterFunc1Proc
)GetProcAddress(hCoreDll
, _T("UnregisterFunc1")); 
6321         if (procUnregisterFunc
) 
6322             procUnregisterFunc(modifiers
, id
); 
6323         FreeLibrary(hCoreDll
); 
6328 bool wxWindowMSW::RegisterHotKey(int hotkeyId
, int modifiers
, int keycode
) 
6330     UINT win_modifiers
=0; 
6331     if ( modifiers 
& wxMOD_ALT 
) 
6332         win_modifiers 
|= MOD_ALT
; 
6333     if ( modifiers 
& wxMOD_SHIFT 
) 
6334         win_modifiers 
|= MOD_SHIFT
; 
6335     if ( modifiers 
& wxMOD_CONTROL 
) 
6336         win_modifiers 
|= MOD_CONTROL
; 
6337     if ( modifiers 
& wxMOD_WIN 
) 
6338         win_modifiers 
|= MOD_WIN
; 
6340 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
6341     // Required for PPC and Smartphone hardware buttons 
6342     if (keycode 
>= WXK_SPECIAL1 
&& keycode 
<= WXK_SPECIAL20
) 
6343         WinCEUnregisterHotKey(win_modifiers
, hotkeyId
); 
6346     if ( !::RegisterHotKey(GetHwnd(), hotkeyId
, win_modifiers
, keycode
) ) 
6348         wxLogLastError(_T("RegisterHotKey")); 
6356 bool wxWindowMSW::UnregisterHotKey(int hotkeyId
) 
6358 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
6359     WinCEUnregisterHotKey(MOD_WIN
, hotkeyId
); 
6362     if ( !::UnregisterHotKey(GetHwnd(), hotkeyId
) ) 
6364         wxLogLastError(_T("UnregisterHotKey")); 
6374 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam
, WXLPARAM lParam
) 
6376     int hotkeyId 
= wParam
; 
6377     int virtualKey 
= HIWORD(lParam
); 
6378     int win_modifiers 
= LOWORD(lParam
); 
6380     wxKeyEvent 
event(CreateKeyEvent(wxEVT_HOTKEY
, virtualKey
, wParam
, lParam
)); 
6381     event
.SetId(hotkeyId
); 
6382     event
.m_shiftDown 
= (win_modifiers 
& MOD_SHIFT
) != 0; 
6383     event
.m_controlDown 
= (win_modifiers 
& MOD_CONTROL
) != 0; 
6384     event
.m_altDown 
= (win_modifiers 
& MOD_ALT
) != 0; 
6385     event
.m_metaDown 
= (win_modifiers 
& MOD_WIN
) != 0; 
6387     return GetEventHandler()->ProcessEvent(event
); 
6390 #endif // wxUSE_ACCEL 
6392 #endif // wxUSE_HOTKEY 
6394 // Not tested under WinCE 
6397 // this class installs a message hook which really wakes up our idle processing 
6398 // each time a WM_NULL is received (wxWakeUpIdle does this), even if we're 
6399 // sitting inside a local modal loop (e.g. a menu is opened or scrollbar is 
6400 // being dragged or even inside ::MessageBox()) and so don't control message 
6401 // dispatching otherwise 
6402 class wxIdleWakeUpModule 
: public wxModule
 
6405     virtual bool OnInit() 
6407         ms_hMsgHookProc 
= ::SetWindowsHookEx
 
6410                              &wxIdleWakeUpModule::MsgHookProc
, 
6412                              GetCurrentThreadId() 
6415         if ( !ms_hMsgHookProc 
) 
6417             wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)")); 
6425     virtual void OnExit() 
6427         ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc
); 
6430     static LRESULT CALLBACK 
MsgHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
) 
6432         MSG 
*msg 
= (MSG
*)lParam
; 
6434         // only process the message if it is actually going to be removed from 
6435         // the message queue, this prevents that the same event from being 
6436         // processed multiple times if now someone just called PeekMessage() 
6437         if ( msg
->message 
== WM_NULL 
&& wParam 
== PM_REMOVE 
) 
6439             wxTheApp
->ProcessPendingEvents(); 
6442         return CallNextHookEx(ms_hMsgHookProc
, nCode
, wParam
, lParam
); 
6446     static HHOOK ms_hMsgHookProc
; 
6448     DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule
) 
6451 HHOOK 
wxIdleWakeUpModule::ms_hMsgHookProc 
= 0; 
6453 IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule
, wxModule
) 
6455 #endif // __WXWINCE__ 
6460 static void wxAdjustZOrder(wxWindow
* parent
) 
6462     if (parent
->IsKindOf(CLASSINFO(wxStaticBox
))) 
6464         // Set the z-order correctly 
6465         SetWindowPos((HWND
) parent
->GetHWND(), HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
); 
6468     wxWindowList::compatibility_iterator current 
= parent
->GetChildren().GetFirst(); 
6471         wxWindow 
*childWin 
= current
->GetData(); 
6472         wxAdjustZOrder(childWin
); 
6473         current 
= current
->GetNext(); 
6478 // We need to adjust the z-order of static boxes in WinCE, to 
6479 // make 'contained' controls visible 
6480 void wxWindowMSW::OnInitDialog( wxInitDialogEvent
& event 
) 
6483     wxAdjustZOrder(this);