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" 
  31     #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly" 
  32     #include "wx/msw/missing.h" 
  36     #include "wx/dcclient.h" 
  37     #include "wx/dcmemory.h" 
  40     #include "wx/layout.h" 
  41     #include "wx/dialog.h" 
  43     #include "wx/listbox.h" 
  44     #include "wx/button.h" 
  45     #include "wx/msgdlg.h" 
  46     #include "wx/settings.h" 
  47     #include "wx/statbox.h" 
  51     #include "wx/textctrl.h" 
  52     #include "wx/menuitem.h" 
  53     #include "wx/module.h" 
  56 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__) 
  57     #include "wx/ownerdrw.h" 
  60 #include "wx/hashmap.h" 
  61 #include "wx/evtloop.h" 
  63 #include "wx/sysopt.h" 
  65 #if wxUSE_DRAG_AND_DROP 
  69 #if wxUSE_ACCESSIBILITY 
  70     #include "wx/access.h" 
  74         #define WM_GETOBJECT 0x003D 
  77         #define OBJID_CLIENT 0xFFFFFFFC 
  81 #include "wx/msw/private.h" 
  82 #include "wx/msw/private/keyboard.h" 
  83 #include "wx/msw/dcclient.h" 
  86     #include "wx/tooltip.h" 
  94     #include "wx/radiobox.h" 
  95 #endif // wxUSE_RADIOBOX 
  98     #include "wx/spinctrl.h" 
  99 #endif // wxUSE_SPINCTRL 
 101 #include "wx/notebook.h" 
 102 #include "wx/listctrl.h" 
 103 #include "wx/dynlib.h" 
 107 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) 
 108     #include <shellapi.h> 
 109     #include <mmsystem.h> 
 113     #include <windowsx.h> 
 116 #if defined(__WXWINCE__) 
 117     #include "wx/msw/wince/missing.h" 
 120     #include <shellapi.h> 
 122     #include <aygshell.h> 
 127     #include "wx/msw/uxtheme.h" 
 128     #define EP_EDITTEXT         1 
 131     #define ETS_SELECTED        3 
 132     #define ETS_DISABLED        4 
 133     #define ETS_FOCUSED         5 
 134     #define ETS_READONLY        6 
 138 // define the constants used by AnimateWindow() if our SDK doesn't have them 
 140     #define AW_HOR_POSITIVE 0x00000001 
 141     #define AW_HOR_NEGATIVE 0x00000002 
 142     #define AW_VER_POSITIVE 0x00000004 
 143     #define AW_VER_NEGATIVE 0x00000008 
 144     #define AW_CENTER       0x00000010 
 145     #define AW_HIDE         0x00010000 
 146     #define AW_ACTIVATE     0x00020000 
 147     #define AW_SLIDE        0x00040000 
 148     #define AW_BLEND        0x00080000 
 151 #if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS 
 152     #define HAVE_TRACKMOUSEEVENT 
 153 #endif // everything needed for TrackMouseEvent() 
 155 // set this to 1 to filter out duplicate mouse events, e.g. mouse move events 
 156 // when mouse position didnd't change 
 158     #define wxUSE_MOUSEEVENT_HACK 0 
 160     #define wxUSE_MOUSEEVENT_HACK 1 
 163 // not all compilers/platforms have X button related declarations (notably 
 164 // Windows CE doesn't, and probably some old SDKs don't neither) 
 165 #ifdef WM_XBUTTONDOWN 
 166     #define wxHAS_XBUTTON 
 169 #ifndef MAPVK_VK_TO_CHAR 
 170     #define MAPVK_VK_TO_CHAR 2 
 173 // --------------------------------------------------------------------------- 
 175 // --------------------------------------------------------------------------- 
 177 #if wxUSE_MENUS_NATIVE 
 178 extern wxMenu 
*wxCurrentPopupMenu
; 
 182 // This is a hack used by the owner-drawn wxButton implementation to ensure 
 183 // that the brush used for erasing its background is correctly aligned with the 
 185 wxWindowMSW 
*wxWindowBeingErased 
= NULL
; 
 186 #endif // wxUSE_UXTHEME 
 191 // true if we had already created the std colour map, used by 
 192 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT) 
 193 bool gs_hasStdCmap 
= false; 
 195 // last mouse event information we need to filter out the duplicates 
 196 #if wxUSE_MOUSEEVENT_HACK 
 197 struct MouseEventInfoDummy
 
 199     // mouse position (in screen coordinates) 
 202     // last mouse event type 
 205 #endif // wxUSE_MOUSEEVENT_HACK 
 207 // hash containing the registered handlers for the custom messages 
 208 WX_DECLARE_HASH_MAP(int, wxWindow::MSWMessageHandler
, 
 209                     wxIntegerHash
, wxIntegerEqual
, 
 212 MSWMessageHandlers gs_messageHandlers
; 
 214 // hash containing all our windows, it uses HWND keys and wxWindow* values 
 215 WX_DECLARE_HASH_MAP(HWND
, wxWindow 
*, 
 216                     wxPointerHash
, wxPointerEqual
, 
 219 WindowHandles gs_windowHandles
; 
 221 #ifdef wxHAS_MSW_BACKGROUND_ERASE_HOOK 
 223 // temporary override for WM_ERASEBKGND processing: we don't store this in 
 224 // wxWindow itself as we don't need it during most of the time so don't 
 225 // increase the size of all window objects unnecessarily 
 226 WX_DECLARE_HASH_MAP(wxWindow 
*, wxWindow 
*, 
 227                     wxPointerHash
, wxPointerEqual
, 
 230 EraseBgHooks gs_eraseBgHooks
; 
 232 #endif // wxHAS_MSW_BACKGROUND_ERASE_HOOK 
 234 // If this variable is strictly positive, EVT_CHAR_HOOK is not generated for 
 235 // Escape key presses as it can't be intercepted because it's needed by some 
 236 // currently shown window, e.g. IME entry. 
 238 // This is currently global as we allow using UI from the main thread only 
 239 // anyhow but could be replaced with a thread-specific value in the future if 
 241 int gs_modalEntryWindowCount 
= 0; 
 243 } // anonymous namespace 
 245 // --------------------------------------------------------------------------- 
 247 // --------------------------------------------------------------------------- 
 249 // the window proc for all our windows 
 250 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
 251                                    WPARAM wParam
, LPARAM lParam
); 
 254 #if wxDEBUG_LEVEL >= 2 
 255     const wxChar 
*wxGetMessageName(int message
); 
 256 #endif  // wxDEBUG_LEVEL >= 2 
 258 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 259 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 261 // get the text metrics for the current font 
 262 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
); 
 265 // find the window for the mouse event at the specified position 
 266 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
); 
 267 #endif // __WXWINCE__ 
 269 // wrapper around BringWindowToTop() API 
 270 static inline void wxBringWindowToTop(HWND hwnd
) 
 272 #ifdef __WXMICROWIN__ 
 273     // It seems that MicroWindows brings the _parent_ of the window to the top, 
 274     // which can be the wrong one. 
 276     // activate (set focus to) specified window 
 280     // raise top level parent to top of z order 
 281     if (!::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE 
| SWP_NOSIZE
)) 
 283         wxLogLastError(wxT("SetWindowPos")); 
 289 // ensure that all our parent windows have WS_EX_CONTROLPARENT style 
 290 static void EnsureParentHasControlParentStyle(wxWindow 
*parent
) 
 293        If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our 
 294        parent as well as otherwise several Win32 functions using 
 295        GetNextDlgTabItem() to iterate over all controls such as 
 296        IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, 
 297        all of them iterate over all the controls starting from the currently 
 298        focused one and stop iterating when they get back to the focus but 
 299        unless all parents have WS_EX_CONTROLPARENT bit set, they would never 
 300        get back to the initial (focused) window: as we do have this style, 
 301        GetNextDlgTabItem() will leave this window and continue in its parent, 
 302        but if the parent doesn't have it, it wouldn't recurse inside it later 
 303        on and so wouldn't have a chance of getting back to this window either. 
 305     while ( parent 
&& !parent
->IsTopLevel() ) 
 307         LONG exStyle 
= wxGetWindowExStyle(parent
); 
 308         if ( !(exStyle 
& WS_EX_CONTROLPARENT
) ) 
 310             // force the parent to have this style 
 311             wxSetWindowExStyle(parent
, exStyle 
| WS_EX_CONTROLPARENT
); 
 314         parent 
= parent
->GetParent(); 
 318 #endif // !__WXWINCE__ 
 320 // GetCursorPos can return an error, so use this function 
 322 // Error originally observed with WinCE, but later using Remote Desktop 
 324 void wxGetCursorPosMSW(POINT
* pt
) 
 326     if (!GetCursorPos(pt
)) 
 329         wxLogLastError(wxT("GetCursorPos")); 
 331         DWORD pos 
= GetMessagePos(); 
 332         // the coordinates may be negative in multi-monitor systems 
 333         pt
->x 
= GET_X_LPARAM(pos
); 
 334         pt
->y 
= GET_Y_LPARAM(pos
); 
 338 // --------------------------------------------------------------------------- 
 340 // --------------------------------------------------------------------------- 
 342 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
 344 #ifdef __WXUNIVERSAL__ 
 345     IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
) 
 346 #endif // __WXUNIVERSAL__ 
 348 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
) 
 349     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
) 
 351     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
) 
 355 // =========================================================================== 
 357 // =========================================================================== 
 359 // --------------------------------------------------------------------------- 
 360 // wxWindow utility functions 
 361 // --------------------------------------------------------------------------- 
 363 // Find an item given the MS Windows id 
 364 wxWindow 
*wxWindowMSW::FindItem(long id
) const 
 367     wxControl 
*item 
= wxDynamicCastThis(wxControl
); 
 370         // is it us or one of our "internal" children? 
 371         if ( item
->GetId() == id
 
 372 #ifndef __WXUNIVERSAL__ 
 373                 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
) 
 374 #endif // __WXUNIVERSAL__ 
 380 #endif // wxUSE_CONTROLS 
 382     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 385         wxWindow 
*childWin 
= current
->GetData(); 
 387         wxWindow 
*wnd 
= childWin
->FindItem(id
); 
 391         current 
= current
->GetNext(); 
 397 // Find an item given the MS Windows handle 
 398 wxWindow 
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const 
 400     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 403         wxWindow 
*parent 
= current
->GetData(); 
 405         // Do a recursive search. 
 406         wxWindow 
*wnd 
= parent
->FindItemByHWND(hWnd
); 
 412                 || parent
->IsKindOf(CLASSINFO(wxControl
)) 
 413 #endif // wxUSE_CONTROLS 
 416             wxWindow 
*item 
= current
->GetData(); 
 417             if ( item
->GetHWND() == hWnd 
) 
 421                 if ( item
->ContainsHWND(hWnd
) ) 
 426         current 
= current
->GetNext(); 
 431 // Default command handler 
 432 bool wxWindowMSW::MSWCommand(WXUINT 
WXUNUSED(param
), WXWORD 
WXUNUSED(id
)) 
 437 // ---------------------------------------------------------------------------- 
 438 // constructors and such 
 439 // ---------------------------------------------------------------------------- 
 441 void wxWindowMSW::Init() 
 445     m_mouseInWindow 
= false; 
 446     m_lastKeydownProcessed 
= false; 
 453 #if wxUSE_DEFERRED_SIZING 
 455     m_pendingPosition 
= wxDefaultPosition
; 
 456     m_pendingSize 
= wxDefaultSize
; 
 457 #endif // wxUSE_DEFERRED_SIZING 
 460     m_contextMenuEnabled 
= false; 
 465 wxWindowMSW::~wxWindowMSW() 
 469 #ifndef __WXUNIVERSAL__ 
 470     // VS: make sure there's no wxFrame with last focus set to us: 
 471     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
 473         wxTopLevelWindow 
*frame 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 476             if ( frame
->GetLastFocus() == this ) 
 478                 frame
->SetLastFocus(NULL
); 
 481             // apparently sometimes we can end up with our grand parent 
 482             // pointing to us as well: this is surely a bug in focus handling 
 483             // code but it's not clear where it happens so for now just try to 
 484             // fix it here by not breaking out of the loop 
 488 #endif // __WXUNIVERSAL__ 
 490     // VS: destroy children first and _then_ detach *this from its parent. 
 491     //     If we did it the other way around, children wouldn't be able 
 492     //     find their parent frame (see above). 
 497         // VZ: test temp removed to understand what really happens here 
 498         //if (::IsWindow(GetHwnd())) 
 500             if ( !::DestroyWindow(GetHwnd()) ) 
 502                 wxLogLastError(wxT("DestroyWindow")); 
 506         // remove hWnd <-> wxWindow association 
 507         wxRemoveHandleAssociation(this); 
 513 const wxChar 
*wxWindowMSW::MSWGetRegisteredClassName() 
 515     return wxApp::GetRegisteredClassName(wxT("wxWindow"), COLOR_BTNFACE
); 
 518 // real construction (Init() must have been called before!) 
 519 bool wxWindowMSW::Create(wxWindow 
*parent
, 
 524                          const wxString
& name
) 
 526     wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") ); 
 528     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 531     parent
->AddChild(this); 
 534     DWORD msflags 
= MSWGetCreateWindowFlags(&exstyle
); 
 536 #ifdef __WXUNIVERSAL__ 
 537     // no borders, we draw them ourselves 
 538     exstyle 
&= ~(WS_EX_DLGMODALFRAME 
| 
 542     msflags 
&= ~WS_BORDER
; 
 543 #endif // wxUniversal 
 547         msflags 
|= WS_VISIBLE
; 
 550     if ( !MSWCreate(MSWGetRegisteredClassName(), 
 551                     NULL
, pos
, size
, msflags
, exstyle
) ) 
 559 // --------------------------------------------------------------------------- 
 561 // --------------------------------------------------------------------------- 
 563 void wxWindowMSW::SetFocus() 
 565     HWND hWnd 
= GetHwnd(); 
 566     wxCHECK_RET( hWnd
, wxT("can't set focus to invalid window") ); 
 568 #if !defined(__WXWINCE__) 
 572     if ( !::SetFocus(hWnd
) ) 
 574         // was there really an error? 
 575         DWORD dwRes 
= ::GetLastError(); 
 578             HWND hwndFocus 
= ::GetFocus(); 
 579             if ( hwndFocus 
!= hWnd 
) 
 581                 wxLogApiError(wxT("SetFocus"), dwRes
); 
 587 void wxWindowMSW::SetFocusFromKbd() 
 589     // when the focus is given to the control with DLGC_HASSETSEL style from 
 590     // keyboard its contents should be entirely selected: this is what 
 591     // ::IsDialogMessage() does and so we should do it as well to provide the 
 592     // same LNF as the native programs 
 593     if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL 
) 
 595         ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1); 
 598     // do this after (maybe) setting the selection as like this when 
 599     // wxEVT_SET_FOCUS handler is called, the selection would have been already 
 600     // set correctly -- this may be important 
 601     wxWindowBase::SetFocusFromKbd(); 
 604 // Get the window with the focus 
 605 wxWindow 
*wxWindowBase::DoFindFocus() 
 607     HWND hWnd 
= ::GetFocus(); 
 610         return wxGetWindowFromHWND((WXHWND
)hWnd
); 
 616 void wxWindowMSW::DoEnable( bool enable 
) 
 618     MSWEnableHWND(GetHwnd(), enable
); 
 621 bool wxWindowMSW::MSWEnableHWND(WXHWND hWnd
, bool enable
) 
 626     // If disabling focused control, we move focus to the next one, as if the 
 627     // user pressed Tab. That's because we can't keep focus on a disabled 
 628     // control, Tab-navigation would stop working then. 
 629     if ( !enable 
&& ::GetFocus() == hWnd 
) 
 632     return ::EnableWindow(hWnd
, (BOOL
)enable
) != 0; 
 635 bool wxWindowMSW::Show(bool show
) 
 637     if ( !wxWindowBase::Show(show
) ) 
 640     HWND hWnd 
= GetHwnd(); 
 642     // we could be called before the underlying window is created (this is 
 643     // actually useful to prevent it from being initially shown), e.g. 
 645     //      wxFoo *foo = new wxFoo; 
 647     //      foo->Create(parent, ...); 
 649     // should work without errors 
 652         ::ShowWindow(hWnd
, show 
? SW_SHOW 
: SW_HIDE
); 
 657         // DoFreeze/DoThaw don't do anything if the window is not shown, so 
 658         // we have to call them from here now 
 669 wxWindowMSW::MSWShowWithEffect(bool show
, 
 673     if ( effect 
== wxSHOW_EFFECT_NONE 
) 
 676     if ( !wxWindowBase::Show(show
) ) 
 679     typedef BOOL (WINAPI 
*AnimateWindow_t
)(HWND
, DWORD
, DWORD
); 
 681     static AnimateWindow_t s_pfnAnimateWindow 
= NULL
; 
 682     static bool s_initDone 
= false; 
 685         wxDynamicLibrary 
dllUser32(wxT("user32.dll"), wxDL_VERBATIM 
| wxDL_QUIET
); 
 686         wxDL_INIT_FUNC(s_pfn
, AnimateWindow
, dllUser32
); 
 690         // notice that it's ok to unload user32.dll here as it won't be really 
 691         // unloaded, being still in use because we link to it statically too 
 694     if ( !s_pfnAnimateWindow 
) 
 697     // Show() has a side effect of sending a WM_SIZE to the window, which helps 
 698     // ensuring that it's laid out correctly, but AnimateWindow() doesn't do 
 699     // this so send the event ourselves 
 702     // prepare to use AnimateWindow() 
 705         timeout 
= 200; // this is the default animation timeout, per MSDN 
 707     DWORD dwFlags 
= show 
? 0 : AW_HIDE
; 
 711         case wxSHOW_EFFECT_ROLL_TO_LEFT
: 
 712             dwFlags 
|= AW_HOR_NEGATIVE
; 
 715         case wxSHOW_EFFECT_ROLL_TO_RIGHT
: 
 716             dwFlags 
|= AW_HOR_POSITIVE
; 
 719         case wxSHOW_EFFECT_ROLL_TO_TOP
: 
 720             dwFlags 
|= AW_VER_NEGATIVE
; 
 723         case wxSHOW_EFFECT_ROLL_TO_BOTTOM
: 
 724             dwFlags 
|= AW_VER_POSITIVE
; 
 727         case wxSHOW_EFFECT_SLIDE_TO_LEFT
: 
 728             dwFlags 
|= AW_SLIDE 
| AW_HOR_NEGATIVE
; 
 731         case wxSHOW_EFFECT_SLIDE_TO_RIGHT
: 
 732             dwFlags 
|= AW_SLIDE 
| AW_HOR_POSITIVE
; 
 735         case wxSHOW_EFFECT_SLIDE_TO_TOP
: 
 736             dwFlags 
|= AW_SLIDE 
| AW_VER_NEGATIVE
; 
 739         case wxSHOW_EFFECT_SLIDE_TO_BOTTOM
: 
 740             dwFlags 
|= AW_SLIDE 
| AW_VER_POSITIVE
; 
 743         case wxSHOW_EFFECT_BLEND
: 
 747         case wxSHOW_EFFECT_EXPAND
: 
 748             dwFlags 
|= AW_CENTER
; 
 752         case wxSHOW_EFFECT_MAX
: 
 753             wxFAIL_MSG( wxT("invalid window show effect") ); 
 757             wxFAIL_MSG( wxT("unknown window show effect") ); 
 761     if ( !(*s_pfnAnimateWindow
)(GetHwnd(), timeout
, dwFlags
) ) 
 763         wxLogLastError(wxT("AnimateWindow")); 
 771 // Raise the window to the top of the Z order 
 772 void wxWindowMSW::Raise() 
 774     wxBringWindowToTop(GetHwnd()); 
 777 // Lower the window to the bottom of the Z order 
 778 void wxWindowMSW::Lower() 
 780     ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0, 
 781                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
 784 void wxWindowMSW::DoCaptureMouse() 
 786     HWND hWnd 
= GetHwnd(); 
 793 void wxWindowMSW::DoReleaseMouse() 
 795     if ( !::ReleaseCapture() ) 
 797         wxLogLastError(wxT("ReleaseCapture")); 
 801 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 803     HWND hwnd 
= ::GetCapture(); 
 804     return hwnd 
? wxFindWinFromHandle(hwnd
) : NULL
; 
 807 bool wxWindowMSW::SetFont(const wxFont
& font
) 
 809     if ( !wxWindowBase::SetFont(font
) ) 
 815     HWND hWnd 
= GetHwnd(); 
 818         // note the use of GetFont() instead of m_font: our own font could have 
 819         // just been reset and in this case we need to change the font used by 
 820         // the native window to the default for this class, i.e. exactly what 
 822         WXHANDLE hFont 
= GetFont().GetResourceHandle(); 
 824         wxASSERT_MSG( hFont
, wxT("should have valid font") ); 
 826         ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0)); 
 832 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
) 
 834     if ( !wxWindowBase::SetCursor(cursor
) ) 
 840     // don't "overwrite" busy cursor 
 844     if ( m_cursor
.IsOk() ) 
 846         // normally we should change the cursor only if it's over this window 
 847         // but we should do it always if we capture the mouse currently 
 848         bool set 
= HasCapture(); 
 851             HWND hWnd 
= GetHwnd(); 
 854             ::wxGetCursorPosMSW(&point
); 
 856             RECT rect 
= wxGetWindowRect(hWnd
); 
 858             set 
= ::PtInRect(&rect
, point
) != 0; 
 863             ::SetCursor(GetHcursorOf(m_cursor
)); 
 865         //else: will be set later when the mouse enters this window 
 867     else // Invalid cursor: this means reset to the default one. 
 869         // To revert to the correct cursor we need to find the window currently 
 870         // under the cursor and ask it to set its cursor itself as only it 
 873         wxGetCursorPosMSW(&pt
); 
 875         const wxWindowMSW
* win 
= wxFindWindowAtPoint(wxPoint(pt
.x
, pt
.y
)); 
 879         ::SendMessage(GetHwndOf(win
), WM_SETCURSOR
, 
 880                       (WPARAM
)GetHwndOf(win
), 
 881                       MAKELPARAM(HTCLIENT
, WM_MOUSEMOVE
)); 
 887 void wxWindowMSW::WarpPointer(int x
, int y
) 
 889     ClientToScreen(&x
, &y
); 
 891     if ( !::SetCursorPos(x
, y
) ) 
 893         wxLogLastError(wxT("SetCursorPos")); 
 897 void wxWindowMSW::MSWUpdateUIState(int action
, int state
) 
 899     // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good 
 900     // to use it on older systems -- and could possibly do some harm 
 901     static int s_needToUpdate 
= -1; 
 902     if ( s_needToUpdate 
== -1 ) 
 905         s_needToUpdate 
= wxGetOsVersion(&verMaj
, &verMin
) == wxOS_WINDOWS_NT 
&& 
 909     if ( s_needToUpdate 
) 
 911         // we send WM_CHANGEUISTATE so if nothing needs changing then the system 
 912         // won't send WM_UPDATEUISTATE 
 913         ::SendMessage(GetHwnd(), WM_CHANGEUISTATE
, MAKEWPARAM(action
, state
), 0); 
 917 // --------------------------------------------------------------------------- 
 919 // --------------------------------------------------------------------------- 
 924 inline int GetScrollPosition(HWND hWnd
, int wOrient
) 
 926 #ifdef __WXMICROWIN__ 
 927     return ::GetScrollPosWX(hWnd
, wOrient
); 
 929     WinStruct
<SCROLLINFO
> scrollInfo
; 
 930     scrollInfo
.cbSize 
= sizeof(SCROLLINFO
); 
 931     scrollInfo
.fMask 
= SIF_POS
; 
 932     ::GetScrollInfo(hWnd
, wOrient
, &scrollInfo 
); 
 934     return scrollInfo
.nPos
; 
 939 inline UINT 
WXOrientToSB(int orient
) 
 941     return orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
; 
 944 } // anonymous namespace 
 946 int wxWindowMSW::GetScrollPos(int orient
) const 
 948     HWND hWnd 
= GetHwnd(); 
 949     wxCHECK_MSG( hWnd
, 0, wxT("no HWND in GetScrollPos") ); 
 951     return GetScrollPosition(hWnd
, WXOrientToSB(orient
)); 
 954 // This now returns the whole range, not just the number 
 955 // of positions that we can scroll. 
 956 int wxWindowMSW::GetScrollRange(int orient
) const 
 959     HWND hWnd 
= GetHwnd(); 
 962     WinStruct
<SCROLLINFO
> scrollInfo
; 
 963     scrollInfo
.fMask 
= SIF_RANGE
; 
 964     if ( !::GetScrollInfo(hWnd
, WXOrientToSB(orient
), &scrollInfo
) ) 
 966         // Most of the time this is not really an error, since the return 
 967         // value can also be zero when there is no scrollbar yet. 
 968         // wxLogLastError(wxT("GetScrollInfo")); 
 970     maxPos 
= scrollInfo
.nMax
; 
 972     // undo "range - 1" done in SetScrollbar() 
 976 int wxWindowMSW::GetScrollThumb(int orient
) const 
 978     return orient 
== wxHORIZONTAL 
? m_xThumbSize 
: m_yThumbSize
; 
 981 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
) 
 983     HWND hWnd 
= GetHwnd(); 
 984     wxCHECK_RET( hWnd
, wxT("SetScrollPos: no HWND") ); 
 986     WinStruct
<SCROLLINFO
> info
; 
 990     info
.fMask 
= SIF_POS
; 
 991     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 993         // disable scrollbar instead of removing it then 
 994         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 997     ::SetScrollInfo(hWnd
, WXOrientToSB(orient
), &info
, refresh
); 
1000 // New function that will replace some of the above. 
1001 void wxWindowMSW::SetScrollbar(int orient
, 
1007     // We have to set the variables here to make them valid in events 
1008     // triggered by ::SetScrollInfo() 
1009     *(orient 
== wxHORIZONTAL 
? &m_xThumbSize 
: &m_yThumbSize
) = pageSize
; 
1011     HWND hwnd 
= GetHwnd(); 
1015     WinStruct
<SCROLLINFO
> info
; 
1018         info
.nPage 
= pageSize
; 
1019         info
.nMin 
= 0;              // range is nMax - nMin + 1 
1020         info
.nMax 
= range 
- 1;      //  as both nMax and nMax are inclusive 
1023         // We normally also reenable scrollbar in case it had been previously 
1024         // disabled by specifying SIF_DISABLENOSCROLL below but we should only 
1025         // do this if it has valid range, otherwise it would be enabled but not 
1027         if ( range 
>= pageSize 
) 
1029             ::EnableScrollBar(hwnd
, WXOrientToSB(orient
), ESB_ENABLE_BOTH
); 
1032     //else: leave all the fields to be 0 
1034     info
.fMask 
= SIF_RANGE 
| SIF_PAGE 
| SIF_POS
; 
1035     if ( HasFlag(wxALWAYS_SHOW_SB
) || range 
== -1 ) 
1037         // disable scrollbar instead of removing it then 
1038         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
1041     ::SetScrollInfo(hwnd
, WXOrientToSB(orient
), &info
, refresh
); 
1044 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect 
*prect
) 
1050         wxCopyRectToRECT(*prect
, rect
); 
1060     // FIXME: is this the exact equivalent of the line below? 
1061     ::ScrollWindowEx(GetHwnd(), dx
, dy
, pr
, pr
, 0, 0, SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
); 
1063     ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
); 
1067 static bool ScrollVertically(HWND hwnd
, int kind
, int count
) 
1069     int posStart 
= GetScrollPosition(hwnd
, SB_VERT
); 
1072     for ( int n 
= 0; n 
< count
; n
++ ) 
1074         ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0); 
1076         int posNew 
= GetScrollPosition(hwnd
, SB_VERT
); 
1077         if ( posNew 
== pos 
) 
1079             // don't bother to continue, we're already at top/bottom 
1086     return pos 
!= posStart
; 
1089 bool wxWindowMSW::ScrollLines(int lines
) 
1091     bool down 
= lines 
> 0; 
1093     return ScrollVertically(GetHwnd(), 
1094                             down 
? SB_LINEDOWN 
: SB_LINEUP
, 
1095                             down 
? lines 
: -lines
); 
1098 bool wxWindowMSW::ScrollPages(int pages
) 
1100     bool down 
= pages 
> 0; 
1102     return ScrollVertically(GetHwnd(), 
1103                             down 
? SB_PAGEDOWN 
: SB_PAGEUP
, 
1104                             down 
? pages 
: -pages
); 
1107 // ---------------------------------------------------------------------------- 
1109 // ---------------------------------------------------------------------------- 
1111 void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir
) 
1116     wxCHECK_RET( GetHwnd(), 
1117                  wxT("layout direction must be set after window creation") ); 
1119     LONG styleOld 
= wxGetWindowExStyle(this); 
1121     LONG styleNew 
= styleOld
; 
1124         case wxLayout_LeftToRight
: 
1125             styleNew 
&= ~WS_EX_LAYOUTRTL
; 
1128         case wxLayout_RightToLeft
: 
1129             styleNew 
|= WS_EX_LAYOUTRTL
; 
1133             wxFAIL_MSG(wxT("unsupported layout direction")); 
1137     if ( styleNew 
!= styleOld 
) 
1139         wxSetWindowExStyle(this, styleNew
); 
1144 wxLayoutDirection 
wxWindowMSW::GetLayoutDirection() const 
1147     return wxLayout_Default
; 
1149     wxCHECK_MSG( GetHwnd(), wxLayout_Default
, wxT("invalid window") ); 
1151     return wxHasWindowExStyle(this, WS_EX_LAYOUTRTL
) ? wxLayout_RightToLeft
 
1152                                                      : wxLayout_LeftToRight
; 
1157 wxWindowMSW::AdjustForLayoutDirection(wxCoord x
, 
1158                                       wxCoord 
WXUNUSED(width
), 
1159                                       wxCoord 
WXUNUSED(widthTotal
)) const 
1161     // Win32 mirrors the coordinates of RTL windows automatically, so don't 
1162     // redo it ourselves 
1166 // --------------------------------------------------------------------------- 
1168 // --------------------------------------------------------------------------- 
1170 void wxWindowMSW::SubclassWin(WXHWND hWnd
) 
1172     wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") ); 
1174     HWND hwnd 
= (HWND
)hWnd
; 
1175     wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") ); 
1179     wxAssociateWinWithHandle(hwnd
, this); 
1181     m_oldWndProc 
= (WXFARPROC
)wxGetWindowProc((HWND
)hWnd
); 
1183     // we don't need to subclass the window of our own class (in the Windows 
1184     // sense of the word) 
1185     if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) ) 
1187         wxSetWindowProc(hwnd
, wxWndProc
); 
1191         // don't bother restoring it either: this also makes it easy to 
1192         // implement IsOfStandardClass() method which returns true for the 
1193         // standard controls and false for the wxWidgets own windows as it can 
1194         // simply check m_oldWndProc 
1195         m_oldWndProc 
= NULL
; 
1198     // we're officially created now, send the event 
1199     wxWindowCreateEvent 
event((wxWindow 
*)this); 
1200     (void)HandleWindowEvent(event
); 
1203 void wxWindowMSW::UnsubclassWin() 
1205     wxRemoveHandleAssociation(this); 
1207     // Restore old Window proc 
1208     HWND hwnd 
= GetHwnd(); 
1213         wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") ); 
1217             if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) ) 
1219                 wxSetWindowProc(hwnd
, (WNDPROC
)m_oldWndProc
); 
1222             m_oldWndProc 
= NULL
; 
1227 void wxWindowMSW::AssociateHandle(WXWidget handle
) 
1231       if ( !::DestroyWindow(GetHwnd()) ) 
1233         wxLogLastError(wxT("DestroyWindow")); 
1237     WXHWND wxhwnd 
= (WXHWND
)handle
; 
1239     // this also calls SetHWND(wxhwnd) 
1240     SubclassWin(wxhwnd
); 
1243 void wxWindowMSW::DissociateHandle() 
1245     // this also calls SetHWND(0) for us 
1250 bool wxCheckWindowWndProc(WXHWND hWnd
, 
1251                           WXFARPROC 
WXUNUSED(wndProc
)) 
1253     const wxString 
str(wxGetWindowClass(hWnd
)); 
1255     // TODO: get rid of wxTLWHiddenParent special case (currently it's not 
1256     //       registered by wxApp but using ad hoc code in msw/toplevel.cpp); 
1257     //       there is also a hidden window class used by sockets &c 
1258     return wxApp::IsRegisteredClassName(str
) || str 
== wxT("wxTLWHiddenParent"); 
1261 // ---------------------------------------------------------------------------- 
1263 // ---------------------------------------------------------------------------- 
1265 void wxWindowMSW::SetWindowStyleFlag(long flags
) 
1267     long flagsOld 
= GetWindowStyleFlag(); 
1268     if ( flags 
== flagsOld 
) 
1271     // update the internal variable 
1272     wxWindowBase::SetWindowStyleFlag(flags
); 
1274     // and the real window flags 
1275     MSWUpdateStyle(flagsOld
, GetExtraStyle()); 
1278 void wxWindowMSW::SetExtraStyle(long exflags
) 
1280     long exflagsOld 
= GetExtraStyle(); 
1281     if ( exflags 
== exflagsOld 
) 
1284     // update the internal variable 
1285     wxWindowBase::SetExtraStyle(exflags
); 
1287     // and the real window flags 
1288     MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld
); 
1291 void wxWindowMSW::MSWUpdateStyle(long flagsOld
, long exflagsOld
) 
1293     // now update the Windows style as well if needed - and if the window had 
1294     // been already created 
1298     // we may need to call SetWindowPos() when we change some styles 
1299     bool callSWP 
= false; 
1302     long style 
= MSWGetStyle(GetWindowStyleFlag(), &exstyle
); 
1304     // this is quite a horrible hack but we need it because MSWGetStyle() 
1305     // doesn't take exflags as parameter but uses GetExtraStyle() internally 
1306     // and so we have to modify the window exflags temporarily to get the 
1307     // correct exstyleOld 
1308     long exflagsNew 
= GetExtraStyle(); 
1309     wxWindowBase::SetExtraStyle(exflagsOld
); 
1312     long styleOld 
= MSWGetStyle(flagsOld
, &exstyleOld
); 
1314     wxWindowBase::SetExtraStyle(exflagsNew
); 
1317     if ( style 
!= styleOld 
) 
1319         // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by 
1320         // this function so instead of simply setting the style to the new 
1321         // value we clear the bits which were set in styleOld but are set in 
1322         // the new one and set the ones which were not set before 
1323         long styleReal 
= ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
1324         styleReal 
&= ~styleOld
; 
1327         ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
); 
1329         // we need to call SetWindowPos() if any of the styles affecting the 
1330         // frame appearance have changed 
1331         callSWP 
= ((styleOld 
^ style 
) & (WS_BORDER 
| 
1340     // and the extended style 
1341     long exstyleReal 
= wxGetWindowExStyle(this); 
1343     if ( exstyle 
!= exstyleOld 
) 
1345         exstyleReal 
&= ~exstyleOld
; 
1346         exstyleReal 
|= exstyle
; 
1348         wxSetWindowExStyle(this, exstyleReal
); 
1350         // ex style changes don't take effect without calling SetWindowPos 
1356         // we must call SetWindowPos() to flush the cached extended style and 
1357         // also to make the change to wxSTAY_ON_TOP style take effect: just 
1358         // setting the style simply doesn't work 
1359         if ( !::SetWindowPos(GetHwnd(), 
1360                              exstyleReal 
& WS_EX_TOPMOST 
? HWND_TOPMOST
 
1363                              SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE 
| 
1366             wxLogLastError(wxT("SetWindowPos")); 
1371 wxBorder 
wxWindowMSW::GetDefaultBorderForControl() const 
1373     return wxBORDER_THEME
; 
1376 wxBorder 
wxWindowMSW::GetDefaultBorder() const 
1378     return wxWindowBase::GetDefaultBorder(); 
1381 // Translate wxBORDER_THEME (and other border styles if necessary) to the value 
1382 // that makes most sense for this Windows environment 
1383 wxBorder 
wxWindowMSW::TranslateBorder(wxBorder border
) const 
1385 #if defined(__POCKETPC__) || defined(__SMARTPHONE__) 
1386     if (border 
== wxBORDER_THEME 
|| border 
== wxBORDER_SUNKEN 
|| border 
== wxBORDER_SIMPLE
) 
1387         return wxBORDER_SIMPLE
; 
1389         return wxBORDER_NONE
; 
1392     if (border 
== wxBORDER_THEME
) 
1394         if (CanApplyThemeBorder()) 
1396             wxUxThemeEngine
* theme 
= wxUxThemeEngine::GetIfActive(); 
1398                 return wxBORDER_THEME
; 
1400         return wxBORDER_SUNKEN
; 
1408 WXDWORD 
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD 
*exstyle
) const 
1410     // translate common wxWidgets styles to Windows ones 
1412     // most of windows are child ones, those which are not (such as 
1413     // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle() 
1414     WXDWORD style 
= WS_CHILD
; 
1416     // using this flag results in very significant reduction in flicker, 
1417     // especially with controls inside the static boxes (as the interior of the 
1418     // box is not redrawn twice), but sometimes results in redraw problems, so 
1419     // optionally allow the old code to continue to use it provided a special 
1420     // system option is turned on 
1421     if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) 
1422             || (flags 
& wxCLIP_CHILDREN
) ) 
1423         style 
|= WS_CLIPCHILDREN
; 
1425     // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially 
1426     // don't support overlapping windows and it only makes sense for them and, 
1427     // presumably, gives the system some extra work (to manage more clipping 
1428     // regions), so avoid it alltogether 
1431     if ( flags 
& wxVSCROLL 
) 
1432         style 
|= WS_VSCROLL
; 
1434     if ( flags 
& wxHSCROLL 
) 
1435         style 
|= WS_HSCROLL
; 
1437     const wxBorder border 
= TranslateBorder(GetBorder(flags
)); 
1439     // After translation, border is now optimized for the specific version of Windows 
1440     // and theme engine presence. 
1442     // WS_BORDER is only required for wxBORDER_SIMPLE 
1443     if ( border 
== wxBORDER_SIMPLE 
) 
1446     // now deal with ext style if the caller wants it 
1452         if ( flags 
& wxTRANSPARENT_WINDOW 
) 
1453             *exstyle 
|= WS_EX_TRANSPARENT
; 
1459             case wxBORDER_DEFAULT
: 
1460                 wxFAIL_MSG( wxT("unknown border style") ); 
1464             case wxBORDER_SIMPLE
: 
1465             case wxBORDER_THEME
: 
1468             case wxBORDER_STATIC
: 
1469                 *exstyle 
|= WS_EX_STATICEDGE
; 
1472             case wxBORDER_RAISED
: 
1473                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1476             case wxBORDER_SUNKEN
: 
1477                 *exstyle 
|= WS_EX_CLIENTEDGE
; 
1478                 style 
&= ~WS_BORDER
; 
1481 //            case wxBORDER_DOUBLE: 
1482 //                *exstyle |= WS_EX_DLGMODALFRAME; 
1486         // wxUniv doesn't use Windows dialog navigation functions at all 
1487 #if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__) 
1488         // to make the dialog navigation work with the nested panels we must 
1489         // use this style (top level windows such as dialogs don't need it) 
1490         if ( (flags 
& wxTAB_TRAVERSAL
) && !IsTopLevel() ) 
1492             *exstyle 
|= WS_EX_CONTROLPARENT
; 
1494 #endif // __WXUNIVERSAL__ 
1500 // Setup background and foreground colours correctly 
1501 void wxWindowMSW::SetupColours() 
1504         SetBackgroundColour(GetParent()->GetBackgroundColour()); 
1507 bool wxWindowMSW::IsMouseInWindow() const 
1509     // get the mouse position 
1511     wxGetCursorPosMSW(&pt
); 
1513     // find the window which currently has the cursor and go up the window 
1514     // chain until we find this window - or exhaust it 
1515     HWND hwnd 
= ::WindowFromPoint(pt
); 
1516     while ( hwnd 
&& (hwnd 
!= GetHwnd()) ) 
1517         hwnd 
= ::GetParent(hwnd
); 
1519     return hwnd 
!= NULL
; 
1522 void wxWindowMSW::OnInternalIdle() 
1524 #ifndef HAVE_TRACKMOUSEEVENT 
1525     // Check if we need to send a LEAVE event 
1526     if ( m_mouseInWindow 
) 
1528         // note that we should generate the leave event whether the window has 
1529         // or doesn't have mouse capture 
1530         if ( !IsMouseInWindow() ) 
1532             GenerateMouseLeave(); 
1535 #endif // !HAVE_TRACKMOUSEEVENT 
1537     wxWindowBase::OnInternalIdle(); 
1540 // Set this window to be the child of 'parent'. 
1541 bool wxWindowMSW::Reparent(wxWindowBase 
*parent
) 
1543     if ( !wxWindowBase::Reparent(parent
) ) 
1546     HWND hWndChild 
= GetHwnd(); 
1547     HWND hWndParent 
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0; 
1549     ::SetParent(hWndChild
, hWndParent
); 
1552     if ( wxHasWindowExStyle(this, WS_EX_CONTROLPARENT
) ) 
1554         EnsureParentHasControlParentStyle(GetParent()); 
1556 #endif // !__WXWINCE__ 
1561 static inline void SendSetRedraw(HWND hwnd
, bool on
) 
1563 #ifndef __WXMICROWIN__ 
1564     ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0); 
1568 void wxWindowMSW::DoFreeze() 
1571         return; // no point in freezing hidden window 
1573     SendSetRedraw(GetHwnd(), false); 
1576 void wxWindowMSW::DoThaw() 
1579         return; // hidden windows aren't frozen by DoFreeze 
1581     SendSetRedraw(GetHwnd(), true); 
1583     // we need to refresh everything or otherwise the invalidated area 
1584     // is not going to be repainted 
1588 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1590     HWND hWnd 
= GetHwnd(); 
1597             wxCopyRectToRECT(*rect
, mswRect
); 
1605         // RedrawWindow not available on SmartPhone or eVC++ 3 
1606 #if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400) 
1607         UINT flags 
= RDW_INVALIDATE 
| RDW_ALLCHILDREN
; 
1611         ::RedrawWindow(hWnd
, pRect
, NULL
, flags
); 
1613         ::InvalidateRect(hWnd
, pRect
, eraseBack
); 
1618 void wxWindowMSW::Update() 
1620     if ( !::UpdateWindow(GetHwnd()) ) 
1622         wxLogLastError(wxT("UpdateWindow")); 
1625 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
1626     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT 
1627     // handler needs to be really drawn right now 
1632 // --------------------------------------------------------------------------- 
1634 // --------------------------------------------------------------------------- 
1636 #if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__) 
1640 // we need to lower the sibling static boxes so controls contained within can be 
1642 static void AdjustStaticBoxZOrder(wxWindow 
*parent
) 
1644     // no sibling static boxes if we have no parent (ie TLW) 
1648     for ( wxWindowList::compatibility_iterator node 
= parent
->GetChildren().GetFirst(); 
1650           node 
= node
->GetNext() ) 
1652         wxStaticBox 
*statbox 
= wxDynamicCast(node
->GetData(), wxStaticBox
); 
1655             ::SetWindowPos(GetHwndOf(statbox
), HWND_BOTTOM
, 0, 0, 0, 0, 
1656                            SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
1661 #else // !wxUSE_STATBOX 
1663 static inline void AdjustStaticBoxZOrder(wxWindow 
* WXUNUSED(parent
)) 
1667 #endif // wxUSE_STATBOX/!wxUSE_STATBOX 
1669 #endif // drag and drop is used 
1671 #if wxUSE_DRAG_AND_DROP 
1672 void wxWindowMSW::SetDropTarget(wxDropTarget 
*pDropTarget
) 
1674     if ( m_dropTarget 
!= 0 ) { 
1675         m_dropTarget
->Revoke(m_hWnd
); 
1676         delete m_dropTarget
; 
1679     m_dropTarget 
= pDropTarget
; 
1680     if ( m_dropTarget 
!= 0 ) 
1682         AdjustStaticBoxZOrder(GetParent()); 
1683         m_dropTarget
->Register(m_hWnd
); 
1686 #endif // wxUSE_DRAG_AND_DROP 
1688 // old-style file manager drag&drop support: we retain the old-style 
1689 // DragAcceptFiles in parallel with SetDropTarget. 
1690 void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept
)) 
1693     HWND hWnd 
= GetHwnd(); 
1696         AdjustStaticBoxZOrder(GetParent()); 
1697         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
1702 // ---------------------------------------------------------------------------- 
1704 // ---------------------------------------------------------------------------- 
1708 void wxWindowMSW::DoSetToolTip(wxToolTip 
*tooltip
) 
1710     wxWindowBase::DoSetToolTip(tooltip
); 
1713         m_tooltip
->SetWindow((wxWindow 
*)this); 
1716 #endif // wxUSE_TOOLTIPS 
1718 // --------------------------------------------------------------------------- 
1719 // moving and resizing 
1720 // --------------------------------------------------------------------------- 
1722 bool wxWindowMSW::IsSizeDeferred() const 
1724 #if wxUSE_DEFERRED_SIZING 
1725     if ( m_pendingPosition 
!= wxDefaultPosition 
|| 
1726          m_pendingSize     
!= wxDefaultSize 
) 
1728 #endif // wxUSE_DEFERRED_SIZING 
1734 void wxWindowMSW::DoGetSize(int *x
, int *y
) const 
1736 #if wxUSE_DEFERRED_SIZING 
1737     // if SetSize() had been called at wx level but not realized at Windows 
1738     // level yet (i.e. EndDeferWindowPos() not called), we still should return 
1739     // the new and not the old position to the other wx code 
1740     if ( m_pendingSize 
!= wxDefaultSize 
) 
1743             *x 
= m_pendingSize
.x
; 
1745             *y 
= m_pendingSize
.y
; 
1747     else // use current size 
1748 #endif // wxUSE_DEFERRED_SIZING 
1750         RECT rect 
= wxGetWindowRect(GetHwnd()); 
1753             *x 
= rect
.right 
- rect
.left
; 
1755             *y 
= rect
.bottom 
- rect
.top
; 
1759 // Get size *available for subwindows* i.e. excluding menu bar etc. 
1760 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const 
1762 #if wxUSE_DEFERRED_SIZING 
1763     if ( m_pendingSize 
!= wxDefaultSize 
) 
1765         // we need to calculate the client size corresponding to pending size 
1767         // FIXME: Unfortunately this doesn't work correctly for the maximized 
1768         //        top level windows, the returned values are too small (e.g. 
1769         //        under Windows 7 on a 1600*1200 screen with task bar on the 
1770         //        right the pending size for a maximized window is 1538*1200 
1771         //        and WM_NCCALCSIZE returns 1528*1172 even though the correct 
1772         //        client size of such window is 1538*1182). No idea how to fix 
1773         //        it though, setting WS_MAXIMIZE in GWL_STYLE before calling 
1774         //        WM_NCCALCSIZE doesn't help and AdjustWindowRectEx() doesn't 
1775         //        work in this direction neither. So we just have to live with 
1776         //        the slightly wrong results and relayout the window when it 
1777         //        gets finally shown in its maximized state (see #11762). 
1779         rect
.left 
= m_pendingPosition
.x
; 
1780         rect
.top 
= m_pendingPosition
.y
; 
1781         rect
.right 
= rect
.left 
+ m_pendingSize
.x
; 
1782         rect
.bottom 
= rect
.top 
+ m_pendingSize
.y
; 
1784         ::SendMessage(GetHwnd(), WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
); 
1787             *x 
= rect
.right 
- rect
.left
; 
1789             *y 
= rect
.bottom 
- rect
.top
; 
1792 #endif // wxUSE_DEFERRED_SIZING 
1794         RECT rect 
= wxGetClientRect(GetHwnd()); 
1802     // The size of the client window can't be negative but ::GetClientRect() 
1803     // can return negative size for an extremely small (1x1) window with 
1804     // borders so ensure that we correct it here as having negative sizes is 
1805     // completely unexpected. 
1812 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const 
1814     wxWindow 
* const parent 
= GetParent(); 
1817 #if wxUSE_DEFERRED_SIZING 
1818     if ( m_pendingPosition 
!= wxDefaultPosition 
) 
1820         pos 
= m_pendingPosition
; 
1822     else // use current position 
1823 #endif // wxUSE_DEFERRED_SIZING 
1825         RECT rect 
= wxGetWindowRect(GetHwnd()); 
1828         point
.x 
= rect
.left
; 
1831         // we do the adjustments with respect to the parent only for the "real" 
1832         // children, not for the dialogs/frames 
1833         if ( !IsTopLevel() ) 
1835             if ( wxTheApp
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
1837                 // In RTL mode, we want the logical left x-coordinate, 
1838                 // which would be the physical right x-coordinate. 
1839                 point
.x 
= rect
.right
; 
1842             // Since we now have the absolute screen coords, if there's a 
1843             // parent we must subtract its top left corner 
1846                 ::ScreenToClient(GetHwndOf(parent
), &point
); 
1854     // we also must adjust by the client area offset: a control which is just 
1855     // under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx 
1856     if ( parent 
&& !IsTopLevel() ) 
1858         const wxPoint 
pt(parent
->GetClientAreaOrigin()); 
1869 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const 
1877     ::ScreenToClient(GetHwnd(), &pt
); 
1885 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const 
1893     ::ClientToScreen(GetHwnd(), &pt
); 
1902 wxWindowMSW::DoMoveSibling(WXHWND hwnd
, int x
, int y
, int width
, int height
) 
1904 #if wxUSE_DEFERRED_SIZING 
1905     // if our parent had prepared a defer window handle for us, use it (unless 
1906     // we are a top level window) 
1907     wxWindowMSW 
* const parent 
= IsTopLevel() ? NULL 
: GetParent(); 
1909     HDWP hdwp 
= parent 
? (HDWP
)parent
->m_hDWP 
: NULL
; 
1912         hdwp 
= ::DeferWindowPos(hdwp
, (HWND
)hwnd
, NULL
, x
, y
, width
, height
, 
1913                                 SWP_NOZORDER 
| SWP_NOOWNERZORDER 
| SWP_NOACTIVATE
); 
1916             wxLogLastError(wxT("DeferWindowPos")); 
1922         // hdwp must be updated as it may have been changed 
1923         parent
->m_hDWP 
= (WXHANDLE
)hdwp
; 
1928         // did deferred move, remember new coordinates of the window as they're 
1929         // different from what Windows would return for it 
1933     // otherwise (or if deferring failed) move the window in place immediately 
1934 #endif // wxUSE_DEFERRED_SIZING 
1935     if ( !::MoveWindow((HWND
)hwnd
, x
, y
, width
, height
, IsShown()) ) 
1937         wxLogLastError(wxT("MoveWindow")); 
1940     // if wxUSE_DEFERRED_SIZING, indicates that we didn't use deferred move, 
1941     // ignored otherwise 
1945 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
) 
1947     // TODO: is this consistent with other platforms? 
1948     // Still, negative width or height shouldn't be allowed 
1954     if ( DoMoveSibling(m_hWnd
, x
, y
, width
, height
) ) 
1956 #if wxUSE_DEFERRED_SIZING 
1957         m_pendingPosition 
= wxPoint(x
, y
); 
1958         m_pendingSize 
= wxSize(width
, height
); 
1960     else // window was moved immediately, without deferring it 
1962         m_pendingPosition 
= wxDefaultPosition
; 
1963         m_pendingSize 
= wxDefaultSize
; 
1964 #endif // wxUSE_DEFERRED_SIZING 
1968 // set the size of the window: if the dimensions are positive, just use them, 
1969 // but if any of them is equal to -1, it means that we must find the value for 
1970 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
1971 // which case -1 is a valid value for x and y) 
1973 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
1974 // the width/height to best suit our contents, otherwise we reuse the current 
1976 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
1978     // get the current size and position... 
1979     int currentX
, currentY
; 
1980     int currentW
, currentH
; 
1982     GetPosition(¤tX
, ¤tY
); 
1983     GetSize(¤tW
, ¤tH
); 
1985     // ... and don't do anything (avoiding flicker) if it's already ok unless 
1986     // we're forced to resize the window 
1987     if ( x 
== currentX 
&& y 
== currentY 
&& 
1988          width 
== currentW 
&& height 
== currentH 
&& 
1989             !(sizeFlags 
& wxSIZE_FORCE
) ) 
1991         if (sizeFlags 
& wxSIZE_FORCE_EVENT
) 
1993             wxSizeEvent 
event( wxSize(width
,height
), GetId() ); 
1994             event
.SetEventObject( this ); 
1995             HandleWindowEvent( event 
); 
2000     if ( x 
== wxDefaultCoord 
&& !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
2002     if ( y 
== wxDefaultCoord 
&& !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
2005     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
2007     wxSize size 
= wxDefaultSize
; 
2008     if ( width 
== wxDefaultCoord 
) 
2010         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
2012             size 
= GetBestSize(); 
2017             // just take the current one 
2022     if ( height 
== wxDefaultCoord 
) 
2024         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
2026             if ( size
.x 
== wxDefaultCoord 
) 
2028                 size 
= GetBestSize(); 
2030             //else: already called GetBestSize() above 
2036             // just take the current one 
2041     DoMoveWindow(x
, y
, width
, height
); 
2044 void wxWindowMSW::DoSetClientSize(int width
, int height
) 
2046     // setting the client size is less obvious than it could have been 
2047     // because in the result of changing the total size the window scrollbar 
2048     // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect() 
2049     // doesn't take neither into account) and so the client size will not be 
2050     // correct as the difference between the total and client size changes -- 
2051     // so we keep changing it until we get it right 
2053     // normally this loop shouldn't take more than 3 iterations (usually 1 but 
2054     // if scrollbars [dis]appear as the result of the first call, then 2 and it 
2055     // may become 3 if the window had 0 size originally and so we didn't 
2056     // calculate the scrollbar correction correctly during the first iteration) 
2057     // but just to be on the safe side we check for it instead of making it an 
2058     // "infinite" loop (i.e. leaving break inside as the only way to get out) 
2059     for ( int i 
= 0; i 
< 4; i
++ ) 
2062         ::GetClientRect(GetHwnd(), &rectClient
); 
2064         // if the size is already ok, stop here (NB: rectClient.left = top = 0) 
2065         if ( (rectClient
.right 
== width 
|| width 
== wxDefaultCoord
) && 
2066              (rectClient
.bottom 
== height 
|| height 
== wxDefaultCoord
) ) 
2071         // Find the difference between the entire window (title bar and all) 
2072         // and the client area; add this to the new client size to move the 
2075         ::GetWindowRect(GetHwnd(), &rectWin
); 
2077         const int widthWin 
= rectWin
.right 
- rectWin
.left
, 
2078                   heightWin 
= rectWin
.bottom 
- rectWin
.top
; 
2080         // MoveWindow positions the child windows relative to the parent, so 
2081         // adjust if necessary 
2082         if ( !IsTopLevel() ) 
2084             wxWindow 
*parent 
= GetParent(); 
2087                 ::ScreenToClient(GetHwndOf(parent
), (POINT 
*)&rectWin
); 
2091         // don't call DoMoveWindow() because we want to move window immediately 
2092         // and not defer it here as otherwise the value returned by 
2093         // GetClient/WindowRect() wouldn't change as the window wouldn't be 
2095         if ( !::MoveWindow(GetHwnd(), 
2098                            width 
+ widthWin 
- rectClient
.right
, 
2099                            height 
+ heightWin 
- rectClient
.bottom
, 
2102             wxLogLastError(wxT("MoveWindow")); 
2107 wxSize 
wxWindowMSW::DoGetBorderSize() const 
2110     switch ( GetBorder() ) 
2112         case wxBORDER_STATIC
: 
2113         case wxBORDER_SIMPLE
: 
2117         case wxBORDER_SUNKEN
: 
2121         case wxBORDER_RAISED
: 
2122         case wxBORDER_DOUBLE
: 
2127             wxFAIL_MSG( wxT("unknown border style") ); 
2134     return 2*wxSize(border
, border
); 
2137 // --------------------------------------------------------------------------- 
2139 // --------------------------------------------------------------------------- 
2141 int wxWindowMSW::GetCharHeight() const 
2143     return wxGetTextMetrics(this).tmHeight
; 
2146 int wxWindowMSW::GetCharWidth() const 
2148     // +1 is needed because Windows apparently adds it when calculating the 
2149     // dialog units size in pixels 
2150 #if wxDIALOG_UNIT_COMPATIBILITY 
2151     return wxGetTextMetrics(this).tmAveCharWidth
; 
2153     return wxGetTextMetrics(this).tmAveCharWidth 
+ 1; 
2157 void wxWindowMSW::DoGetTextExtent(const wxString
& string
, 
2160                                   int *externalLeading
, 
2161                                   const wxFont 
*fontToUse
) const 
2163     wxASSERT_MSG( !fontToUse 
|| fontToUse
->IsOk(), 
2164                     wxT("invalid font in GetTextExtent()") ); 
2168         hfontToUse 
= GetHfontOf(*fontToUse
); 
2170         hfontToUse 
= GetHfontOf(GetFont()); 
2172     WindowHDC 
hdc(GetHwnd()); 
2173     SelectInHDC 
selectFont(hdc
, hfontToUse
); 
2177     ::GetTextExtentPoint32(hdc
, string
.wx_str(), string
.length(), &sizeRect
); 
2178     GetTextMetrics(hdc
, &tm
); 
2185         *descent 
= tm
.tmDescent
; 
2186     if ( externalLeading 
) 
2187         *externalLeading 
= tm
.tmExternalLeading
; 
2190 // --------------------------------------------------------------------------- 
2192 // --------------------------------------------------------------------------- 
2194 #if wxUSE_MENUS_NATIVE 
2196 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue 
2197 // immediately, without waiting for the next event loop iteration 
2199 // NB: this function should probably be made public later as it can almost 
2200 //     surely replace wxYield() elsewhere as well 
2201 static void wxYieldForCommandsOnly() 
2203     // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't 
2204     // want to process it here) 
2206     while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) ) 
2208         if ( msg
.message 
== WM_QUIT 
) 
2210             // if we retrieved a WM_QUIT, insert back into the message queue. 
2211             ::PostQuitMessage(0); 
2215         // luckily (as we don't have access to wxEventLoopImpl method from here 
2216         // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it 
2218         ::TranslateMessage(&msg
); 
2219         ::DispatchMessage(&msg
); 
2223 bool wxWindowMSW::DoPopupMenu(wxMenu 
*menu
, int x
, int y
) 
2228     if ( x 
== wxDefaultCoord 
&& y 
== wxDefaultCoord 
) 
2230         pt 
= wxGetMousePosition(); 
2234         pt 
= ClientToScreen(wxPoint(x
, y
)); 
2237 #if defined(__WXWINCE__) 
2238     static const UINT flags 
= 0; 
2239 #else // !__WXWINCE__ 
2240     UINT flags 
= TPM_RIGHTBUTTON
; 
2241     // NT4 doesn't support TPM_RECURSE and simply doesn't show the menu at all 
2242     // when it's use, I'm not sure about Win95/98 but prefer to err on the safe 
2243     // side and not to use it there neither -- modify the test if it does work 
2245     if ( wxGetWinVersion() >= wxWinVersion_5 
) 
2247         // using TPM_RECURSE allows us to show a popup menu while another menu 
2248         // is opened which can be useful and is supported by the other 
2249         // platforms, so allow it under Windows too 
2250         flags 
|= TPM_RECURSE
; 
2252 #endif // __WXWINCE__/!__WXWINCE__ 
2254     ::TrackPopupMenu(GetHmenuOf(menu
), flags
, pt
.x
, pt
.y
, 0, GetHwnd(), NULL
); 
2256     // we need to do it right now as otherwise the events are never going to be 
2257     // sent to wxCurrentPopupMenu from HandleCommand() 
2259     // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't 
2260     // help and we'd still need wxYieldForCommandsOnly() as the menu may be 
2261     // destroyed as soon as we return (it can be a local variable in the caller 
2262     // for example) and so we do need to process the event immediately 
2263     wxYieldForCommandsOnly(); 
2268 #endif // wxUSE_MENUS_NATIVE 
2270 // =========================================================================== 
2271 // pre/post message processing 
2272 // =========================================================================== 
2274 WXLRESULT 
wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
2278         rc 
= ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
2280         rc 
= ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
); 
2282     // Special hack used by wxTextEntry auto-completion only: this event is 
2283     // sent after the normal keyboard processing so that its handler could use 
2284     // the updated contents of the text control, after taking the key that was 
2285     // pressed into account. 
2286     if ( nMsg 
== WM_CHAR 
) 
2288         wxKeyEvent 
event(CreateCharEvent(wxEVT_AFTER_CHAR
, wParam
, lParam
)); 
2289         HandleWindowEvent(event
); 
2295 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
) 
2297     // wxUniversal implements tab traversal itself 
2298 #ifndef __WXUNIVERSAL__ 
2299     if ( m_hWnd 
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) ) 
2301         // intercept dialog navigation keys 
2302         MSG 
*msg 
= (MSG 
*)pMsg
; 
2304         // here we try to do all the job which ::IsDialogMessage() usually does 
2306         if ( msg
->message 
== WM_KEYDOWN 
) 
2308             bool bCtrlDown 
= wxIsCtrlDown(); 
2309             bool bShiftDown 
= wxIsShiftDown(); 
2311             // WM_GETDLGCODE: ask the control if it wants the key for itself, 
2312             // don't process it if it's the case (except for Ctrl-Tab/Enter 
2313             // combinations which are always processed) 
2314             LONG lDlgCode 
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0); 
2316             // surprisingly, DLGC_WANTALLKEYS bit mask doesn't contain the 
2317             // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, 
2318             // it, of course, implies them 
2319             if ( lDlgCode 
& DLGC_WANTALLKEYS 
) 
2321                 lDlgCode 
|= DLGC_WANTTAB 
| DLGC_WANTARROWS
; 
2324             bool bForward 
= true, 
2325                  bWindowChange 
= false, 
2328             // should we process this message specially? 
2329             bool bProcess 
= true; 
2330             switch ( msg
->wParam 
) 
2333                     if ( (lDlgCode 
& DLGC_WANTTAB
) && !bCtrlDown 
) 
2335                         // let the control have the TAB 
2338                     else // use it for navigation 
2340                         // Ctrl-Tab cycles thru notebook pages 
2341                         bWindowChange 
= bCtrlDown
; 
2342                         bForward 
= !bShiftDown
; 
2349                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
2357                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
2366                     // we treat PageUp/Dn as arrows because chances are that 
2367                     // a control which needs arrows also needs them for 
2368                     // navigation (e.g. wxTextCtrl, wxListCtrl, ...) 
2369                     if ( (lDlgCode 
& DLGC_WANTARROWS
) && !bCtrlDown 
) 
2371                     else // OTOH Ctrl-PageUp/Dn works as [Shift-]Ctrl-Tab 
2372                         bWindowChange 
= true; 
2378                         // currently active button should get enter press even 
2379                         // if there is a default button elsewhere so check if 
2380                         // this window is a button first 
2381                         wxWindow 
*btn 
= NULL
; 
2382                         if ( lDlgCode 
& DLGC_DEFPUSHBUTTON 
) 
2384                             // let IsDialogMessage() handle this for all 
2385                             // buttons except the owner-drawn ones which it 
2386                             // just seems to ignore 
2387                             long style 
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
); 
2388                             if ( (style 
& BS_OWNERDRAW
) == BS_OWNERDRAW 
) 
2390                                 // emulate the button click 
2391                                 btn 
= wxFindWinFromHandle(msg
->hwnd
); 
2394                         else // not a button itself, do we have default button? 
2396                             // check if this window or any of its ancestors 
2397                             // wants the message for itself (we always reserve 
2398                             // Ctrl-Enter for dialog navigation though) 
2399                             wxWindow 
*win 
= this; 
2402                                 // this will contain the dialog code of this 
2403                                 // window and all of its parent windows in turn 
2404                                 LONG lDlgCode2 
= lDlgCode
; 
2408                                     if ( lDlgCode2 
& DLGC_WANTMESSAGE 
) 
2410                                         // as it wants to process Enter itself, 
2411                                         // don't call IsDialogMessage() which 
2416                                     // don't propagate keyboard messages beyond 
2417                                     // the first top level window parent 
2418                                     if ( win
->IsTopLevel() ) 
2421                                     win 
= win
->GetParent(); 
2423                                     lDlgCode2 
= ::SendMessage
 
2434                                 win 
= wxGetTopLevelParent(win
); 
2437                             wxTopLevelWindow 
* const 
2438                                 tlw 
= wxDynamicCast(win
, wxTopLevelWindow
); 
2441                                 btn 
= wxDynamicCast(tlw
->GetDefaultItem(), 
2446                         if ( btn 
&& btn
->IsEnabled() ) 
2448                             btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
2452                         // This "Return" key press won't be actually used for 
2453                         // navigation so don't generate wxNavigationKeyEvent 
2454                         // for it but still pass it to IsDialogMessage() as it 
2455                         // may handle it in some other way (e.g. by playing the 
2456                         // default error sound). 
2459 #endif // wxUSE_BUTTON 
2462                         // map Enter presses into button presses on PDAs 
2463                         wxJoystickEvent 
event(wxEVT_JOY_BUTTON_DOWN
); 
2464                         event
.SetEventObject(this); 
2465                         if ( HandleWindowEvent(event
) ) 
2467 #endif // __WXWINCE__ 
2477                 wxNavigationKeyEvent event
; 
2478                 event
.SetDirection(bForward
); 
2479                 event
.SetWindowChange(bWindowChange
); 
2480                 event
.SetFromTab(bFromTab
); 
2481                 event
.SetEventObject(this); 
2483                 if ( HandleWindowEvent(event
) ) 
2485                     // as we don't call IsDialogMessage(), which would take of 
2486                     // this by default, we need to manually send this message 
2487                     // so that controls can change their UI state if needed 
2488                     MSWUpdateUIState(UIS_CLEAR
, UISF_HIDEFOCUS
); 
2495         if ( ::IsDialogMessage(GetHwnd(), msg
) ) 
2497             // IsDialogMessage() did something... 
2501 #endif // __WXUNIVERSAL__ 
2506         // relay mouse move events to the tooltip control 
2507         MSG 
*msg 
= (MSG 
*)pMsg
; 
2508         if ( msg
->message 
== WM_MOUSEMOVE 
) 
2509             wxToolTip::RelayEvent(pMsg
); 
2511 #endif // wxUSE_TOOLTIPS 
2516 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
) 
2518 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__) 
2519     return m_acceleratorTable
.Translate(this, pMsg
); 
2523 #endif // wxUSE_ACCEL 
2526 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* msg
) 
2528     // all tests below have to deal with various bugs/misfeatures of 
2529     // IsDialogMessage(): we have to prevent it from being called from our 
2530     // MSWProcessMessage() in some situations 
2532     // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the 
2533     // message even when there is no cancel button and when the message is 
2534     // needed by the control itself: in particular, it prevents the tree in 
2535     // place edit control from being closed with Escape in a dialog 
2536     if ( msg
->message 
== WM_KEYDOWN 
&& msg
->wParam 
== VK_ESCAPE 
) 
2541     // ::IsDialogMessage() is broken and may sometimes hang the application by 
2542     // going into an infinite loop when it tries to find the control to give 
2543     // focus to when Alt-<key> is pressed, so we try to detect [some of] the 
2544     // situations when this may happen and not call it then 
2545     if ( msg
->message 
!= WM_SYSCHAR 
) 
2548     // assume we can call it by default 
2549     bool canSafelyCallIsDlgMsg 
= true; 
2551     HWND hwndFocus 
= ::GetFocus(); 
2553     // if the currently focused window itself has WS_EX_CONTROLPARENT style, 
2554     // ::IsDialogMessage() will also enter an infinite loop, because it will 
2555     // recursively check the child windows but not the window itself and so if 
2556     // none of the children accepts focus it loops forever (as it only stops 
2557     // when it gets back to the window it started from) 
2559     // while it is very unusual that a window with WS_EX_CONTROLPARENT 
2560     // style has the focus, it can happen. One such possibility is if 
2561     // all windows are either toplevel, wxDialog, wxPanel or static 
2562     // controls and no window can actually accept keyboard input. 
2563 #if !defined(__WXWINCE__) 
2564     if ( ::GetWindowLong(hwndFocus
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
2566         // pessimistic by default 
2567         canSafelyCallIsDlgMsg 
= false; 
2568         for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
2570               node 
= node
->GetNext() ) 
2572             wxWindow 
* const win 
= node
->GetData(); 
2573             if ( win
->CanAcceptFocus() && 
2574                     !wxHasWindowExStyle(win
, WS_EX_CONTROLPARENT
) ) 
2576                 // it shouldn't hang... 
2577                 canSafelyCallIsDlgMsg 
= true; 
2583 #endif // !__WXWINCE__ 
2585     if ( canSafelyCallIsDlgMsg 
) 
2587         // ::IsDialogMessage() can enter in an infinite loop when the 
2588         // currently focused window is disabled or hidden and its 
2589         // parent has WS_EX_CONTROLPARENT style, so don't call it in 
2593             if ( !::IsWindowEnabled(hwndFocus
) || 
2594                     !::IsWindowVisible(hwndFocus
) ) 
2596                 // it would enter an infinite loop if we do this! 
2597                 canSafelyCallIsDlgMsg 
= false; 
2602             if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) ) 
2604                 // it's a top level window, don't go further -- e.g. even 
2605                 // if the parent of a dialog is disabled, this doesn't 
2606                 // break navigation inside the dialog 
2610             hwndFocus 
= ::GetParent(hwndFocus
); 
2614     return canSafelyCallIsDlgMsg
; 
2617 // --------------------------------------------------------------------------- 
2618 // message params unpackers 
2619 // --------------------------------------------------------------------------- 
2621 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2622                              WORD 
*id
, WXHWND 
*hwnd
, WORD 
*cmd
) 
2624     *id 
= LOWORD(wParam
); 
2625     *hwnd 
= (WXHWND
)lParam
; 
2626     *cmd 
= HIWORD(wParam
); 
2629 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2630                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2632     *state 
= LOWORD(wParam
); 
2633     *minimized 
= HIWORD(wParam
); 
2634     *hwnd 
= (WXHWND
)lParam
; 
2637 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2638                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2640     *code 
= LOWORD(wParam
); 
2641     *pos 
= HIWORD(wParam
); 
2642     *hwnd 
= (WXHWND
)lParam
; 
2645 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2646                                  WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2648     *hwnd 
= (WXHWND
)lParam
; 
2649     *hdc 
= (WXHDC
)wParam
; 
2652 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2653                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2655     *item 
= (WXWORD
)wParam
; 
2656     *flags 
= HIWORD(wParam
); 
2657     *hmenu 
= (WXHMENU
)lParam
; 
2660 // --------------------------------------------------------------------------- 
2661 // Main wxWidgets window proc and the window proc for wxWindow 
2662 // --------------------------------------------------------------------------- 
2664 // Hook for new window just as it's being created, when the window isn't yet 
2665 // associated with the handle 
2666 static wxWindowMSW 
*gs_winBeingCreated 
= NULL
; 
2668 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the 
2669 // window being created and insures that it's always unset back later 
2670 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW 
*winBeingCreated
) 
2672     gs_winBeingCreated 
= winBeingCreated
; 
2675 wxWindowCreationHook::~wxWindowCreationHook() 
2677     gs_winBeingCreated 
= NULL
; 
2681 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) 
2683     // trace all messages: useful for the debugging but noticeably slows down 
2684     // the code so don't do it by default 
2685 #if wxDEBUG_LEVEL >= 2 
2686     // notice that we cast wParam and lParam to long to avoid mismatch with 
2687     // format specifiers in 64 bit builds where they are both int64 quantities 
2689     // casting like this loses information, of course, but it shouldn't matter 
2690     // much for this diagnostic code and it keeps the code simple 
2691     wxLogTrace("winmsg", 
2692                wxT("Processing %s(hWnd=%p, wParam=%08lx, lParam=%08lx)"), 
2693                wxGetMessageName(message
), hWnd
, (long)wParam
, (long)lParam
); 
2694 #endif // wxDEBUG_LEVEL >= 2 
2696     wxWindowMSW 
*wnd 
= wxFindWinFromHandle(hWnd
); 
2698     // when we get the first message for the HWND we just created, we associate 
2699     // it with wxWindow stored in gs_winBeingCreated 
2700     if ( !wnd 
&& gs_winBeingCreated 
) 
2702         wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
); 
2703         wnd 
= gs_winBeingCreated
; 
2704         gs_winBeingCreated 
= NULL
; 
2705         wnd
->SetHWND((WXHWND
)hWnd
); 
2710     if ( wnd 
&& wxGUIEventLoop::AllowProcessing(wnd
) ) 
2711         rc 
= wnd
->MSWWindowProc(message
, wParam
, lParam
); 
2713         rc 
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
); 
2719 wxWindowMSW::MSWHandleMessage(WXLRESULT 
*result
, 
2724     // did we process the message? 
2725     bool processed 
= false; 
2735     // for most messages we should return 0 when we do process the message 
2743                 processed 
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
); 
2746                     // return 0 to allow window creation 
2747                     rc
.result 
= mayCreate 
? 0 : -1; 
2753             // never set processed to true and *always* pass WM_DESTROY to 
2754             // DefWindowProc() as Windows may do some internal cleanup when 
2755             // processing it and failing to pass the message along may cause 
2756             // memory and resource leaks! 
2757             (void)HandleDestroy(); 
2761             processed 
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), wParam
); 
2765             processed 
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2768 #if !defined(__WXWINCE__) 
2771                 LPRECT pRect 
= (LPRECT
)lParam
; 
2773                 rc
.SetLeft(pRect
->left
); 
2774                 rc
.SetTop(pRect
->top
); 
2775                 rc
.SetRight(pRect
->right
); 
2776                 rc
.SetBottom(pRect
->bottom
); 
2777                 processed 
= HandleMoving(rc
); 
2779                     pRect
->left 
= rc
.GetLeft(); 
2780                     pRect
->top 
= rc
.GetTop(); 
2781                     pRect
->right 
= rc
.GetRight(); 
2782                     pRect
->bottom 
= rc
.GetBottom(); 
2787         case WM_ENTERSIZEMOVE
: 
2789                 processed 
= HandleEnterSizeMove(); 
2793         case WM_EXITSIZEMOVE
: 
2795                 processed 
= HandleExitSizeMove(); 
2801                 LPRECT pRect 
= (LPRECT
)lParam
; 
2803                 rc
.SetLeft(pRect
->left
); 
2804                 rc
.SetTop(pRect
->top
); 
2805                 rc
.SetRight(pRect
->right
); 
2806                 rc
.SetBottom(pRect
->bottom
); 
2807                 processed 
= HandleSizing(rc
); 
2809                     pRect
->left 
= rc
.GetLeft(); 
2810                     pRect
->top 
= rc
.GetTop(); 
2811                     pRect
->right 
= rc
.GetRight(); 
2812                     pRect
->bottom 
= rc
.GetBottom(); 
2816 #endif // !__WXWINCE__ 
2818 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
2819         case WM_ACTIVATEAPP
: 
2820             // This implicitly sends a wxEVT_ACTIVATE_APP event 
2821             wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
2827                 WXWORD state
, minimized
; 
2829                 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
); 
2831                 processed 
= HandleActivate(state
, minimized 
!= 0, (WXHWND
)hwnd
); 
2836             processed 
= HandleSetFocus((WXHWND
)wParam
); 
2840             processed 
= HandleKillFocus((WXHWND
)wParam
); 
2843         case WM_PRINTCLIENT
: 
2844             processed 
= HandlePrintClient((WXHDC
)wParam
); 
2850                 wxPaintDCEx 
dc((wxWindow 
*)this, (WXHDC
)wParam
); 
2852                 processed 
= HandlePaint(); 
2856                 processed 
= HandlePaint(); 
2861 #ifdef __WXUNIVERSAL__ 
2862             // Universal uses its own wxFrame/wxDialog, so we don't receive 
2863             // close events unless we have this. 
2865 #endif // __WXUNIVERSAL__ 
2867             // don't let the DefWindowProc() destroy our window - we'll do it 
2868             // ourselves in ~wxWindow 
2874             processed 
= HandleShow(wParam 
!= 0, (int)lParam
); 
2878             processed 
= HandleMouseMove(GET_X_LPARAM(lParam
), 
2879                                         GET_Y_LPARAM(lParam
), 
2883 #ifdef HAVE_TRACKMOUSEEVENT 
2885             // filter out excess WM_MOUSELEAVE events sent after PopupMenu() 
2887             if ( m_mouseInWindow 
) 
2889                 GenerateMouseLeave(); 
2892             // always pass processed back as false, this allows the window 
2893             // manager to process the message too.  This is needed to 
2894             // ensure windows XP themes work properly as the mouse moves 
2895             // over widgets like buttons. So don't set processed to true here. 
2897 #endif // HAVE_TRACKMOUSEEVENT 
2899 #if wxUSE_MOUSEWHEEL 
2901             processed 
= HandleMouseWheel(wxMOUSE_WHEEL_VERTICAL
, wParam
, lParam
); 
2904         case WM_MOUSEHWHEEL
: 
2905             processed 
= HandleMouseWheel(wxMOUSE_WHEEL_HORIZONTAL
, wParam
, lParam
); 
2907 #endif // wxUSE_MOUSEWHEEL 
2909         case WM_LBUTTONDOWN
: 
2911         case WM_LBUTTONDBLCLK
: 
2912         case WM_RBUTTONDOWN
: 
2914         case WM_RBUTTONDBLCLK
: 
2915         case WM_MBUTTONDOWN
: 
2917         case WM_MBUTTONDBLCLK
: 
2918 #ifdef wxHAS_XBUTTON 
2919         case WM_XBUTTONDOWN
: 
2921         case WM_XBUTTONDBLCLK
: 
2922 #endif // wxHAS_XBUTTON 
2924 #ifdef __WXMICROWIN__ 
2925                 // MicroWindows seems to ignore the fact that a window is 
2926                 // disabled. So catch mouse events and throw them away if 
2928                 wxWindowMSW
* win 
= this; 
2931                     if (!win
->IsEnabled()) 
2937                     win 
= win
->GetParent(); 
2938                     if ( !win 
|| win
->IsTopLevel() ) 
2945 #endif // __WXMICROWIN__ 
2946                 int x 
= GET_X_LPARAM(lParam
), 
2947                     y 
= GET_Y_LPARAM(lParam
); 
2950                 // redirect the event to a static control if necessary by 
2951                 // finding one under mouse because under CE the static controls 
2952                 // don't generate mouse events (even with SS_NOTIFY) 
2954                 if ( GetCapture() == this ) 
2956                     // but don't do it if the mouse is captured by this window 
2957                     // because then it should really get this event itself 
2962                     win 
= FindWindowForMouseEvent(this, &x
, &y
); 
2964                     // this should never happen 
2965                     wxCHECK_MSG( win
, 0, 
2966                                  wxT("FindWindowForMouseEvent() returned NULL") ); 
2969                 if (IsContextMenuEnabled() && message 
== WM_LBUTTONDOWN
) 
2971                     SHRGINFO shrgi 
= {0}; 
2973                     shrgi
.cbSize 
= sizeof(SHRGINFO
); 
2974                     shrgi
.hwndClient 
= (HWND
) GetHWND(); 
2978                     shrgi
.dwFlags 
= SHRG_RETURNCMD
; 
2979                     // shrgi.dwFlags = SHRG_NOTIFYPARENT; 
2981                     if (GN_CONTEXTMENU 
== ::SHRecognizeGesture(&shrgi
)) 
2984                         pt 
= ClientToScreen(pt
); 
2986                         wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
2988                         evtCtx
.SetEventObject(this); 
2989                         if (HandleWindowEvent(evtCtx
)) 
2998 #else // !__WXWINCE__ 
2999                 wxWindowMSW 
*win 
= this; 
3000 #endif // __WXWINCE__/!__WXWINCE__ 
3002                 processed 
= win
->HandleMouseEvent(message
, x
, y
, wParam
); 
3004                 // if the app didn't eat the event, handle it in the default 
3005                 // way, that is by giving this window the focus 
3008                     // for the standard classes their WndProc sets the focus to 
3009                     // them anyhow and doing it from here results in some weird 
3010                     // problems, so don't do it for them (unnecessary anyhow) 
3011                     if ( !win
->IsOfStandardClass() ) 
3013                         if ( message 
== WM_LBUTTONDOWN 
&& win
->IsFocusable() ) 
3025         case MM_JOY1BUTTONDOWN
: 
3026         case MM_JOY2BUTTONDOWN
: 
3027         case MM_JOY1BUTTONUP
: 
3028         case MM_JOY2BUTTONUP
: 
3029             processed 
= HandleJoystickEvent(message
, 
3034 #endif // __WXMICROWIN__ 
3040                 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
); 
3042                 processed 
= HandleCommand(id
, cmd
, hwnd
); 
3047             processed 
= HandleNotify((int)wParam
, lParam
, &rc
.result
); 
3050         // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU, 
3051         // otherwise DefWindowProc() does it perfectly fine for us, but MSLU 
3052         // apparently doesn't always behave properly and needs some help 
3053 #if wxUSE_UNICODE_MSLU && defined(NF_QUERY) 
3054         case WM_NOTIFYFORMAT
: 
3055             if ( lParam 
== NF_QUERY 
) 
3058                 rc
.result 
= NFR_UNICODE
; 
3061 #endif // wxUSE_UNICODE_MSLU 
3063             // for these messages we must return true if process the message 
3066             processed 
= MSWOnDrawItem(wParam
, (WXDRAWITEMSTRUCT 
*)lParam
); 
3071         case WM_MEASUREITEM
: 
3072             processed 
= MSWOnMeasureItem(wParam
, (WXMEASUREITEMSTRUCT 
*)lParam
); 
3076 #endif // defined(WM_DRAWITEM) 
3079             if ( !IsOfStandardClass() || HasFlag(wxWANTS_CHARS
) ) 
3081                 // we always want to get the char events 
3082                 rc
.result 
= DLGC_WANTCHARS
; 
3084                 if ( HasFlag(wxWANTS_CHARS
) ) 
3086                     // in fact, we want everything 
3087                     rc
.result 
|= DLGC_WANTARROWS 
| 
3094             //else: get the dlg code from the DefWindowProc() 
3099             // Generate the key down event in any case. 
3100             m_lastKeydownProcessed 
= HandleKeyDown((WORD
) wParam
, lParam
); 
3101             if ( m_lastKeydownProcessed 
) 
3103                 // If it was processed by an event handler, we stop here, 
3104                 // notably we intentionally don't generate char event then. 
3107             else // key down event not handled 
3109                 // Examine the event to decide whether we need to generate a 
3110                 // char event for it ourselves or let Windows do it. Window 
3111                 // mostly only does it for the keys which produce printable 
3112                 // characters (although there are exceptions, e.g. VK_ESCAPE or 
3113                 // VK_BACK (but not VK_DELETE)) while we do it for all keys 
3114                 // except the modifier ones (the wisdom of this is debatable 
3115                 // but by now this decision is enshrined forever due to 
3116                 // backwards compatibility). 
3119                     // No wxEVT_CHAR events are generated for these keys at all. 
3127                     // Windows will send us WM_CHAR for these ones so we'll 
3128                     // generate wxEVT_CHAR for them later when we get it. 
3164                     // special case of VK_APPS: treat it the same as right mouse 
3165                     // click because both usually pop up a context menu 
3167                         processed 
= HandleMouseEvent(WM_RBUTTONDOWN
, -1, -1, 0); 
3172                         if ( (wParam 
>= '0' && wParam 
<= '9') || 
3173                                 (wParam 
>= 'A' && wParam 
<= 'Z') ) 
3175                             // We'll get WM_CHAR for those later too. 
3179                         // But for the rest we won't get WM_CHAR later so we do 
3180                         // need to generate the event right now. 
3181                         wxKeyEvent 
event(wxEVT_CHAR
); 
3182                         InitAnyKeyEvent(event
, wParam
, lParam
); 
3184                         // Set the "extended" bit in lParam because we want to 
3185                         // generate CHAR events with WXK_HOME and not 
3186                         // WXK_NUMPAD_HOME even if the "Home" key on numpad was 
3188                         event
.m_keyCode 
= wxMSWKeyboard::VKToWX
 
3191                                             lParam 
| (KF_EXTENDED 
<< 16) 
3194                         // Don't produce events without any valid character 
3195                         // code (even if this shouldn't normally happen...). 
3196                         if ( event
.m_keyCode 
!= WXK_NONE 
) 
3197                             processed 
= HandleWindowEvent(event
); 
3200             if (message 
== WM_SYSKEYDOWN
)  // Let Windows still handle the SYSKEYs 
3207             // special case of VK_APPS: treat it the same as right mouse button 
3208             if ( wParam 
== VK_APPS 
) 
3210                 processed 
= HandleMouseEvent(WM_RBUTTONUP
, -1, -1, 0); 
3215                 processed 
= HandleKeyUp((WORD
) wParam
, lParam
); 
3220         case WM_CHAR
: // Always an ASCII character 
3221             if ( m_lastKeydownProcessed 
) 
3223                 // The key was handled in the EVT_KEY_DOWN and handling 
3224                 // a key in an EVT_KEY_DOWN handler is meant, by 
3225                 // design, to prevent EVT_CHARs from happening 
3226                 m_lastKeydownProcessed 
= false; 
3231                 processed 
= HandleChar((WORD
)wParam
, lParam
); 
3235         case WM_IME_STARTCOMPOSITION
: 
3236             // IME popup needs Escape as it should undo the changes in its 
3237             // entry window instead of e.g. closing the dialog for which the 
3238             // IME is used (and losing all the changes in the IME window). 
3239             gs_modalEntryWindowCount
++; 
3242         case WM_IME_ENDCOMPOSITION
: 
3243             gs_modalEntryWindowCount
--; 
3248             processed 
= HandleHotKey((WORD
)wParam
, lParam
); 
3250 #endif // wxUSE_HOTKEY 
3255             processed 
= HandleClipboardEvent(message
); 
3263                 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
); 
3265                 processed 
= MSWOnScroll(message 
== WM_HSCROLL 
? wxHORIZONTAL
 
3271         // CTLCOLOR messages are sent by children to query the parent for their 
3273 #ifndef __WXMICROWIN__ 
3274         case WM_CTLCOLORMSGBOX
: 
3275         case WM_CTLCOLOREDIT
: 
3276         case WM_CTLCOLORLISTBOX
: 
3277         case WM_CTLCOLORBTN
: 
3278         case WM_CTLCOLORDLG
: 
3279         case WM_CTLCOLORSCROLLBAR
: 
3280         case WM_CTLCOLORSTATIC
: 
3284                 UnpackCtlColor(wParam
, lParam
, &hdc
, &hwnd
); 
3286                 processed 
= HandleCtlColor(&rc
.hBrush
, (WXHDC
)hdc
, (WXHWND
)hwnd
); 
3289 #endif // !__WXMICROWIN__ 
3291         case WM_SYSCOLORCHANGE
: 
3292             // the return value for this message is ignored 
3293             processed 
= HandleSysColorChange(); 
3296 #if !defined(__WXWINCE__) 
3297         case WM_DISPLAYCHANGE
: 
3298             processed 
= HandleDisplayChange(); 
3302         case WM_PALETTECHANGED
: 
3303             processed 
= HandlePaletteChanged((WXHWND
)wParam
); 
3306         case WM_CAPTURECHANGED
: 
3307             processed 
= HandleCaptureChanged((WXHWND
)lParam
); 
3310         case WM_SETTINGCHANGE
: 
3311             processed 
= HandleSettingChange(wParam
, lParam
); 
3314         case WM_QUERYNEWPALETTE
: 
3315             processed 
= HandleQueryNewPalette(); 
3320 #ifdef wxHAS_MSW_BACKGROUND_ERASE_HOOK 
3321                 // check if an override was configured for this window 
3322                 EraseBgHooks::const_iterator it 
= gs_eraseBgHooks
.find(this); 
3323                 if ( it 
!= gs_eraseBgHooks
.end() ) 
3324                     processed 
= it
->second
->MSWEraseBgHook((WXHDC
)wParam
); 
3326 #endif // wxHAS_MSW_BACKGROUND_ERASE_HOOK 
3327                     processed 
= HandleEraseBkgnd((WXHDC
)wParam
); 
3332                 // we processed the message, i.e. erased the background 
3337 #if !defined(__WXWINCE__) 
3339             processed 
= HandleDropFiles(wParam
); 
3344             processed 
= HandleInitDialog((WXHWND
)wParam
); 
3348                 // we never set focus from here 
3353 #if !defined(__WXWINCE__) 
3354         case WM_QUERYENDSESSION
: 
3355             processed 
= HandleQueryEndSession(lParam
, &rc
.allow
); 
3359             processed 
= HandleEndSession(wParam 
!= 0, lParam
); 
3362         case WM_GETMINMAXINFO
: 
3363             processed 
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
); 
3368             processed 
= HandleSetCursor((WXHWND
)wParam
, 
3369                                         LOWORD(lParam
),     // hit test 
3370                                         HIWORD(lParam
));    // mouse msg 
3374                 // returning TRUE stops the DefWindowProc() from further 
3375                 // processing this message - exactly what we need because we've 
3376                 // just set the cursor. 
3381 #if wxUSE_ACCESSIBILITY 
3384                 //WPARAM dwFlags = (WPARAM) (DWORD) wParam; 
3385                 LPARAM dwObjId 
= (LPARAM
) (DWORD
) lParam
; 
3387                 if (dwObjId 
== (LPARAM
)OBJID_CLIENT 
&& GetOrCreateAccessible()) 
3389                     return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible()); 
3395 #if defined(WM_HELP) 
3398                 // by default, WM_HELP is propagated by DefWindowProc() upwards 
3399                 // to the window parent but as we do it ourselves already 
3400                 // (wxHelpEvent is derived from wxCommandEvent), we don't want 
3401                 // to get the other events if we process this message at all 
3404                 // WM_HELP doesn't use lParam under CE 
3406                 HELPINFO
* info 
= (HELPINFO
*) lParam
; 
3407                 if ( info
->iContextType 
== HELPINFO_WINDOW 
) 
3409 #endif // !__WXWINCE__ 
3410                     wxHelpEvent helpEvent
 
3415                                     wxGetMousePosition() // what else? 
3417                                     wxPoint(info
->MousePos
.x
, info
->MousePos
.y
) 
3421                     helpEvent
.SetEventObject(this); 
3422                     HandleWindowEvent(helpEvent
); 
3425                 else if ( info
->iContextType 
== HELPINFO_MENUITEM 
) 
3427                     wxHelpEvent 
helpEvent(wxEVT_HELP
, info
->iCtrlId
); 
3428                     helpEvent
.SetEventObject(this); 
3429                     HandleWindowEvent(helpEvent
); 
3432                 else // unknown help event? 
3436 #endif // !__WXWINCE__ 
3441 #if !defined(__WXWINCE__) 
3442         case WM_CONTEXTMENU
: 
3444                 // we don't convert from screen to client coordinates as 
3445                 // the event may be handled by a parent window 
3446                 wxPoint 
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
3448                 wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
3450                 // we could have got an event from our child, reflect it back 
3451                 // to it if this is the case 
3452                 wxWindowMSW 
*win 
= NULL
; 
3453                 WXHWND hWnd 
= (WXHWND
)wParam
; 
3454                 if ( hWnd 
!= m_hWnd 
) 
3456                     win 
= FindItemByHWND(hWnd
); 
3462                 evtCtx
.SetEventObject(win
); 
3463                 processed 
= win
->HandleWindowEvent(evtCtx
); 
3470             // we're only interested in our own menus, not MF_SYSMENU 
3471             if ( HIWORD(wParam
) == MF_POPUP 
) 
3473                 // handle menu chars for ownerdrawn menu items 
3474                 int i 
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
); 
3475                 if ( i 
!= wxNOT_FOUND 
) 
3477                     rc
.result 
= MAKELRESULT(i
, MNC_EXECUTE
); 
3482 #endif // wxUSE_MENUS 
3485         case WM_POWERBROADCAST
: 
3488                 processed 
= HandlePower(wParam
, lParam
, &vetoed
); 
3489                 rc
.result 
= processed 
&& vetoed 
? BROADCAST_QUERY_DENY 
: TRUE
; 
3492 #endif // __WXWINCE__ 
3495         // If we want the default themed border then we need to draw it ourselves 
3498                 wxUxThemeEngine
* theme 
= wxUxThemeEngine::GetIfActive(); 
3499                 const wxBorder border 
= TranslateBorder(GetBorder()); 
3500                 if (theme 
&& border 
== wxBORDER_THEME
) 
3502                     // first ask the widget to calculate the border size 
3503                     rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
3506                     // now alter the client size making room for drawing a 
3509                     NCCALCSIZE_PARAMS 
*csparam 
= NULL
; 
3512                         csparam 
= (NCCALCSIZE_PARAMS 
*)lParam
; 
3513                         rect 
= &csparam
->rgrc
[0]; 
3517                         rect 
= (RECT 
*)lParam
; 
3520                     wxUxThemeHandle 
hTheme((const wxWindow 
*)this, L
"EDIT"); 
3521                     RECT rcClient 
= { 0, 0, 0, 0 }; 
3522                     wxClientDC 
dc((wxWindow 
*)this); 
3523                     wxMSWDCImpl 
*impl 
= (wxMSWDCImpl
*) dc
.GetImpl(); 
3525                     if ( theme
->GetThemeBackgroundContentRect
 
3532                                  &rcClient
) == S_OK 
) 
3534                         InflateRect(&rcClient
, -1, -1); 
3536                             csparam
->rgrc
[0] = rcClient
; 
3538                             *((RECT
*)lParam
) = rcClient
; 
3540                         // WVR_REDRAW triggers a bug whereby child windows are moved up and left, 
3542                         // rc.result = WVR_REDRAW; 
3550                 wxUxThemeEngine
* theme 
= wxUxThemeEngine::GetIfActive(); 
3551                 const wxBorder border 
= TranslateBorder(GetBorder()); 
3552                 if (theme 
&& border 
== wxBORDER_THEME
) 
3554                     // first ask the widget to paint its non-client area, such as scrollbars, etc. 
3555                     rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
3558                     wxUxThemeHandle 
hTheme((const wxWindow 
*)this, L
"EDIT"); 
3559                     wxWindowDC 
dc((wxWindow 
*)this); 
3560                     wxMSWDCImpl 
*impl 
= (wxMSWDCImpl
*) dc
.GetImpl(); 
3562                     // Clip the DC so that you only draw on the non-client area 
3564                     wxCopyRectToRECT(GetSize(), rcBorder
); 
3567                     theme
->GetThemeBackgroundContentRect( 
3568                         hTheme
, GetHdcOf(*impl
), EP_EDITTEXT
, ETS_NORMAL
, &rcBorder
, &rcClient
); 
3569                     InflateRect(&rcClient
, -1, -1); 
3571                     ::ExcludeClipRect(GetHdcOf(*impl
), rcClient
.left
, rcClient
.top
, 
3572                                       rcClient
.right
, rcClient
.bottom
); 
3574                     // Make sure the background is in a proper state 
3575                     if (theme
->IsThemeBackgroundPartiallyTransparent(hTheme
, EP_EDITTEXT
, ETS_NORMAL
)) 
3577                         theme
->DrawThemeParentBackground(GetHwnd(), GetHdcOf(*impl
), &rcBorder
); 
3583                         nState 
= ETS_DISABLED
; 
3584                     // should we check this? 
3585                     //else if ( ::GetWindowLong(GetHwnd(), GWL_STYLE) & ES_READONLY) 
3586                     //    nState = ETS_READONLY; 
3588                         nState 
= ETS_NORMAL
; 
3589                     theme
->DrawThemeBackground(hTheme
, GetHdcOf(*impl
), EP_EDITTEXT
, nState
, &rcBorder
, NULL
); 
3594 #endif // wxUSE_UXTHEME 
3597             // try a custom message handler 
3598             const MSWMessageHandlers::const_iterator
 
3599                 i 
= gs_messageHandlers
.find(message
); 
3600             if ( i 
!= gs_messageHandlers
.end() ) 
3602                 processed 
= (*i
->second
)(this, message
, wParam
, lParam
); 
3609     *result 
= rc
.result
; 
3614 WXLRESULT 
wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
3617     if ( !MSWHandleMessage(&result
, message
, wParam
, lParam
) ) 
3619 #if wxDEBUG_LEVEL >= 2 
3620         wxLogTrace("winmsg", wxT("Forwarding %s to DefWindowProc."), 
3621                    wxGetMessageName(message
)); 
3622 #endif // wxDEBUG_LEVEL >= 2 
3623         result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
3629 // ---------------------------------------------------------------------------- 
3630 // wxWindow <-> HWND map 
3631 // ---------------------------------------------------------------------------- 
3633 wxWindow 
*wxFindWinFromHandle(HWND hwnd
) 
3635     WindowHandles::const_iterator i 
= gs_windowHandles
.find(hwnd
); 
3636     return i 
== gs_windowHandles
.end() ? NULL 
: i
->second
; 
3639 void wxAssociateWinWithHandle(HWND hwnd
, wxWindowMSW 
*win
) 
3641     // adding NULL hwnd is (first) surely a result of an error and 
3642     // (secondly) breaks menu command processing 
3643     wxCHECK_RET( hwnd 
!= (HWND
)NULL
, 
3644                  wxT("attempt to add a NULL hwnd to window list ignored") ); 
3647     WindowHandles::const_iterator i 
= gs_windowHandles
.find(hwnd
); 
3648     if ( i 
!= gs_windowHandles
.end() ) 
3650         if ( i
->second 
!= win 
) 
3654                     wxT("HWND %p already associated with another window (%s)"), 
3655                     hwnd
, win
->GetClassInfo()->GetClassName() 
3659         //else: this actually happens currently because we associate the window 
3660         //      with its HWND during creation (if we create it) and also when 
3661         //      SubclassWin() is called later, this is ok 
3663 #endif // wxDEBUG_LEVEL 
3665     gs_windowHandles
[hwnd
] = (wxWindow 
*)win
; 
3668 void wxRemoveHandleAssociation(wxWindowMSW 
*win
) 
3670     gs_windowHandles
.erase(GetHwndOf(win
)); 
3673 // ---------------------------------------------------------------------------- 
3674 // various MSW speciic class dependent functions 
3675 // ---------------------------------------------------------------------------- 
3677 // Default destroyer - override if you destroy it in some other way 
3678 // (e.g. with MDI child windows) 
3679 void wxWindowMSW::MSWDestroyWindow() 
3683 void wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
, 
3686                                            int& w
, int& h
) const 
3688     // CW_USEDEFAULT can't be used for child windows so just position them at 
3689     // the origin by default 
3690     x 
= pos
.x 
== wxDefaultCoord 
? 0 : pos
.x
; 
3691     y 
= pos
.y 
== wxDefaultCoord 
? 0 : pos
.y
; 
3693     AdjustForParentClientOrigin(x
, y
); 
3695     // We don't have any clearly good choice for the size by default neither 
3696     // but we must use something non-zero. 
3697     w 
= WidthDefault(size
.x
); 
3698     h 
= HeightDefault(size
.y
); 
3701       NB: there used to be some code here which set the initial size of the 
3702           window to the client size of the parent if no explicit size was 
3703           specified. This was wrong because wxWidgets programs often assume 
3704           that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke 
3705           it. To see why, you should understand that Windows sends WM_SIZE from 
3706           inside ::CreateWindow() anyhow. However, ::CreateWindow() is called 
3707           from some base class ctor and so this WM_SIZE is not processed in the 
3708           real class' OnSize() (because it's not fully constructed yet and the 
3709           event goes to some base class OnSize() instead). So the WM_SIZE we 
3710           rely on is the one sent when the parent frame resizes its children 
3711           but here is the problem: if the child already has just the right 
3712           size, nothing will happen as both wxWidgets and Windows check for 
3713           this and ignore any attempts to change the window size to the size it 
3714           already has - so no WM_SIZE would be sent. 
3718 WXHWND 
wxWindowMSW::MSWGetParent() const 
3720     return m_parent 
? m_parent
->GetHWND() : WXHWND(NULL
); 
3723 bool wxWindowMSW::MSWCreate(const wxChar 
*wclass
, 
3724                             const wxChar 
*title
, 
3728                             WXDWORD extendedStyle
) 
3730     // check a common bug in the user code: if the window is created with a 
3731     // non-default ctor and Create() is called too, we'd create 2 HWND for a 
3732     // single wxWindow object and this results in all sorts of trouble, 
3733     // especially for wxTLWs 
3734     wxCHECK_MSG( !m_hWnd
, true, "window can't be recreated" ); 
3736     // this can happen if this function is called using the return value of 
3737     // wxApp::GetRegisteredClassName() which failed 
3738     wxCHECK_MSG( wclass
, false, "failed to register window class?" ); 
3741     // choose the position/size for the new window 
3743     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
3745     // controlId is menu handle for the top level windows, so set it to 0 
3746     // unless we're creating a child window 
3747     int controlId 
= style 
& WS_CHILD 
? GetId() : 0; 
3749     // for each class "Foo" we have we also have "FooNR" ("no repaint") class 
3750     // which is the same but without CS_[HV]REDRAW class styles so using it 
3751     // ensures that the window is not fully repainted on each resize 
3752     wxString 
className(wclass
); 
3753     if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE
) ) 
3755         className 
+= wxApp::GetNoRedrawClassSuffix(); 
3758     // do create the window 
3759     wxWindowCreationHook 
hook(this); 
3761     m_hWnd 
= (WXHWND
)::CreateWindowEx
 
3765                         title 
? title 
: m_windowName
.wx_str(), 
3768                         (HWND
)MSWGetParent(), 
3769                         (HMENU
)wxUIntToPtr(controlId
), 
3771                         NULL                        
// no extra data 
3776         wxLogSysError(_("Can't create window of class %s"), className
.c_str()); 
3781     SubclassWin(m_hWnd
); 
3786 // =========================================================================== 
3787 // MSW message handlers 
3788 // =========================================================================== 
3790 // --------------------------------------------------------------------------- 
3792 // --------------------------------------------------------------------------- 
3794 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
3796 #ifndef __WXMICROWIN__ 
3797     LPNMHDR hdr 
= (LPNMHDR
)lParam
; 
3798     HWND hWnd 
= hdr
->hwndFrom
; 
3799     wxWindow 
*win 
= wxFindWinFromHandle(hWnd
); 
3801     // if the control is one of our windows, let it handle the message itself 
3804         return win
->MSWOnNotify(idCtrl
, lParam
, result
); 
3807     // VZ: why did we do it? normally this is unnecessary and, besides, it 
3808     //     breaks the message processing for the toolbars because the tooltip 
3809     //     notifications were being forwarded to the toolbar child controls 
3810     //     (if it had any) before being passed to the toolbar itself, so in my 
3811     //     example the tooltip for the combobox was always shown instead of the 
3812     //     correct button tooltips 
3814     // try all our children 
3815     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3818         wxWindow 
*child 
= node
->GetData(); 
3819         if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) ) 
3824         node 
= node
->GetNext(); 
3828     // by default, handle it ourselves 
3829     return MSWOnNotify(idCtrl
, lParam
, result
); 
3830 #else // __WXMICROWIN__ 
3837 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
, 
3839                                       const wxString
& ttip
) 
3841     // I don't know why it happens, but the versions of comctl32.dll starting 
3842     // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally, 
3843     // this message is supposed to be sent to Unicode programs only) -- hence 
3844     // we need to handle it as well, otherwise no tooltips will be shown in 
3847     if ( !(code 
== (WXUINT
) TTN_NEEDTEXTA 
|| code 
== (WXUINT
) TTN_NEEDTEXTW
) 
3850         // not a tooltip message or no tooltip to show anyhow 
3855     LPTOOLTIPTEXT ttText 
= (LPTOOLTIPTEXT
)lParam
; 
3857     // We don't want to use the szText buffer because it has a limit of 80 
3858     // bytes and this is not enough, especially for Unicode build where it 
3859     // limits the tooltip string length to only 40 characters 
3861     // The best would be, of course, to not impose any length limitations at 
3862     // all but then the buffer would have to be dynamic and someone would have 
3863     // to free it and we don't have the tooltip owner object here any more, so 
3864     // for now use our own static buffer with a higher fixed max length. 
3866     // Note that using a static buffer should not be a problem as only a single 
3867     // tooltip can be shown at the same time anyhow. 
3869     if ( code 
== (WXUINT
) TTN_NEEDTEXTW 
) 
3871         // We need to convert tooltip from multi byte to Unicode on the fly. 
3872         static wchar_t buf
[513]; 
3874         // Truncate tooltip length if needed as otherwise we might not have 
3875         // enough space for it in the buffer and MultiByteToWideChar() would 
3877         size_t tipLength 
= wxMin(ttip
.length(), WXSIZEOF(buf
) - 1); 
3879         // Convert to WideChar without adding the NULL character. The NULL 
3880         // character is added afterwards (this is more efficient). 
3881         int len 
= ::MultiByteToWideChar
 
3893             wxLogLastError(wxT("MultiByteToWideChar()")); 
3897         ttText
->lpszText 
= (LPSTR
) buf
; 
3899     else // TTN_NEEDTEXTA 
3900 #endif // !wxUSE_UNICODE 
3902         // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or 
3903         // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have 
3904         // to copy the string we have into the buffer 
3905         static wxChar buf
[513]; 
3906         wxStrlcpy(buf
, ttip
.c_str(), WXSIZEOF(buf
)); 
3907         ttText
->lpszText 
= buf
; 
3913 #endif // wxUSE_TOOLTIPS 
3915 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
), 
3917                               WXLPARAM
* WXUNUSED(result
)) 
3922         NMHDR
* hdr 
= (NMHDR 
*)lParam
; 
3923         if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip())) 
3930     wxUnusedVar(lParam
); 
3931 #endif // wxUSE_TOOLTIPS 
3936 // --------------------------------------------------------------------------- 
3937 // end session messages 
3938 // --------------------------------------------------------------------------- 
3940 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
) 
3942 #ifdef ENDSESSION_LOGOFF 
3943     wxCloseEvent 
event(wxEVT_QUERY_END_SESSION
, wxID_ANY
); 
3944     event
.SetEventObject(wxTheApp
); 
3945     event
.SetCanVeto(true); 
3946     event
.SetLoggingOff(logOff 
== (long)ENDSESSION_LOGOFF
); 
3948     bool rc 
= wxTheApp
->ProcessEvent(event
); 
3952         // we may end only if the app didn't veto session closing (double 
3954         *mayEnd 
= !event
.GetVeto(); 
3959     wxUnusedVar(logOff
); 
3960     wxUnusedVar(mayEnd
); 
3965 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
) 
3967 #ifdef ENDSESSION_LOGOFF 
3968     // do nothing if the session isn't ending 
3973     if ( (this != wxTheApp
->GetTopWindow()) ) 
3976     wxCloseEvent 
event(wxEVT_END_SESSION
, wxID_ANY
); 
3977     event
.SetEventObject(wxTheApp
); 
3978     event
.SetCanVeto(false); 
3979     event
.SetLoggingOff((logOff 
& ENDSESSION_LOGOFF
) != 0); 
3981     return wxTheApp
->ProcessEvent(event
); 
3983     wxUnusedVar(endSession
); 
3984     wxUnusedVar(logOff
); 
3989 // --------------------------------------------------------------------------- 
3990 // window creation/destruction 
3991 // --------------------------------------------------------------------------- 
3993 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT 
WXUNUSED_IN_WINCE(cs
), 
3996     // VZ: why is this commented out for WinCE? If it doesn't support 
3997     //     WS_EX_CONTROLPARENT at all it should be somehow handled globally, 
3998     //     not with multiple #ifdef's! 
4000     if ( ((CREATESTRUCT 
*)cs
)->dwExStyle 
& WS_EX_CONTROLPARENT 
) 
4001         EnsureParentHasControlParentStyle(GetParent()); 
4002 #endif // !__WXWINCE__ 
4009 bool wxWindowMSW::HandleDestroy() 
4011     // delete our drop target if we've got one 
4012 #if wxUSE_DRAG_AND_DROP 
4013     if ( m_dropTarget 
!= NULL 
) 
4015         m_dropTarget
->Revoke(m_hWnd
); 
4017         wxDELETE(m_dropTarget
); 
4019 #endif // wxUSE_DRAG_AND_DROP 
4021     // WM_DESTROY handled 
4025 // --------------------------------------------------------------------------- 
4027 // --------------------------------------------------------------------------- 
4029 bool wxWindowMSW::HandleActivate(int state
, 
4030                               bool WXUNUSED(minimized
), 
4031                               WXHWND 
WXUNUSED(activate
)) 
4033     wxActivateEvent 
event(wxEVT_ACTIVATE
, 
4034                           (state 
== WA_ACTIVE
) || (state 
== WA_CLICKACTIVE
), 
4036     event
.SetEventObject(this); 
4038     return HandleWindowEvent(event
); 
4041 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
) 
4043     // Strangly enough, some controls get set focus events when they are being 
4044     // deleted, even if they already had focus before. 
4045     if ( m_isBeingDeleted 
) 
4050     // notify the parent keeping track of focus for the kbd navigation 
4051     // purposes that we got it 
4052     wxChildFocusEvent 
eventFocus((wxWindow 
*)this); 
4053     (void)HandleWindowEvent(eventFocus
); 
4059         m_caret
->OnSetFocus(); 
4061 #endif // wxUSE_CARET 
4063     wxFocusEvent 
event(wxEVT_SET_FOCUS
, m_windowId
); 
4064     event
.SetEventObject(this); 
4066     // wxFindWinFromHandle() may return NULL, it is ok 
4067     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
4069     return HandleWindowEvent(event
); 
4072 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
) 
4078         m_caret
->OnKillFocus(); 
4080 #endif // wxUSE_CARET 
4082     // Don't send the event when in the process of being deleted.  This can 
4083     // only cause problems if the event handler tries to access the object. 
4084     if ( m_isBeingDeleted 
) 
4089     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, m_windowId
); 
4090     event
.SetEventObject(this); 
4092     // wxFindWinFromHandle() may return NULL, it is ok 
4093     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
4095     return HandleWindowEvent(event
); 
4098 // --------------------------------------------------------------------------- 
4100 // --------------------------------------------------------------------------- 
4102 void wxWindowMSW::SetLabel( const wxString
& label
) 
4104     SetWindowText(GetHwnd(), label
.c_str()); 
4107 wxString 
wxWindowMSW::GetLabel() const 
4109     return wxGetWindowText(GetHWND()); 
4112 // --------------------------------------------------------------------------- 
4114 // --------------------------------------------------------------------------- 
4116 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
)) 
4118     wxShowEvent 
event(GetId(), show
); 
4119     event
.SetEventObject(this); 
4121     return HandleWindowEvent(event
); 
4124 bool wxWindowMSW::HandleInitDialog(WXHWND 
WXUNUSED(hWndFocus
)) 
4126     wxInitDialogEvent 
event(GetId()); 
4127     event
.SetEventObject(this); 
4129     return HandleWindowEvent(event
); 
4132 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
) 
4134 #if defined (__WXMICROWIN__) || defined(__WXWINCE__) 
4135     wxUnusedVar(wParam
); 
4137 #else // __WXMICROWIN__ 
4138     HDROP hFilesInfo 
= (HDROP
) wParam
; 
4140     // Get the total number of files dropped 
4141     UINT gwFilesDropped 
= ::DragQueryFile
 
4149     wxString 
*files 
= new wxString
[gwFilesDropped
]; 
4150     for ( UINT wIndex 
= 0; wIndex 
< gwFilesDropped
; wIndex
++ ) 
4152         // first get the needed buffer length (+1 for terminating NUL) 
4153         size_t len 
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1; 
4155         // and now get the file name 
4156         ::DragQueryFile(hFilesInfo
, wIndex
, 
4157                         wxStringBuffer(files
[wIndex
], len
), len
); 
4160     wxDropFilesEvent 
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
); 
4161     event
.SetEventObject(this); 
4164     DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
); 
4165     event
.m_pos
.x 
= dropPoint
.x
; 
4166     event
.m_pos
.y 
= dropPoint
.y
; 
4168     DragFinish(hFilesInfo
); 
4170     return HandleWindowEvent(event
); 
4175 bool wxWindowMSW::HandleSetCursor(WXHWND 
WXUNUSED(hWnd
), 
4177                                   int WXUNUSED(mouseMsg
)) 
4179 #ifndef __WXMICROWIN__ 
4180     // the logic is as follows: 
4181     //  0. if we're busy, set the busy cursor (even for non client elements) 
4182     //  1. don't set custom cursor for non client area of enabled windows 
4183     //  2. ask user EVT_SET_CURSOR handler for the cursor 
4184     //  3. if still no cursor but we're in a TLW, set the global cursor 
4186     HCURSOR hcursor 
= 0; 
4189         hcursor 
= wxGetCurrentBusyCursor(); 
4193         if ( nHitTest 
!= HTCLIENT 
) 
4196         // first ask the user code - it may wish to set the cursor in some very 
4197         // specific way (for example, depending on the current position) 
4199         wxGetCursorPosMSW(&pt
); 
4203         ScreenToClient(&x
, &y
); 
4204         wxSetCursorEvent 
event(x
, y
); 
4205         event
.SetId(GetId()); 
4206         event
.SetEventObject(this); 
4208         bool processedEvtSetCursor 
= HandleWindowEvent(event
); 
4209         if ( processedEvtSetCursor 
&& event
.HasCursor() ) 
4211             hcursor 
= GetHcursorOf(event
.GetCursor()); 
4216             // the test for processedEvtSetCursor is here to prevent using 
4217             // m_cursor if the user code caught EVT_SET_CURSOR() and returned 
4218             // nothing from it - this is a way to say that our cursor shouldn't 
4219             // be used for this point 
4220             if ( !processedEvtSetCursor 
&& m_cursor
.IsOk() ) 
4222                 hcursor 
= GetHcursorOf(m_cursor
); 
4225             if ( !hcursor 
&& !GetParent() ) 
4227                 const wxCursor 
*cursor 
= wxGetGlobalCursor(); 
4228                 if ( cursor 
&& cursor
->IsOk() ) 
4230                     hcursor 
= GetHcursorOf(*cursor
); 
4239         ::SetCursor(hcursor
); 
4241         // cursor set, stop here 
4244 #endif // __WXMICROWIN__ 
4246     // pass up the window chain 
4250 bool wxWindowMSW::HandlePower(WXWPARAM 
WXUNUSED_IN_WINCE(wParam
), 
4251                               WXLPARAM 
WXUNUSED(lParam
), 
4252                               bool *WXUNUSED_IN_WINCE(vetoed
)) 
4258     wxEventType evtType
; 
4261         case PBT_APMQUERYSUSPEND
: 
4262             evtType 
= wxEVT_POWER_SUSPENDING
; 
4265         case PBT_APMQUERYSUSPENDFAILED
: 
4266             evtType 
= wxEVT_POWER_SUSPEND_CANCEL
; 
4269         case PBT_APMSUSPEND
: 
4270             evtType 
= wxEVT_POWER_SUSPENDED
; 
4273         case PBT_APMRESUMESUSPEND
: 
4274             evtType 
= wxEVT_POWER_RESUME
; 
4278             wxLogDebug(wxT("Unknown WM_POWERBROADCAST(%d) event"), wParam
); 
4281         // these messages are currently not mapped to wx events 
4282         case PBT_APMQUERYSTANDBY
: 
4283         case PBT_APMQUERYSTANDBYFAILED
: 
4284         case PBT_APMSTANDBY
: 
4285         case PBT_APMRESUMESTANDBY
: 
4286         case PBT_APMBATTERYLOW
: 
4287         case PBT_APMPOWERSTATUSCHANGE
: 
4288         case PBT_APMOEMEVENT
: 
4289         case PBT_APMRESUMECRITICAL
: 
4290 #ifdef PBT_APMRESUMEAUTOMATIC 
4291         case PBT_APMRESUMEAUTOMATIC
: 
4293             evtType 
= wxEVT_NULL
; 
4297     // don't handle unknown messages 
4298     if ( evtType 
== wxEVT_NULL 
) 
4301     // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events? 
4303     wxPowerEvent 
event(evtType
); 
4304     if ( !HandleWindowEvent(event
) ) 
4307     *vetoed 
= event
.IsVetoed(); 
4313 bool wxWindowMSW::IsDoubleBuffered() const 
4315     for ( const wxWindowMSW 
*win 
= this; win
; win 
= win
->GetParent() ) 
4317         if ( wxHasWindowExStyle(win
, WS_EX_COMPOSITED
) ) 
4320         if ( win
->IsTopLevel() ) 
4327 void wxWindowMSW::SetDoubleBuffered(bool on
) 
4329     // Get the current extended style bits 
4330     long exstyle 
= wxGetWindowExStyle(this); 
4332     // Twiddle the bit as needed 
4334         exstyle 
|= WS_EX_COMPOSITED
; 
4336         exstyle 
&= ~WS_EX_COMPOSITED
; 
4339     wxSetWindowExStyle(this, exstyle
); 
4342 // --------------------------------------------------------------------------- 
4343 // owner drawn stuff 
4344 // --------------------------------------------------------------------------- 
4346 #if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \ 
4347         (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)) 
4348     #define WXUNUSED_UNLESS_ODRAWN(param) param 
4350     #define WXUNUSED_UNLESS_ODRAWN(param) 
4354 wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id
), 
4355                            WXDRAWITEMSTRUCT 
* WXUNUSED_UNLESS_ODRAWN(itemStruct
)) 
4357 #if wxUSE_OWNER_DRAWN 
4359 #if wxUSE_MENUS_NATIVE 
4360     // is it a menu item? 
4361     DRAWITEMSTRUCT 
*pDrawStruct 
= (DRAWITEMSTRUCT 
*)itemStruct
; 
4362     if ( id 
== 0 && pDrawStruct
->CtlType 
== ODT_MENU 
) 
4364         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pDrawStruct
->itemData
); 
4366         // see comment before the same test in MSWOnMeasureItem() below 
4370         wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
), 
4371                          false, wxT("MSWOnDrawItem: bad wxMenuItem pointer") ); 
4373         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent 
4374         // the DC from being released 
4375         wxDCTemp 
dc((WXHDC
)pDrawStruct
->hDC
); 
4376         wxRect 
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
, 
4377                     pDrawStruct
->rcItem
.right 
- pDrawStruct
->rcItem
.left
, 
4378                     pDrawStruct
->rcItem
.bottom 
- pDrawStruct
->rcItem
.top
); 
4380         return pMenuItem
->OnDrawItem
 
4384                 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
, 
4385                 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
 
4388 #endif // wxUSE_MENUS_NATIVE 
4390 #endif // USE_OWNER_DRAWN 
4392 #if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) 
4394 #if wxUSE_OWNER_DRAWN 
4395     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
4396 #else // !wxUSE_OWNER_DRAWN 
4397     // we may still have owner-drawn buttons internally because we have to make 
4398     // them owner-drawn to support colour change 
4401                          wxDynamicCast(FindItem(id
), wxButton
) 
4406 #endif // USE_OWNER_DRAWN 
4410         return item
->MSWOnDraw(itemStruct
); 
4413 #endif // wxUSE_CONTROLS 
4419 wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT 
*itemStruct
) 
4421 #if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE 
4422     // is it a menu item? 
4423     MEASUREITEMSTRUCT 
*pMeasureStruct 
= (MEASUREITEMSTRUCT 
*)itemStruct
; 
4424     if ( id 
== 0 && pMeasureStruct
->CtlType 
== ODT_MENU 
) 
4426         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pMeasureStruct
->itemData
); 
4428         // according to Carsten Fuchs the pointer may be NULL under XP if an 
4429         // MDI child frame is initially maximized, see this for more info: 
4430         // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745 
4432         // so silently ignore it instead of asserting 
4436         wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
), 
4437                         false, wxT("MSWOnMeasureItem: bad wxMenuItem pointer") ); 
4440         bool rc 
= pMenuItem
->OnMeasureItem(&w
, &h
); 
4442         pMeasureStruct
->itemWidth 
= w
; 
4443         pMeasureStruct
->itemHeight 
= h
; 
4448     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
4451         return item
->MSWOnMeasure(itemStruct
); 
4455     wxUnusedVar(itemStruct
); 
4456 #endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE 
4461 // --------------------------------------------------------------------------- 
4462 // colours and palettes 
4463 // --------------------------------------------------------------------------- 
4465 bool wxWindowMSW::HandleSysColorChange() 
4467     wxSysColourChangedEvent event
; 
4468     event
.SetEventObject(this); 
4470     (void)HandleWindowEvent(event
); 
4472     // always let the system carry on the default processing to allow the 
4473     // native controls to react to the colours update 
4477 bool wxWindowMSW::HandleDisplayChange() 
4479     wxDisplayChangedEvent event
; 
4480     event
.SetEventObject(this); 
4482     return HandleWindowEvent(event
); 
4485 #ifndef __WXMICROWIN__ 
4487 bool wxWindowMSW::HandleCtlColor(WXHBRUSH 
*brush
, WXHDC hDC
, WXHWND hWnd
) 
4489 #if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__) 
4493     wxControl 
*item 
= wxDynamicCast(FindItemByHWND(hWnd
, true), wxControl
); 
4496         *brush 
= item
->MSWControlColor(hDC
, hWnd
); 
4498 #endif // wxUSE_CONTROLS 
4501     return *brush 
!= NULL
; 
4504 #endif // __WXMICROWIN__ 
4506 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
) 
4509     // same as below except we don't respond to our own messages 
4510     if ( hWndPalChange 
!= GetHWND() ) 
4512         // check to see if we our our parents have a custom palette 
4513         wxWindowMSW 
*win 
= this; 
4514         while ( win 
&& !win
->HasCustomPalette() ) 
4516             win 
= win
->GetParent(); 
4519         if ( win 
&& win
->HasCustomPalette() ) 
4521             // realize the palette to see whether redrawing is needed 
4522             HDC hdc 
= ::GetDC((HWND
) hWndPalChange
); 
4523             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
4524                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
4526             int result 
= ::RealizePalette(hdc
); 
4528             // restore the palette (before releasing the DC) 
4529             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
4530                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
4531             ::RealizePalette(hdc
); 
4532             ::ReleaseDC((HWND
) hWndPalChange
, hdc
); 
4534             // now check for the need to redraw 
4536                 ::InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
); 
4540 #endif // wxUSE_PALETTE 
4542     wxPaletteChangedEvent 
event(GetId()); 
4543     event
.SetEventObject(this); 
4544     event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
)); 
4546     return HandleWindowEvent(event
); 
4549 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
) 
4551     // notify windows on the capture stack about lost capture 
4552     // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863): 
4553     wxWindowBase::NotifyCaptureLost(); 
4555     wxWindow 
*win 
= wxFindWinFromHandle(hWndGainedCapture
); 
4556     wxMouseCaptureChangedEvent 
event(GetId(), win
); 
4557     event
.SetEventObject(this); 
4558     return HandleWindowEvent(event
); 
4561 bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam
, WXLPARAM lParam
) 
4563     // despite MSDN saying "(This message cannot be sent directly to a window.)" 
4564     // we need to send this to child windows (it is only sent to top-level 
4565     // windows) so {list,tree}ctrls can adjust their font size if necessary 
4566     // this is exactly how explorer does it to enable the font size changes 
4568     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4571         // top-level windows already get this message from the system 
4572         wxWindow 
*win 
= node
->GetData(); 
4573         if ( !win
->IsTopLevel() ) 
4575             ::SendMessage(GetHwndOf(win
), WM_SETTINGCHANGE
, wParam
, lParam
); 
4578         node 
= node
->GetNext(); 
4581     // let the system handle it 
4585 bool wxWindowMSW::HandleQueryNewPalette() 
4589     // check to see if we our our parents have a custom palette 
4590     wxWindowMSW 
*win 
= this; 
4591     while (!win
->HasCustomPalette() && win
->GetParent()) win 
= win
->GetParent(); 
4592     if (win
->HasCustomPalette()) { 
4593         /* realize the palette to see whether redrawing is needed */ 
4594         HDC hdc 
= ::GetDC((HWND
) GetHWND()); 
4595         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
4596              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) ); 
4598         int result 
= ::RealizePalette(hdc
); 
4599         /* restore the palette (before releasing the DC) */ 
4600         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
4601              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) ); 
4602         ::RealizePalette(hdc
); 
4603         ::ReleaseDC((HWND
) GetHWND(), hdc
); 
4604         /* now check for the need to redraw */ 
4606             ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
); 
4608 #endif // wxUSE_PALETTE 
4610     wxQueryNewPaletteEvent 
event(GetId()); 
4611     event
.SetEventObject(this); 
4613     return HandleWindowEvent(event
) && event
.GetPaletteRealized(); 
4616 // Responds to colour changes: passes event on to children. 
4617 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
4619     // the top level window also reset the standard colour map as it might have 
4620     // changed (there is no need to do it for the non top level windows as we 
4621     // only have to do it once) 
4625         gs_hasStdCmap 
= false; 
4627     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4630         // Only propagate to non-top-level windows because Windows already 
4631         // sends this event to all top-level ones 
4632         wxWindow 
*win 
= node
->GetData(); 
4633         if ( !win
->IsTopLevel() ) 
4635             // we need to send the real WM_SYSCOLORCHANGE and not just trigger 
4636             // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for 
4637             // the standard controls 
4638             ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0); 
4641         node 
= node
->GetNext(); 
4645 extern wxCOLORMAP 
*wxGetStdColourMap() 
4647     static COLORREF s_stdColours
[wxSTD_COL_MAX
]; 
4648     static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
]; 
4650     if ( !gs_hasStdCmap 
) 
4652         static bool s_coloursInit 
= false; 
4654         if ( !s_coloursInit 
) 
4656             // When a bitmap is loaded, the RGB values can change (apparently 
4657             // because Windows adjusts them to care for the old programs always 
4658             // using 0xc0c0c0 while the transparent colour for the new Windows 
4659             // versions is different). But we do this adjustment ourselves so 
4660             // we want to avoid Windows' "help" and for this we need to have a 
4661             // reference bitmap which can tell us what the RGB values change 
4663             wxLogNull logNo
; // suppress error if we couldn't load the bitmap 
4664             wxBitmap 
stdColourBitmap(wxT("wxBITMAP_STD_COLOURS")); 
4665             if ( stdColourBitmap
.IsOk() ) 
4667                 // the pixels in the bitmap must correspond to wxSTD_COL_XXX! 
4668                 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
, 
4669                               wxT("forgot to update wxBITMAP_STD_COLOURS!") ); 
4672                 memDC
.SelectObject(stdColourBitmap
); 
4675                 for ( size_t i 
= 0; i 
< WXSIZEOF(s_stdColours
); i
++ ) 
4677                     memDC
.GetPixel(i
, 0, &colour
); 
4678                     s_stdColours
[i
] = wxColourToRGB(colour
); 
4681             else // wxBITMAP_STD_COLOURS couldn't be loaded 
4683                 s_stdColours
[0] = RGB(000,000,000);     // black 
4684                 s_stdColours
[1] = RGB(128,128,128);     // dark grey 
4685                 s_stdColours
[2] = RGB(192,192,192);     // light grey 
4686                 s_stdColours
[3] = RGB(255,255,255);     // white 
4687                 //s_stdColours[4] = RGB(000,000,255);     // blue 
4688                 //s_stdColours[5] = RGB(255,000,255);     // magenta 
4691             s_coloursInit 
= true; 
4694         gs_hasStdCmap 
= true; 
4696         // create the colour map 
4697 #define INIT_CMAP_ENTRY(col) \ 
4698             s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \ 
4699             s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col) 
4701         INIT_CMAP_ENTRY(BTNTEXT
); 
4702         INIT_CMAP_ENTRY(BTNSHADOW
); 
4703         INIT_CMAP_ENTRY(BTNFACE
); 
4704         INIT_CMAP_ENTRY(BTNHIGHLIGHT
); 
4706 #undef INIT_CMAP_ENTRY 
4712 #if wxUSE_UXTHEME && !defined(TMT_FILLCOLOR) 
4713     #define TMT_FILLCOLOR       3802 
4714     #define TMT_TEXTCOLOR       3803 
4715     #define TMT_BORDERCOLOR     3801 
4718 wxColour 
wxWindowMSW::MSWGetThemeColour(const wchar_t *themeName
, 
4721                                         MSWThemeColour themeColour
, 
4722                                         wxSystemColour fallback
) const 
4725     const wxUxThemeEngine
* theme 
= wxUxThemeEngine::GetIfActive(); 
4728         int themeProperty 
= 0; 
4730         // TODO: Convert this into a table? Sure would be faster. 
4731         switch ( themeColour 
) 
4733             case ThemeColourBackground
: 
4734                 themeProperty 
= TMT_FILLCOLOR
; 
4736             case ThemeColourText
: 
4737                 themeProperty 
= TMT_TEXTCOLOR
; 
4739             case ThemeColourBorder
: 
4740                 themeProperty 
= TMT_BORDERCOLOR
; 
4743                 wxFAIL_MSG(wxT("unsupported theme colour")); 
4746         wxUxThemeHandle 
hTheme((const wxWindow 
*)this, themeName
); 
4748         HRESULT hr 
= theme
->GetThemeColor
 
4757         if ( SUCCEEDED(hr
) ) 
4758             return wxRGBToColour(col
); 
4762                 "GetThemeColor(%s, %i, %i, %i)", 
4763                 themeName
, themePart
, themeState
, themeProperty
), 
4767     wxUnusedVar(themeName
); 
4768     wxUnusedVar(themePart
); 
4769     wxUnusedVar(themeState
); 
4770     wxUnusedVar(themeColour
); 
4772     return wxSystemSettings::GetColour(fallback
); 
4775 // --------------------------------------------------------------------------- 
4777 // --------------------------------------------------------------------------- 
4779 // this variable is used to check that a paint event handler which processed 
4780 // the event did create a wxPaintDC inside its code and called BeginPaint() to 
4781 // validate the invalidated window area as otherwise we'd keep getting an 
4782 // endless stream of WM_PAINT messages for this window resulting in a lot of 
4783 // difficult to debug problems (e.g. impossibility to repaint other windows, 
4784 // lack of timer and idle events and so on) 
4785 extern bool wxDidCreatePaintDC
; 
4786 bool wxDidCreatePaintDC 
= false; 
4788 bool wxWindowMSW::HandlePaint() 
4790     HRGN hRegion 
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle 
4793         wxLogLastError(wxT("CreateRectRgn")); 
4795     if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR 
) 
4797         wxLogLastError(wxT("GetUpdateRgn")); 
4800     m_updateRegion 
= wxRegion((WXHRGN
) hRegion
); 
4802     wxDidCreatePaintDC 
= false; 
4804     wxPaintEvent 
event(m_windowId
); 
4805     event
.SetEventObject(this); 
4807     bool processed 
= HandleWindowEvent(event
); 
4809     if ( processed 
&& !wxDidCreatePaintDC 
) 
4811         // do call MSWDefWindowProc() to validate the update region to avoid 
4812         // the problems mentioned above 
4816     // note that we must generate NC event after the normal one as otherwise 
4817     // BeginPaint() will happily overwrite our decorations with the background 
4819     wxNcPaintEvent 
eventNc(m_windowId
); 
4820     eventNc
.SetEventObject(this); 
4821     HandleWindowEvent(eventNc
); 
4823     // don't keep an HRGN we don't need any longer (GetUpdateRegion() can only 
4824     // be called from inside the event handlers called above) 
4825     m_updateRegion
.Clear(); 
4830 // Can be called from an application's OnPaint handler 
4831 void wxWindowMSW::OnPaint(wxPaintEvent
& event
) 
4833 #ifdef __WXUNIVERSAL__ 
4836     HDC hDC 
= (HDC
) wxPaintDCImpl::FindDCInCache((wxWindow
*) event
.GetEventObject()); 
4839         MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0); 
4844 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
) 
4846     switch ( GetBackgroundStyle() ) 
4848         case wxBG_STYLE_ERASE
: 
4849         case wxBG_STYLE_COLOUR
: 
4850             // we need to generate an erase background event 
4852                 wxDCTemp 
dc(hdc
, GetClientSize()); 
4853                 wxDCTempImpl 
*impl 
= (wxDCTempImpl
*) dc
.GetImpl(); 
4856                 impl
->SetWindow((wxWindow 
*)this); 
4858                 wxEraseEvent 
event(m_windowId
, &dc
); 
4859                 event
.SetEventObject(this); 
4860                 bool rc 
= HandleWindowEvent(event
); 
4862                 // must be called manually as ~wxDC doesn't do anything for 
4864                 impl
->SelectOldObjects(hdc
); 
4868                     // background erased by the user-defined handler 
4874         case wxBG_STYLE_SYSTEM
: 
4875             if ( !DoEraseBackground(hdc
) ) 
4877                 // let the default processing to take place if we didn't erase 
4878                 // the background ourselves 
4883         case wxBG_STYLE_PAINT
: 
4884         case wxBG_STYLE_TRANSPARENT
: 
4885             // no need to do anything here at all, background will be entirely 
4886             // redrawn in WM_PAINT handler 
4890             wxFAIL_MSG( "unknown background style" ); 
4896 #ifdef wxHAS_MSW_BACKGROUND_ERASE_HOOK 
4898 bool wxWindowMSW::MSWHasEraseBgHook() const 
4900     return gs_eraseBgHooks
.find(const_cast<wxWindowMSW 
*>(this)) 
4901                 != gs_eraseBgHooks
.end(); 
4904 void wxWindowMSW::MSWSetEraseBgHook(wxWindow 
*child
) 
4908         if ( !gs_eraseBgHooks
.insert( 
4909                 EraseBgHooks::value_type(this, child
)).second 
) 
4911             wxFAIL_MSG( wxT("Setting erase background hook twice?") ); 
4914     else // reset the hook 
4916         if ( gs_eraseBgHooks
.erase(this) != 1 ) 
4918             wxFAIL_MSG( wxT("Resetting erase background which was not set?") ); 
4923 #endif // wxHAS_MSW_BACKGROUND_ERASE_HOOK 
4925 bool wxWindowMSW::DoEraseBackground(WXHDC hDC
) 
4927     HBRUSH hbr 
= (HBRUSH
)MSWGetBgBrush(hDC
); 
4931     // erase just the client area of the window, this is important for the 
4932     // frames to avoid drawing over the toolbar part of the window (you might 
4933     // think using WS_CLIPCHILDREN would prevent this from happening, but it 
4936     wxCopyRectToRECT(GetClientRect(), rc
); 
4937     ::FillRect((HDC
)hDC
, &rc
, hbr
); 
4943 wxWindowMSW::MSWGetBgBrushForChild(WXHDC hDC
, wxWindowMSW 
*child
) 
4945     // Test for the custom background brush first. 
4946     WXHBRUSH hbrush 
= MSWGetCustomBgBrush(); 
4949         // We assume that this is either a stipple or hatched brush and not a 
4950         // solid one as otherwise it would have been enough to set the 
4951         // background colour and such brushes need to be positioned correctly 
4952         // in order to align when different windows are painted, so do it here. 
4954         ::GetWindowRect(GetHwndOf(child
), &rc
); 
4956         ::MapWindowPoints(NULL
, GetHwnd(), (POINT 
*)&rc
, 1); 
4958         if ( !::SetBrushOrgEx((HDC
)hDC
, -rc
.left
, -rc
.top
, NULL
) ) 
4960             wxLogLastError(wxT("SetBrushOrgEx(bg brush)")); 
4966     // Otherwise see if we have a custom background colour. 
4970             brush 
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour()); 
4972         return (WXHBRUSH
)GetHbrushOf(*brush
); 
4978 WXHBRUSH 
wxWindowMSW::MSWGetBgBrush(WXHDC hDC
) 
4980     // Use the special wxWindowBeingErased variable if it is set as the child 
4982     wxWindowMSW 
* const child 
= 
4984                                 wxWindowBeingErased 
? wxWindowBeingErased 
: 
4988     for ( wxWindowMSW 
*win 
= this; win
; win 
= win
->GetParent() ) 
4990         WXHBRUSH hBrush 
= win
->MSWGetBgBrushForChild(hDC
, child
); 
4994         // don't use the parent background if we're not transparent 
4995         if ( !win
->HasTransparentBackground() ) 
4998         // background is not inherited beyond top level windows 
4999         if ( win
->IsTopLevel() ) 
5006 bool wxWindowMSW::HandlePrintClient(WXHDC hDC
) 
5008     // we receive this message when DrawThemeParentBackground() is 
5009     // called from def window proc of several controls under XP and we 
5010     // must draw properly themed background here 
5012     // note that naively I'd expect filling the client rect with the 
5013     // brush returned by MSWGetBgBrush() work -- but for some reason it 
5014     // doesn't and we have to call parents MSWPrintChild() which is 
5015     // supposed to call DrawThemeBackground() with appropriate params 
5017     // also note that in this case lParam == PRF_CLIENT but we're 
5018     // clearly expected to paint the background and nothing else! 
5020     if ( IsTopLevel() || InheritsBackgroundColour() ) 
5023     // sometimes we don't want the parent to handle it at all, instead 
5024     // return whatever value this window wants 
5025     if ( !MSWShouldPropagatePrintChild() ) 
5026         return MSWPrintChild(hDC
, (wxWindow 
*)this); 
5028     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
5030         if ( win
->MSWPrintChild(hDC
, (wxWindow 
*)this) ) 
5033         if ( win
->IsTopLevel() || win
->InheritsBackgroundColour() ) 
5040 // --------------------------------------------------------------------------- 
5041 // moving and resizing 
5042 // --------------------------------------------------------------------------- 
5044 bool wxWindowMSW::HandleMinimize() 
5046     wxIconizeEvent 
event(m_windowId
); 
5047     event
.SetEventObject(this); 
5049     return HandleWindowEvent(event
); 
5052 bool wxWindowMSW::HandleMaximize() 
5054     wxMaximizeEvent 
event(m_windowId
); 
5055     event
.SetEventObject(this); 
5057     return HandleWindowEvent(event
); 
5060 bool wxWindowMSW::HandleMove(int x
, int y
) 
5063     wxMoveEvent 
event(point
, m_windowId
); 
5064     event
.SetEventObject(this); 
5066     return HandleWindowEvent(event
); 
5069 bool wxWindowMSW::HandleMoving(wxRect
& rect
) 
5071     wxMoveEvent 
event(rect
, m_windowId
); 
5072     event
.SetEventObject(this); 
5074     bool rc 
= HandleWindowEvent(event
); 
5076         rect 
= event
.GetRect(); 
5080 bool wxWindowMSW::HandleEnterSizeMove() 
5082     wxMoveEvent 
event(wxPoint(0,0), m_windowId
); 
5083     event
.SetEventType(wxEVT_MOVE_START
); 
5084     event
.SetEventObject(this); 
5086     return HandleWindowEvent(event
); 
5089 bool wxWindowMSW::HandleExitSizeMove() 
5091     wxMoveEvent 
event(wxPoint(0,0), m_windowId
); 
5092     event
.SetEventType(wxEVT_MOVE_END
); 
5093     event
.SetEventObject(this); 
5095     return HandleWindowEvent(event
); 
5098 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), WXUINT wParam
) 
5100 #if wxUSE_DEFERRED_SIZING 
5101     // when we resize this window, its children are probably going to be 
5102     // repositioned as well, prepare to use DeferWindowPos() for them 
5103     int numChildren 
= 0; 
5104     for ( HWND child 
= ::GetWindow(GetHwndOf(this), GW_CHILD
); 
5106           child 
= ::GetWindow(child
, GW_HWNDNEXT
) ) 
5111     // Protect against valid m_hDWP being overwritten 
5112     bool useDefer 
= false; 
5114     if ( numChildren 
> 1 ) 
5118             m_hDWP 
= (WXHANDLE
)::BeginDeferWindowPos(numChildren
); 
5121                 wxLogLastError(wxT("BeginDeferWindowPos")); 
5127 #endif // wxUSE_DEFERRED_SIZING 
5129     // update this window size 
5130     bool processed 
= false; 
5134             wxFAIL_MSG( wxT("unexpected WM_SIZE parameter") ); 
5135             // fall through nevertheless 
5139             // we're not interested in these messages at all 
5142         case SIZE_MINIMIZED
: 
5143             processed 
= HandleMinimize(); 
5146         case SIZE_MAXIMIZED
: 
5147             /* processed = */ HandleMaximize(); 
5148             // fall through to send a normal size event as well 
5151             // don't use w and h parameters as they specify the client size 
5152             // while according to the docs EVT_SIZE handler is supposed to 
5153             // receive the total size 
5154             wxSizeEvent 
event(GetSize(), m_windowId
); 
5155             event
.SetEventObject(this); 
5157             processed 
= HandleWindowEvent(event
); 
5160 #if wxUSE_DEFERRED_SIZING 
5161     // and finally change the positions of all child windows at once 
5162     if ( useDefer 
&& m_hDWP 
) 
5164         // reset m_hDWP to NULL so that child windows don't try to use our 
5165         // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't 
5166         // happen anyhow normally but who knows what weird flow of control we 
5167         // may have depending on what the users EVT_SIZE handler does...) 
5168         HDWP hDWP 
= (HDWP
)m_hDWP
; 
5171         // do put all child controls in place at once 
5172         if ( !::EndDeferWindowPos(hDWP
) ) 
5174             wxLogLastError(wxT("EndDeferWindowPos")); 
5177         // Reset our children's pending pos/size values. 
5178         for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
5180               node 
= node
->GetNext() ) 
5182             wxWindowMSW 
* const child 
= node
->GetData(); 
5183             child
->MSWEndDeferWindowPos(); 
5186 #endif // wxUSE_DEFERRED_SIZING 
5191 bool wxWindowMSW::HandleSizing(wxRect
& rect
) 
5193     wxSizeEvent 
event(rect
, m_windowId
); 
5194     event
.SetEventObject(this); 
5196     bool rc 
= HandleWindowEvent(event
); 
5198         rect 
= event
.GetRect(); 
5202 bool wxWindowMSW::HandleGetMinMaxInfo(void *WXUNUSED_IN_WINCE(mmInfo
)) 
5207     MINMAXINFO 
*info 
= (MINMAXINFO 
*)mmInfo
; 
5211     int minWidth 
= GetMinWidth(), 
5212         minHeight 
= GetMinHeight(), 
5213         maxWidth 
= GetMaxWidth(), 
5214         maxHeight 
= GetMaxHeight(); 
5216     if ( minWidth 
!= wxDefaultCoord 
) 
5218         info
->ptMinTrackSize
.x 
= minWidth
; 
5222     if ( minHeight 
!= wxDefaultCoord 
) 
5224         info
->ptMinTrackSize
.y 
= minHeight
; 
5228     if ( maxWidth 
!= wxDefaultCoord 
) 
5230         info
->ptMaxTrackSize
.x 
= maxWidth
; 
5234     if ( maxHeight 
!= wxDefaultCoord 
) 
5236         info
->ptMaxTrackSize
.y 
= maxHeight
; 
5244 // --------------------------------------------------------------------------- 
5246 // --------------------------------------------------------------------------- 
5248 bool wxWindowMSW::HandleCommand(WXWORD id_
, WXWORD cmd
, WXHWND control
) 
5250     // sign extend to int from short before comparing with the other int ids 
5251     int id 
= (signed short)id_
; 
5253 #if wxUSE_MENUS_NATIVE 
5254     if ( !cmd 
&& wxCurrentPopupMenu 
) 
5256         wxMenu 
*popupMenu 
= wxCurrentPopupMenu
; 
5257         wxCurrentPopupMenu 
= NULL
; 
5259         return popupMenu
->MSWCommand(cmd
, id
); 
5261 #endif // wxUSE_MENUS_NATIVE 
5263     wxWindow 
*win 
= NULL
; 
5265     // first try to find it from HWND - this works even with the broken 
5266     // programs using the same ids for different controls 
5269         win 
= wxFindWinFromHandle(control
); 
5280         return win
->MSWCommand(cmd
, id
); 
5283     // the messages sent from the in-place edit control used by the treectrl 
5284     // for label editing have id == 0, but they should _not_ be treated as menu 
5285     // messages (they are EN_XXX ones, in fact) so don't translate anything 
5286     // coming from a control to wxEVT_COMMAND_MENU_SELECTED 
5289         wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
, id
); 
5290         event
.SetEventObject(this); 
5293         return HandleWindowEvent(event
); 
5297 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
5298         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND 
5299         // notifications to its parent which we want to reflect back to 
5301         wxSpinCtrl 
*spin 
= wxSpinCtrl::GetSpinForTextCtrl(control
); 
5302         if ( spin 
&& spin
->ProcessTextCommand(cmd
, id
) ) 
5304 #endif // wxUSE_SPINCTRL 
5306 #if wxUSE_CHOICE && defined(__SMARTPHONE__) 
5307         // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND 
5308         // notifications to its parent which we want to reflect back to 
5310         wxChoice 
*choice 
= wxChoice::GetChoiceForListBox(control
); 
5311         if ( choice 
&& choice
->MSWCommand(cmd
, id
) ) 
5319 // --------------------------------------------------------------------------- 
5321 // --------------------------------------------------------------------------- 
5323 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
, 
5327     // our client coords are not quite the same as Windows ones 
5328     wxPoint pt 
= GetClientAreaOrigin(); 
5329     event
.m_x 
= x 
- pt
.x
; 
5330     event
.m_y 
= y 
- pt
.y
; 
5332     event
.m_shiftDown 
= (flags 
& MK_SHIFT
) != 0; 
5333     event
.m_controlDown 
= (flags 
& MK_CONTROL
) != 0; 
5334     event
.m_leftDown 
= (flags 
& MK_LBUTTON
) != 0; 
5335     event
.m_middleDown 
= (flags 
& MK_MBUTTON
) != 0; 
5336     event
.m_rightDown 
= (flags 
& MK_RBUTTON
) != 0; 
5337 #ifdef wxHAS_XBUTTON 
5338     event
.m_aux1Down 
= (flags 
& MK_XBUTTON1
) != 0; 
5339     event
.m_aux2Down 
= (flags 
& MK_XBUTTON2
) != 0; 
5340 #endif // wxHAS_XBUTTON 
5341     event
.m_altDown 
= ::wxIsAltDown(); 
5344     event
.SetTimestamp(::GetMessageTime()); 
5347     event
.SetEventObject(this); 
5348     event
.SetId(GetId()); 
5350 #if wxUSE_MOUSEEVENT_HACK 
5351     gs_lastMouseEvent
.pos 
= ClientToScreen(wxPoint(x
, y
)); 
5352     gs_lastMouseEvent
.type 
= event
.GetEventType(); 
5353 #endif // wxUSE_MOUSEEVENT_HACK 
5357 // Windows doesn't send the mouse events to the static controls (which are 
5358 // transparent in the sense that their WM_NCHITTEST handler returns 
5359 // HTTRANSPARENT) at all but we want all controls to receive the mouse events 
5360 // and so we manually check if we don't have a child window under mouse and if 
5361 // we do, send the event to it instead of the window Windows had sent WM_XXX 
5364 // Notice that this is not done for the mouse move events because this could 
5365 // (would?) be too slow, but only for clicks which means that the static texts 
5366 // still don't get move, enter nor leave events. 
5367 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
) 
5369     wxCHECK_MSG( x 
&& y
, win
, wxT("NULL pointer in FindWindowForMouseEvent") ); 
5371     // first try to find a non transparent child: this allows us to send events 
5372     // to a static text which is inside a static box, for example 
5373     POINT pt 
= { *x
, *y 
}; 
5374     HWND hwnd 
= GetHwndOf(win
), 
5378     hwndUnderMouse 
= ::ChildWindowFromPoint
 
5384     hwndUnderMouse 
= ::ChildWindowFromPointEx
 
5394     if ( !hwndUnderMouse 
|| hwndUnderMouse 
== hwnd 
) 
5396         // now try any child window at all 
5397         hwndUnderMouse 
= ::ChildWindowFromPoint(hwnd
, pt
); 
5400     // check that we have a child window which is susceptible to receive mouse 
5401     // events: for this it must be shown and enabled 
5402     if ( hwndUnderMouse 
&& 
5403             hwndUnderMouse 
!= hwnd 
&& 
5404                 ::IsWindowVisible(hwndUnderMouse
) && 
5405                     ::IsWindowEnabled(hwndUnderMouse
) ) 
5407         wxWindow 
*winUnderMouse 
= wxFindWinFromHandle(hwndUnderMouse
); 
5408         if ( winUnderMouse 
) 
5410             // translate the mouse coords to the other window coords 
5411             win
->ClientToScreen(x
, y
); 
5412             winUnderMouse
->ScreenToClient(x
, y
); 
5414             win 
= winUnderMouse
; 
5420 #endif // __WXWINCE__ 
5422 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
5424     // the mouse events take consecutive IDs from WM_MOUSEFIRST to 
5425     // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST 
5426     // from the message id and take the value in the table to get wxWin event 
5428     static const wxEventType eventsMouse
[] = 
5439         wxEVT_MIDDLE_DCLICK
, 
5440         0, // this one is for wxEVT_MOTION which is not used here 
5449 #ifdef wxHAS_XBUTTON 
5450     // the same messages are used for both auxillary mouse buttons so we need 
5451     // to adjust the index manually 
5454         case WM_XBUTTONDOWN
: 
5456         case WM_XBUTTONDBLCLK
: 
5457             if ( flags 
& MK_XBUTTON2 
) 
5458                 msg 
+= wxEVT_AUX2_DOWN 
- wxEVT_AUX1_DOWN
; 
5460 #endif // wxHAS_XBUTTON 
5462     wxMouseEvent 
event(eventsMouse
[msg 
- WM_MOUSEMOVE
]); 
5463     InitMouseEvent(event
, x
, y
, flags
); 
5465     return HandleWindowEvent(event
); 
5468 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
) 
5470     if ( !m_mouseInWindow 
) 
5472         // it would be wrong to assume that just because we get a mouse move 
5473         // event that the mouse is inside the window: although this is usually 
5474         // true, it is not if we had captured the mouse, so we need to check 
5475         // the mouse coordinates here 
5476         if ( !HasCapture() || IsMouseInWindow() ) 
5478             // Generate an ENTER event 
5479             m_mouseInWindow 
= true; 
5481 #ifdef HAVE_TRACKMOUSEEVENT 
5482             typedef BOOL (WINAPI 
*_TrackMouseEvent_t
)(LPTRACKMOUSEEVENT
); 
5484             static const _TrackMouseEvent_t
 
5485                 s_pfn_TrackMouseEvent 
= _TrackMouseEvent
; 
5486 #else // !__WXWINCE__ 
5487             static _TrackMouseEvent_t s_pfn_TrackMouseEvent
; 
5488             static bool s_initDone 
= false; 
5491                 // see comment in wxApp::GetComCtl32Version() explaining the 
5492                 // use of wxLoadedDLL 
5493                 wxLoadedDLL 
dllComCtl32(wxT("comctl32.dll")); 
5494                 if ( dllComCtl32
.IsLoaded() ) 
5496                     s_pfn_TrackMouseEvent 
= (_TrackMouseEvent_t
) 
5497                         dllComCtl32
.RawGetSymbol(wxT("_TrackMouseEvent")); 
5503             if ( s_pfn_TrackMouseEvent 
) 
5504 #endif // __WXWINCE__/!__WXWINCE__ 
5506                 WinStruct
<TRACKMOUSEEVENT
> trackinfo
; 
5508                 trackinfo
.dwFlags 
= TME_LEAVE
; 
5509                 trackinfo
.hwndTrack 
= GetHwnd(); 
5511                 (*s_pfn_TrackMouseEvent
)(&trackinfo
); 
5513 #endif // HAVE_TRACKMOUSEEVENT 
5515             wxMouseEvent 
event(wxEVT_ENTER_WINDOW
); 
5516             InitMouseEvent(event
, x
, y
, flags
); 
5518             (void)HandleWindowEvent(event
); 
5521 #ifdef HAVE_TRACKMOUSEEVENT 
5522     else // mouse not in window 
5524         // Check if we need to send a LEAVE event 
5525         // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so 
5526         // send it here if we are using native mouse leave tracking 
5527         if ( HasCapture() && !IsMouseInWindow() ) 
5529             GenerateMouseLeave(); 
5532 #endif // HAVE_TRACKMOUSEEVENT 
5534 #if wxUSE_MOUSEEVENT_HACK 
5535     // Windows often generates mouse events even if mouse position hasn't 
5536     // changed (http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/66576) 
5538     // Filter this out as it can result in unexpected behaviour compared to 
5540     if ( gs_lastMouseEvent
.type 
== wxEVT_RIGHT_DOWN 
|| 
5541          gs_lastMouseEvent
.type 
== wxEVT_LEFT_DOWN 
|| 
5542          gs_lastMouseEvent
.type 
== wxEVT_MIDDLE_DOWN 
|| 
5543          gs_lastMouseEvent
.type 
== wxEVT_MOTION 
) 
5545         if ( ClientToScreen(wxPoint(x
, y
)) == gs_lastMouseEvent
.pos 
) 
5547             gs_lastMouseEvent
.type 
= wxEVT_MOTION
; 
5552 #endif // wxUSE_MOUSEEVENT_HACK 
5554     return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
); 
5559 wxWindowMSW::HandleMouseWheel(wxMouseWheelAxis axis
, 
5560                               WXWPARAM wParam
, WXLPARAM lParam
) 
5562 #if wxUSE_MOUSEWHEEL 
5563     // notice that WM_MOUSEWHEEL position is in screen coords (as it's 
5564     // forwarded up to the parent by DefWindowProc()) and not in the client 
5565     // ones as all the other messages, translate them to the client coords for 
5568         pt 
= ScreenToClient(wxPoint(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
))); 
5569     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
5570     InitMouseEvent(event
, pt
.x
, pt
.y
, LOWORD(wParam
)); 
5571     event
.m_wheelRotation 
= (short)HIWORD(wParam
); 
5572     event
.m_wheelDelta 
= WHEEL_DELTA
; 
5573     event
.m_wheelAxis 
= axis
; 
5575     static int s_linesPerRotation 
= -1; 
5576     if ( s_linesPerRotation 
== -1 ) 
5578         if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, 
5579                                      &s_linesPerRotation
, 0)) 
5581             // this is not supposed to happen 
5582             wxLogLastError(wxT("SystemParametersInfo(GETWHEELSCROLLLINES)")); 
5584             // the default is 3, so use it if SystemParametersInfo() failed 
5585             s_linesPerRotation 
= 3; 
5589     event
.m_linesPerAction 
= s_linesPerRotation
; 
5590     return HandleWindowEvent(event
); 
5592 #else // !wxUSE_MOUSEWHEEL 
5593     wxUnusedVar(wParam
); 
5594     wxUnusedVar(lParam
); 
5597 #endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL 
5600 void wxWindowMSW::GenerateMouseLeave() 
5602     m_mouseInWindow 
= false; 
5605     if ( wxIsShiftDown() ) 
5607     if ( wxIsCtrlDown() ) 
5608         state 
|= MK_CONTROL
; 
5610     // Only the high-order bit should be tested 
5611     if ( GetKeyState( VK_LBUTTON 
) & (1<<15) ) 
5612         state 
|= MK_LBUTTON
; 
5613     if ( GetKeyState( VK_MBUTTON 
) & (1<<15) ) 
5614         state 
|= MK_MBUTTON
; 
5615     if ( GetKeyState( VK_RBUTTON 
) & (1<<15) ) 
5616         state 
|= MK_RBUTTON
; 
5619     wxGetCursorPosMSW(&pt
); 
5621     // we need to have client coordinates here for symmetry with 
5622     // wxEVT_ENTER_WINDOW 
5623     RECT rect 
= wxGetWindowRect(GetHwnd()); 
5627     wxMouseEvent 
event(wxEVT_LEAVE_WINDOW
); 
5628     InitMouseEvent(event
, pt
.x
, pt
.y
, state
); 
5630     (void)HandleWindowEvent(event
); 
5633 // --------------------------------------------------------------------------- 
5634 // keyboard handling 
5635 // --------------------------------------------------------------------------- 
5640 // Implementation of InitAnyKeyEvent() which can also be used when there is no 
5641 // associated window: this can happen for the wxEVT_CHAR_HOOK events created by 
5642 // the global keyboard hook (e.g. the event might have happened in a non-wx 
5645 MSWInitAnyKeyEvent(wxKeyEvent
& event
, 
5648                    const wxWindowBase 
*win 
/* may be NULL */) 
5652         event
.SetId(win
->GetId()); 
5653         event
.SetEventObject(const_cast<wxWindowBase 
*>(win
)); 
5655     else // No associated window. 
5657         // Use wxID_ANY for compatibility with the old code even if wxID_NONE 
5658         // would arguably make more sense. 
5659         event
.SetId(wxID_ANY
); 
5662     event
.m_shiftDown 
= wxIsShiftDown(); 
5663     event
.m_controlDown 
= wxIsCtrlDown(); 
5664     event
.m_altDown 
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
; 
5666     event
.m_rawCode 
= (wxUint32
) wParam
; 
5667     event
.m_rawFlags 
= (wxUint32
) lParam
; 
5669     event
.SetTimestamp(::GetMessageTime()); 
5672     // Event coordinates must be in window client coordinates system which 
5673     // doesn't make sense if there is no window. 
5675     // We could use screen coordinates for such events but this would make the 
5676     // logic of the event handlers more complicated: you'd need to test for the 
5677     // event object and interpret the coordinates differently according to 
5678     // whether it's NULL or not so unless somebody really asks for this let's 
5679     // just avoid the issue. 
5682         const wxPoint mousePos 
= win
->ScreenToClient(wxGetMousePosition()); 
5683         event
.m_x 
= mousePos
.x
; 
5684         event
.m_y 
= mousePos
.y
; 
5688 } // anonymous namespace 
5691 wxWindowMSW::InitAnyKeyEvent(wxKeyEvent
& event
, 
5693                              WXLPARAM lParam
) const 
5695     MSWInitAnyKeyEvent(event
, wParam
, lParam
, this); 
5699 wxWindowMSW::CreateKeyEvent(wxEventType evType
, 
5701                             WXLPARAM lParam
) const 
5703     // Catch any attempts to use this with WM_CHAR, it wouldn't work because 
5704     // wParam is supposed to be a virtual key and not a character here. 
5705     wxASSERT_MSG( evType 
!= wxEVT_CHAR 
&& evType 
!= wxEVT_CHAR_HOOK
, 
5706                     "CreateKeyEvent() can't be used for char events" ); 
5708     wxKeyEvent 
event(evType
); 
5709     InitAnyKeyEvent(event
, wParam
, lParam
); 
5711     event
.m_keyCode 
= wxMSWKeyboard::VKToWX
 
5717 #endif // wxUSE_UNICODE 
5724 wxWindowMSW::CreateCharEvent(wxEventType evType
, 
5726                              WXLPARAM lParam
) const 
5728     wxKeyEvent 
event(evType
); 
5729     InitAnyKeyEvent(event
, wParam
, lParam
); 
5732     // TODO: wParam uses UTF-16 so this is incorrect for characters outside of 
5733     //       the BMP, we should use WM_UNICHAR to handle them. 
5734     event
.m_uniChar 
= wParam
; 
5735 #endif // wxUSE_UNICODE 
5737     // Set non-Unicode key code too for compatibility if possible. 
5738     if ( wParam 
< 0x80 ) 
5740         // It's an ASCII character, no need to translate it. 
5741         event
.m_keyCode 
= wParam
; 
5745         // Check if this key can be represented (as a single character) in the 
5747         const wchar_t wc 
= wParam
; 
5749         if ( wxConvLibc
.FromWChar(&ch
, 1, &wc
, 1) != wxCONV_FAILED 
) 
5751             // For compatibility continue to provide the key code in this field 
5752             // even though using GetUnicodeKey() is recommended now. 
5753             event
.m_keyCode 
= static_cast<unsigned char>(ch
); 
5755         //else: Key can't be represented in the current locale, leave m_keyCode 
5756         //      as WXK_NONE and use GetUnicodeKey() to access the character. 
5759     // the alphanumeric keys produced by pressing AltGr+something on European 
5760     // keyboards have both Ctrl and Alt modifiers which may confuse the user 
5761     // code as, normally, keys with Ctrl and/or Alt don't result in anything 
5762     // alphanumeric, so pretend that there are no modifiers at all (the 
5763     // KEY_DOWN event would still have the correct modifiers if they're really 
5765     if ( event
.m_controlDown 
&& event
.m_altDown 
&& 
5766             (event
.m_keyCode 
>= 32 && event
.m_keyCode 
< 256) ) 
5768         event
.m_controlDown 
= 
5769         event
.m_altDown 
= false; 
5775 // isASCII is true only when we're called from WM_CHAR handler and not from 
5777 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
) 
5779     wxKeyEvent 
event(CreateCharEvent(wxEVT_CHAR
, wParam
, lParam
)); 
5780     return HandleWindowEvent(event
); 
5783 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
) 
5785     wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_DOWN
, wParam
, lParam
)); 
5786     return HandleWindowEvent(event
); 
5789 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
) 
5791     wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_UP
, wParam
, lParam
)); 
5792     return HandleWindowEvent(event
); 
5796 int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel
), 
5797                                 WXLPARAM 
WXUNUSED_IN_WINCE(lParam
)) 
5799     // FIXME: implement GetMenuItemCount for WinCE, possibly 
5800     // in terms of GetMenuItemInfo 
5802     const HMENU hmenu 
= (HMENU
)lParam
; 
5804     WinStruct
<MENUITEMINFO
> mii
; 
5806     // we could use MIIM_FTYPE here as we only need to know if the item is 
5807     // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but 
5808     // MIIM_FTYPE is not supported under Win95 
5809     mii
.fMask 
= MIIM_TYPE 
| MIIM_DATA
; 
5811     // find if we have this letter in any owner drawn item 
5812     const int count 
= ::GetMenuItemCount(hmenu
); 
5813     for ( int i 
= 0; i 
< count
; i
++ ) 
5815         // previous loop iteration could modify it, reset it back before 
5816         // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData 
5819         if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) ) 
5821             if ( mii
.fType 
== MFT_OWNERDRAW 
) 
5823                 //  dwItemData member of the MENUITEMINFO is a 
5824                 //  pointer to the associated wxMenuItem -- see the 
5825                 //  menu creation code 
5826                 wxMenuItem 
*item 
= (wxMenuItem
*)mii
.dwItemData
; 
5828                 const wxString 
label(item
->GetItemLabel()); 
5829                 const wxChar 
*p 
= wxStrchr(label
.wx_str(), wxT('&')); 
5832                     if ( *p 
== wxT('&') ) 
5834                         // this is not the accel char, find the real one 
5835                         p 
= wxStrchr(p 
+ 1, wxT('&')); 
5837                     else // got the accel char 
5839                         // FIXME-UNICODE: this comparison doesn't risk to work 
5840                         // for non ASCII accelerator characters I'm afraid, but 
5842                         if ( (wchar_t)wxToupper(*p
) == (wchar_t)chAccel 
) 
5848                             // this one doesn't match 
5855         else // failed to get the menu text? 
5857             // it's not fatal, so don't show error, but still log it 
5858             wxLogLastError(wxT("GetMenuItemInfo")); 
5865 #endif // wxUSE_MENUS 
5867 bool wxWindowMSW::HandleClipboardEvent(WXUINT nMsg
) 
5869     const wxEventType type 
= nMsg 
== WM_CUT       
? wxEVT_COMMAND_TEXT_CUT
 
5870                            : nMsg 
== WM_COPY      
? wxEVT_COMMAND_TEXT_COPY
 
5871                            : /* nMsg == WM_PASTE */ wxEVT_COMMAND_TEXT_PASTE
; 
5872     wxClipboardTextEvent 
evt(type
, GetId()); 
5874     evt
.SetEventObject(this); 
5876     return HandleWindowEvent(evt
); 
5879 // --------------------------------------------------------------------------- 
5881 // --------------------------------------------------------------------------- 
5883 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
5887     if ( flags 
& JOY_BUTTON1CHG 
) 
5888         change 
= wxJOY_BUTTON1
; 
5889     if ( flags 
& JOY_BUTTON2CHG 
) 
5890         change 
= wxJOY_BUTTON2
; 
5891     if ( flags 
& JOY_BUTTON3CHG 
) 
5892         change 
= wxJOY_BUTTON3
; 
5893     if ( flags 
& JOY_BUTTON4CHG 
) 
5894         change 
= wxJOY_BUTTON4
; 
5897     if ( flags 
& JOY_BUTTON1 
) 
5898         buttons 
|= wxJOY_BUTTON1
; 
5899     if ( flags 
& JOY_BUTTON2 
) 
5900         buttons 
|= wxJOY_BUTTON2
; 
5901     if ( flags 
& JOY_BUTTON3 
) 
5902         buttons 
|= wxJOY_BUTTON3
; 
5903     if ( flags 
& JOY_BUTTON4 
) 
5904         buttons 
|= wxJOY_BUTTON4
; 
5906     // the event ids aren't consecutive so we can't use table based lookup 
5908     wxEventType eventType
; 
5913             eventType 
= wxEVT_JOY_MOVE
; 
5918             eventType 
= wxEVT_JOY_MOVE
; 
5923             eventType 
= wxEVT_JOY_ZMOVE
; 
5928             eventType 
= wxEVT_JOY_ZMOVE
; 
5931         case MM_JOY1BUTTONDOWN
: 
5933             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
5936         case MM_JOY2BUTTONDOWN
: 
5938             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
5941         case MM_JOY1BUTTONUP
: 
5943             eventType 
= wxEVT_JOY_BUTTON_UP
; 
5946         case MM_JOY2BUTTONUP
: 
5948             eventType 
= wxEVT_JOY_BUTTON_UP
; 
5952             wxFAIL_MSG(wxT("no such joystick event")); 
5957     wxJoystickEvent 
event(eventType
, buttons
, joystick
, change
); 
5958     if ( eventType 
== wxEVT_JOY_ZMOVE 
) 
5959         event
.SetZPosition(x
); 
5961         event
.SetPosition(wxPoint(x
, y
)); 
5962     event
.SetEventObject(this); 
5964     return HandleWindowEvent(event
); 
5974 // --------------------------------------------------------------------------- 
5976 // --------------------------------------------------------------------------- 
5978 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
, 
5979                               WXWORD pos
, WXHWND control
) 
5981     if ( control 
&& control 
!= m_hWnd 
) // Prevent infinite recursion 
5983         wxWindow 
*child 
= wxFindWinFromHandle(control
); 
5985             return child
->MSWOnScroll(orientation
, wParam
, pos
, control
); 
5988     wxScrollWinEvent event
; 
5989     event
.SetPosition(pos
); 
5990     event
.SetOrientation(orientation
); 
5991     event
.SetEventObject(this); 
5996         event
.SetEventType(wxEVT_SCROLLWIN_TOP
); 
6000         event
.SetEventType(wxEVT_SCROLLWIN_BOTTOM
); 
6004         event
.SetEventType(wxEVT_SCROLLWIN_LINEUP
); 
6008         event
.SetEventType(wxEVT_SCROLLWIN_LINEDOWN
); 
6012         event
.SetEventType(wxEVT_SCROLLWIN_PAGEUP
); 
6016         event
.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN
); 
6019     case SB_THUMBPOSITION
: 
6021         // under Win32, the scrollbar range and position are 32 bit integers, 
6022         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must 
6023         // explicitly query the scrollbar for the correct position (this must 
6024         // be done only for these two SB_ events as they are the only one 
6025         // carrying the scrollbar position) 
6027             WinStruct
<SCROLLINFO
> scrollInfo
; 
6028             scrollInfo
.fMask 
= SIF_TRACKPOS
; 
6030             if ( !::GetScrollInfo(GetHwnd(), 
6031                                   WXOrientToSB(orientation
), 
6034                 // Not necessarily an error, if there are no scrollbars yet. 
6035                 // wxLogLastError(wxT("GetScrollInfo")); 
6038             event
.SetPosition(scrollInfo
.nTrackPos
); 
6041         event
.SetEventType( wParam 
== SB_THUMBPOSITION
 
6042                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
 
6043                                 : wxEVT_SCROLLWIN_THUMBTRACK 
); 
6050     return HandleWindowEvent(event
); 
6053 // ---------------------------------------------------------------------------- 
6054 // custom message handlers 
6055 // ---------------------------------------------------------------------------- 
6058 wxWindowMSW::MSWRegisterMessageHandler(int msg
, MSWMessageHandler handler
) 
6060     wxCHECK_MSG( gs_messageHandlers
.find(msg
) == gs_messageHandlers
.end(), 
6061                  false, wxT("registering handler for the same message twice") ); 
6063     gs_messageHandlers
[msg
] = handler
; 
6068 wxWindowMSW::MSWUnregisterMessageHandler(int msg
, MSWMessageHandler handler
) 
6070     const MSWMessageHandlers::iterator i 
= gs_messageHandlers
.find(msg
); 
6071     wxCHECK_RET( i 
!= gs_messageHandlers
.end() && i
->second 
== handler
, 
6072                  wxT("unregistering non-registered handler?") ); 
6074     gs_messageHandlers
.erase(i
); 
6077 // =========================================================================== 
6079 // =========================================================================== 
6081 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
& the_font
) 
6084     HDC dc 
= ::GetDC((HWND
) wnd
); 
6087     //    the_font.UseResource(); 
6088     //    the_font.RealizeResource(); 
6089     HFONT fnt 
= (HFONT
)the_font
.GetResourceHandle(); // const_cast 
6091         was 
= (HFONT
) SelectObject(dc
,fnt
); 
6093     GetTextMetrics(dc
, &tm
); 
6096         SelectObject(dc
,was
); 
6098     ReleaseDC((HWND
)wnd
, dc
); 
6101         *x 
= tm
.tmAveCharWidth
; 
6103         *y 
= tm
.tmHeight 
+ tm
.tmExternalLeading
; 
6105     //   the_font.ReleaseResource(); 
6108 // ---------------------------------------------------------------------------- 
6110 // ---------------------------------------------------------------------------- 
6112 namespace wxMSWKeyboard
 
6118 // use the "extended" bit of lParam to distinguish extended keys from normal 
6119 // keys as the same virtual key code is sent for both by Windows 
6121 int ChooseNormalOrExtended(int lParam
, int keyNormal
, int keyExtended
) 
6123     // except that if lParam is 0, it means we don't have real lParam from 
6124     // WM_KEYDOWN but are just translating just a VK constant (e.g. done from 
6125     // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a 
6126     // non-numpad (hence extended) key as this is a more common case 
6127     return !lParam 
|| (HIWORD(lParam
) & KF_EXTENDED
) ? keyExtended 
: keyNormal
; 
6130 // this array contains the Windows virtual key codes which map one to one to 
6131 // WXK_xxx constants and is used in wxMSWKeyboard::VKToWX/WXToVK() below 
6133 // note that keys having a normal and numpad version (e.g. WXK_HOME and 
6134 // WXK_NUMPAD_HOME) are not included in this table as the mapping is not 1-to-1 
6135 const struct wxKeyMapping
 
6139 } gs_specialKeys
[] = 
6141     { VK_CANCEL
,        WXK_CANCEL 
}, 
6142     { VK_BACK
,          WXK_BACK 
}, 
6143     { VK_TAB
,           WXK_TAB 
}, 
6144     { VK_CLEAR
,         WXK_CLEAR 
}, 
6145     { VK_SHIFT
,         WXK_SHIFT 
}, 
6146     { VK_CONTROL
,       WXK_CONTROL 
}, 
6147     { VK_MENU 
,         WXK_ALT 
}, 
6148     { VK_PAUSE
,         WXK_PAUSE 
}, 
6149     { VK_CAPITAL
,       WXK_CAPITAL 
}, 
6150     { VK_SPACE
,         WXK_SPACE 
}, 
6151     { VK_ESCAPE
,        WXK_ESCAPE 
}, 
6152     { VK_SELECT
,        WXK_SELECT 
}, 
6153     { VK_PRINT
,         WXK_PRINT 
}, 
6154     { VK_EXECUTE
,       WXK_EXECUTE 
}, 
6155     { VK_SNAPSHOT
,      WXK_SNAPSHOT 
}, 
6156     { VK_HELP
,          WXK_HELP 
}, 
6158     { VK_NUMPAD0
,       WXK_NUMPAD0 
}, 
6159     { VK_NUMPAD1
,       WXK_NUMPAD1 
}, 
6160     { VK_NUMPAD2
,       WXK_NUMPAD2 
}, 
6161     { VK_NUMPAD3
,       WXK_NUMPAD3 
}, 
6162     { VK_NUMPAD4
,       WXK_NUMPAD4 
}, 
6163     { VK_NUMPAD5
,       WXK_NUMPAD5 
}, 
6164     { VK_NUMPAD6
,       WXK_NUMPAD6 
}, 
6165     { VK_NUMPAD7
,       WXK_NUMPAD7 
}, 
6166     { VK_NUMPAD8
,       WXK_NUMPAD8 
}, 
6167     { VK_NUMPAD9
,       WXK_NUMPAD9 
}, 
6168     { VK_MULTIPLY
,      WXK_NUMPAD_MULTIPLY 
}, 
6169     { VK_ADD
,           WXK_NUMPAD_ADD 
}, 
6170     { VK_SUBTRACT
,      WXK_NUMPAD_SUBTRACT 
}, 
6171     { VK_DECIMAL
,       WXK_NUMPAD_DECIMAL 
}, 
6172     { VK_DIVIDE
,        WXK_NUMPAD_DIVIDE 
}, 
6183     { VK_F10
,           WXK_F10 
}, 
6184     { VK_F11
,           WXK_F11 
}, 
6185     { VK_F12
,           WXK_F12 
}, 
6186     { VK_F13
,           WXK_F13 
}, 
6187     { VK_F14
,           WXK_F14 
}, 
6188     { VK_F15
,           WXK_F15 
}, 
6189     { VK_F16
,           WXK_F16 
}, 
6190     { VK_F17
,           WXK_F17 
}, 
6191     { VK_F18
,           WXK_F18 
}, 
6192     { VK_F19
,           WXK_F19 
}, 
6193     { VK_F20
,           WXK_F20 
}, 
6194     { VK_F21
,           WXK_F21 
}, 
6195     { VK_F22
,           WXK_F22 
}, 
6196     { VK_F23
,           WXK_F23 
}, 
6197     { VK_F24
,           WXK_F24 
}, 
6199     { VK_NUMLOCK
,       WXK_NUMLOCK 
}, 
6200     { VK_SCROLL
,        WXK_SCROLL 
}, 
6203     { VK_LWIN
,          WXK_WINDOWS_LEFT 
}, 
6204     { VK_RWIN
,          WXK_WINDOWS_RIGHT 
}, 
6205     { VK_APPS
,          WXK_WINDOWS_MENU 
}, 
6206 #endif // VK_APPS defined 
6209 } // anonymous namespace 
6211 int VKToWX(WXWORD vk
, WXLPARAM lParam
, wchar_t *uc
) 
6215     // check the table first 
6216     for ( size_t n 
= 0; n 
< WXSIZEOF(gs_specialKeys
); n
++ ) 
6218         if ( gs_specialKeys
[n
].vk 
== vk 
) 
6220             wxk 
= gs_specialKeys
[n
].wxk
; 
6221             if ( wxk 
< WXK_START 
) 
6223                 // Unicode code for this key is the same as its ASCII code. 
6232     // keys requiring special handling 
6247             // MapVirtualKey() returns 0 if it fails to convert the virtual 
6248             // key which nicely corresponds to our WXK_NONE. 
6249             wxk 
= ::MapVirtualKey(vk
, MAPVK_VK_TO_CHAR
); 
6251             if ( HIWORD(wxk
) & 0x8000 ) 
6253                 // It's a dead key and we don't return anything at all for them 
6254                 // as we simply don't have any way to indicate the difference 
6255                 // between e.g. a normal "'" and "'" as a dead key -- and 
6256                 // generating the same events for them just doesn't seem like a 
6261             // In any case return this as a Unicode character value. 
6265             // For compatibility with the old non-Unicode code we continue 
6266             // returning key codes for Latin-1 characters directly 
6267             // (normally it would really only make sense to do it for the 
6268             // ASCII characters, not Latin-1 ones). 
6271                 // But for anything beyond this we can only return the key 
6272                 // value as a real Unicode character, not a wxKeyCode 
6273                 // because this enum values clash with Unicode characters 
6274                 // (e.g. WXK_LBUTTON also happens to be U+012C a.k.a. 
6275                 // "LATIN CAPITAL LETTER I WITH BREVE"). 
6280         // handle extended keys 
6282             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_PAGEUP
, WXK_PAGEUP
); 
6286             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_PAGEDOWN
, WXK_PAGEDOWN
); 
6290             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_END
, WXK_END
); 
6294             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_HOME
, WXK_HOME
); 
6298             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_LEFT
, WXK_LEFT
); 
6302             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_UP
, WXK_UP
); 
6306             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_RIGHT
, WXK_RIGHT
); 
6310             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_DOWN
, WXK_DOWN
); 
6314             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_INSERT
, WXK_INSERT
); 
6318             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_DELETE
, WXK_DELETE
); 
6322             // don't use ChooseNormalOrExtended() here as the keys are reversed 
6323             // here: numpad enter is the extended one 
6324             wxk 
= HIWORD(lParam
) & KF_EXTENDED 
? WXK_NUMPAD_ENTER 
: WXK_RETURN
; 
6331             if ( (vk 
>= '0' && vk 
<= '9') || (vk 
>= 'A' && vk 
<= 'Z') ) 
6333                 // A simple alphanumeric key and the values of them coincide in 
6334                 // Windows and wx for both ASCII and Unicode codes. 
6337             else // Something we simply don't know about at all. 
6349 WXWORD 
WXToVK(int wxk
, bool *isExtended
) 
6351     // check the table first 
6352     for ( size_t n 
= 0; n 
< WXSIZEOF(gs_specialKeys
); n
++ ) 
6354         if ( gs_specialKeys
[n
].wxk 
== wxk 
) 
6356             // All extended keys (i.e. non-numpad versions of the keys that 
6357             // exist both in the numpad and outside of it) are dealt with 
6360                 *isExtended 
= false; 
6362             return gs_specialKeys
[n
].vk
; 
6366     // and then check for special keys not included in the table 
6367     bool extended 
= false; 
6373         case WXK_NUMPAD_PAGEUP
: 
6379         case WXK_NUMPAD_PAGEDOWN
: 
6385         case WXK_NUMPAD_END
: 
6391         case WXK_NUMPAD_HOME
: 
6397         case WXK_NUMPAD_LEFT
: 
6409         case WXK_NUMPAD_RIGHT
: 
6415         case WXK_NUMPAD_DOWN
: 
6421         case WXK_NUMPAD_INSERT
: 
6427         case WXK_NUMPAD_DELETE
: 
6432             // no VkKeyScan() under CE unfortunately, we need to test how does 
6433             // it handle OEM keys 
6435             // check to see if its one of the OEM key codes. 
6436             BYTE vks 
= LOBYTE(VkKeyScan(wxk
)); 
6442 #endif // !__WXWINCE__ 
6449         *isExtended 
= extended
; 
6454 } // namespace wxMSWKeyboard 
6456 // small helper for wxGetKeyState() and wxGetMouseState() 
6457 static inline bool wxIsKeyDown(WXWORD vk
) 
6459     // SM_SWAPBUTTON is not available under CE, so don't swap buttons there 
6460 #ifdef SM_SWAPBUTTON 
6461     if ( vk 
== VK_LBUTTON 
|| vk 
== VK_RBUTTON 
) 
6463         if ( ::GetSystemMetrics(SM_SWAPBUTTON
) ) 
6465             if ( vk 
== VK_LBUTTON 
) 
6467             else // vk == VK_RBUTTON 
6471 #endif // SM_SWAPBUTTON 
6473     // the low order bit indicates whether the key was pressed since the last 
6474     // call and the high order one indicates whether it is down right now and 
6475     // we only want that one 
6476     return (GetAsyncKeyState(vk
) & (1<<15)) != 0; 
6479 bool wxGetKeyState(wxKeyCode key
) 
6481     // although this does work under Windows, it is not supported under other 
6482     // platforms so don't allow it, you must use wxGetMouseState() instead 
6483     wxASSERT_MSG( key 
!= VK_LBUTTON 
&& 
6484                     key 
!= VK_RBUTTON 
&& 
6486                     wxT("can't use wxGetKeyState() for mouse buttons") ); 
6488     const WXWORD vk 
= wxMSWKeyboard::WXToVK(key
); 
6490     // if the requested key is a LED key, return true if the led is pressed 
6491     if ( key 
== WXK_NUMLOCK 
|| key 
== WXK_CAPITAL 
|| key 
== WXK_SCROLL 
) 
6493         // low order bit means LED is highlighted and high order one means the 
6494         // key is down; for compatibility with the other ports return true if 
6495         // either one is set 
6496         return GetKeyState(vk
) != 0; 
6501         return wxIsKeyDown(vk
); 
6506 wxMouseState 
wxGetMouseState() 
6510     wxGetCursorPosMSW(&pt
); 
6514     ms
.SetLeftDown(wxIsKeyDown(VK_LBUTTON
)); 
6515     ms
.SetMiddleDown(wxIsKeyDown(VK_MBUTTON
)); 
6516     ms
.SetRightDown(wxIsKeyDown(VK_RBUTTON
)); 
6517 #ifdef wxHAS_XBUTTON 
6518     ms
.SetAux1Down(wxIsKeyDown(VK_XBUTTON1
)); 
6519     ms
.SetAux2Down(wxIsKeyDown(VK_XBUTTON2
)); 
6520 #endif // wxHAS_XBUTTON 
6522     ms
.SetControlDown(wxIsCtrlDown ()); 
6523     ms
.SetShiftDown  (wxIsShiftDown()); 
6524     ms
.SetAltDown    (wxIsAltDown  ()); 
6525 //    ms.SetMetaDown(); 
6531 wxWindow 
*wxGetActiveWindow() 
6533     HWND hWnd 
= GetActiveWindow(); 
6536         return wxFindWinFromHandle(hWnd
); 
6541 extern wxWindow 
*wxGetWindowFromHWND(WXHWND hWnd
) 
6543     HWND hwnd 
= (HWND
)hWnd
; 
6545     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set 
6546     // by code in msw/radiobox.cpp), for all the others we just search up the 
6548     wxWindow 
*win 
= NULL
; 
6551         win 
= wxFindWinFromHandle(hwnd
); 
6554 #if wxUSE_RADIOBOX && !defined(__WXUNIVERSAL__) 
6555             // native radiobuttons return DLGC_RADIOBUTTON here and for any 
6556             // wxWindow class which overrides WM_GETDLGCODE processing to 
6557             // do it as well, win would be already non NULL 
6558             if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON 
) 
6560                 win 
= wxRadioBox::GetFromRadioButtonHWND(hwnd
); 
6562             //else: it's a wxRadioButton, not a radiobutton from wxRadioBox 
6563 #endif // wxUSE_RADIOBOX 
6565             // spin control text buddy window should be mapped to spin ctrl 
6566             // itself so try it too 
6567 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
6570                 win 
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
); 
6572 #endif // wxUSE_SPINCTRL 
6576     while ( hwnd 
&& !win 
) 
6578         // this is a really ugly hack needed to avoid mistakenly returning the 
6579         // parent frame wxWindow for the find/replace modeless dialog HWND - 
6580         // this, in turn, is needed to call IsDialogMessage() from 
6581         // wxApp::ProcessMessage() as for this we must return NULL from here 
6583         // FIXME: this is clearly not the best way to do it but I think we'll 
6584         //        need to change HWND <-> wxWindow code more heavily than I can 
6585         //        do it now to fix it 
6586 #ifndef __WXMICROWIN__ 
6587         if ( ::GetWindow(hwnd
, GW_OWNER
) ) 
6589             // it's a dialog box, don't go upwards 
6594         hwnd 
= ::GetParent(hwnd
); 
6595         win 
= wxFindWinFromHandle(hwnd
); 
6601 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
6603 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE 
6604 // in active frames and dialogs, regardless of where the focus is. 
6605 static HHOOK wxTheKeyboardHook 
= 0; 
6608 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
) 
6610     DWORD hiWord 
= HIWORD(lParam
); 
6611     if ( nCode 
!= HC_NOREMOVE 
&& ((hiWord 
& KF_UP
) == 0) ) 
6614         int id 
= wxMSWKeyboard::VKToWX(wParam
, lParam
, &uc
); 
6616         // Don't intercept keyboard entry (notably Escape) if a modal window 
6617         // (not managed by wx, e.g. IME one) is currently opened as more often 
6618         // than not it needs all the keys for itself. 
6620         // Also don't catch it if a window currently captures the mouse as 
6621         // Escape is normally used to release the mouse capture and if you 
6622         // really need to catch all the keys in the window that has mouse 
6623         // capture it can be easily done in its own EVT_CHAR handler as it is 
6624         // certain to have focus while it has the capture. 
6625         if ( !gs_modalEntryWindowCount 
&& !::GetCapture() ) 
6629                     || static_cast<int>(uc
) != WXK_NONE
 
6630 #endif // wxUSE_UNICODE 
6633                 wxWindow 
const* win 
= wxWindow::DoFindFocus(); 
6636                     // Even if the focus got lost somehow, still send the event 
6637                     // to the top level parent to allow a wxDialog to always 
6639                     win 
= wxGetActiveWindow(); 
6642                 wxKeyEvent 
event(wxEVT_CHAR_HOOK
); 
6643                 MSWInitAnyKeyEvent(event
, wParam
, lParam
, win
); 
6645                 event
.m_keyCode 
= id
; 
6647                 event
.m_uniChar 
= uc
; 
6648 #endif // wxUSE_UNICODE 
6650                 wxEvtHandler 
* const handler 
= win 
? win
->GetEventHandler() 
6653                 if ( handler 
&& handler
->ProcessEvent(event
) ) 
6655                     if ( !event
.IsNextEventAllowed() ) 
6657                         // Stop processing of this event. 
6665     return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
); 
6668 void wxSetKeyboardHook(bool doIt
) 
6672         wxTheKeyboardHook 
= ::SetWindowsHookEx
 
6675                                 (HOOKPROC
)wxKeyboardHook
, 
6676                                 NULL
,   // must be NULL for process hook 
6677                                 ::GetCurrentThreadId() 
6679         if ( !wxTheKeyboardHook 
) 
6681             wxLogLastError(wxT("SetWindowsHookEx(wxKeyboardHook)")); 
6686         if ( wxTheKeyboardHook 
) 
6687             ::UnhookWindowsHookEx(wxTheKeyboardHook
); 
6691 #endif // !__WXMICROWIN__ 
6693 #if wxDEBUG_LEVEL >= 2 
6694 const wxChar 
*wxGetMessageName(int message
) 
6698         case 0x0000: return wxT("WM_NULL"); 
6699         case 0x0001: return wxT("WM_CREATE"); 
6700         case 0x0002: return wxT("WM_DESTROY"); 
6701         case 0x0003: return wxT("WM_MOVE"); 
6702         case 0x0005: return wxT("WM_SIZE"); 
6703         case 0x0006: return wxT("WM_ACTIVATE"); 
6704         case 0x0007: return wxT("WM_SETFOCUS"); 
6705         case 0x0008: return wxT("WM_KILLFOCUS"); 
6706         case 0x000A: return wxT("WM_ENABLE"); 
6707         case 0x000B: return wxT("WM_SETREDRAW"); 
6708         case 0x000C: return wxT("WM_SETTEXT"); 
6709         case 0x000D: return wxT("WM_GETTEXT"); 
6710         case 0x000E: return wxT("WM_GETTEXTLENGTH"); 
6711         case 0x000F: return wxT("WM_PAINT"); 
6712         case 0x0010: return wxT("WM_CLOSE"); 
6713         case 0x0011: return wxT("WM_QUERYENDSESSION"); 
6714         case 0x0012: return wxT("WM_QUIT"); 
6715         case 0x0013: return wxT("WM_QUERYOPEN"); 
6716         case 0x0014: return wxT("WM_ERASEBKGND"); 
6717         case 0x0015: return wxT("WM_SYSCOLORCHANGE"); 
6718         case 0x0016: return wxT("WM_ENDSESSION"); 
6719         case 0x0017: return wxT("WM_SYSTEMERROR"); 
6720         case 0x0018: return wxT("WM_SHOWWINDOW"); 
6721         case 0x0019: return wxT("WM_CTLCOLOR"); 
6722         case 0x001A: return wxT("WM_WININICHANGE"); 
6723         case 0x001B: return wxT("WM_DEVMODECHANGE"); 
6724         case 0x001C: return wxT("WM_ACTIVATEAPP"); 
6725         case 0x001D: return wxT("WM_FONTCHANGE"); 
6726         case 0x001E: return wxT("WM_TIMECHANGE"); 
6727         case 0x001F: return wxT("WM_CANCELMODE"); 
6728         case 0x0020: return wxT("WM_SETCURSOR"); 
6729         case 0x0021: return wxT("WM_MOUSEACTIVATE"); 
6730         case 0x0022: return wxT("WM_CHILDACTIVATE"); 
6731         case 0x0023: return wxT("WM_QUEUESYNC"); 
6732         case 0x0024: return wxT("WM_GETMINMAXINFO"); 
6733         case 0x0026: return wxT("WM_PAINTICON"); 
6734         case 0x0027: return wxT("WM_ICONERASEBKGND"); 
6735         case 0x0028: return wxT("WM_NEXTDLGCTL"); 
6736         case 0x002A: return wxT("WM_SPOOLERSTATUS"); 
6737         case 0x002B: return wxT("WM_DRAWITEM"); 
6738         case 0x002C: return wxT("WM_MEASUREITEM"); 
6739         case 0x002D: return wxT("WM_DELETEITEM"); 
6740         case 0x002E: return wxT("WM_VKEYTOITEM"); 
6741         case 0x002F: return wxT("WM_CHARTOITEM"); 
6742         case 0x0030: return wxT("WM_SETFONT"); 
6743         case 0x0031: return wxT("WM_GETFONT"); 
6744         case 0x0037: return wxT("WM_QUERYDRAGICON"); 
6745         case 0x0039: return wxT("WM_COMPAREITEM"); 
6746         case 0x0041: return wxT("WM_COMPACTING"); 
6747         case 0x0044: return wxT("WM_COMMNOTIFY"); 
6748         case 0x0046: return wxT("WM_WINDOWPOSCHANGING"); 
6749         case 0x0047: return wxT("WM_WINDOWPOSCHANGED"); 
6750         case 0x0048: return wxT("WM_POWER"); 
6752         case 0x004A: return wxT("WM_COPYDATA"); 
6753         case 0x004B: return wxT("WM_CANCELJOURNAL"); 
6754         case 0x004E: return wxT("WM_NOTIFY"); 
6755         case 0x0050: return wxT("WM_INPUTLANGCHANGEREQUEST"); 
6756         case 0x0051: return wxT("WM_INPUTLANGCHANGE"); 
6757         case 0x0052: return wxT("WM_TCARD"); 
6758         case 0x0053: return wxT("WM_HELP"); 
6759         case 0x0054: return wxT("WM_USERCHANGED"); 
6760         case 0x0055: return wxT("WM_NOTIFYFORMAT"); 
6761         case 0x007B: return wxT("WM_CONTEXTMENU"); 
6762         case 0x007C: return wxT("WM_STYLECHANGING"); 
6763         case 0x007D: return wxT("WM_STYLECHANGED"); 
6764         case 0x007E: return wxT("WM_DISPLAYCHANGE"); 
6765         case 0x007F: return wxT("WM_GETICON"); 
6766         case 0x0080: return wxT("WM_SETICON"); 
6768         case 0x0081: return wxT("WM_NCCREATE"); 
6769         case 0x0082: return wxT("WM_NCDESTROY"); 
6770         case 0x0083: return wxT("WM_NCCALCSIZE"); 
6771         case 0x0084: return wxT("WM_NCHITTEST"); 
6772         case 0x0085: return wxT("WM_NCPAINT"); 
6773         case 0x0086: return wxT("WM_NCACTIVATE"); 
6774         case 0x0087: return wxT("WM_GETDLGCODE"); 
6775         case 0x00A0: return wxT("WM_NCMOUSEMOVE"); 
6776         case 0x00A1: return wxT("WM_NCLBUTTONDOWN"); 
6777         case 0x00A2: return wxT("WM_NCLBUTTONUP"); 
6778         case 0x00A3: return wxT("WM_NCLBUTTONDBLCLK"); 
6779         case 0x00A4: return wxT("WM_NCRBUTTONDOWN"); 
6780         case 0x00A5: return wxT("WM_NCRBUTTONUP"); 
6781         case 0x00A6: return wxT("WM_NCRBUTTONDBLCLK"); 
6782         case 0x00A7: return wxT("WM_NCMBUTTONDOWN"); 
6783         case 0x00A8: return wxT("WM_NCMBUTTONUP"); 
6784         case 0x00A9: return wxT("WM_NCMBUTTONDBLCLK"); 
6786         case 0x00B0: return wxT("EM_GETSEL"); 
6787         case 0x00B1: return wxT("EM_SETSEL"); 
6788         case 0x00B2: return wxT("EM_GETRECT"); 
6789         case 0x00B3: return wxT("EM_SETRECT"); 
6790         case 0x00B4: return wxT("EM_SETRECTNP"); 
6791         case 0x00B5: return wxT("EM_SCROLL"); 
6792         case 0x00B6: return wxT("EM_LINESCROLL"); 
6793         case 0x00B7: return wxT("EM_SCROLLCARET"); 
6794         case 0x00B8: return wxT("EM_GETMODIFY"); 
6795         case 0x00B9: return wxT("EM_SETMODIFY"); 
6796         case 0x00BA: return wxT("EM_GETLINECOUNT"); 
6797         case 0x00BB: return wxT("EM_LINEINDEX"); 
6798         case 0x00BC: return wxT("EM_SETHANDLE"); 
6799         case 0x00BD: return wxT("EM_GETHANDLE"); 
6800         case 0x00BE: return wxT("EM_GETTHUMB"); 
6801         case 0x00C1: return wxT("EM_LINELENGTH"); 
6802         case 0x00C2: return wxT("EM_REPLACESEL"); 
6803         case 0x00C4: return wxT("EM_GETLINE"); 
6804         case 0x00C5: return wxT("EM_LIMITTEXT/EM_SETLIMITTEXT"); /* ;win40 Name change */ 
6805         case 0x00C6: return wxT("EM_CANUNDO"); 
6806         case 0x00C7: return wxT("EM_UNDO"); 
6807         case 0x00C8: return wxT("EM_FMTLINES"); 
6808         case 0x00C9: return wxT("EM_LINEFROMCHAR"); 
6809         case 0x00CB: return wxT("EM_SETTABSTOPS"); 
6810         case 0x00CC: return wxT("EM_SETPASSWORDCHAR"); 
6811         case 0x00CD: return wxT("EM_EMPTYUNDOBUFFER"); 
6812         case 0x00CE: return wxT("EM_GETFIRSTVISIBLELINE"); 
6813         case 0x00CF: return wxT("EM_SETREADONLY"); 
6814         case 0x00D0: return wxT("EM_SETWORDBREAKPROC"); 
6815         case 0x00D1: return wxT("EM_GETWORDBREAKPROC"); 
6816         case 0x00D2: return wxT("EM_GETPASSWORDCHAR"); 
6817         case 0x00D3: return wxT("EM_SETMARGINS"); 
6818         case 0x00D4: return wxT("EM_GETMARGINS"); 
6819         case 0x00D5: return wxT("EM_GETLIMITTEXT"); 
6820         case 0x00D6: return wxT("EM_POSFROMCHAR"); 
6821         case 0x00D7: return wxT("EM_CHARFROMPOS"); 
6822         case 0x00D8: return wxT("EM_SETIMESTATUS"); 
6823         case 0x00D9: return wxT("EM_GETIMESTATUS"); 
6825         case 0x0100: return wxT("WM_KEYDOWN"); 
6826         case 0x0101: return wxT("WM_KEYUP"); 
6827         case 0x0102: return wxT("WM_CHAR"); 
6828         case 0x0103: return wxT("WM_DEADCHAR"); 
6829         case 0x0104: return wxT("WM_SYSKEYDOWN"); 
6830         case 0x0105: return wxT("WM_SYSKEYUP"); 
6831         case 0x0106: return wxT("WM_SYSCHAR"); 
6832         case 0x0107: return wxT("WM_SYSDEADCHAR"); 
6833         case 0x0108: return wxT("WM_KEYLAST"); 
6835         case 0x010D: return wxT("WM_IME_STARTCOMPOSITION"); 
6836         case 0x010E: return wxT("WM_IME_ENDCOMPOSITION"); 
6837         case 0x010F: return wxT("WM_IME_COMPOSITION"); 
6839         case 0x0110: return wxT("WM_INITDIALOG"); 
6840         case 0x0111: return wxT("WM_COMMAND"); 
6841         case 0x0112: return wxT("WM_SYSCOMMAND"); 
6842         case 0x0113: return wxT("WM_TIMER"); 
6843         case 0x0114: return wxT("WM_HSCROLL"); 
6844         case 0x0115: return wxT("WM_VSCROLL"); 
6845         case 0x0116: return wxT("WM_INITMENU"); 
6846         case 0x0117: return wxT("WM_INITMENUPOPUP"); 
6847         case 0x011F: return wxT("WM_MENUSELECT"); 
6848         case 0x0120: return wxT("WM_MENUCHAR"); 
6849         case 0x0121: return wxT("WM_ENTERIDLE"); 
6851         case 0x0127: return wxT("WM_CHANGEUISTATE"); 
6852         case 0x0128: return wxT("WM_UPDATEUISTATE"); 
6853         case 0x0129: return wxT("WM_QUERYUISTATE"); 
6855         case 0x0132: return wxT("WM_CTLCOLORMSGBOX"); 
6856         case 0x0133: return wxT("WM_CTLCOLOREDIT"); 
6857         case 0x0134: return wxT("WM_CTLCOLORLISTBOX"); 
6858         case 0x0135: return wxT("WM_CTLCOLORBTN"); 
6859         case 0x0136: return wxT("WM_CTLCOLORDLG"); 
6860         case 0x0137: return wxT("WM_CTLCOLORSCROLLBAR"); 
6861         case 0x0138: return wxT("WM_CTLCOLORSTATIC"); 
6862         case 0x01E1: return wxT("MN_GETHMENU"); 
6864         case 0x0200: return wxT("WM_MOUSEMOVE"); 
6865         case 0x0201: return wxT("WM_LBUTTONDOWN"); 
6866         case 0x0202: return wxT("WM_LBUTTONUP"); 
6867         case 0x0203: return wxT("WM_LBUTTONDBLCLK"); 
6868         case 0x0204: return wxT("WM_RBUTTONDOWN"); 
6869         case 0x0205: return wxT("WM_RBUTTONUP"); 
6870         case 0x0206: return wxT("WM_RBUTTONDBLCLK"); 
6871         case 0x0207: return wxT("WM_MBUTTONDOWN"); 
6872         case 0x0208: return wxT("WM_MBUTTONUP"); 
6873         case 0x0209: return wxT("WM_MBUTTONDBLCLK"); 
6874         case 0x020A: return wxT("WM_MOUSEWHEEL"); 
6875         case 0x020B: return wxT("WM_XBUTTONDOWN"); 
6876         case 0x020C: return wxT("WM_XBUTTONUP"); 
6877         case 0x020D: return wxT("WM_XBUTTONDBLCLK"); 
6878         case 0x0210: return wxT("WM_PARENTNOTIFY"); 
6879         case 0x0211: return wxT("WM_ENTERMENULOOP"); 
6880         case 0x0212: return wxT("WM_EXITMENULOOP"); 
6882         case 0x0213: return wxT("WM_NEXTMENU"); 
6883         case 0x0214: return wxT("WM_SIZING"); 
6884         case 0x0215: return wxT("WM_CAPTURECHANGED"); 
6885         case 0x0216: return wxT("WM_MOVING"); 
6886         case 0x0218: return wxT("WM_POWERBROADCAST"); 
6887         case 0x0219: return wxT("WM_DEVICECHANGE"); 
6889         case 0x0220: return wxT("WM_MDICREATE"); 
6890         case 0x0221: return wxT("WM_MDIDESTROY"); 
6891         case 0x0222: return wxT("WM_MDIACTIVATE"); 
6892         case 0x0223: return wxT("WM_MDIRESTORE"); 
6893         case 0x0224: return wxT("WM_MDINEXT"); 
6894         case 0x0225: return wxT("WM_MDIMAXIMIZE"); 
6895         case 0x0226: return wxT("WM_MDITILE"); 
6896         case 0x0227: return wxT("WM_MDICASCADE"); 
6897         case 0x0228: return wxT("WM_MDIICONARRANGE"); 
6898         case 0x0229: return wxT("WM_MDIGETACTIVE"); 
6899         case 0x0230: return wxT("WM_MDISETMENU"); 
6900         case 0x0233: return wxT("WM_DROPFILES"); 
6902         case 0x0281: return wxT("WM_IME_SETCONTEXT"); 
6903         case 0x0282: return wxT("WM_IME_NOTIFY"); 
6904         case 0x0283: return wxT("WM_IME_CONTROL"); 
6905         case 0x0284: return wxT("WM_IME_COMPOSITIONFULL"); 
6906         case 0x0285: return wxT("WM_IME_SELECT"); 
6907         case 0x0286: return wxT("WM_IME_CHAR"); 
6908         case 0x0290: return wxT("WM_IME_KEYDOWN"); 
6909         case 0x0291: return wxT("WM_IME_KEYUP"); 
6911         case 0x02A0: return wxT("WM_NCMOUSEHOVER"); 
6912         case 0x02A1: return wxT("WM_MOUSEHOVER"); 
6913         case 0x02A2: return wxT("WM_NCMOUSELEAVE"); 
6914         case 0x02A3: return wxT("WM_MOUSELEAVE"); 
6916         case 0x0300: return wxT("WM_CUT"); 
6917         case 0x0301: return wxT("WM_COPY"); 
6918         case 0x0302: return wxT("WM_PASTE"); 
6919         case 0x0303: return wxT("WM_CLEAR"); 
6920         case 0x0304: return wxT("WM_UNDO"); 
6921         case 0x0305: return wxT("WM_RENDERFORMAT"); 
6922         case 0x0306: return wxT("WM_RENDERALLFORMATS"); 
6923         case 0x0307: return wxT("WM_DESTROYCLIPBOARD"); 
6924         case 0x0308: return wxT("WM_DRAWCLIPBOARD"); 
6925         case 0x0309: return wxT("WM_PAINTCLIPBOARD"); 
6926         case 0x030A: return wxT("WM_VSCROLLCLIPBOARD"); 
6927         case 0x030B: return wxT("WM_SIZECLIPBOARD"); 
6928         case 0x030C: return wxT("WM_ASKCBFORMATNAME"); 
6929         case 0x030D: return wxT("WM_CHANGECBCHAIN"); 
6930         case 0x030E: return wxT("WM_HSCROLLCLIPBOARD"); 
6931         case 0x030F: return wxT("WM_QUERYNEWPALETTE"); 
6932         case 0x0310: return wxT("WM_PALETTEISCHANGING"); 
6933         case 0x0311: return wxT("WM_PALETTECHANGED"); 
6934         case 0x0312: return wxT("WM_HOTKEY"); 
6936         case 0x0317: return wxT("WM_PRINT"); 
6937         case 0x0318: return wxT("WM_PRINTCLIENT"); 
6939         // common controls messages - although they're not strictly speaking 
6940         // standard, it's nice to decode them nevertheless 
6943         case 0x1000 + 0: return wxT("LVM_GETBKCOLOR"); 
6944         case 0x1000 + 1: return wxT("LVM_SETBKCOLOR"); 
6945         case 0x1000 + 2: return wxT("LVM_GETIMAGELIST"); 
6946         case 0x1000 + 3: return wxT("LVM_SETIMAGELIST"); 
6947         case 0x1000 + 4: return wxT("LVM_GETITEMCOUNT"); 
6948         case 0x1000 + 5: return wxT("LVM_GETITEMA"); 
6949         case 0x1000 + 75: return wxT("LVM_GETITEMW"); 
6950         case 0x1000 + 6: return wxT("LVM_SETITEMA"); 
6951         case 0x1000 + 76: return wxT("LVM_SETITEMW"); 
6952         case 0x1000 + 7: return wxT("LVM_INSERTITEMA"); 
6953         case 0x1000 + 77: return wxT("LVM_INSERTITEMW"); 
6954         case 0x1000 + 8: return wxT("LVM_DELETEITEM"); 
6955         case 0x1000 + 9: return wxT("LVM_DELETEALLITEMS"); 
6956         case 0x1000 + 10: return wxT("LVM_GETCALLBACKMASK"); 
6957         case 0x1000 + 11: return wxT("LVM_SETCALLBACKMASK"); 
6958         case 0x1000 + 12: return wxT("LVM_GETNEXTITEM"); 
6959         case 0x1000 + 13: return wxT("LVM_FINDITEMA"); 
6960         case 0x1000 + 83: return wxT("LVM_FINDITEMW"); 
6961         case 0x1000 + 14: return wxT("LVM_GETITEMRECT"); 
6962         case 0x1000 + 15: return wxT("LVM_SETITEMPOSITION"); 
6963         case 0x1000 + 16: return wxT("LVM_GETITEMPOSITION"); 
6964         case 0x1000 + 17: return wxT("LVM_GETSTRINGWIDTHA"); 
6965         case 0x1000 + 87: return wxT("LVM_GETSTRINGWIDTHW"); 
6966         case 0x1000 + 18: return wxT("LVM_HITTEST"); 
6967         case 0x1000 + 19: return wxT("LVM_ENSUREVISIBLE"); 
6968         case 0x1000 + 20: return wxT("LVM_SCROLL"); 
6969         case 0x1000 + 21: return wxT("LVM_REDRAWITEMS"); 
6970         case 0x1000 + 22: return wxT("LVM_ARRANGE"); 
6971         case 0x1000 + 23: return wxT("LVM_EDITLABELA"); 
6972         case 0x1000 + 118: return wxT("LVM_EDITLABELW"); 
6973         case 0x1000 + 24: return wxT("LVM_GETEDITCONTROL"); 
6974         case 0x1000 + 25: return wxT("LVM_GETCOLUMNA"); 
6975         case 0x1000 + 95: return wxT("LVM_GETCOLUMNW"); 
6976         case 0x1000 + 26: return wxT("LVM_SETCOLUMNA"); 
6977         case 0x1000 + 96: return wxT("LVM_SETCOLUMNW"); 
6978         case 0x1000 + 27: return wxT("LVM_INSERTCOLUMNA"); 
6979         case 0x1000 + 97: return wxT("LVM_INSERTCOLUMNW"); 
6980         case 0x1000 + 28: return wxT("LVM_DELETECOLUMN"); 
6981         case 0x1000 + 29: return wxT("LVM_GETCOLUMNWIDTH"); 
6982         case 0x1000 + 30: return wxT("LVM_SETCOLUMNWIDTH"); 
6983         case 0x1000 + 31: return wxT("LVM_GETHEADER"); 
6984         case 0x1000 + 33: return wxT("LVM_CREATEDRAGIMAGE"); 
6985         case 0x1000 + 34: return wxT("LVM_GETVIEWRECT"); 
6986         case 0x1000 + 35: return wxT("LVM_GETTEXTCOLOR"); 
6987         case 0x1000 + 36: return wxT("LVM_SETTEXTCOLOR"); 
6988         case 0x1000 + 37: return wxT("LVM_GETTEXTBKCOLOR"); 
6989         case 0x1000 + 38: return wxT("LVM_SETTEXTBKCOLOR"); 
6990         case 0x1000 + 39: return wxT("LVM_GETTOPINDEX"); 
6991         case 0x1000 + 40: return wxT("LVM_GETCOUNTPERPAGE"); 
6992         case 0x1000 + 41: return wxT("LVM_GETORIGIN"); 
6993         case 0x1000 + 42: return wxT("LVM_UPDATE"); 
6994         case 0x1000 + 43: return wxT("LVM_SETITEMSTATE"); 
6995         case 0x1000 + 44: return wxT("LVM_GETITEMSTATE"); 
6996         case 0x1000 + 45: return wxT("LVM_GETITEMTEXTA"); 
6997         case 0x1000 + 115: return wxT("LVM_GETITEMTEXTW"); 
6998         case 0x1000 + 46: return wxT("LVM_SETITEMTEXTA"); 
6999         case 0x1000 + 116: return wxT("LVM_SETITEMTEXTW"); 
7000         case 0x1000 + 47: return wxT("LVM_SETITEMCOUNT"); 
7001         case 0x1000 + 48: return wxT("LVM_SORTITEMS"); 
7002         case 0x1000 + 49: return wxT("LVM_SETITEMPOSITION32"); 
7003         case 0x1000 + 50: return wxT("LVM_GETSELECTEDCOUNT"); 
7004         case 0x1000 + 51: return wxT("LVM_GETITEMSPACING"); 
7005         case 0x1000 + 52: return wxT("LVM_GETISEARCHSTRINGA"); 
7006         case 0x1000 + 117: return wxT("LVM_GETISEARCHSTRINGW"); 
7007         case 0x1000 + 53: return wxT("LVM_SETICONSPACING"); 
7008         case 0x1000 + 54: return wxT("LVM_SETEXTENDEDLISTVIEWSTYLE"); 
7009         case 0x1000 + 55: return wxT("LVM_GETEXTENDEDLISTVIEWSTYLE"); 
7010         case 0x1000 + 56: return wxT("LVM_GETSUBITEMRECT"); 
7011         case 0x1000 + 57: return wxT("LVM_SUBITEMHITTEST"); 
7012         case 0x1000 + 58: return wxT("LVM_SETCOLUMNORDERARRAY"); 
7013         case 0x1000 + 59: return wxT("LVM_GETCOLUMNORDERARRAY"); 
7014         case 0x1000 + 60: return wxT("LVM_SETHOTITEM"); 
7015         case 0x1000 + 61: return wxT("LVM_GETHOTITEM"); 
7016         case 0x1000 + 62: return wxT("LVM_SETHOTCURSOR"); 
7017         case 0x1000 + 63: return wxT("LVM_GETHOTCURSOR"); 
7018         case 0x1000 + 64: return wxT("LVM_APPROXIMATEVIEWRECT"); 
7019         case 0x1000 + 65: return wxT("LVM_SETWORKAREA"); 
7022         case 0x1100 + 0: return wxT("TVM_INSERTITEMA"); 
7023         case 0x1100 + 50: return wxT("TVM_INSERTITEMW"); 
7024         case 0x1100 + 1: return wxT("TVM_DELETEITEM"); 
7025         case 0x1100 + 2: return wxT("TVM_EXPAND"); 
7026         case 0x1100 + 4: return wxT("TVM_GETITEMRECT"); 
7027         case 0x1100 + 5: return wxT("TVM_GETCOUNT"); 
7028         case 0x1100 + 6: return wxT("TVM_GETINDENT"); 
7029         case 0x1100 + 7: return wxT("TVM_SETINDENT"); 
7030         case 0x1100 + 8: return wxT("TVM_GETIMAGELIST"); 
7031         case 0x1100 + 9: return wxT("TVM_SETIMAGELIST"); 
7032         case 0x1100 + 10: return wxT("TVM_GETNEXTITEM"); 
7033         case 0x1100 + 11: return wxT("TVM_SELECTITEM"); 
7034         case 0x1100 + 12: return wxT("TVM_GETITEMA"); 
7035         case 0x1100 + 62: return wxT("TVM_GETITEMW"); 
7036         case 0x1100 + 13: return wxT("TVM_SETITEMA"); 
7037         case 0x1100 + 63: return wxT("TVM_SETITEMW"); 
7038         case 0x1100 + 14: return wxT("TVM_EDITLABELA"); 
7039         case 0x1100 + 65: return wxT("TVM_EDITLABELW"); 
7040         case 0x1100 + 15: return wxT("TVM_GETEDITCONTROL"); 
7041         case 0x1100 + 16: return wxT("TVM_GETVISIBLECOUNT"); 
7042         case 0x1100 + 17: return wxT("TVM_HITTEST"); 
7043         case 0x1100 + 18: return wxT("TVM_CREATEDRAGIMAGE"); 
7044         case 0x1100 + 19: return wxT("TVM_SORTCHILDREN"); 
7045         case 0x1100 + 20: return wxT("TVM_ENSUREVISIBLE"); 
7046         case 0x1100 + 21: return wxT("TVM_SORTCHILDRENCB"); 
7047         case 0x1100 + 22: return wxT("TVM_ENDEDITLABELNOW"); 
7048         case 0x1100 + 23: return wxT("TVM_GETISEARCHSTRINGA"); 
7049         case 0x1100 + 64: return wxT("TVM_GETISEARCHSTRINGW"); 
7050         case 0x1100 + 24: return wxT("TVM_SETTOOLTIPS"); 
7051         case 0x1100 + 25: return wxT("TVM_GETTOOLTIPS"); 
7054         case 0x1200 + 0: return wxT("HDM_GETITEMCOUNT"); 
7055         case 0x1200 + 1: return wxT("HDM_INSERTITEMA"); 
7056         case 0x1200 + 10: return wxT("HDM_INSERTITEMW"); 
7057         case 0x1200 + 2: return wxT("HDM_DELETEITEM"); 
7058         case 0x1200 + 3: return wxT("HDM_GETITEMA"); 
7059         case 0x1200 + 11: return wxT("HDM_GETITEMW"); 
7060         case 0x1200 + 4: return wxT("HDM_SETITEMA"); 
7061         case 0x1200 + 12: return wxT("HDM_SETITEMW"); 
7062         case 0x1200 + 5: return wxT("HDM_LAYOUT"); 
7063         case 0x1200 + 6: return wxT("HDM_HITTEST"); 
7064         case 0x1200 + 7: return wxT("HDM_GETITEMRECT"); 
7065         case 0x1200 + 8: return wxT("HDM_SETIMAGELIST"); 
7066         case 0x1200 + 9: return wxT("HDM_GETIMAGELIST"); 
7067         case 0x1200 + 15: return wxT("HDM_ORDERTOINDEX"); 
7068         case 0x1200 + 16: return wxT("HDM_CREATEDRAGIMAGE"); 
7069         case 0x1200 + 17: return wxT("HDM_GETORDERARRAY"); 
7070         case 0x1200 + 18: return wxT("HDM_SETORDERARRAY"); 
7071         case 0x1200 + 19: return wxT("HDM_SETHOTDIVIDER"); 
7074         case 0x1300 + 2: return wxT("TCM_GETIMAGELIST"); 
7075         case 0x1300 + 3: return wxT("TCM_SETIMAGELIST"); 
7076         case 0x1300 + 4: return wxT("TCM_GETITEMCOUNT"); 
7077         case 0x1300 + 5: return wxT("TCM_GETITEMA"); 
7078         case 0x1300 + 60: return wxT("TCM_GETITEMW"); 
7079         case 0x1300 + 6: return wxT("TCM_SETITEMA"); 
7080         case 0x1300 + 61: return wxT("TCM_SETITEMW"); 
7081         case 0x1300 + 7: return wxT("TCM_INSERTITEMA"); 
7082         case 0x1300 + 62: return wxT("TCM_INSERTITEMW"); 
7083         case 0x1300 + 8: return wxT("TCM_DELETEITEM"); 
7084         case 0x1300 + 9: return wxT("TCM_DELETEALLITEMS"); 
7085         case 0x1300 + 10: return wxT("TCM_GETITEMRECT"); 
7086         case 0x1300 + 11: return wxT("TCM_GETCURSEL"); 
7087         case 0x1300 + 12: return wxT("TCM_SETCURSEL"); 
7088         case 0x1300 + 13: return wxT("TCM_HITTEST"); 
7089         case 0x1300 + 14: return wxT("TCM_SETITEMEXTRA"); 
7090         case 0x1300 + 40: return wxT("TCM_ADJUSTRECT"); 
7091         case 0x1300 + 41: return wxT("TCM_SETITEMSIZE"); 
7092         case 0x1300 + 42: return wxT("TCM_REMOVEIMAGE"); 
7093         case 0x1300 + 43: return wxT("TCM_SETPADDING"); 
7094         case 0x1300 + 44: return wxT("TCM_GETROWCOUNT"); 
7095         case 0x1300 + 45: return wxT("TCM_GETTOOLTIPS"); 
7096         case 0x1300 + 46: return wxT("TCM_SETTOOLTIPS"); 
7097         case 0x1300 + 47: return wxT("TCM_GETCURFOCUS"); 
7098         case 0x1300 + 48: return wxT("TCM_SETCURFOCUS"); 
7099         case 0x1300 + 49: return wxT("TCM_SETMINTABWIDTH"); 
7100         case 0x1300 + 50: return wxT("TCM_DESELECTALL"); 
7103         case WM_USER
+1: return wxT("TB_ENABLEBUTTON"); 
7104         case WM_USER
+2: return wxT("TB_CHECKBUTTON"); 
7105         case WM_USER
+3: return wxT("TB_PRESSBUTTON"); 
7106         case WM_USER
+4: return wxT("TB_HIDEBUTTON"); 
7107         case WM_USER
+5: return wxT("TB_INDETERMINATE"); 
7108         case WM_USER
+9: return wxT("TB_ISBUTTONENABLED"); 
7109         case WM_USER
+10: return wxT("TB_ISBUTTONCHECKED"); 
7110         case WM_USER
+11: return wxT("TB_ISBUTTONPRESSED"); 
7111         case WM_USER
+12: return wxT("TB_ISBUTTONHIDDEN"); 
7112         case WM_USER
+13: return wxT("TB_ISBUTTONINDETERMINATE"); 
7113         case WM_USER
+17: return wxT("TB_SETSTATE"); 
7114         case WM_USER
+18: return wxT("TB_GETSTATE"); 
7115         case WM_USER
+19: return wxT("TB_ADDBITMAP"); 
7116         case WM_USER
+20: return wxT("TB_ADDBUTTONS"); 
7117         case WM_USER
+21: return wxT("TB_INSERTBUTTON"); 
7118         case WM_USER
+22: return wxT("TB_DELETEBUTTON"); 
7119         case WM_USER
+23: return wxT("TB_GETBUTTON"); 
7120         case WM_USER
+24: return wxT("TB_BUTTONCOUNT"); 
7121         case WM_USER
+25: return wxT("TB_COMMANDTOINDEX"); 
7122         case WM_USER
+26: return wxT("TB_SAVERESTOREA"); 
7123         case WM_USER
+76: return wxT("TB_SAVERESTOREW"); 
7124         case WM_USER
+27: return wxT("TB_CUSTOMIZE"); 
7125         case WM_USER
+28: return wxT("TB_ADDSTRINGA"); 
7126         case WM_USER
+77: return wxT("TB_ADDSTRINGW"); 
7127         case WM_USER
+29: return wxT("TB_GETITEMRECT"); 
7128         case WM_USER
+30: return wxT("TB_BUTTONSTRUCTSIZE"); 
7129         case WM_USER
+31: return wxT("TB_SETBUTTONSIZE"); 
7130         case WM_USER
+32: return wxT("TB_SETBITMAPSIZE"); 
7131         case WM_USER
+33: return wxT("TB_AUTOSIZE"); 
7132         case WM_USER
+35: return wxT("TB_GETTOOLTIPS"); 
7133         case WM_USER
+36: return wxT("TB_SETTOOLTIPS"); 
7134         case WM_USER
+37: return wxT("TB_SETPARENT"); 
7135         case WM_USER
+39: return wxT("TB_SETROWS"); 
7136         case WM_USER
+40: return wxT("TB_GETROWS"); 
7137         case WM_USER
+42: return wxT("TB_SETCMDID"); 
7138         case WM_USER
+43: return wxT("TB_CHANGEBITMAP"); 
7139         case WM_USER
+44: return wxT("TB_GETBITMAP"); 
7140         case WM_USER
+45: return wxT("TB_GETBUTTONTEXTA"); 
7141         case WM_USER
+75: return wxT("TB_GETBUTTONTEXTW"); 
7142         case WM_USER
+46: return wxT("TB_REPLACEBITMAP"); 
7143         case WM_USER
+47: return wxT("TB_SETINDENT"); 
7144         case WM_USER
+48: return wxT("TB_SETIMAGELIST"); 
7145         case WM_USER
+49: return wxT("TB_GETIMAGELIST"); 
7146         case WM_USER
+50: return wxT("TB_LOADIMAGES"); 
7147         case WM_USER
+51: return wxT("TB_GETRECT"); 
7148         case WM_USER
+52: return wxT("TB_SETHOTIMAGELIST"); 
7149         case WM_USER
+53: return wxT("TB_GETHOTIMAGELIST"); 
7150         case WM_USER
+54: return wxT("TB_SETDISABLEDIMAGELIST"); 
7151         case WM_USER
+55: return wxT("TB_GETDISABLEDIMAGELIST"); 
7152         case WM_USER
+56: return wxT("TB_SETSTYLE"); 
7153         case WM_USER
+57: return wxT("TB_GETSTYLE"); 
7154         case WM_USER
+58: return wxT("TB_GETBUTTONSIZE"); 
7155         case WM_USER
+59: return wxT("TB_SETBUTTONWIDTH"); 
7156         case WM_USER
+60: return wxT("TB_SETMAXTEXTROWS"); 
7157         case WM_USER
+61: return wxT("TB_GETTEXTROWS"); 
7158         case WM_USER
+41: return wxT("TB_GETBITMAPFLAGS"); 
7161             static wxString s_szBuf
; 
7162             s_szBuf
.Printf(wxT("<unknown message = %d>"), message
); 
7163             return s_szBuf
.c_str(); 
7166 #endif // wxDEBUG_LEVEL >= 2 
7168 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
) 
7172     HWND hwnd 
= GetHwndOf(win
); 
7173     HDC hdc 
= ::GetDC(hwnd
); 
7175 #if !wxDIALOG_UNIT_COMPATIBILITY 
7176     // and select the current font into it 
7177     HFONT hfont 
= GetHfontOf(win
->GetFont()); 
7180         hfont 
= (HFONT
)::SelectObject(hdc
, hfont
); 
7184     // finally retrieve the text metrics from it 
7185     GetTextMetrics(hdc
, &tm
); 
7187 #if !wxDIALOG_UNIT_COMPATIBILITY 
7191         (void)::SelectObject(hdc
, hfont
); 
7195     ::ReleaseDC(hwnd
, hdc
); 
7200 // Find the wxWindow at the current mouse position, returning the mouse 
7202 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
7204     pt 
= wxGetMousePosition(); 
7205     return wxFindWindowAtPoint(pt
); 
7208 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
7214     HWND hWnd 
= ::WindowFromPoint(pt2
); 
7217         // WindowFromPoint() ignores the disabled children but we're supposed 
7218         // to take them into account, so check if we have a child at this 
7220         ::ScreenToClient(hWnd
, &pt2
); 
7221         hWnd 
= ::ChildWindowFromPointEx(hWnd
, pt2
, CWP_SKIPINVISIBLE
); 
7224     return wxGetWindowFromHWND((WXHWND
)hWnd
); 
7227 // Get the current mouse position. 
7228 wxPoint 
wxGetMousePosition() 
7231     wxGetCursorPosMSW(&pt
); 
7233     return wxPoint(pt
.x
, pt
.y
); 
7238 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
7239 static void WinCEUnregisterHotKey(int modifiers
, int id
) 
7241     // Register hotkeys for the hardware buttons 
7243     typedef BOOL (WINAPI 
*UnregisterFunc1Proc
)(UINT
, UINT
); 
7245     UnregisterFunc1Proc procUnregisterFunc
; 
7246     hCoreDll 
= LoadLibrary(wxT("coredll.dll")); 
7249         procUnregisterFunc 
= (UnregisterFunc1Proc
)GetProcAddress(hCoreDll
, wxT("UnregisterFunc1")); 
7250         if (procUnregisterFunc
) 
7251             procUnregisterFunc(modifiers
, id
); 
7252         FreeLibrary(hCoreDll
); 
7257 bool wxWindowMSW::RegisterHotKey(int hotkeyId
, int modifiers
, int keycode
) 
7259     UINT win_modifiers
=0; 
7260     if ( modifiers 
& wxMOD_ALT 
) 
7261         win_modifiers 
|= MOD_ALT
; 
7262     if ( modifiers 
& wxMOD_SHIFT 
) 
7263         win_modifiers 
|= MOD_SHIFT
; 
7264     if ( modifiers 
& wxMOD_CONTROL 
) 
7265         win_modifiers 
|= MOD_CONTROL
; 
7266     if ( modifiers 
& wxMOD_WIN 
) 
7267         win_modifiers 
|= MOD_WIN
; 
7269 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
7270     // Required for PPC and Smartphone hardware buttons 
7271     if (keycode 
>= WXK_SPECIAL1 
&& keycode 
<= WXK_SPECIAL20
) 
7272         WinCEUnregisterHotKey(win_modifiers
, hotkeyId
); 
7275     if ( !::RegisterHotKey(GetHwnd(), hotkeyId
, win_modifiers
, keycode
) ) 
7277         wxLogLastError(wxT("RegisterHotKey")); 
7285 bool wxWindowMSW::UnregisterHotKey(int hotkeyId
) 
7287 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
7288     WinCEUnregisterHotKey(MOD_WIN
, hotkeyId
); 
7291     if ( !::UnregisterHotKey(GetHwnd(), hotkeyId
) ) 
7293         wxLogLastError(wxT("UnregisterHotKey")); 
7303 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam
, WXLPARAM lParam
) 
7305     int win_modifiers 
= LOWORD(lParam
); 
7307     wxKeyEvent 
event(CreateKeyEvent(wxEVT_HOTKEY
, HIWORD(lParam
))); 
7308     event
.SetId(wParam
); 
7309     event
.m_shiftDown 
= (win_modifiers 
& MOD_SHIFT
) != 0; 
7310     event
.m_controlDown 
= (win_modifiers 
& MOD_CONTROL
) != 0; 
7311     event
.m_altDown 
= (win_modifiers 
& MOD_ALT
) != 0; 
7312     event
.m_metaDown 
= (win_modifiers 
& MOD_WIN
) != 0; 
7314     return HandleWindowEvent(event
); 
7317 #endif // wxUSE_ACCEL 
7319 #endif // wxUSE_HOTKEY 
7321 // Not tested under WinCE 
7324 // this class installs a message hook which really wakes up our idle processing 
7325 // each time a WM_NULL is received (wxWakeUpIdle does this), even if we're 
7326 // sitting inside a local modal loop (e.g. a menu is opened or scrollbar is 
7327 // being dragged or even inside ::MessageBox()) and so don't control message 
7328 // dispatching otherwise 
7329 class wxIdleWakeUpModule 
: public wxModule
 
7332     virtual bool OnInit() 
7334         ms_hMsgHookProc 
= ::SetWindowsHookEx
 
7337                              &wxIdleWakeUpModule::MsgHookProc
, 
7339                              GetCurrentThreadId() 
7342         if ( !ms_hMsgHookProc 
) 
7344             wxLogLastError(wxT("SetWindowsHookEx(WH_GETMESSAGE)")); 
7352     virtual void OnExit() 
7354         ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc
); 
7357     static LRESULT CALLBACK 
MsgHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
) 
7359         MSG 
*msg 
= (MSG
*)lParam
; 
7361         // only process the message if it is actually going to be removed from 
7362         // the message queue, this prevents that the same event from being 
7363         // processed multiple times if now someone just called PeekMessage() 
7364         if ( msg
->message 
== WM_NULL 
&& wParam 
== PM_REMOVE 
) 
7366             wxTheApp
->ProcessPendingEvents(); 
7369         return CallNextHookEx(ms_hMsgHookProc
, nCode
, wParam
, lParam
); 
7373     static HHOOK ms_hMsgHookProc
; 
7375     DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule
) 
7378 HHOOK 
wxIdleWakeUpModule::ms_hMsgHookProc 
= 0; 
7380 IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule
, wxModule
) 
7382 #endif // __WXWINCE__ 
7387 static void wxAdjustZOrder(wxWindow
* parent
) 
7389     if (parent
->IsKindOf(CLASSINFO(wxStaticBox
))) 
7391         // Set the z-order correctly 
7392         SetWindowPos((HWND
) parent
->GetHWND(), HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
); 
7395     wxWindowList::compatibility_iterator current 
= parent
->GetChildren().GetFirst(); 
7398         wxWindow 
*childWin 
= current
->GetData(); 
7399         wxAdjustZOrder(childWin
); 
7400         current 
= current
->GetNext(); 
7405 // We need to adjust the z-order of static boxes in WinCE, to 
7406 // make 'contained' controls visible 
7407 void wxWindowMSW::OnInitDialog( wxInitDialogEvent
& event 
) 
7410     wxAdjustZOrder(this);