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/evtloop.h" 
  62 #include "wx/sysopt.h" 
  64 #if wxUSE_DRAG_AND_DROP 
  68 #if wxUSE_ACCESSIBILITY 
  69     #include "wx/access.h" 
  73         #define WM_GETOBJECT 0x003D 
  76         #define OBJID_CLIENT 0xFFFFFFFC 
  80 #include "wx/msw/private.h" 
  83     #include "wx/tooltip.h" 
  91     #include "wx/spinctrl.h" 
  92 #endif // wxUSE_SPINCTRL 
  94 #include "wx/notebook.h" 
  95 #include "wx/listctrl.h" 
  96 #include "wx/dynlib.h" 
 100 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) 
 101     #include <shellapi.h> 
 102     #include <mmsystem.h> 
 106     #include <windowsx.h> 
 109 #if !defined __WXWINCE__ && !defined NEED_PBT_H 
 113 #if defined(__WXWINCE__) 
 114     #include "wx/msw/wince/missing.h" 
 117     #include <shellapi.h> 
 119     #include <aygshell.h> 
 123 #if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS 
 124     #define HAVE_TRACKMOUSEEVENT 
 125 #endif // everything needed for TrackMouseEvent() 
 127 // if this is set to 1, we use deferred window sizing to reduce flicker when 
 128 // resizing complicated window hierarchies, but this can in theory result in 
 129 // different behaviour than the old code so we keep the possibility to use it 
 130 // by setting this to 0 (in the future this should be removed completely) 
 132 #define USE_DEFERRED_SIZING 0 
 134 #define USE_DEFERRED_SIZING 1 
 137 // set this to 1 to filter out duplicate mouse events, e.g. mouse move events 
 138 // when mouse position didnd't change 
 140     #define wxUSE_MOUSEEVENT_HACK 0 
 142     #define wxUSE_MOUSEEVENT_HACK 1 
 145 // --------------------------------------------------------------------------- 
 147 // --------------------------------------------------------------------------- 
 149 #if wxUSE_MENUS_NATIVE 
 150 wxMenu 
*wxCurrentPopupMenu 
= NULL
; 
 151 #endif // wxUSE_MENUS_NATIVE 
 154 extern       wxChar 
*wxCanvasClassName
; 
 156 extern const wxChar 
*wxCanvasClassName
; 
 159 // true if we had already created the std colour map, used by 
 160 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT) 
 161 static bool gs_hasStdCmap 
= false; 
 163 // last mouse event information we need to filter out the duplicates 
 164 #if wxUSE_MOUSEEVENT_HACK 
 165 static struct MouseEventInfoDummy
 
 167     // mouse position (in screen coordinates) 
 170     // last mouse event type 
 173 #endif // wxUSE_MOUSEEVENT_HACK 
 175 // --------------------------------------------------------------------------- 
 177 // --------------------------------------------------------------------------- 
 179 // the window proc for all our windows 
 180 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
 181                                    WPARAM wParam
, LPARAM lParam
); 
 185     const wxChar 
*wxGetMessageName(int message
); 
 188 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 189 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 190 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
); 
 192 // get the text metrics for the current font 
 193 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
); 
 196 // find the window for the mouse event at the specified position 
 197 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
); 
 198 #endif // __WXWINCE__ 
 200 // wrapper around BringWindowToTop() API 
 201 static inline void wxBringWindowToTop(HWND hwnd
) 
 203 #ifdef __WXMICROWIN__ 
 204     // It seems that MicroWindows brings the _parent_ of the window to the top, 
 205     // which can be the wrong one. 
 207     // activate (set focus to) specified window 
 211     // raise top level parent to top of z order 
 212     if (!::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE 
| SWP_NOSIZE
)) 
 214         wxLogLastError(_T("SetWindowPos")); 
 220 // ensure that all our parent windows have WS_EX_CONTROLPARENT style 
 221 static void EnsureParentHasControlParentStyle(wxWindow 
*parent
) 
 224        If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our 
 225        parent as well as otherwise several Win32 functions using 
 226        GetNextDlgTabItem() to iterate over all controls such as 
 227        IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, 
 228        all of them iterate over all the controls starting from the currently 
 229        focused one and stop iterating when they get back to the focus but 
 230        unless all parents have WS_EX_CONTROLPARENT bit set, they would never 
 231        get back to the initial (focused) window: as we do have this style, 
 232        GetNextDlgTabItem() will leave this window and continue in its parent, 
 233        but if the parent doesn't have it, it wouldn't recurse inside it later 
 234        on and so wouldn't have a chance of getting back to this window either. 
 236     while ( parent 
&& !parent
->IsTopLevel() ) 
 238         LONG exStyle 
= ::GetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
); 
 239         if ( !(exStyle 
& WS_EX_CONTROLPARENT
) ) 
 241             // force the parent to have this style 
 242             ::SetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
, 
 243                             exStyle 
| WS_EX_CONTROLPARENT
); 
 246         parent 
= parent
->GetParent(); 
 250 #endif // !__WXWINCE__ 
 253 // On Windows CE, GetCursorPos can return an error, so use this function 
 255 bool GetCursorPosWinCE(POINT
* pt
) 
 257     if (!GetCursorPos(pt
)) 
 259         DWORD pos 
= GetMessagePos(); 
 267 // --------------------------------------------------------------------------- 
 269 // --------------------------------------------------------------------------- 
 271 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
 273 #ifdef __WXUNIVERSAL__ 
 274     IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
) 
 276 #if wxUSE_EXTENDED_RTTI 
 278 // windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls 
 279 // must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as 
 280 // windows with negative ids never can be recreated anyway 
 282 bool wxWindowStreamingCallback( const wxObject 
*object
, wxWriter 
* , wxPersister 
* , wxxVariantArray 
& ) 
 284     const wxWindow 
* win 
= dynamic_cast<const wxWindow
*>(object
) ; 
 285     if ( win 
&& win
->GetId() < 0 ) 
 290 IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow
, wxWindowBase
,"wx/window.h", wxWindowStreamingCallback
) 
 292 // make wxWindowList known before the property is used 
 294 wxCOLLECTION_TYPE_INFO( wxWindow
* , wxWindowList 
) ; 
 296 template<> void wxCollectionToVariantArray( wxWindowList 
const &theList
, wxxVariantArray 
&value
) 
 298     wxListCollectionToVariantArray
<wxWindowList::compatibility_iterator
>( theList 
, value 
) ; 
 301 WX_DEFINE_FLAGS( wxWindowStyle 
) 
 303 wxBEGIN_FLAGS( wxWindowStyle 
) 
 304     // new style border flags, we put them first to 
 305     // use them for streaming out 
 307     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
 308     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
 309     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
 310     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
 311     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
 312     wxFLAGS_MEMBER(wxBORDER_NONE
) 
 314     // old style border flags 
 315     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
 316     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
 317     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
 318     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
 319     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
 320     wxFLAGS_MEMBER(wxBORDER
) 
 322     // standard window styles 
 323     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
 324     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
 325     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
 326     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
 327     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
 328     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
 329     wxFLAGS_MEMBER(wxVSCROLL
) 
 330     wxFLAGS_MEMBER(wxHSCROLL
) 
 332 wxEND_FLAGS( wxWindowStyle 
) 
 334 wxBEGIN_PROPERTIES_TABLE(wxWindow
) 
 335     wxEVENT_PROPERTY( Close 
, wxEVT_CLOSE_WINDOW 
, wxCloseEvent
) 
 336     wxEVENT_PROPERTY( Create 
, wxEVT_CREATE 
, wxWindowCreateEvent 
) 
 337     wxEVENT_PROPERTY( Destroy 
, wxEVT_DESTROY 
, wxWindowDestroyEvent 
) 
 338     // Always constructor Properties first 
 340     wxREADONLY_PROPERTY( Parent
,wxWindow
*, GetParent
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 341     wxPROPERTY( Id
,wxWindowID
, SetId
, GetId
, -1 /*wxID_ANY*/ , 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
 342     wxPROPERTY( Position
,wxPoint
, SetPosition 
, GetPosition
, wxDefaultPosition 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos 
 343     wxPROPERTY( Size
,wxSize
, SetSize
, GetSize
, wxDefaultSize 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size 
 344     wxPROPERTY( WindowStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
 346     // Then all relations of the object graph 
 348     wxREADONLY_PROPERTY_COLLECTION( Children 
, wxWindowList 
, wxWindowBase
* , GetWindowChildren 
, wxPROP_OBJECT_GRAPH 
/*flags*/ , wxT("Helpstring") , wxT("group")) 
 350    // and finally all other properties 
 352     wxPROPERTY( ExtraStyle 
, long , SetExtraStyle 
, GetExtraStyle 
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle 
 353     wxPROPERTY( BackgroundColour 
, wxColour 
, SetBackgroundColour 
, GetBackgroundColour 
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg 
 354     wxPROPERTY( ForegroundColour 
, wxColour 
, SetForegroundColour 
, GetForegroundColour 
, EMPTY_MACROVALUE 
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg 
 355     wxPROPERTY( Enabled 
, bool , Enable 
, IsEnabled 
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 356     wxPROPERTY( Shown 
, bool , Show 
, IsShown 
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 358     // possible property candidates (not in xrc) or not valid in all subclasses 
 359     wxPROPERTY( Title
,wxString
, SetTitle
, GetTitle
, wxEmptyString 
) 
 360     wxPROPERTY( Font 
, wxFont 
, SetFont 
, GetWindowFont  
, ) 
 361     wxPROPERTY( Label
,wxString
, SetLabel
, GetLabel
, wxEmptyString 
) 
 362     // MaxHeight, Width , MinHeight , Width 
 363     // TODO switch label to control and title to toplevels 
 365     wxPROPERTY( ThemeEnabled 
, bool , SetThemeEnabled 
, GetThemeEnabled 
, ) 
 366     //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , ) 
 367     // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , ) 
 368     wxPROPERTY( AutoLayout 
, bool , SetAutoLayout 
, GetAutoLayout 
, ) 
 373 wxEND_PROPERTIES_TABLE() 
 375 wxBEGIN_HANDLERS_TABLE(wxWindow
) 
 376 wxEND_HANDLERS_TABLE() 
 378 wxCONSTRUCTOR_DUMMY(wxWindow
) 
 381     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
 383 #endif // __WXUNIVERSAL__/__WXMSW__ 
 385 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
) 
 386     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
) 
 387     EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
) 
 389     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
) 
 393 // =========================================================================== 
 395 // =========================================================================== 
 397 // --------------------------------------------------------------------------- 
 398 // wxWindow utility functions 
 399 // --------------------------------------------------------------------------- 
 401 // Find an item given the MS Windows id 
 402 wxWindow 
*wxWindowMSW::FindItem(long id
) const 
 405     wxControl 
*item 
= wxDynamicCastThis(wxControl
); 
 408         // is it us or one of our "internal" children? 
 409         if ( item
->GetId() == id
 
 410 #ifndef __WXUNIVERSAL__ 
 411                 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
) 
 412 #endif // __WXUNIVERSAL__ 
 418 #endif // wxUSE_CONTROLS 
 420     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 423         wxWindow 
*childWin 
= current
->GetData(); 
 425         wxWindow 
*wnd 
= childWin
->FindItem(id
); 
 429         current 
= current
->GetNext(); 
 435 // Find an item given the MS Windows handle 
 436 wxWindow 
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const 
 438     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 441         wxWindow 
*parent 
= current
->GetData(); 
 443         // Do a recursive search. 
 444         wxWindow 
*wnd 
= parent
->FindItemByHWND(hWnd
); 
 450                 || parent
->IsKindOf(CLASSINFO(wxControl
)) 
 451 #endif // wxUSE_CONTROLS 
 454             wxWindow 
*item 
= current
->GetData(); 
 455             if ( item
->GetHWND() == hWnd 
) 
 459                 if ( item
->ContainsHWND(hWnd
) ) 
 464         current 
= current
->GetNext(); 
 469 // Default command handler 
 470 bool wxWindowMSW::MSWCommand(WXUINT 
WXUNUSED(param
), WXWORD 
WXUNUSED(id
)) 
 475 // ---------------------------------------------------------------------------- 
 476 // constructors and such 
 477 // ---------------------------------------------------------------------------- 
 479 void wxWindowMSW::Init() 
 482     m_isBeingDeleted 
= false; 
 484     m_mouseInWindow 
= false; 
 485     m_lastKeydownProcessed 
= false; 
 495     m_pendingPosition 
= wxDefaultPosition
; 
 496     m_pendingSize 
= wxDefaultSize
; 
 499     m_contextMenuEnabled 
= false; 
 504 wxWindowMSW::~wxWindowMSW() 
 506     m_isBeingDeleted 
= true; 
 508 #ifndef __WXUNIVERSAL__ 
 509     // VS: make sure there's no wxFrame with last focus set to us: 
 510     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
 512         wxTopLevelWindow 
*frame 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 515             if ( frame
->GetLastFocus() == this ) 
 517                 frame
->SetLastFocus(NULL
); 
 520             // apparently sometimes we can end up with our grand parent 
 521             // pointing to us as well: this is surely a bug in focus handling 
 522             // code but it's not clear where it happens so for now just try to 
 523             // fix it here by not breaking out of the loop 
 527 #endif // __WXUNIVERSAL__ 
 529     // VS: destroy children first and _then_ detach *this from its parent. 
 530     //     If we did it the other way around, children wouldn't be able 
 531     //     find their parent frame (see above). 
 536         // VZ: test temp removed to understand what really happens here 
 537         //if (::IsWindow(GetHwnd())) 
 539             if ( !::DestroyWindow(GetHwnd()) ) 
 540                 wxLogLastError(wxT("DestroyWindow")); 
 543         // remove hWnd <-> wxWindow association 
 544         wxRemoveHandleAssociation(this); 
 549 // real construction (Init() must have been called before!) 
 550 bool wxWindowMSW::Create(wxWindow 
*parent
, 
 555                          const wxString
& name
) 
 557     wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") ); 
 559     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 562     parent
->AddChild(this); 
 565     DWORD msflags 
= MSWGetCreateWindowFlags(&exstyle
); 
 567 #ifdef __WXUNIVERSAL__ 
 568     // no borders, we draw them ourselves 
 569     exstyle 
&= ~(WS_EX_DLGMODALFRAME 
| 
 573     msflags 
&= ~WS_BORDER
; 
 574 #endif // wxUniversal 
 578         msflags 
|= WS_VISIBLE
; 
 581     if ( !MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
) ) 
 589 // --------------------------------------------------------------------------- 
 591 // --------------------------------------------------------------------------- 
 593 void wxWindowMSW::SetFocus() 
 595     HWND hWnd 
= GetHwnd(); 
 596     wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") ); 
 598 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
 602     if ( !::SetFocus(hWnd
) ) 
 604 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__) 
 605         // was there really an error? 
 606         DWORD dwRes 
= ::GetLastError(); 
 609             HWND hwndFocus 
= ::GetFocus(); 
 610             if ( hwndFocus 
!= hWnd 
) 
 612                 wxLogApiError(_T("SetFocus"), dwRes
); 
 619 void wxWindowMSW::SetFocusFromKbd() 
 621     // when the focus is given to the control with DLGC_HASSETSEL style from 
 622     // keyboard its contents should be entirely selected: this is what 
 623     // ::IsDialogMessage() does and so we should do it as well to provide the 
 624     // same LNF as the native programs 
 625     if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL 
) 
 627         ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1); 
 630     // do this after (maybe) setting the selection as like this when 
 631     // wxEVT_SET_FOCUS handler is called, the selection would have been already 
 632     // set correctly -- this may be important 
 633     wxWindowBase::SetFocusFromKbd(); 
 636 // Get the window with the focus 
 637 wxWindow 
*wxWindowBase::DoFindFocus() 
 639     HWND hWnd 
= ::GetFocus(); 
 642         return wxGetWindowFromHWND((WXHWND
)hWnd
); 
 648 void wxWindowMSW::DoEnable( bool enable 
) 
 650     HWND hWnd 
= GetHwnd(); 
 652         ::EnableWindow(hWnd
, (BOOL
)enable
); 
 655 bool wxWindowMSW::Show(bool show
) 
 657     if ( !wxWindowBase::Show(show
) ) 
 660     HWND hWnd 
= GetHwnd(); 
 662     // we could be called before the underlying window is created (this is 
 663     // actually useful to prevent it from being initially shown), e.g. 
 665     //      wxFoo *foo = new wxFoo; 
 667     //      foo->Create(parent, ...); 
 669     // should work without errors 
 672         ::ShowWindow(hWnd
, show 
? SW_SHOW 
: SW_HIDE
); 
 678 // Raise the window to the top of the Z order 
 679 void wxWindowMSW::Raise() 
 681     wxBringWindowToTop(GetHwnd()); 
 684 // Lower the window to the bottom of the Z order 
 685 void wxWindowMSW::Lower() 
 687     ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0, 
 688                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
 691 void wxWindowMSW::DoCaptureMouse() 
 693     HWND hWnd 
= GetHwnd(); 
 700 void wxWindowMSW::DoReleaseMouse() 
 702     if ( !::ReleaseCapture() ) 
 704         wxLogLastError(_T("ReleaseCapture")); 
 708 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 710     HWND hwnd 
= ::GetCapture(); 
 711     return hwnd 
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow 
*)NULL
; 
 714 bool wxWindowMSW::SetFont(const wxFont
& font
) 
 716     if ( !wxWindowBase::SetFont(font
) ) 
 722     HWND hWnd 
= GetHwnd(); 
 725         WXHANDLE hFont 
= m_font
.GetResourceHandle(); 
 727         wxASSERT_MSG( hFont
, wxT("should have valid font") ); 
 729         ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0)); 
 734 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
) 
 736     if ( !wxWindowBase::SetCursor(cursor
) ) 
 742     // don't "overwrite" busy cursor 
 743     if ( m_cursor
.Ok() && !wxIsBusy() ) 
 745         // normally we should change the cursor only if it's over this window 
 746         // but we should do it always if we capture the mouse currently 
 747         bool set 
= HasCapture(); 
 750             HWND hWnd 
= GetHwnd(); 
 754             ::GetCursorPosWinCE(&point
); 
 756             ::GetCursorPos(&point
); 
 759             RECT rect 
= wxGetWindowRect(hWnd
); 
 761             set 
= ::PtInRect(&rect
, point
) != 0; 
 766             ::SetCursor(GetHcursorOf(m_cursor
)); 
 768         //else: will be set later when the mouse enters this window 
 774 void wxWindowMSW::WarpPointer(int x
, int y
) 
 776     ClientToScreen(&x
, &y
); 
 778     if ( !::SetCursorPos(x
, y
) ) 
 780         wxLogLastError(_T("SetCursorPos")); 
 784 void wxWindowMSW::MSWUpdateUIState(int action
, int state
) 
 786     // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good 
 787     // to use it on older systems -- and could possibly do some harm 
 788     static int s_needToUpdate 
= -1; 
 789     if ( s_needToUpdate 
== -1 ) 
 792         s_needToUpdate 
= wxGetOsVersion(&verMaj
, &verMin
) == wxOS_WINDOWS_NT 
&& 
 796     if ( s_needToUpdate 
) 
 798         // we send WM_CHANGEUISTATE so if nothing needs changing then the system 
 799         // won't send WM_UPDATEUISTATE 
 800         ::SendMessage(GetHwnd(), WM_CHANGEUISTATE
, MAKEWPARAM(action
, state
), 0); 
 804 // --------------------------------------------------------------------------- 
 806 // --------------------------------------------------------------------------- 
 808 inline int GetScrollPosition(HWND hWnd
, int wOrient
) 
 810 #ifdef __WXMICROWIN__ 
 811     return ::GetScrollPosWX(hWnd
, wOrient
); 
 813     WinStruct
<SCROLLINFO
> scrollInfo
; 
 814     scrollInfo
.cbSize 
= sizeof(SCROLLINFO
); 
 815     scrollInfo
.fMask 
= SIF_POS
; 
 816     ::GetScrollInfo(hWnd
, wOrient
, &scrollInfo 
); 
 818     return scrollInfo
.nPos
; 
 823 int wxWindowMSW::GetScrollPos(int orient
) const 
 825     HWND hWnd 
= GetHwnd(); 
 826     wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") ); 
 828     return GetScrollPosition(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
); 
 831 // This now returns the whole range, not just the number 
 832 // of positions that we can scroll. 
 833 int wxWindowMSW::GetScrollRange(int orient
) const 
 836     HWND hWnd 
= GetHwnd(); 
 840     ::GetScrollRange(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 843     WinStruct
<SCROLLINFO
> scrollInfo
; 
 844     scrollInfo
.fMask 
= SIF_RANGE
; 
 845     if ( !::GetScrollInfo(hWnd
, 
 846                           orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 849         // Most of the time this is not really an error, since the return 
 850         // value can also be zero when there is no scrollbar yet. 
 851         // wxLogLastError(_T("GetScrollInfo")); 
 853     maxPos 
= scrollInfo
.nMax
; 
 855     // undo "range - 1" done in SetScrollbar() 
 859 int wxWindowMSW::GetScrollThumb(int orient
) const 
 861     return orient 
== wxHORIZONTAL 
? m_xThumbSize 
: m_yThumbSize
; 
 864 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
) 
 866     HWND hWnd 
= GetHwnd(); 
 867     wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") ); 
 869     WinStruct
<SCROLLINFO
> info
; 
 873     info
.fMask 
= SIF_POS
; 
 874     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 876         // disable scrollbar instead of removing it then 
 877         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 880     ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 884 // New function that will replace some of the above. 
 885 void wxWindowMSW::SetScrollbar(int orient
, 
 891     WinStruct
<SCROLLINFO
> info
; 
 892     info
.nPage 
= pageSize
; 
 893     info
.nMin 
= 0;              // range is nMax - nMin + 1 
 894     info
.nMax 
= range 
- 1;      //  as both nMax and nMax are inclusive 
 896     info
.fMask 
= SIF_RANGE 
| SIF_PAGE 
| SIF_POS
; 
 897     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 899         // disable scrollbar instead of removing it then 
 900         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 903     HWND hWnd 
= GetHwnd(); 
 906         // We have to set the variables here to make them valid in events 
 907         // triggered by ::SetScrollInfo() 
 908         *(orient 
== wxHORIZONTAL 
? &m_xThumbSize 
: &m_yThumbSize
) = pageSize
; 
 910         ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 915 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect 
*prect
) 
 921         rect
.left 
= prect
->x
; 
 923         rect
.right 
= prect
->x 
+ prect
->width
; 
 924         rect
.bottom 
= prect
->y 
+ prect
->height
; 
 934     // FIXME: is this the exact equivalent of the line below? 
 935     ::ScrollWindowEx(GetHwnd(), dx
, dy
, pr
, pr
, 0, 0, SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
); 
 937     ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
); 
 941 static bool ScrollVertically(HWND hwnd
, int kind
, int count
) 
 943     int posStart 
= GetScrollPosition(hwnd
, SB_VERT
); 
 946     for ( int n 
= 0; n 
< count
; n
++ ) 
 948         ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0); 
 950         int posNew 
= GetScrollPosition(hwnd
, SB_VERT
); 
 953             // don't bother to continue, we're already at top/bottom 
 960     return pos 
!= posStart
; 
 963 bool wxWindowMSW::ScrollLines(int lines
) 
 965     bool down 
= lines 
> 0; 
 967     return ScrollVertically(GetHwnd(), 
 968                             down 
? SB_LINEDOWN 
: SB_LINEUP
, 
 969                             down 
? lines 
: -lines
); 
 972 bool wxWindowMSW::ScrollPages(int pages
) 
 974     bool down 
= pages 
> 0; 
 976     return ScrollVertically(GetHwnd(), 
 977                             down 
? SB_PAGEDOWN 
: SB_PAGEUP
, 
 978                             down 
? pages 
: -pages
); 
 981 // ---------------------------------------------------------------------------- 
 983 // ---------------------------------------------------------------------------- 
 985 void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir
) 
 990     const HWND hwnd 
= GetHwnd(); 
 991     wxCHECK_RET( hwnd
, _T("layout direction must be set after window creation") ); 
 993     LONG styleOld 
= ::GetWindowLong(hwnd
, GWL_EXSTYLE
); 
 995     LONG styleNew 
= styleOld
; 
 998         case wxLayout_LeftToRight
: 
 999             styleNew 
&= ~WS_EX_LAYOUTRTL
; 
1002         case wxLayout_RightToLeft
: 
1003             styleNew 
|= WS_EX_LAYOUTRTL
; 
1007             wxFAIL_MSG(_T("unsupported layout direction")); 
1011     if ( styleNew 
!= styleOld 
) 
1013         ::SetWindowLong(hwnd
, GWL_EXSTYLE
, styleNew
); 
1018 wxLayoutDirection 
wxWindowMSW::GetLayoutDirection() const 
1021     return wxLayout_Default
; 
1023     const HWND hwnd 
= GetHwnd(); 
1024     wxCHECK_MSG( hwnd
, wxLayout_Default
, _T("invalid window") ); 
1026     return ::GetWindowLong(hwnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
 
1027                 ? wxLayout_RightToLeft
 
1028                 : wxLayout_LeftToRight
; 
1033 wxWindowMSW::AdjustForLayoutDirection(wxCoord x
, 
1034                                       wxCoord 
WXUNUSED(width
), 
1035                                       wxCoord 
WXUNUSED(widthTotal
)) const 
1037     // Win32 mirrors the coordinates of RTL windows automatically, so don't 
1038     // redo it ourselves 
1042 // --------------------------------------------------------------------------- 
1044 // --------------------------------------------------------------------------- 
1046 void wxWindowMSW::SubclassWin(WXHWND hWnd
) 
1048     wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") ); 
1050     HWND hwnd 
= (HWND
)hWnd
; 
1051     wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") ); 
1053     wxAssociateWinWithHandle(hwnd
, this); 
1055     m_oldWndProc 
= (WXFARPROC
)wxGetWindowProc((HWND
)hWnd
); 
1057     // we don't need to subclass the window of our own class (in the Windows 
1058     // sense of the word) 
1059     if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) ) 
1061         wxSetWindowProc(hwnd
, wxWndProc
); 
1065         // don't bother restoring it either: this also makes it easy to 
1066         // implement IsOfStandardClass() method which returns true for the 
1067         // standard controls and false for the wxWidgets own windows as it can 
1068         // simply check m_oldWndProc 
1069         m_oldWndProc 
= NULL
; 
1072     // we're officially created now, send the event 
1073     wxWindowCreateEvent 
event((wxWindow 
*)this); 
1074     (void)GetEventHandler()->ProcessEvent(event
); 
1077 void wxWindowMSW::UnsubclassWin() 
1079     wxRemoveHandleAssociation(this); 
1081     // Restore old Window proc 
1082     HWND hwnd 
= GetHwnd(); 
1087         wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") ); 
1091             if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) ) 
1093                 wxSetWindowProc(hwnd
, (WNDPROC
)m_oldWndProc
); 
1096             m_oldWndProc 
= NULL
; 
1101 void wxWindowMSW::AssociateHandle(WXWidget handle
) 
1105       if ( !::DestroyWindow(GetHwnd()) ) 
1106         wxLogLastError(wxT("DestroyWindow")); 
1109     WXHWND wxhwnd 
= (WXHWND
)handle
; 
1112     SubclassWin(wxhwnd
); 
1115 void wxWindowMSW::DissociateHandle() 
1117     // this also calls SetHWND(0) for us 
1122 bool wxCheckWindowWndProc(WXHWND hWnd
, 
1123                           WXFARPROC 
WXUNUSED(wndProc
)) 
1125 // TODO: This list of window class names should be factored out so they can be 
1126 // managed in one place and then accessed from here and other places, such as 
1127 // wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses() 
1130     extern       wxChar 
*wxCanvasClassName
; 
1131     extern       wxChar 
*wxCanvasClassNameNR
; 
1133     extern const wxChar 
*wxCanvasClassName
; 
1134     extern const wxChar 
*wxCanvasClassNameNR
; 
1136     extern const wxChar 
*wxMDIFrameClassName
; 
1137     extern const wxChar 
*wxMDIFrameClassNameNoRedraw
; 
1138     extern const wxChar 
*wxMDIChildFrameClassName
; 
1139     extern const wxChar 
*wxMDIChildFrameClassNameNoRedraw
; 
1140     wxString 
str(wxGetWindowClass(hWnd
)); 
1141     if (str 
== wxCanvasClassName 
|| 
1142         str 
== wxCanvasClassNameNR 
|| 
1144         str 
== _T("wxGLCanvasClass") || 
1145         str 
== _T("wxGLCanvasClassNR") || 
1146 #endif // wxUSE_GLCANVAS 
1147         str 
== wxMDIFrameClassName 
|| 
1148         str 
== wxMDIFrameClassNameNoRedraw 
|| 
1149         str 
== wxMDIChildFrameClassName 
|| 
1150         str 
== wxMDIChildFrameClassNameNoRedraw 
|| 
1151         str 
== _T("wxTLWHiddenParent")) 
1152         return true; // Effectively means don't subclass 
1157 // ---------------------------------------------------------------------------- 
1159 // ---------------------------------------------------------------------------- 
1161 void wxWindowMSW::SetWindowStyleFlag(long flags
) 
1163     long flagsOld 
= GetWindowStyleFlag(); 
1164     if ( flags 
== flagsOld 
) 
1167     // update the internal variable 
1168     wxWindowBase::SetWindowStyleFlag(flags
); 
1170     // and the real window flags 
1171     MSWUpdateStyle(flagsOld
, GetExtraStyle()); 
1174 void wxWindowMSW::SetExtraStyle(long exflags
) 
1176     long exflagsOld 
= GetExtraStyle(); 
1177     if ( exflags 
== exflagsOld 
) 
1180     // update the internal variable 
1181     wxWindowBase::SetExtraStyle(exflags
); 
1183     // and the real window flags 
1184     MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld
); 
1187 void wxWindowMSW::MSWUpdateStyle(long flagsOld
, long exflagsOld
) 
1189     // now update the Windows style as well if needed - and if the window had 
1190     // been already created 
1194     // we may need to call SetWindowPos() when we change some styles 
1195     bool callSWP 
= false; 
1198     long style 
= MSWGetStyle(GetWindowStyleFlag(), &exstyle
); 
1200     // this is quite a horrible hack but we need it because MSWGetStyle() 
1201     // doesn't take exflags as parameter but uses GetExtraStyle() internally 
1202     // and so we have to modify the window exflags temporarily to get the 
1203     // correct exstyleOld 
1204     long exflagsNew 
= GetExtraStyle(); 
1205     wxWindowBase::SetExtraStyle(exflagsOld
); 
1208     long styleOld 
= MSWGetStyle(flagsOld
, &exstyleOld
); 
1210     wxWindowBase::SetExtraStyle(exflagsNew
); 
1213     if ( style 
!= styleOld 
) 
1215         // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by 
1216         // this function so instead of simply setting the style to the new 
1217         // value we clear the bits which were set in styleOld but are set in 
1218         // the new one and set the ones which were not set before 
1219         long styleReal 
= ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
1220         styleReal 
&= ~styleOld
; 
1223         ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
); 
1225         // we need to call SetWindowPos() if any of the styles affecting the 
1226         // frame appearance have changed 
1227         callSWP 
= ((styleOld 
^ style 
) & (WS_BORDER 
| 
1236     // and the extended style 
1237     long exstyleReal 
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1239     if ( exstyle 
!= exstyleOld 
) 
1241         exstyleReal 
&= ~exstyleOld
; 
1242         exstyleReal 
|= exstyle
; 
1244         ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
); 
1246         // ex style changes don't take effect without calling SetWindowPos 
1252         // we must call SetWindowPos() to flush the cached extended style and 
1253         // also to make the change to wxSTAY_ON_TOP style take effect: just 
1254         // setting the style simply doesn't work 
1255         if ( !::SetWindowPos(GetHwnd(), 
1256                              exstyleReal 
& WS_EX_TOPMOST 
? HWND_TOPMOST
 
1259                              SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_FRAMECHANGED
) ) 
1261             wxLogLastError(_T("SetWindowPos")); 
1266 WXDWORD 
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD 
*exstyle
) const 
1268     // translate common wxWidgets styles to Windows ones 
1270     // most of windows are child ones, those which are not (such as 
1271     // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle() 
1272     WXDWORD style 
= WS_CHILD
; 
1274     // using this flag results in very significant reduction in flicker, 
1275     // especially with controls inside the static boxes (as the interior of the 
1276     // box is not redrawn twice), but sometimes results in redraw problems, so 
1277     // optionally allow the old code to continue to use it provided a special 
1278     // system option is turned on 
1279     if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) 
1280             || (flags 
& wxCLIP_CHILDREN
) ) 
1281         style 
|= WS_CLIPCHILDREN
; 
1283     // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially 
1284     // don't support overlapping windows and it only makes sense for them and, 
1285     // presumably, gives the system some extra work (to manage more clipping 
1286     // regions), so avoid it alltogether 
1289     if ( flags 
& wxVSCROLL 
) 
1290         style 
|= WS_VSCROLL
; 
1292     if ( flags 
& wxHSCROLL 
) 
1293         style 
|= WS_HSCROLL
; 
1295     const wxBorder border 
= GetBorder(flags
); 
1297     // WS_BORDER is only required for wxBORDER_SIMPLE 
1298     if ( border 
== wxBORDER_SIMPLE 
) 
1301     // now deal with ext style if the caller wants it 
1307         if ( flags 
& wxTRANSPARENT_WINDOW 
) 
1308             *exstyle 
|= WS_EX_TRANSPARENT
; 
1314             case wxBORDER_DEFAULT
: 
1315                 wxFAIL_MSG( _T("unknown border style") ); 
1319             case wxBORDER_SIMPLE
: 
1322             case wxBORDER_STATIC
: 
1323                 *exstyle 
|= WS_EX_STATICEDGE
; 
1326             case wxBORDER_RAISED
: 
1327                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1330             case wxBORDER_SUNKEN
: 
1331                 *exstyle 
|= WS_EX_CLIENTEDGE
; 
1332                 style 
&= ~WS_BORDER
; 
1335             case wxBORDER_DOUBLE
: 
1336                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1340         // wxUniv doesn't use Windows dialog navigation functions at all 
1341 #if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__) 
1342         // to make the dialog navigation work with the nested panels we must 
1343         // use this style (top level windows such as dialogs don't need it) 
1344         if ( (flags 
& wxTAB_TRAVERSAL
) && !IsTopLevel() ) 
1346             *exstyle 
|= WS_EX_CONTROLPARENT
; 
1348 #endif // __WXUNIVERSAL__ 
1354 // Setup background and foreground colours correctly 
1355 void wxWindowMSW::SetupColours() 
1358         SetBackgroundColour(GetParent()->GetBackgroundColour()); 
1361 bool wxWindowMSW::IsMouseInWindow() const 
1363     // get the mouse position 
1366     ::GetCursorPosWinCE(&pt
); 
1368     ::GetCursorPos(&pt
); 
1371     // find the window which currently has the cursor and go up the window 
1372     // chain until we find this window - or exhaust it 
1373     HWND hwnd 
= ::WindowFromPoint(pt
); 
1374     while ( hwnd 
&& (hwnd 
!= GetHwnd()) ) 
1375         hwnd 
= ::GetParent(hwnd
); 
1377     return hwnd 
!= NULL
; 
1380 void wxWindowMSW::OnInternalIdle() 
1382 #ifndef HAVE_TRACKMOUSEEVENT 
1383     // Check if we need to send a LEAVE event 
1384     if ( m_mouseInWindow 
) 
1386         // note that we should generate the leave event whether the window has 
1387         // or doesn't have mouse capture 
1388         if ( !IsMouseInWindow() ) 
1390             GenerateMouseLeave(); 
1393 #endif // !HAVE_TRACKMOUSEEVENT 
1395     if (wxUpdateUIEvent::CanUpdate(this)) 
1396         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
1399 // Set this window to be the child of 'parent'. 
1400 bool wxWindowMSW::Reparent(wxWindowBase 
*parent
) 
1402     if ( !wxWindowBase::Reparent(parent
) ) 
1405     HWND hWndChild 
= GetHwnd(); 
1406     HWND hWndParent 
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0; 
1408     ::SetParent(hWndChild
, hWndParent
); 
1411     if ( ::GetWindowLong(hWndChild
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
1413         EnsureParentHasControlParentStyle(GetParent()); 
1415 #endif // !__WXWINCE__ 
1420 static inline void SendSetRedraw(HWND hwnd
, bool on
) 
1422 #ifndef __WXMICROWIN__ 
1423     ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0); 
1427 void wxWindowMSW::Freeze() 
1429     if ( !m_frozenness
++ ) 
1432             SendSetRedraw(GetHwnd(), false); 
1436 void wxWindowMSW::Thaw() 
1438     wxASSERT_MSG( m_frozenness 
> 0, _T("Thaw() without matching Freeze()") ); 
1440     if ( --m_frozenness 
== 0 ) 
1444             SendSetRedraw(GetHwnd(), true); 
1446             // we need to refresh everything or otherwise the invalidated area 
1447             // is not going to be repainted 
1453 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1455     HWND hWnd 
= GetHwnd(); 
1462             mswRect
.left 
= rect
->x
; 
1463             mswRect
.top 
= rect
->y
; 
1464             mswRect
.right 
= rect
->x 
+ rect
->width
; 
1465             mswRect
.bottom 
= rect
->y 
+ rect
->height
; 
1474         // RedrawWindow not available on SmartPhone or eVC++ 3 
1475 #if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400) 
1476         UINT flags 
= RDW_INVALIDATE 
| RDW_ALLCHILDREN
; 
1480         ::RedrawWindow(hWnd
, pRect
, NULL
, flags
); 
1482         ::InvalidateRect(hWnd
, pRect
, eraseBack
); 
1487 void wxWindowMSW::Update() 
1489     if ( !::UpdateWindow(GetHwnd()) ) 
1491         wxLogLastError(_T("UpdateWindow")); 
1494 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
1495     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT 
1496     // handler needs to be really drawn right now 
1501 // --------------------------------------------------------------------------- 
1503 // --------------------------------------------------------------------------- 
1505 #if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__) 
1509 // we need to lower the sibling static boxes so controls contained within can be 
1511 static void AdjustStaticBoxZOrder(wxWindow 
*parent
) 
1513     // no sibling static boxes if we have no parent (ie TLW) 
1517     for ( wxWindowList::compatibility_iterator node 
= parent
->GetChildren().GetFirst(); 
1519           node 
= node
->GetNext() ) 
1521         wxStaticBox 
*statbox 
= wxDynamicCast(node
->GetData(), wxStaticBox
); 
1524             ::SetWindowPos(GetHwndOf(statbox
), HWND_BOTTOM
, 0, 0, 0, 0, 
1525                            SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
1530 #else // !wxUSE_STATBOX 
1532 static inline void AdjustStaticBoxZOrder(wxWindow 
* WXUNUSED(parent
)) 
1536 #endif // wxUSE_STATBOX/!wxUSE_STATBOX 
1538 #endif // drag and drop is used 
1540 #if wxUSE_DRAG_AND_DROP 
1541 void wxWindowMSW::SetDropTarget(wxDropTarget 
*pDropTarget
) 
1543     if ( m_dropTarget 
!= 0 ) { 
1544         m_dropTarget
->Revoke(m_hWnd
); 
1545         delete m_dropTarget
; 
1548     m_dropTarget 
= pDropTarget
; 
1549     if ( m_dropTarget 
!= 0 ) 
1551         AdjustStaticBoxZOrder(GetParent()); 
1552         m_dropTarget
->Register(m_hWnd
); 
1555 #endif // wxUSE_DRAG_AND_DROP 
1557 // old-style file manager drag&drop support: we retain the old-style 
1558 // DragAcceptFiles in parallel with SetDropTarget. 
1559 void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept
)) 
1562     HWND hWnd 
= GetHwnd(); 
1565         AdjustStaticBoxZOrder(GetParent()); 
1566         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
1571 // ---------------------------------------------------------------------------- 
1573 // ---------------------------------------------------------------------------- 
1577 void wxWindowMSW::DoSetToolTip(wxToolTip 
*tooltip
) 
1579     wxWindowBase::DoSetToolTip(tooltip
); 
1582         m_tooltip
->SetWindow((wxWindow 
*)this); 
1585 #endif // wxUSE_TOOLTIPS 
1587 // --------------------------------------------------------------------------- 
1588 // moving and resizing 
1589 // --------------------------------------------------------------------------- 
1591 bool wxWindowMSW::IsSizeDeferred() const 
1593 #if USE_DEFERRED_SIZING 
1594     if ( m_pendingPosition 
!= wxDefaultPosition 
|| 
1595          m_pendingSize     
!= wxDefaultSize 
) 
1597 #endif // USE_DEFERRED_SIZING 
1603 void wxWindowMSW::DoGetSize(int *x
, int *y
) const 
1605 #if USE_DEFERRED_SIZING 
1606     // if SetSize() had been called at wx level but not realized at Windows 
1607     // level yet (i.e. EndDeferWindowPos() not called), we still should return 
1608     // the new and not the old position to the other wx code 
1609     if ( m_pendingSize 
!= wxDefaultSize 
) 
1612             *x 
= m_pendingSize
.x
; 
1614             *y 
= m_pendingSize
.y
; 
1616     else // use current size 
1617 #endif // USE_DEFERRED_SIZING 
1619         RECT rect 
= wxGetWindowRect(GetHwnd()); 
1622             *x 
= rect
.right 
- rect
.left
; 
1624             *y 
= rect
.bottom 
- rect
.top
; 
1628 // Get size *available for subwindows* i.e. excluding menu bar etc. 
1629 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const 
1631 #if USE_DEFERRED_SIZING 
1632     if ( m_pendingSize 
!= wxDefaultSize 
) 
1634         // we need to calculate the client size corresponding to pending size 
1636         rect
.left 
= m_pendingPosition
.x
; 
1637         rect
.top 
= m_pendingPosition
.y
; 
1638         rect
.right 
= rect
.left 
+ m_pendingSize
.x
; 
1639         rect
.bottom 
= rect
.top 
+ m_pendingSize
.y
; 
1641         ::SendMessage(GetHwnd(), WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
); 
1644             *x 
= rect
.right 
- rect
.left
; 
1646             *y 
= rect
.bottom 
- rect
.top
; 
1649 #endif // USE_DEFERRED_SIZING 
1651         RECT rect 
= wxGetClientRect(GetHwnd()); 
1660 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const 
1662     wxWindow 
* const parent 
= GetParent(); 
1665     if ( m_pendingPosition 
!= wxDefaultPosition 
) 
1667         pos 
= m_pendingPosition
; 
1669     else // use current position 
1671         RECT rect 
= wxGetWindowRect(GetHwnd()); 
1674         point
.x 
= rect
.left
; 
1677         // we do the adjustments with respect to the parent only for the "real" 
1678         // children, not for the dialogs/frames 
1679         if ( !IsTopLevel() ) 
1681             if ( wxTheApp
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
1683                 // In RTL mode, we want the logical left x-coordinate, 
1684                 // which would be the physical right x-coordinate. 
1685                 point
.x 
= rect
.right
; 
1688             // Since we now have the absolute screen coords, if there's a 
1689             // parent we must subtract its top left corner 
1692                 ::ScreenToClient(GetHwndOf(parent
), &point
); 
1700     // we also must adjust by the client area offset: a control which is just 
1701     // under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx 
1702     if ( parent 
&& !IsTopLevel() ) 
1704         const wxPoint 
pt(parent
->GetClientAreaOrigin()); 
1715 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const 
1723     ::ScreenToClient(GetHwnd(), &pt
); 
1731 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const 
1739     ::ClientToScreen(GetHwnd(), &pt
); 
1748 wxWindowMSW::DoMoveSibling(WXHWND hwnd
, int x
, int y
, int width
, int height
) 
1750 #if USE_DEFERRED_SIZING 
1751     // if our parent had prepared a defer window handle for us, use it (unless 
1752     // we are a top level window) 
1753     wxWindowMSW 
* const parent 
= IsTopLevel() ? NULL 
: GetParent(); 
1755     HDWP hdwp 
= parent 
? (HDWP
)parent
->m_hDWP 
: NULL
; 
1758         hdwp 
= ::DeferWindowPos(hdwp
, (HWND
)hwnd
, NULL
, x
, y
, width
, height
, 
1759                                 SWP_NOZORDER 
| SWP_NOOWNERZORDER 
| SWP_NOACTIVATE
); 
1762             wxLogLastError(_T("DeferWindowPos")); 
1768         // hdwp must be updated as it may have been changed 
1769         parent
->m_hDWP 
= (WXHANDLE
)hdwp
; 
1774         // did deferred move, remember new coordinates of the window as they're 
1775         // different from what Windows would return for it 
1779     // otherwise (or if deferring failed) move the window in place immediately 
1780 #endif // USE_DEFERRED_SIZING 
1781     if ( !::MoveWindow((HWND
)hwnd
, x
, y
, width
, height
, IsShown()) ) 
1783         wxLogLastError(wxT("MoveWindow")); 
1786     // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move, 
1787     // ignored otherwise 
1791 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
) 
1793     // TODO: is this consistent with other platforms? 
1794     // Still, negative width or height shouldn't be allowed 
1800     if ( DoMoveSibling(m_hWnd
, x
, y
, width
, height
) ) 
1802 #if USE_DEFERRED_SIZING 
1803         m_pendingPosition 
= wxPoint(x
, y
); 
1804         m_pendingSize 
= wxSize(width
, height
); 
1805 #endif // USE_DEFERRED_SIZING 
1809 // set the size of the window: if the dimensions are positive, just use them, 
1810 // but if any of them is equal to -1, it means that we must find the value for 
1811 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
1812 // which case -1 is a valid value for x and y) 
1814 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
1815 // the width/height to best suit our contents, otherwise we reuse the current 
1817 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
1819     // get the current size and position... 
1820     int currentX
, currentY
; 
1821     int currentW
, currentH
; 
1823     GetPosition(¤tX
, ¤tY
); 
1824     GetSize(¤tW
, ¤tH
); 
1826     // ... and don't do anything (avoiding flicker) if it's already ok unless 
1827     // we're forced to resize the window 
1828     if ( x 
== currentX 
&& y 
== currentY 
&& 
1829          width 
== currentW 
&& height 
== currentH 
&& 
1830             !(sizeFlags 
& wxSIZE_FORCE
) ) 
1835     if ( x 
== wxDefaultCoord 
&& !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1837     if ( y 
== wxDefaultCoord 
&& !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1840     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
1842     wxSize size 
= wxDefaultSize
; 
1843     if ( width 
== wxDefaultCoord 
) 
1845         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
1847             size 
= DoGetBestSize(); 
1852             // just take the current one 
1857     if ( height 
== wxDefaultCoord 
) 
1859         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
1861             if ( size
.x 
== wxDefaultCoord 
) 
1863                 size 
= DoGetBestSize(); 
1865             //else: already called DoGetBestSize() above 
1871             // just take the current one 
1876     DoMoveWindow(x
, y
, width
, height
); 
1879 void wxWindowMSW::DoSetClientSize(int width
, int height
) 
1881     // setting the client size is less obvious than it could have been 
1882     // because in the result of changing the total size the window scrollbar 
1883     // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect() 
1884     // doesn't take neither into account) and so the client size will not be 
1885     // correct as the difference between the total and client size changes -- 
1886     // so we keep changing it until we get it right 
1888     // normally this loop shouldn't take more than 3 iterations (usually 1 but 
1889     // if scrollbars [dis]appear as the result of the first call, then 2 and it 
1890     // may become 3 if the window had 0 size originally and so we didn't 
1891     // calculate the scrollbar correction correctly during the first iteration) 
1892     // but just to be on the safe side we check for it instead of making it an 
1893     // "infinite" loop (i.e. leaving break inside as the only way to get out) 
1894     for ( int i 
= 0; i 
< 4; i
++ ) 
1897         ::GetClientRect(GetHwnd(), &rectClient
); 
1899         // if the size is already ok, stop here (NB: rectClient.left = top = 0) 
1900         if ( (rectClient
.right 
== width 
|| width 
== wxDefaultCoord
) && 
1901              (rectClient
.bottom 
== height 
|| height 
== wxDefaultCoord
) ) 
1906         // Find the difference between the entire window (title bar and all) 
1907         // and the client area; add this to the new client size to move the 
1910         ::GetWindowRect(GetHwnd(), &rectWin
); 
1912         const int widthWin 
= rectWin
.right 
- rectWin
.left
, 
1913                   heightWin 
= rectWin
.bottom 
- rectWin
.top
; 
1915         // MoveWindow positions the child windows relative to the parent, so 
1916         // adjust if necessary 
1917         if ( !IsTopLevel() ) 
1919             wxWindow 
*parent 
= GetParent(); 
1922                 ::ScreenToClient(GetHwndOf(parent
), (POINT 
*)&rectWin
); 
1926         // don't call DoMoveWindow() because we want to move window immediately 
1927         // and not defer it here as otherwise the value returned by 
1928         // GetClient/WindowRect() wouldn't change as the window wouldn't be 
1930         if ( !::MoveWindow(GetHwnd(), 
1933                            width 
+ widthWin 
- rectClient
.right
, 
1934                            height 
+ heightWin 
- rectClient
.bottom
, 
1937             wxLogLastError(_T("MoveWindow")); 
1942 // --------------------------------------------------------------------------- 
1944 // --------------------------------------------------------------------------- 
1946 int wxWindowMSW::GetCharHeight() const 
1948     return wxGetTextMetrics(this).tmHeight
; 
1951 int wxWindowMSW::GetCharWidth() const 
1953     // +1 is needed because Windows apparently adds it when calculating the 
1954     // dialog units size in pixels 
1955 #if wxDIALOG_UNIT_COMPATIBILITY 
1956     return wxGetTextMetrics(this).tmAveCharWidth
; 
1958     return wxGetTextMetrics(this).tmAveCharWidth 
+ 1; 
1962 void wxWindowMSW::GetTextExtent(const wxString
& string
, 
1964                              int *descent
, int *externalLeading
, 
1965                              const wxFont 
*theFont
) const 
1967     wxASSERT_MSG( !theFont 
|| theFont
->Ok(), 
1968                     _T("invalid font in GetTextExtent()") ); 
1972         fontToUse 
= *theFont
; 
1974         fontToUse 
= GetFont(); 
1976     WindowHDC 
hdc(GetHwnd()); 
1977     SelectInHDC 
selectFont(hdc
, GetHfontOf(fontToUse
)); 
1981     ::GetTextExtentPoint32(hdc
, string
, string
.length(), &sizeRect
); 
1982     GetTextMetrics(hdc
, &tm
); 
1989         *descent 
= tm
.tmDescent
; 
1990     if ( externalLeading 
) 
1991         *externalLeading 
= tm
.tmExternalLeading
; 
1994 // --------------------------------------------------------------------------- 
1996 // --------------------------------------------------------------------------- 
1998 #if wxUSE_MENUS_NATIVE 
2000 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue 
2001 // immediately, without waiting for the next event loop iteration 
2003 // NB: this function should probably be made public later as it can almost 
2004 //     surely replace wxYield() elsewhere as well 
2005 static void wxYieldForCommandsOnly() 
2007     // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't 
2008     // want to process it here) 
2010     while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) ) 
2012         if ( msg
.message 
== WM_QUIT 
) 
2014             // if we retrieved a WM_QUIT, insert back into the message queue. 
2015             ::PostQuitMessage(0); 
2019         // luckily (as we don't have access to wxEventLoopImpl method from here 
2020         // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it 
2022         ::TranslateMessage(&msg
); 
2023         ::DispatchMessage(&msg
); 
2027 bool wxWindowMSW::DoPopupMenu(wxMenu 
*menu
, int x
, int y
) 
2029     menu
->SetInvokingWindow(this); 
2032     if ( x 
== wxDefaultCoord 
&& y 
== wxDefaultCoord 
) 
2034         wxPoint mouse 
= ScreenToClient(wxGetMousePosition()); 
2035         x 
= mouse
.x
; y 
= mouse
.y
; 
2038     HWND hWnd 
= GetHwnd(); 
2039     HMENU hMenu 
= GetHmenuOf(menu
); 
2043     ::ClientToScreen(hWnd
, &point
); 
2044     wxCurrentPopupMenu 
= menu
; 
2045 #if defined(__WXWINCE__) 
2048     UINT flags 
= TPM_RIGHTBUTTON 
| TPM_RECURSE
; 
2050     ::TrackPopupMenu(hMenu
, flags
, point
.x
, point
.y
, 0, hWnd
, NULL
); 
2052     // we need to do it right now as otherwise the events are never going to be 
2053     // sent to wxCurrentPopupMenu from HandleCommand() 
2055     // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't 
2056     // help and we'd still need wxYieldForCommandsOnly() as the menu may be 
2057     // destroyed as soon as we return (it can be a local variable in the caller 
2058     // for example) and so we do need to process the event immediately 
2059     wxYieldForCommandsOnly(); 
2061     wxCurrentPopupMenu 
= NULL
; 
2063     menu
->SetInvokingWindow(NULL
); 
2068 #endif // wxUSE_MENUS_NATIVE 
2070 // =========================================================================== 
2071 // pre/post message processing 
2072 // =========================================================================== 
2074 WXLRESULT 
wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
2077         return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
2079         return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
); 
2082 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
) 
2084     // wxUniversal implements tab traversal itself 
2085 #ifndef __WXUNIVERSAL__ 
2086     if ( m_hWnd 
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) ) 
2088         // intercept dialog navigation keys 
2089         MSG 
*msg 
= (MSG 
*)pMsg
; 
2091         // here we try to do all the job which ::IsDialogMessage() usually does 
2093         if ( msg
->message 
== WM_KEYDOWN 
) 
2095             bool bCtrlDown 
= wxIsCtrlDown(); 
2096             bool bShiftDown 
= wxIsShiftDown(); 
2098             // WM_GETDLGCODE: ask the control if it wants the key for itself, 
2099             // don't process it if it's the case (except for Ctrl-Tab/Enter 
2100             // combinations which are always processed) 
2101             LONG lDlgCode 
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0); 
2103             // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the 
2104             // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, 
2105             // it, of course, implies them 
2106             if ( lDlgCode 
& DLGC_WANTALLKEYS 
) 
2108                 lDlgCode 
|= DLGC_WANTTAB 
| DLGC_WANTARROWS
; 
2111             bool bForward 
= true, 
2112                  bWindowChange 
= false, 
2115             // should we process this message specially? 
2116             bool bProcess 
= true; 
2117             switch ( msg
->wParam 
) 
2120                     if ( (lDlgCode 
& DLGC_WANTTAB
) && !bCtrlDown 
) 
2122                         // let the control have the TAB 
2125                     else // use it for navigation 
2127                         // Ctrl-Tab cycles thru notebook pages 
2128                         bWindowChange 
= bCtrlDown
; 
2129                         bForward 
= !bShiftDown
; 
2136                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
2144                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
2153                     // we treat PageUp/Dn as arrows because chances are that 
2154                     // a control which needs arrows also needs them for 
2155                     // navigation (e.g. wxTextCtrl, wxListCtrl, ...) 
2156                     if ( (lDlgCode 
& DLGC_WANTARROWS
) && !bCtrlDown 
) 
2158                     else // OTOH Ctrl-PageUp/Dn works as [Shift-]Ctrl-Tab 
2159                         bWindowChange 
= true; 
2164                         if ( (lDlgCode 
& DLGC_WANTMESSAGE
) && !bCtrlDown 
) 
2166                             // control wants to process Enter itself, don't 
2167                             // call IsDialogMessage() which would consume it 
2172                         // currently active button should get enter press even 
2173                         // if there is a default button elsewhere so check if 
2174                         // this window is a button first 
2175                         wxWindow 
*btn 
= NULL
; 
2176                         if ( lDlgCode 
& DLGC_DEFPUSHBUTTON 
) 
2178                             // let IsDialogMessage() handle this for all 
2179                             // buttons except the owner-drawn ones which it 
2180                             // just seems to ignore 
2181                             long style 
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
); 
2182                             if ( (style 
& BS_OWNERDRAW
) == BS_OWNERDRAW 
) 
2184                                 // emulate the button click 
2185                                 btn 
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
); 
2190                         else // not a button itself, do we have default button? 
2193                                 tlw 
= wxDynamicCast(wxGetTopLevelParent(this), 
2197                                 btn 
= wxDynamicCast(tlw
->GetDefaultItem(), 
2202                         if ( btn 
&& btn
->IsEnabled() ) 
2204                             btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
2208 #endif // wxUSE_BUTTON 
2211                         // map Enter presses into button presses on PDAs 
2212                         wxJoystickEvent 
event(wxEVT_JOY_BUTTON_DOWN
); 
2213                         event
.SetEventObject(this); 
2214                         if ( GetEventHandler()->ProcessEvent(event
) ) 
2216 #endif // __WXWINCE__ 
2226                 wxNavigationKeyEvent event
; 
2227                 event
.SetDirection(bForward
); 
2228                 event
.SetWindowChange(bWindowChange
); 
2229                 event
.SetFromTab(bFromTab
); 
2230                 event
.SetEventObject(this); 
2232                 if ( GetEventHandler()->ProcessEvent(event
) ) 
2234                     // as we don't call IsDialogMessage(), which would take of 
2235                     // this by default, we need to manually send this message 
2236                     // so that controls can change their UI state if needed 
2237                     MSWUpdateUIState(UIS_CLEAR
, UISF_HIDEFOCUS
); 
2244         if ( ::IsDialogMessage(GetHwnd(), msg
) ) 
2246             // IsDialogMessage() did something... 
2250 #endif // __WXUNIVERSAL__ 
2255         // relay mouse move events to the tooltip control 
2256         MSG 
*msg 
= (MSG 
*)pMsg
; 
2257         if ( msg
->message 
== WM_MOUSEMOVE 
) 
2258             wxToolTip::RelayEvent(pMsg
); 
2260 #endif // wxUSE_TOOLTIPS 
2265 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
) 
2267 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__) 
2268     return m_acceleratorTable
.Translate(this, pMsg
); 
2272 #endif // wxUSE_ACCEL 
2275 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* msg
) 
2277     // all tests below have to deal with various bugs/misfeatures of 
2278     // IsDialogMessage(): we have to prevent it from being called from our 
2279     // MSWProcessMessage() in some situations 
2281     // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the 
2282     // message even when there is no cancel button and when the message is 
2283     // needed by the control itself: in particular, it prevents the tree in 
2284     // place edit control from being closed with Escape in a dialog 
2285     if ( msg
->message 
== WM_KEYDOWN 
&& msg
->wParam 
== VK_ESCAPE 
) 
2290     // ::IsDialogMessage() is broken and may sometimes hang the application by 
2291     // going into an infinite loop when it tries to find the control to give 
2292     // focus to when Alt-<key> is pressed, so we try to detect [some of] the 
2293     // situations when this may happen and not call it then 
2294     if ( msg
->message 
!= WM_SYSCHAR 
) 
2297     // assume we can call it by default 
2298     bool canSafelyCallIsDlgMsg 
= true; 
2300     HWND hwndFocus 
= ::GetFocus(); 
2302     // if the currently focused window itself has WS_EX_CONTROLPARENT style, 
2303     // ::IsDialogMessage() will also enter an infinite loop, because it will 
2304     // recursively check the child windows but not the window itself and so if 
2305     // none of the children accepts focus it loops forever (as it only stops 
2306     // when it gets back to the window it started from) 
2308     // while it is very unusual that a window with WS_EX_CONTROLPARENT 
2309     // style has the focus, it can happen. One such possibility is if 
2310     // all windows are either toplevel, wxDialog, wxPanel or static 
2311     // controls and no window can actually accept keyboard input. 
2312 #if !defined(__WXWINCE__) 
2313     if ( ::GetWindowLong(hwndFocus
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
2315         // pessimistic by default 
2316         canSafelyCallIsDlgMsg 
= false; 
2317         for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
2319               node 
= node
->GetNext() ) 
2321             wxWindow 
* const win 
= node
->GetData(); 
2322             if ( win
->AcceptsFocus() && 
2323                     !(::GetWindowLong(GetHwndOf(win
), GWL_EXSTYLE
) & 
2324                         WS_EX_CONTROLPARENT
) ) 
2326                 // it shouldn't hang... 
2327                 canSafelyCallIsDlgMsg 
= true; 
2333 #endif // !__WXWINCE__ 
2335     if ( canSafelyCallIsDlgMsg 
) 
2337         // ::IsDialogMessage() can enter in an infinite loop when the 
2338         // currently focused window is disabled or hidden and its 
2339         // parent has WS_EX_CONTROLPARENT style, so don't call it in 
2343             if ( !::IsWindowEnabled(hwndFocus
) || 
2344                     !::IsWindowVisible(hwndFocus
) ) 
2346                 // it would enter an infinite loop if we do this! 
2347                 canSafelyCallIsDlgMsg 
= false; 
2352             if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) ) 
2354                 // it's a top level window, don't go further -- e.g. even 
2355                 // if the parent of a dialog is disabled, this doesn't 
2356                 // break navigation inside the dialog 
2360             hwndFocus 
= ::GetParent(hwndFocus
); 
2364     return canSafelyCallIsDlgMsg
; 
2367 // --------------------------------------------------------------------------- 
2368 // message params unpackers 
2369 // --------------------------------------------------------------------------- 
2371 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2372                              WORD 
*id
, WXHWND 
*hwnd
, WORD 
*cmd
) 
2374     *id 
= LOWORD(wParam
); 
2375     *hwnd 
= (WXHWND
)lParam
; 
2376     *cmd 
= HIWORD(wParam
); 
2379 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2380                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2382     *state 
= LOWORD(wParam
); 
2383     *minimized 
= HIWORD(wParam
); 
2384     *hwnd 
= (WXHWND
)lParam
; 
2387 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2388                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2390     *code 
= LOWORD(wParam
); 
2391     *pos 
= HIWORD(wParam
); 
2392     *hwnd 
= (WXHWND
)lParam
; 
2395 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2396                                  WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2398     *hwnd 
= (WXHWND
)lParam
; 
2399     *hdc 
= (WXHDC
)wParam
; 
2402 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2403                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2405     *item 
= (WXWORD
)wParam
; 
2406     *flags 
= HIWORD(wParam
); 
2407     *hmenu 
= (WXHMENU
)lParam
; 
2410 // --------------------------------------------------------------------------- 
2411 // Main wxWidgets window proc and the window proc for wxWindow 
2412 // --------------------------------------------------------------------------- 
2414 // Hook for new window just as it's being created, when the window isn't yet 
2415 // associated with the handle 
2416 static wxWindowMSW 
*gs_winBeingCreated 
= NULL
; 
2418 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the 
2419 // window being created and insures that it's always unset back later 
2420 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW 
*winBeingCreated
) 
2422     gs_winBeingCreated 
= winBeingCreated
; 
2425 wxWindowCreationHook::~wxWindowCreationHook() 
2427     gs_winBeingCreated 
= NULL
; 
2431 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) 
2433     // trace all messages - useful for the debugging 
2435     wxLogTrace(wxTraceMessages
, 
2436                wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"), 
2437                wxGetMessageName(message
), (long)hWnd
, (long)wParam
, lParam
); 
2438 #endif // __WXDEBUG__ 
2440     wxWindowMSW 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2442     // when we get the first message for the HWND we just created, we associate 
2443     // it with wxWindow stored in gs_winBeingCreated 
2444     if ( !wnd 
&& gs_winBeingCreated 
) 
2446         wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
); 
2447         wnd 
= gs_winBeingCreated
; 
2448         gs_winBeingCreated 
= NULL
; 
2449         wnd
->SetHWND((WXHWND
)hWnd
); 
2454     if ( wnd 
&& wxEventLoop::AllowProcessing(wnd
) ) 
2455         rc 
= wnd
->MSWWindowProc(message
, wParam
, lParam
); 
2457         rc 
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
); 
2462 WXLRESULT 
wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
2464     // did we process the message? 
2465     bool processed 
= false; 
2475     // for most messages we should return 0 when we do process the message 
2483                 processed 
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
); 
2486                     // return 0 to allow window creation 
2487                     rc
.result 
= mayCreate 
? 0 : -1; 
2493             // never set processed to true and *always* pass WM_DESTROY to 
2494             // DefWindowProc() as Windows may do some internal cleanup when 
2495             // processing it and failing to pass the message along may cause 
2496             // memory and resource leaks! 
2497             (void)HandleDestroy(); 
2501             processed 
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), wParam
); 
2505             processed 
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2508 #if !defined(__WXWINCE__) 
2511                 LPRECT pRect 
= (LPRECT
)lParam
; 
2513                 rc
.SetLeft(pRect
->left
); 
2514                 rc
.SetTop(pRect
->top
); 
2515                 rc
.SetRight(pRect
->right
); 
2516                 rc
.SetBottom(pRect
->bottom
); 
2517                 processed 
= HandleMoving(rc
); 
2519                     pRect
->left 
= rc
.GetLeft(); 
2520                     pRect
->top 
= rc
.GetTop(); 
2521                     pRect
->right 
= rc
.GetRight(); 
2522                     pRect
->bottom 
= rc
.GetBottom(); 
2529                 LPRECT pRect 
= (LPRECT
)lParam
; 
2531                 rc
.SetLeft(pRect
->left
); 
2532                 rc
.SetTop(pRect
->top
); 
2533                 rc
.SetRight(pRect
->right
); 
2534                 rc
.SetBottom(pRect
->bottom
); 
2535                 processed 
= HandleSizing(rc
); 
2537                     pRect
->left 
= rc
.GetLeft(); 
2538                     pRect
->top 
= rc
.GetTop(); 
2539                     pRect
->right 
= rc
.GetRight(); 
2540                     pRect
->bottom 
= rc
.GetBottom(); 
2544 #endif // !__WXWINCE__ 
2546 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
2547         case WM_ACTIVATEAPP
: 
2548             // This implicitly sends a wxEVT_ACTIVATE_APP event 
2549             wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
2555                 WXWORD state
, minimized
; 
2557                 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
); 
2559                 processed 
= HandleActivate(state
, minimized 
!= 0, (WXHWND
)hwnd
); 
2564             processed 
= HandleSetFocus((WXHWND
)(HWND
)wParam
); 
2568             processed 
= HandleKillFocus((WXHWND
)(HWND
)wParam
); 
2571         case WM_PRINTCLIENT
: 
2572             processed 
= HandlePrintClient((WXHDC
)wParam
); 
2578                 wxPaintDCEx 
dc((wxWindow 
*)this, (WXHDC
)wParam
); 
2580                 processed 
= HandlePaint(); 
2584                 processed 
= HandlePaint(); 
2589 #ifdef __WXUNIVERSAL__ 
2590             // Universal uses its own wxFrame/wxDialog, so we don't receive 
2591             // close events unless we have this. 
2593 #endif // __WXUNIVERSAL__ 
2595             // don't let the DefWindowProc() destroy our window - we'll do it 
2596             // ourselves in ~wxWindow 
2602             processed 
= HandleShow(wParam 
!= 0, (int)lParam
); 
2606             processed 
= HandleMouseMove(GET_X_LPARAM(lParam
), 
2607                                         GET_Y_LPARAM(lParam
), 
2611 #ifdef HAVE_TRACKMOUSEEVENT 
2613             // filter out excess WM_MOUSELEAVE events sent after PopupMenu() 
2615             if ( m_mouseInWindow 
) 
2617                 GenerateMouseLeave(); 
2620             // always pass processed back as false, this allows the window 
2621             // manager to process the message too.  This is needed to 
2622             // ensure windows XP themes work properly as the mouse moves 
2623             // over widgets like buttons. So don't set processed to true here. 
2625 #endif // HAVE_TRACKMOUSEEVENT 
2627 #if wxUSE_MOUSEWHEEL 
2629             processed 
= HandleMouseWheel(wParam
, lParam
); 
2633         case WM_LBUTTONDOWN
: 
2635         case WM_LBUTTONDBLCLK
: 
2636         case WM_RBUTTONDOWN
: 
2638         case WM_RBUTTONDBLCLK
: 
2639         case WM_MBUTTONDOWN
: 
2641         case WM_MBUTTONDBLCLK
: 
2643 #ifdef __WXMICROWIN__ 
2644                 // MicroWindows seems to ignore the fact that a window is 
2645                 // disabled. So catch mouse events and throw them away if 
2647                 wxWindowMSW
* win 
= this; 
2650                     if (!win
->IsEnabled()) 
2656                     win 
= win
->GetParent(); 
2657                     if ( !win 
|| win
->IsTopLevel() ) 
2664 #endif // __WXMICROWIN__ 
2665                 int x 
= GET_X_LPARAM(lParam
), 
2666                     y 
= GET_Y_LPARAM(lParam
); 
2669                 // redirect the event to a static control if necessary by 
2670                 // finding one under mouse because under CE the static controls 
2671                 // don't generate mouse events (even with SS_NOTIFY) 
2673                 if ( GetCapture() == this ) 
2675                     // but don't do it if the mouse is captured by this window 
2676                     // because then it should really get this event itself 
2681                     win 
= FindWindowForMouseEvent(this, &x
, &y
); 
2683                     // this should never happen 
2684                     wxCHECK_MSG( win
, 0, 
2685                                  _T("FindWindowForMouseEvent() returned NULL") ); 
2688                 if (IsContextMenuEnabled() && message 
== WM_LBUTTONDOWN
) 
2690                     SHRGINFO shrgi 
= {0}; 
2692                     shrgi
.cbSize 
= sizeof(SHRGINFO
); 
2693                     shrgi
.hwndClient 
= (HWND
) GetHWND(); 
2697                     shrgi
.dwFlags 
= SHRG_RETURNCMD
; 
2698                     // shrgi.dwFlags = SHRG_NOTIFYPARENT; 
2700                     if (GN_CONTEXTMENU 
== ::SHRecognizeGesture(&shrgi
)) 
2703                         pt 
= ClientToScreen(pt
); 
2705                         wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
2707                         evtCtx
.SetEventObject(this); 
2708                         if (GetEventHandler()->ProcessEvent(evtCtx
)) 
2717 #else // !__WXWINCE__ 
2718                 wxWindowMSW 
*win 
= this; 
2719 #endif // __WXWINCE__/!__WXWINCE__ 
2721                 processed 
= win
->HandleMouseEvent(message
, x
, y
, wParam
); 
2723                 // if the app didn't eat the event, handle it in the default 
2724                 // way, that is by giving this window the focus 
2727                     // for the standard classes their WndProc sets the focus to 
2728                     // them anyhow and doing it from here results in some weird 
2729                     // problems, so don't do it for them (unnecessary anyhow) 
2730                     if ( !win
->IsOfStandardClass() ) 
2732                         if ( message 
== WM_LBUTTONDOWN 
&& win
->AcceptsFocus() ) 
2744         case MM_JOY1BUTTONDOWN
: 
2745         case MM_JOY2BUTTONDOWN
: 
2746         case MM_JOY1BUTTONUP
: 
2747         case MM_JOY2BUTTONUP
: 
2748             processed 
= HandleJoystickEvent(message
, 
2749                                             GET_X_LPARAM(lParam
), 
2750                                             GET_Y_LPARAM(lParam
), 
2753 #endif // __WXMICROWIN__ 
2759                 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
); 
2761                 processed 
= HandleCommand(id
, cmd
, hwnd
); 
2766             processed 
= HandleNotify((int)wParam
, lParam
, &rc
.result
); 
2769         // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU, 
2770         // otherwise DefWindowProc() does it perfectly fine for us, but MSLU 
2771         // apparently doesn't always behave properly and needs some help 
2772 #if wxUSE_UNICODE_MSLU && defined(NF_QUERY) 
2773         case WM_NOTIFYFORMAT
: 
2774             if ( lParam 
== NF_QUERY 
) 
2777                 rc
.result 
= NFR_UNICODE
; 
2780 #endif // wxUSE_UNICODE_MSLU 
2782             // for these messages we must return true if process the message 
2785         case WM_MEASUREITEM
: 
2787                 int idCtrl 
= (UINT
)wParam
; 
2788                 if ( message 
== WM_DRAWITEM 
) 
2790                     processed 
= MSWOnDrawItem(idCtrl
, 
2791                                               (WXDRAWITEMSTRUCT 
*)lParam
); 
2795                     processed 
= MSWOnMeasureItem(idCtrl
, 
2796                                                  (WXMEASUREITEMSTRUCT 
*)lParam
); 
2803 #endif // defined(WM_DRAWITEM) 
2806             if ( !IsOfStandardClass() || HasFlag(wxWANTS_CHARS
) ) 
2808                 // we always want to get the char events 
2809                 rc
.result 
= DLGC_WANTCHARS
; 
2811                 if ( HasFlag(wxWANTS_CHARS
) ) 
2813                     // in fact, we want everything 
2814                     rc
.result 
|= DLGC_WANTARROWS 
| 
2821             //else: get the dlg code from the DefWindowProc() 
2826             // If this has been processed by an event handler, return 0 now 
2827             // (we've handled it). 
2828             m_lastKeydownProcessed 
= HandleKeyDown((WORD
) wParam
, lParam
); 
2829             if ( m_lastKeydownProcessed 
) 
2838                     // we consider these messages "not interesting" to OnChar, so 
2839                     // just don't do anything more with them 
2849                     // avoid duplicate messages to OnChar for these ASCII keys: 
2850                     // they will be translated by TranslateMessage() and received 
2882                         // but set processed to false, not true to still pass them 
2883                         // to the control's default window proc - otherwise 
2884                         // built-in keyboard handling won't work 
2889                     // special case of VK_APPS: treat it the same as right mouse 
2890                     // click because both usually pop up a context menu 
2892                         processed 
= HandleMouseEvent(WM_RBUTTONDOWN
, -1, -1, 0); 
2897                         // do generate a CHAR event 
2898                         processed 
= HandleChar((WORD
)wParam
, lParam
); 
2901             if (message 
== WM_SYSKEYDOWN
)  // Let Windows still handle the SYSKEYs 
2908             // special case of VK_APPS: treat it the same as right mouse button 
2909             if ( wParam 
== VK_APPS 
) 
2911                 processed 
= HandleMouseEvent(WM_RBUTTONUP
, -1, -1, 0); 
2916                 processed 
= HandleKeyUp((WORD
) wParam
, lParam
); 
2921         case WM_CHAR
: // Always an ASCII character 
2922             if ( m_lastKeydownProcessed 
) 
2924                 // The key was handled in the EVT_KEY_DOWN and handling 
2925                 // a key in an EVT_KEY_DOWN handler is meant, by 
2926                 // design, to prevent EVT_CHARs from happening 
2927                 m_lastKeydownProcessed 
= false; 
2932                 processed 
= HandleChar((WORD
)wParam
, lParam
, true); 
2938             processed 
= HandleHotKey((WORD
)wParam
, lParam
); 
2940 #endif // wxUSE_HOTKEY 
2947                 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
); 
2949                 processed 
= MSWOnScroll(message 
== WM_HSCROLL 
? wxHORIZONTAL
 
2955         // CTLCOLOR messages are sent by children to query the parent for their 
2957 #ifndef __WXMICROWIN__ 
2958         case WM_CTLCOLORMSGBOX
: 
2959         case WM_CTLCOLOREDIT
: 
2960         case WM_CTLCOLORLISTBOX
: 
2961         case WM_CTLCOLORBTN
: 
2962         case WM_CTLCOLORDLG
: 
2963         case WM_CTLCOLORSCROLLBAR
: 
2964         case WM_CTLCOLORSTATIC
: 
2968                 UnpackCtlColor(wParam
, lParam
, &hdc
, &hwnd
); 
2970                 processed 
= HandleCtlColor(&rc
.hBrush
, (WXHDC
)hdc
, (WXHWND
)hwnd
); 
2973 #endif // !__WXMICROWIN__ 
2975         case WM_SYSCOLORCHANGE
: 
2976             // the return value for this message is ignored 
2977             processed 
= HandleSysColorChange(); 
2980 #if !defined(__WXWINCE__) 
2981         case WM_DISPLAYCHANGE
: 
2982             processed 
= HandleDisplayChange(); 
2986         case WM_PALETTECHANGED
: 
2987             processed 
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
); 
2990         case WM_CAPTURECHANGED
: 
2991             processed 
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
); 
2994         case WM_SETTINGCHANGE
: 
2995             processed 
= HandleSettingChange(wParam
, lParam
); 
2998         case WM_QUERYNEWPALETTE
: 
2999             processed 
= HandleQueryNewPalette(); 
3003             processed 
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
3006                 // we processed the message, i.e. erased the background 
3011 #if !defined(__WXWINCE__) 
3013             processed 
= HandleDropFiles(wParam
); 
3018             processed 
= HandleInitDialog((WXHWND
)(HWND
)wParam
); 
3022                 // we never set focus from here 
3027 #if !defined(__WXWINCE__) 
3028         case WM_QUERYENDSESSION
: 
3029             processed 
= HandleQueryEndSession(lParam
, &rc
.allow
); 
3033             processed 
= HandleEndSession(wParam 
!= 0, lParam
); 
3036         case WM_GETMINMAXINFO
: 
3037             processed 
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
); 
3042             processed 
= HandleSetCursor((WXHWND
)(HWND
)wParam
, 
3043                                         LOWORD(lParam
),     // hit test 
3044                                         HIWORD(lParam
));    // mouse msg 
3048                 // returning TRUE stops the DefWindowProc() from further 
3049                 // processing this message - exactly what we need because we've 
3050                 // just set the cursor. 
3055 #if wxUSE_ACCESSIBILITY 
3058                 //WPARAM dwFlags = (WPARAM) (DWORD) wParam; 
3059                 LPARAM dwObjId 
= (LPARAM
) (DWORD
) lParam
; 
3061                 if (dwObjId 
== (LPARAM
)OBJID_CLIENT 
&& GetOrCreateAccessible()) 
3063                     return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible()); 
3069 #if defined(WM_HELP) 
3072                 // by default, WM_HELP is propagated by DefWindowProc() upwards 
3073                 // to the window parent but as we do it ourselves already 
3074                 // (wxHelpEvent is derived from wxCommandEvent), we don't want 
3075                 // to get the other events if we process this message at all 
3078                 // WM_HELP doesn't use lParam under CE 
3080                 HELPINFO
* info 
= (HELPINFO
*) lParam
; 
3081                 if ( info
->iContextType 
== HELPINFO_WINDOW 
) 
3083 #endif // !__WXWINCE__ 
3084                     wxHelpEvent helpEvent
 
3089                                     wxGetMousePosition() // what else? 
3091                                     wxPoint(info
->MousePos
.x
, info
->MousePos
.y
) 
3095                     helpEvent
.SetEventObject(this); 
3096                     GetEventHandler()->ProcessEvent(helpEvent
); 
3099                 else if ( info
->iContextType 
== HELPINFO_MENUITEM 
) 
3101                     wxHelpEvent 
helpEvent(wxEVT_HELP
, info
->iCtrlId
); 
3102                     helpEvent
.SetEventObject(this); 
3103                     GetEventHandler()->ProcessEvent(helpEvent
); 
3106                 else // unknown help event? 
3110 #endif // !__WXWINCE__ 
3115 #if !defined(__WXWINCE__) 
3116         case WM_CONTEXTMENU
: 
3118                 // we don't convert from screen to client coordinates as 
3119                 // the event may be handled by a parent window 
3120                 wxPoint 
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
3122                 wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
3124                 // we could have got an event from our child, reflect it back 
3125                 // to it if this is the case 
3126                 wxWindowMSW 
*win 
= NULL
; 
3127                 if ( (WXHWND
)wParam 
!= m_hWnd 
) 
3129                     win 
= FindItemByHWND((WXHWND
)wParam
); 
3135                 evtCtx
.SetEventObject(win
); 
3136                 processed 
= win
->GetEventHandler()->ProcessEvent(evtCtx
); 
3142             // we're only interested in our own menus, not MF_SYSMENU 
3143             if ( HIWORD(wParam
) == MF_POPUP 
) 
3145                 // handle menu chars for ownerdrawn menu items 
3146                 int i 
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
); 
3147                 if ( i 
!= wxNOT_FOUND 
) 
3149                     rc
.result 
= MAKELRESULT(i
, MNC_EXECUTE
); 
3156         case WM_POWERBROADCAST
: 
3159                 processed 
= HandlePower(wParam
, lParam
, &vetoed
); 
3160                 rc
.result 
= processed 
&& vetoed 
? BROADCAST_QUERY_DENY 
: TRUE
; 
3163 #endif // __WXWINCE__ 
3169         wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."), 
3170                    wxGetMessageName(message
)); 
3171 #endif // __WXDEBUG__ 
3172         rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
3178 // ---------------------------------------------------------------------------- 
3179 // wxWindow <-> HWND map 
3180 // ---------------------------------------------------------------------------- 
3182 wxWinHashTable 
*wxWinHandleHash 
= NULL
; 
3184 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
) 
3186     return (wxWindow
*)wxWinHandleHash
->Get((long)hWnd
); 
3189 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
) 
3191     // adding NULL hWnd is (first) surely a result of an error and 
3192     // (secondly) breaks menu command processing 
3193     wxCHECK_RET( hWnd 
!= (HWND
)NULL
, 
3194                  wxT("attempt to add a NULL hWnd to window list ignored") ); 
3196     wxWindow 
*oldWin 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
3198     if ( oldWin 
&& (oldWin 
!= win
) ) 
3200         wxLogDebug(wxT("HWND %X already associated with another window (%s)"), 
3201                    (int) hWnd
, win
->GetClassInfo()->GetClassName()); 
3204 #endif // __WXDEBUG__ 
3207         wxWinHandleHash
->Put((long)hWnd
, (wxWindow 
*)win
); 
3211 void wxRemoveHandleAssociation(wxWindowMSW 
*win
) 
3213     wxWinHandleHash
->Delete((long)win
->GetHWND()); 
3216 // ---------------------------------------------------------------------------- 
3217 // various MSW speciic class dependent functions 
3218 // ---------------------------------------------------------------------------- 
3220 // Default destroyer - override if you destroy it in some other way 
3221 // (e.g. with MDI child windows) 
3222 void wxWindowMSW::MSWDestroyWindow() 
3226 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
, 
3229                                            int& w
, int& h
) const 
3231     // yes, those are just some arbitrary hardcoded numbers 
3232     static const int DEFAULT_Y 
= 200; 
3234     bool nonDefault 
= false; 
3236     if ( pos
.x 
== wxDefaultCoord 
) 
3238         // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we 
3239         // can just as well set it to CW_USEDEFAULT as well 
3245         // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it 
3246         // neither because it is not handled as a special value by Windows then 
3247         // and so we have to choose some default value for it 
3249         y 
= pos
.y 
== wxDefaultCoord 
? DEFAULT_Y 
: pos
.y
; 
3255       NB: there used to be some code here which set the initial size of the 
3256           window to the client size of the parent if no explicit size was 
3257           specified. This was wrong because wxWidgets programs often assume 
3258           that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke 
3259           it. To see why, you should understand that Windows sends WM_SIZE from 
3260           inside ::CreateWindow() anyhow. However, ::CreateWindow() is called 
3261           from some base class ctor and so this WM_SIZE is not processed in the 
3262           real class' OnSize() (because it's not fully constructed yet and the 
3263           event goes to some base class OnSize() instead). So the WM_SIZE we 
3264           rely on is the one sent when the parent frame resizes its children 
3265           but here is the problem: if the child already has just the right 
3266           size, nothing will happen as both wxWidgets and Windows check for 
3267           this and ignore any attempts to change the window size to the size it 
3268           already has - so no WM_SIZE would be sent. 
3272     // we don't use CW_USEDEFAULT here for several reasons: 
3274     //  1. it results in huge frames on modern screens (1000*800 is not 
3275     //     uncommon on my 1280*1024 screen) which is way too big for a half 
3276     //     empty frame of most of wxWidgets samples for example) 
3278     //  2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which 
3279     //     the default is for whatever reason 8*8 which breaks client <-> 
3280     //     window size calculations (it would be nice if it didn't, but it 
3281     //     does and the simplest way to fix it seemed to change the broken 
3282     //     default size anyhow) 
3284     //  3. there is just no advantage in doing it: with x and y it is 
3285     //     possible that [future versions of] Windows position the new top 
3286     //     level window in some smart way which we can't do, but we can 
3287     //     guess a reasonably good size for a new window just as well 
3290     // However, on PocketPC devices, we must use the default 
3291     // size if possible. 
3293     if (size
.x 
== wxDefaultCoord
) 
3297     if (size
.y 
== wxDefaultCoord
) 
3302     if ( size
.x 
== wxDefaultCoord 
|| size
.y 
== wxDefaultCoord
) 
3306     w 
= WidthDefault(size
.x
); 
3307     h 
= HeightDefault(size
.y
); 
3310     AdjustForParentClientOrigin(x
, y
); 
3315 WXHWND 
wxWindowMSW::MSWGetParent() const 
3317     return m_parent 
? m_parent
->GetHWND() : WXHWND(NULL
); 
3320 bool wxWindowMSW::MSWCreate(const wxChar 
*wclass
, 
3321                             const wxChar 
*title
, 
3325                             WXDWORD extendedStyle
) 
3327     // choose the position/size for the new window 
3329     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
3331     // controlId is menu handle for the top level windows, so set it to 0 
3332     // unless we're creating a child window 
3333     int controlId 
= style 
& WS_CHILD 
? GetId() : 0; 
3335     // for each class "Foo" we have we also have "FooNR" ("no repaint") class 
3336     // which is the same but without CS_[HV]REDRAW class styles so using it 
3337     // ensures that the window is not fully repainted on each resize 
3338     wxString 
className(wclass
); 
3339     if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE
) ) 
3341         className 
+= wxT("NR"); 
3344     // do create the window 
3345     wxWindowCreationHook 
hook(this); 
3347     m_hWnd 
= (WXHWND
)::CreateWindowEx
 
3351                         title 
? title 
: (const wxChar
*)m_windowName
.c_str(), 
3354                         (HWND
)MSWGetParent(), 
3357                         NULL                        
// no extra data 
3362         wxLogSysError(_("Can't create window of class %s"), className
.c_str()); 
3367     SubclassWin(m_hWnd
); 
3372 // =========================================================================== 
3373 // MSW message handlers 
3374 // =========================================================================== 
3376 // --------------------------------------------------------------------------- 
3378 // --------------------------------------------------------------------------- 
3380 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
3382 #ifndef __WXMICROWIN__ 
3383     LPNMHDR hdr 
= (LPNMHDR
)lParam
; 
3384     HWND hWnd 
= hdr
->hwndFrom
; 
3385     wxWindow 
*win 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
3387     // if the control is one of our windows, let it handle the message itself 
3390         return win
->MSWOnNotify(idCtrl
, lParam
, result
); 
3393     // VZ: why did we do it? normally this is unnecessary and, besides, it 
3394     //     breaks the message processing for the toolbars because the tooltip 
3395     //     notifications were being forwarded to the toolbar child controls 
3396     //     (if it had any) before being passed to the toolbar itself, so in my 
3397     //     example the tooltip for the combobox was always shown instead of the 
3398     //     correct button tooltips 
3400     // try all our children 
3401     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3404         wxWindow 
*child 
= node
->GetData(); 
3405         if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) ) 
3410         node 
= node
->GetNext(); 
3414     // by default, handle it ourselves 
3415     return MSWOnNotify(idCtrl
, lParam
, result
); 
3416 #else // __WXMICROWIN__ 
3423 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
, 
3425                                       const wxString
& ttip
) 
3427     // I don't know why it happens, but the versions of comctl32.dll starting 
3428     // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally, 
3429     // this message is supposed to be sent to Unicode programs only) -- hence 
3430     // we need to handle it as well, otherwise no tooltips will be shown in 
3433     if ( !(code 
== (WXUINT
) TTN_NEEDTEXTA 
|| code 
== (WXUINT
) TTN_NEEDTEXTW
) 
3436         // not a tooltip message or no tooltip to show anyhow 
3441     LPTOOLTIPTEXT ttText 
= (LPTOOLTIPTEXT
)lParam
; 
3443     // We don't want to use the szText buffer because it has a limit of 80 
3444     // bytes and this is not enough, especially for Unicode build where it 
3445     // limits the tooltip string length to only 40 characters 
3447     // The best would be, of course, to not impose any length limitations at 
3448     // all but then the buffer would have to be dynamic and someone would have 
3449     // to free it and we don't have the tooltip owner object here any more, so 
3450     // for now use our own static buffer with a higher fixed max length. 
3452     // Note that using a static buffer should not be a problem as only a single 
3453     // tooltip can be shown at the same time anyhow. 
3455     if ( code 
== (WXUINT
) TTN_NEEDTEXTW 
) 
3457         // We need to convert tooltip from multi byte to Unicode on the fly. 
3458         static wchar_t buf
[513]; 
3460         // Truncate tooltip length if needed as otherwise we might not have 
3461         // enough space for it in the buffer and MultiByteToWideChar() would 
3463         size_t tipLength 
= wxMin(ttip
.length(), WXSIZEOF(buf
) - 1); 
3465         // Convert to WideChar without adding the NULL character. The NULL 
3466         // character is added afterwards (this is more efficient). 
3467         int len 
= ::MultiByteToWideChar
 
3479             wxLogLastError(_T("MultiByteToWideChar()")); 
3483         ttText
->lpszText 
= (LPSTR
) buf
; 
3485     else // TTN_NEEDTEXTA 
3486 #endif // !wxUSE_UNICODE 
3488         // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or 
3489         // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have 
3490         // to copy the string we have into the buffer 
3491         static wxChar buf
[513]; 
3492         wxStrncpy(buf
, ttip
.c_str(), WXSIZEOF(buf
) - 1); 
3493         buf
[WXSIZEOF(buf
) - 1] = _T('\0'); 
3494         ttText
->lpszText 
= buf
; 
3500 #endif // wxUSE_TOOLTIPS 
3502 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
), 
3504                               WXLPARAM
* WXUNUSED(result
)) 
3509         NMHDR
* hdr 
= (NMHDR 
*)lParam
; 
3510         if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip())) 
3517     wxUnusedVar(lParam
); 
3518 #endif // wxUSE_TOOLTIPS 
3523 // --------------------------------------------------------------------------- 
3524 // end session messages 
3525 // --------------------------------------------------------------------------- 
3527 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
) 
3529 #ifdef ENDSESSION_LOGOFF 
3530     wxCloseEvent 
event(wxEVT_QUERY_END_SESSION
, wxID_ANY
); 
3531     event
.SetEventObject(wxTheApp
); 
3532     event
.SetCanVeto(true); 
3533     event
.SetLoggingOff(logOff 
== (long)ENDSESSION_LOGOFF
); 
3535     bool rc 
= wxTheApp
->ProcessEvent(event
); 
3539         // we may end only if the app didn't veto session closing (double 
3541         *mayEnd 
= !event
.GetVeto(); 
3546     wxUnusedVar(logOff
); 
3547     wxUnusedVar(mayEnd
); 
3552 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
) 
3554 #ifdef ENDSESSION_LOGOFF 
3555     // do nothing if the session isn't ending 
3560     if ( (this != wxTheApp
->GetTopWindow()) ) 
3563     wxCloseEvent 
event(wxEVT_END_SESSION
, wxID_ANY
); 
3564     event
.SetEventObject(wxTheApp
); 
3565     event
.SetCanVeto(false); 
3566     event
.SetLoggingOff( (logOff 
== (long)ENDSESSION_LOGOFF
) ); 
3568     return wxTheApp
->ProcessEvent(event
); 
3570     wxUnusedVar(endSession
); 
3571     wxUnusedVar(logOff
); 
3576 // --------------------------------------------------------------------------- 
3577 // window creation/destruction 
3578 // --------------------------------------------------------------------------- 
3580 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT 
WXUNUSED_IN_WINCE(cs
), 
3583     // VZ: why is this commented out for WinCE? If it doesn't support 
3584     //     WS_EX_CONTROLPARENT at all it should be somehow handled globally, 
3585     //     not with multiple #ifdef's! 
3587     if ( ((CREATESTRUCT 
*)cs
)->dwExStyle 
& WS_EX_CONTROLPARENT 
) 
3588         EnsureParentHasControlParentStyle(GetParent()); 
3589 #endif // !__WXWINCE__ 
3596 bool wxWindowMSW::HandleDestroy() 
3600     // delete our drop target if we've got one 
3601 #if wxUSE_DRAG_AND_DROP 
3602     if ( m_dropTarget 
!= NULL 
) 
3604         m_dropTarget
->Revoke(m_hWnd
); 
3606         delete m_dropTarget
; 
3607         m_dropTarget 
= NULL
; 
3609 #endif // wxUSE_DRAG_AND_DROP 
3611     // WM_DESTROY handled 
3615 // --------------------------------------------------------------------------- 
3617 // --------------------------------------------------------------------------- 
3619 bool wxWindowMSW::HandleActivate(int state
, 
3620                               bool WXUNUSED(minimized
), 
3621                               WXHWND 
WXUNUSED(activate
)) 
3623     wxActivateEvent 
event(wxEVT_ACTIVATE
, 
3624                           (state 
== WA_ACTIVE
) || (state 
== WA_CLICKACTIVE
), 
3626     event
.SetEventObject(this); 
3628     return GetEventHandler()->ProcessEvent(event
); 
3631 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
) 
3633     // Strangly enough, some controls get set focus events when they are being 
3634     // deleted, even if they already had focus before. 
3635     if ( m_isBeingDeleted 
) 
3640     // notify the parent keeping track of focus for the kbd navigation 
3641     // purposes that we got it 
3642     wxChildFocusEvent 
eventFocus((wxWindow 
*)this); 
3643     (void)GetEventHandler()->ProcessEvent(eventFocus
); 
3649         m_caret
->OnSetFocus(); 
3651 #endif // wxUSE_CARET 
3654     // If it's a wxTextCtrl don't send the event as it will be done 
3655     // after the control gets to process it from EN_FOCUS handler 
3656     if ( wxDynamicCastThis(wxTextCtrl
) ) 
3660 #endif // wxUSE_TEXTCTRL 
3662     wxFocusEvent 
event(wxEVT_SET_FOCUS
, m_windowId
); 
3663     event
.SetEventObject(this); 
3665     // wxFindWinFromHandle() may return NULL, it is ok 
3666     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3668     return GetEventHandler()->ProcessEvent(event
); 
3671 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
) 
3677         m_caret
->OnKillFocus(); 
3679 #endif // wxUSE_CARET 
3682     // If it's a wxTextCtrl don't send the event as it will be done 
3683     // after the control gets to process it. 
3684     wxTextCtrl 
*ctrl 
= wxDynamicCastThis(wxTextCtrl
); 
3691     // Don't send the event when in the process of being deleted.  This can 
3692     // only cause problems if the event handler tries to access the object. 
3693     if ( m_isBeingDeleted 
) 
3698     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, m_windowId
); 
3699     event
.SetEventObject(this); 
3701     // wxFindWinFromHandle() may return NULL, it is ok 
3702     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3704     return GetEventHandler()->ProcessEvent(event
); 
3707 // --------------------------------------------------------------------------- 
3709 // --------------------------------------------------------------------------- 
3711 void wxWindowMSW::SetLabel( const wxString
& label
) 
3713     SetWindowText(GetHwnd(), label
.c_str()); 
3716 wxString 
wxWindowMSW::GetLabel() const 
3718     return wxGetWindowText(GetHWND()); 
3721 // --------------------------------------------------------------------------- 
3723 // --------------------------------------------------------------------------- 
3725 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
)) 
3727     wxShowEvent 
event(GetId(), show
); 
3728     event
.SetEventObject(this); 
3730     return GetEventHandler()->ProcessEvent(event
); 
3733 bool wxWindowMSW::HandleInitDialog(WXHWND 
WXUNUSED(hWndFocus
)) 
3735     wxInitDialogEvent 
event(GetId()); 
3736     event
.SetEventObject(this); 
3738     return GetEventHandler()->ProcessEvent(event
); 
3741 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
) 
3743 #if defined (__WXMICROWIN__) || defined(__WXWINCE__) 
3744     wxUnusedVar(wParam
); 
3746 #else // __WXMICROWIN__ 
3747     HDROP hFilesInfo 
= (HDROP
) wParam
; 
3749     // Get the total number of files dropped 
3750     UINT gwFilesDropped 
= ::DragQueryFile
 
3758     wxString 
*files 
= new wxString
[gwFilesDropped
]; 
3759     for ( UINT wIndex 
= 0; wIndex 
< gwFilesDropped
; wIndex
++ ) 
3761         // first get the needed buffer length (+1 for terminating NUL) 
3762         size_t len 
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1; 
3764         // and now get the file name 
3765         ::DragQueryFile(hFilesInfo
, wIndex
, 
3766                         wxStringBuffer(files
[wIndex
], len
), len
); 
3768     DragFinish (hFilesInfo
); 
3770     wxDropFilesEvent 
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
); 
3771     event
.SetEventObject(this); 
3774     DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
); 
3775     event
.m_pos
.x 
= dropPoint
.x
; 
3776     event
.m_pos
.y 
= dropPoint
.y
; 
3778     return GetEventHandler()->ProcessEvent(event
); 
3783 bool wxWindowMSW::HandleSetCursor(WXHWND 
WXUNUSED(hWnd
), 
3785                                   int WXUNUSED(mouseMsg
)) 
3787 #ifndef __WXMICROWIN__ 
3788     // the logic is as follows: 
3789     // -1. don't set cursor for non client area, including but not limited to 
3790     //     the title bar, scrollbars, &c 
3791     //  0. allow the user to override default behaviour by using EVT_SET_CURSOR 
3792     //  1. if we have the cursor set it unless wxIsBusy() 
3793     //  2. if we're a top level window, set some cursor anyhow 
3794     //  3. if wxIsBusy(), set the busy cursor, otherwise the global one 
3796     if ( nHitTest 
!= HTCLIENT 
) 
3801     HCURSOR hcursor 
= 0; 
3803     // first ask the user code - it may wish to set the cursor in some very 
3804     // specific way (for example, depending on the current position) 
3807     if ( !::GetCursorPosWinCE(&pt
)) 
3809     if ( !::GetCursorPos(&pt
) ) 
3812         wxLogLastError(wxT("GetCursorPos")); 
3817     ScreenToClient(&x
, &y
); 
3818     wxSetCursorEvent 
event(x
, y
); 
3820     bool processedEvtSetCursor 
= GetEventHandler()->ProcessEvent(event
); 
3821     if ( processedEvtSetCursor 
&& event
.HasCursor() ) 
3823         hcursor 
= GetHcursorOf(event
.GetCursor()); 
3828         bool isBusy 
= wxIsBusy(); 
3830         // the test for processedEvtSetCursor is here to prevent using m_cursor 
3831         // if the user code caught EVT_SET_CURSOR() and returned nothing from 
3832         // it - this is a way to say that our cursor shouldn't be used for this 
3834         if ( !processedEvtSetCursor 
&& m_cursor
.Ok() ) 
3836             hcursor 
= GetHcursorOf(m_cursor
); 
3843                 hcursor 
= wxGetCurrentBusyCursor(); 
3845             else if ( !hcursor 
) 
3847                 const wxCursor 
*cursor 
= wxGetGlobalCursor(); 
3848                 if ( cursor 
&& cursor
->Ok() ) 
3850                     hcursor 
= GetHcursorOf(*cursor
); 
3858 //        wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor); 
3860         ::SetCursor(hcursor
); 
3862         // cursor set, stop here 
3865 #endif // __WXMICROWIN__ 
3867     // pass up the window chain 
3871 bool wxWindowMSW::HandlePower(WXWPARAM 
WXUNUSED_IN_WINCE(wParam
), 
3872                               WXLPARAM 
WXUNUSED(lParam
), 
3873                               bool *WXUNUSED_IN_WINCE(vetoed
)) 
3879     wxEventType evtType
; 
3882         case PBT_APMQUERYSUSPEND
: 
3883             evtType 
= wxEVT_POWER_SUSPENDING
; 
3886         case PBT_APMQUERYSUSPENDFAILED
: 
3887             evtType 
= wxEVT_POWER_SUSPEND_CANCEL
; 
3890         case PBT_APMSUSPEND
: 
3891             evtType 
= wxEVT_POWER_SUSPENDED
; 
3894         case PBT_APMRESUMESUSPEND
: 
3895 #ifdef PBT_APMRESUMEAUTOMATIC 
3896         case PBT_APMRESUMEAUTOMATIC
: 
3898             evtType 
= wxEVT_POWER_RESUME
; 
3902             wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam
); 
3905         // these messages are currently not mapped to wx events 
3906         case PBT_APMQUERYSTANDBY
: 
3907         case PBT_APMQUERYSTANDBYFAILED
: 
3908         case PBT_APMSTANDBY
: 
3909         case PBT_APMRESUMESTANDBY
: 
3910         case PBT_APMBATTERYLOW
: 
3911         case PBT_APMPOWERSTATUSCHANGE
: 
3912         case PBT_APMOEMEVENT
: 
3913         case PBT_APMRESUMECRITICAL
: 
3914             evtType 
= wxEVT_NULL
; 
3918     // don't handle unknown messages 
3919     if ( evtType 
== wxEVT_NULL 
) 
3922     // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events? 
3924     wxPowerEvent 
event(evtType
); 
3925     if ( !GetEventHandler()->ProcessEvent(event
) ) 
3928     *vetoed 
= event
.IsVetoed(); 
3934 bool wxWindowMSW::IsDoubleBuffered() const 
3936     for ( const wxWindowMSW 
*wnd 
= this; 
3937           wnd 
&& !wnd
->IsTopLevel(); wnd 
= 
3940         if ( ::GetWindowLong(GetHwndOf(wnd
), GWL_EXSTYLE
) & WS_EX_COMPOSITED 
) 
3947 // --------------------------------------------------------------------------- 
3948 // owner drawn stuff 
3949 // --------------------------------------------------------------------------- 
3951 #if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \ 
3952         (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)) 
3953     #define WXUNUSED_UNLESS_ODRAWN(param) param 
3955     #define WXUNUSED_UNLESS_ODRAWN(param) 
3959 wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id
), 
3960                            WXDRAWITEMSTRUCT 
* WXUNUSED_UNLESS_ODRAWN(itemStruct
)) 
3962 #if wxUSE_OWNER_DRAWN 
3964 #if wxUSE_MENUS_NATIVE 
3965     // is it a menu item? 
3966     DRAWITEMSTRUCT 
*pDrawStruct 
= (DRAWITEMSTRUCT 
*)itemStruct
; 
3967     if ( id 
== 0 && pDrawStruct
->CtlType 
== ODT_MENU 
) 
3969         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pDrawStruct
->itemData
); 
3971         // see comment before the same test in MSWOnMeasureItem() below 
3975         wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
), 
3976                          false, _T("MSWOnDrawItem: bad wxMenuItem pointer") ); 
3978         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent 
3979         // the DC from being released 
3980         wxDCTemp 
dc((WXHDC
)pDrawStruct
->hDC
); 
3981         wxRect 
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
, 
3982                     pDrawStruct
->rcItem
.right 
- pDrawStruct
->rcItem
.left
, 
3983                     pDrawStruct
->rcItem
.bottom 
- pDrawStruct
->rcItem
.top
); 
3985         return pMenuItem
->OnDrawItem
 
3989                 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
, 
3990                 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
 
3993 #endif // wxUSE_MENUS_NATIVE 
3995 #endif // USE_OWNER_DRAWN 
3997 #if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) 
3999 #if wxUSE_OWNER_DRAWN 
4000     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
4001 #else // !wxUSE_OWNER_DRAWN 
4002     // we may still have owner-drawn buttons internally because we have to make 
4003     // them owner-drawn to support colour change 
4006                          wxDynamicCast(FindItem(id
), wxButton
) 
4011 #endif // USE_OWNER_DRAWN 
4015         return item
->MSWOnDraw(itemStruct
); 
4018 #endif // wxUSE_CONTROLS 
4024 wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT 
*itemStruct
) 
4026 #if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE 
4027     // is it a menu item? 
4028     MEASUREITEMSTRUCT 
*pMeasureStruct 
= (MEASUREITEMSTRUCT 
*)itemStruct
; 
4029     if ( id 
== 0 && pMeasureStruct
->CtlType 
== ODT_MENU 
) 
4031         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pMeasureStruct
->itemData
); 
4033         // according to Carsten Fuchs the pointer may be NULL under XP if an 
4034         // MDI child frame is initially maximized, see this for more info: 
4035         // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745 
4037         // so silently ignore it instead of asserting 
4041         wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
), 
4042                         false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") ); 
4045         bool rc 
= pMenuItem
->OnMeasureItem(&w
, &h
); 
4047         pMeasureStruct
->itemWidth 
= w
; 
4048         pMeasureStruct
->itemHeight 
= h
; 
4053     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
4056         return item
->MSWOnMeasure(itemStruct
); 
4060     wxUnusedVar(itemStruct
); 
4061 #endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE 
4066 // --------------------------------------------------------------------------- 
4067 // colours and palettes 
4068 // --------------------------------------------------------------------------- 
4070 bool wxWindowMSW::HandleSysColorChange() 
4072     wxSysColourChangedEvent event
; 
4073     event
.SetEventObject(this); 
4075     (void)GetEventHandler()->ProcessEvent(event
); 
4077     // always let the system carry on the default processing to allow the 
4078     // native controls to react to the colours update 
4082 bool wxWindowMSW::HandleDisplayChange() 
4084     wxDisplayChangedEvent event
; 
4085     event
.SetEventObject(this); 
4087     return GetEventHandler()->ProcessEvent(event
); 
4090 #ifndef __WXMICROWIN__ 
4092 bool wxWindowMSW::HandleCtlColor(WXHBRUSH 
*brush
, WXHDC hDC
, WXHWND hWnd
) 
4094 #if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__) 
4098     wxControl 
*item 
= wxDynamicCast(FindItemByHWND(hWnd
, true), wxControl
); 
4101         *brush 
= item
->MSWControlColor(hDC
, hWnd
); 
4103 #endif // wxUSE_CONTROLS 
4106     return *brush 
!= NULL
; 
4109 #endif // __WXMICROWIN__ 
4111 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
) 
4114     // same as below except we don't respond to our own messages 
4115     if ( hWndPalChange 
!= GetHWND() ) 
4117         // check to see if we our our parents have a custom palette 
4118         wxWindowMSW 
*win 
= this; 
4119         while ( win 
&& !win
->HasCustomPalette() ) 
4121             win 
= win
->GetParent(); 
4124         if ( win 
&& win
->HasCustomPalette() ) 
4126             // realize the palette to see whether redrawing is needed 
4127             HDC hdc 
= ::GetDC((HWND
) hWndPalChange
); 
4128             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
4129                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
4131             int result 
= ::RealizePalette(hdc
); 
4133             // restore the palette (before releasing the DC) 
4134             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
4135                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
4136             ::RealizePalette(hdc
); 
4137             ::ReleaseDC((HWND
) hWndPalChange
, hdc
); 
4139             // now check for the need to redraw 
4141                 ::InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
); 
4145 #endif // wxUSE_PALETTE 
4147     wxPaletteChangedEvent 
event(GetId()); 
4148     event
.SetEventObject(this); 
4149     event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
)); 
4151     return GetEventHandler()->ProcessEvent(event
); 
4154 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
) 
4156     // notify windows on the capture stack about lost capture 
4157     // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863): 
4158     wxWindowBase::NotifyCaptureLost(); 
4160     wxWindow 
*win 
= wxFindWinFromHandle(hWndGainedCapture
); 
4161     wxMouseCaptureChangedEvent 
event(GetId(), win
); 
4162     event
.SetEventObject(this); 
4163     return GetEventHandler()->ProcessEvent(event
); 
4166 bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam
, WXLPARAM lParam
) 
4168     // despite MSDN saying "(This message cannot be sent directly to a window.)" 
4169     // we need to send this to child windows (it is only sent to top-level 
4170     // windows) so {list,tree}ctrls can adjust their font size if necessary 
4171     // this is exactly how explorer does it to enable the font size changes 
4173     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4176         // top-level windows already get this message from the system 
4177         wxWindow 
*win 
= node
->GetData(); 
4178         if ( !win
->IsTopLevel() ) 
4180             ::SendMessage(GetHwndOf(win
), WM_SETTINGCHANGE
, wParam
, lParam
); 
4183         node 
= node
->GetNext(); 
4186     // let the system handle it 
4190 bool wxWindowMSW::HandleQueryNewPalette() 
4194     // check to see if we our our parents have a custom palette 
4195     wxWindowMSW 
*win 
= this; 
4196     while (!win
->HasCustomPalette() && win
->GetParent()) win 
= win
->GetParent(); 
4197     if (win
->HasCustomPalette()) { 
4198         /* realize the palette to see whether redrawing is needed */ 
4199         HDC hdc 
= ::GetDC((HWND
) GetHWND()); 
4200         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
4201              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) ); 
4203         int result 
= ::RealizePalette(hdc
); 
4204         /* restore the palette (before releasing the DC) */ 
4205         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
4206              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) ); 
4207         ::RealizePalette(hdc
); 
4208         ::ReleaseDC((HWND
) GetHWND(), hdc
); 
4209         /* now check for the need to redraw */ 
4211             ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
); 
4213 #endif // wxUSE_PALETTE 
4215     wxQueryNewPaletteEvent 
event(GetId()); 
4216     event
.SetEventObject(this); 
4218     return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized(); 
4221 // Responds to colour changes: passes event on to children. 
4222 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
4224     // the top level window also reset the standard colour map as it might have 
4225     // changed (there is no need to do it for the non top level windows as we 
4226     // only have to do it once) 
4230         gs_hasStdCmap 
= false; 
4232     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4235         // Only propagate to non-top-level windows because Windows already 
4236         // sends this event to all top-level ones 
4237         wxWindow 
*win 
= node
->GetData(); 
4238         if ( !win
->IsTopLevel() ) 
4240             // we need to send the real WM_SYSCOLORCHANGE and not just trigger 
4241             // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for 
4242             // the standard controls 
4243             ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0); 
4246         node 
= node
->GetNext(); 
4250 extern wxCOLORMAP 
*wxGetStdColourMap() 
4252     static COLORREF s_stdColours
[wxSTD_COL_MAX
]; 
4253     static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
]; 
4255     if ( !gs_hasStdCmap 
) 
4257         static bool s_coloursInit 
= false; 
4259         if ( !s_coloursInit 
) 
4261             // When a bitmap is loaded, the RGB values can change (apparently 
4262             // because Windows adjusts them to care for the old programs always 
4263             // using 0xc0c0c0 while the transparent colour for the new Windows 
4264             // versions is different). But we do this adjustment ourselves so 
4265             // we want to avoid Windows' "help" and for this we need to have a 
4266             // reference bitmap which can tell us what the RGB values change 
4268             wxLogNull logNo
; // suppress error if we couldn't load the bitmap 
4269             wxBitmap 
stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); 
4270             if ( stdColourBitmap
.Ok() ) 
4272                 // the pixels in the bitmap must correspond to wxSTD_COL_XXX! 
4273                 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
, 
4274                               _T("forgot to update wxBITMAP_STD_COLOURS!") ); 
4277                 memDC
.SelectObject(stdColourBitmap
); 
4280                 for ( size_t i 
= 0; i 
< WXSIZEOF(s_stdColours
); i
++ ) 
4282                     memDC
.GetPixel(i
, 0, &colour
); 
4283                     s_stdColours
[i
] = wxColourToRGB(colour
); 
4286             else // wxBITMAP_STD_COLOURS couldn't be loaded 
4288                 s_stdColours
[0] = RGB(000,000,000);     // black 
4289                 s_stdColours
[1] = RGB(128,128,128);     // dark grey 
4290                 s_stdColours
[2] = RGB(192,192,192);     // light grey 
4291                 s_stdColours
[3] = RGB(255,255,255);     // white 
4292                 //s_stdColours[4] = RGB(000,000,255);     // blue 
4293                 //s_stdColours[5] = RGB(255,000,255);     // magenta 
4296             s_coloursInit 
= true; 
4299         gs_hasStdCmap 
= true; 
4301         // create the colour map 
4302 #define INIT_CMAP_ENTRY(col) \ 
4303             s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \ 
4304             s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col) 
4306         INIT_CMAP_ENTRY(BTNTEXT
); 
4307         INIT_CMAP_ENTRY(BTNSHADOW
); 
4308         INIT_CMAP_ENTRY(BTNFACE
); 
4309         INIT_CMAP_ENTRY(BTNHIGHLIGHT
); 
4311 #undef INIT_CMAP_ENTRY 
4317 // --------------------------------------------------------------------------- 
4319 // --------------------------------------------------------------------------- 
4321 bool wxWindowMSW::HandlePaint() 
4323     HRGN hRegion 
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle 
4325         wxLogLastError(wxT("CreateRectRgn")); 
4326     if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR 
) 
4327         wxLogLastError(wxT("GetUpdateRgn")); 
4329     m_updateRegion 
= wxRegion((WXHRGN
) hRegion
); 
4331     wxPaintEvent 
event(m_windowId
); 
4332     event
.SetEventObject(this); 
4334     bool processed 
= GetEventHandler()->ProcessEvent(event
); 
4336     // note that we must generate NC event after the normal one as otherwise 
4337     // BeginPaint() will happily overwrite our decorations with the background 
4339     wxNcPaintEvent 
eventNc(m_windowId
); 
4340     eventNc
.SetEventObject(this); 
4341     GetEventHandler()->ProcessEvent(eventNc
); 
4346 // Can be called from an application's OnPaint handler 
4347 void wxWindowMSW::OnPaint(wxPaintEvent
& event
) 
4349 #ifdef __WXUNIVERSAL__ 
4352     HDC hDC 
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject()); 
4355         MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0); 
4360 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
) 
4362     wxDCTemp 
dc(hdc
, GetClientSize()); 
4365     dc
.SetWindow((wxWindow 
*)this); 
4367     wxEraseEvent 
event(m_windowId
, &dc
); 
4368     event
.SetEventObject(this); 
4369     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4371     // must be called manually as ~wxDC doesn't do anything for wxDCTemp 
4372     dc
.SelectOldObjects(hdc
); 
4377 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
) 
4379     // standard non top level controls (i.e. except the dialogs) always erase 
4380     // their background themselves in HandleCtlColor() or have some control- 
4381     // specific ways to set the colours (common controls) 
4382     if ( IsOfStandardClass() && !IsTopLevel() ) 
4388     if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM 
) 
4390         // don't skip the event here, custom background means that the app 
4391         // is drawing it itself in its OnPaint(), so don't draw it at all 
4392         // now to avoid flicker 
4397     // do default background painting 
4398     if ( !DoEraseBackground(GetHdcOf(*event
.GetDC())) ) 
4400         // let the system paint the background 
4405 bool wxWindowMSW::DoEraseBackground(WXHDC hDC
) 
4407     HBRUSH hbr 
= (HBRUSH
)MSWGetBgBrush(hDC
); 
4411     wxFillRect(GetHwnd(), (HDC
)hDC
, hbr
); 
4417 wxWindowMSW::MSWGetBgBrushForChild(WXHDC 
WXUNUSED(hDC
), WXHWND hWnd
) 
4421         // our background colour applies to: 
4422         //  1. this window itself, always 
4423         //  2. all children unless the colour is "not inheritable" 
4424         //  3. even if it is not inheritable, our immediate transparent 
4425         //     children should still inherit it -- but not any transparent 
4426         //     children because it would look wrong if a child of non 
4427         //     transparent child would show our bg colour when the child itself 
4429         wxWindow 
*win 
= wxFindWinFromHandle(hWnd
); 
4432                     (win 
&& win
->HasTransparentBackground() && 
4433                         win
->GetParent() == this) ) 
4435             // draw children with the same colour as the parent 
4437                 brush 
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour()); 
4439             return (WXHBRUSH
)GetHbrushOf(*brush
); 
4446 WXHBRUSH 
wxWindowMSW::MSWGetBgBrush(WXHDC hDC
, WXHWND hWndToPaint
) 
4449         hWndToPaint 
= GetHWND(); 
4451     for ( wxWindowMSW 
*win 
= this; win
; win 
= win
->GetParent() ) 
4453         WXHBRUSH hBrush 
= win
->MSWGetBgBrushForChild(hDC
, hWndToPaint
); 
4457         // background is not inherited beyond top level windows 
4458         if ( win
->IsTopLevel() ) 
4465 bool wxWindowMSW::HandlePrintClient(WXHDC hDC
) 
4467     // we receive this message when DrawThemeParentBackground() is 
4468     // called from def window proc of several controls under XP and we 
4469     // must draw properly themed background here 
4471     // note that naively I'd expect filling the client rect with the 
4472     // brush returned by MSWGetBgBrush() work -- but for some reason it 
4473     // doesn't and we have to call parents MSWPrintChild() which is 
4474     // supposed to call DrawThemeBackground() with appropriate params 
4476     // also note that in this case lParam == PRF_CLIENT but we're 
4477     // clearly expected to paint the background and nothing else! 
4479     if ( IsTopLevel() || InheritsBackgroundColour() ) 
4482     // sometimes we don't want the parent to handle it at all, instead 
4483     // return whatever value this window wants 
4484     if ( !MSWShouldPropagatePrintChild() ) 
4485         return MSWPrintChild(hDC
, (wxWindow 
*)this); 
4487     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
4489         if ( win
->MSWPrintChild(hDC
, (wxWindow 
*)this) ) 
4492         if ( win
->IsTopLevel() || win
->InheritsBackgroundColour() ) 
4499 // --------------------------------------------------------------------------- 
4500 // moving and resizing 
4501 // --------------------------------------------------------------------------- 
4503 bool wxWindowMSW::HandleMinimize() 
4505     wxIconizeEvent 
event(m_windowId
); 
4506     event
.SetEventObject(this); 
4508     return GetEventHandler()->ProcessEvent(event
); 
4511 bool wxWindowMSW::HandleMaximize() 
4513     wxMaximizeEvent 
event(m_windowId
); 
4514     event
.SetEventObject(this); 
4516     return GetEventHandler()->ProcessEvent(event
); 
4519 bool wxWindowMSW::HandleMove(int x
, int y
) 
4522     wxMoveEvent 
event(point
, m_windowId
); 
4523     event
.SetEventObject(this); 
4525     return GetEventHandler()->ProcessEvent(event
); 
4528 bool wxWindowMSW::HandleMoving(wxRect
& rect
) 
4530     wxMoveEvent 
event(rect
, m_windowId
); 
4531     event
.SetEventObject(this); 
4533     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4535         rect 
= event
.GetRect(); 
4539 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), WXUINT wParam
) 
4541 #if USE_DEFERRED_SIZING 
4542     // when we resize this window, its children are probably going to be 
4543     // repositioned as well, prepare to use DeferWindowPos() for them 
4544     int numChildren 
= 0; 
4545     for ( HWND child 
= ::GetWindow(GetHwndOf(this), GW_CHILD
); 
4547           child 
= ::GetWindow(child
, GW_HWNDNEXT
) ) 
4552     // Protect against valid m_hDWP being overwritten 
4553     bool useDefer 
= false; 
4555     if ( numChildren 
> 1 ) 
4559             m_hDWP 
= (WXHANDLE
)::BeginDeferWindowPos(numChildren
); 
4562                 wxLogLastError(_T("BeginDeferWindowPos")); 
4568 #endif // USE_DEFERRED_SIZING 
4570     // update this window size 
4571     bool processed 
= false; 
4575             wxFAIL_MSG( _T("unexpected WM_SIZE parameter") ); 
4576             // fall through nevertheless 
4580             // we're not interested in these messages at all 
4583         case SIZE_MINIMIZED
: 
4584             processed 
= HandleMinimize(); 
4587         case SIZE_MAXIMIZED
: 
4588             /* processed = */ HandleMaximize(); 
4589             // fall through to send a normal size event as well 
4592             // don't use w and h parameters as they specify the client size 
4593             // while according to the docs EVT_SIZE handler is supposed to 
4594             // receive the total size 
4595             wxSizeEvent 
event(GetSize(), m_windowId
); 
4596             event
.SetEventObject(this); 
4598             processed 
= GetEventHandler()->ProcessEvent(event
); 
4601 #if USE_DEFERRED_SIZING 
4602     // and finally change the positions of all child windows at once 
4603     if ( useDefer 
&& m_hDWP 
) 
4605         // reset m_hDWP to NULL so that child windows don't try to use our 
4606         // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't 
4607         // happen anyhow normally but who knows what weird flow of control we 
4608         // may have depending on what the users EVT_SIZE handler does...) 
4609         HDWP hDWP 
= (HDWP
)m_hDWP
; 
4612         // do put all child controls in place at once 
4613         if ( !::EndDeferWindowPos(hDWP
) ) 
4615             wxLogLastError(_T("EndDeferWindowPos")); 
4618         // Reset our children's pending pos/size values. 
4619         for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
4621               node 
= node
->GetNext() ) 
4623             wxWindowMSW 
*child 
= node
->GetData(); 
4624             child
->m_pendingPosition 
= wxDefaultPosition
; 
4625             child
->m_pendingSize 
= wxDefaultSize
; 
4628 #endif // USE_DEFERRED_SIZING 
4633 bool wxWindowMSW::HandleSizing(wxRect
& rect
) 
4635     wxSizeEvent 
event(rect
, m_windowId
); 
4636     event
.SetEventObject(this); 
4638     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4640         rect 
= event
.GetRect(); 
4644 bool wxWindowMSW::HandleGetMinMaxInfo(void *WXUNUSED_IN_WINCE(mmInfo
)) 
4649     MINMAXINFO 
*info 
= (MINMAXINFO 
*)mmInfo
; 
4653     int minWidth 
= GetMinWidth(), 
4654         minHeight 
= GetMinHeight(), 
4655         maxWidth 
= GetMaxWidth(), 
4656         maxHeight 
= GetMaxHeight(); 
4658     if ( minWidth 
!= wxDefaultCoord 
) 
4660         info
->ptMinTrackSize
.x 
= minWidth
; 
4664     if ( minHeight 
!= wxDefaultCoord 
) 
4666         info
->ptMinTrackSize
.y 
= minHeight
; 
4670     if ( maxWidth 
!= wxDefaultCoord 
) 
4672         info
->ptMaxTrackSize
.x 
= maxWidth
; 
4676     if ( maxHeight 
!= wxDefaultCoord 
) 
4678         info
->ptMaxTrackSize
.y 
= maxHeight
; 
4686 // --------------------------------------------------------------------------- 
4688 // --------------------------------------------------------------------------- 
4690 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
) 
4692 #if wxUSE_MENUS_NATIVE 
4693     if ( !cmd 
&& wxCurrentPopupMenu 
) 
4695         wxMenu 
*popupMenu 
= wxCurrentPopupMenu
; 
4696         wxCurrentPopupMenu 
= NULL
; 
4698         return popupMenu
->MSWCommand(cmd
, id
); 
4700 #endif // wxUSE_MENUS_NATIVE 
4702     wxWindow 
*win 
= NULL
; 
4704     // first try to find it from HWND - this works even with the broken 
4705     // programs using the same ids for different controls 
4708         win 
= wxFindWinFromHandle(control
); 
4714         // must cast to a signed type before comparing with other ids! 
4715         win 
= FindItem((signed short)id
); 
4720         return win
->MSWCommand(cmd
, id
); 
4723     // the messages sent from the in-place edit control used by the treectrl 
4724     // for label editing have id == 0, but they should _not_ be treated as menu 
4725     // messages (they are EN_XXX ones, in fact) so don't translate anything 
4726     // coming from a control to wxEVT_COMMAND_MENU_SELECTED 
4729         // If no child window, it may be an accelerator, e.g. for a popup menu 
4732         wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
); 
4733         event
.SetEventObject(this); 
4737         return GetEventHandler()->ProcessEvent(event
); 
4741 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
4742         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND 
4743         // notifications to its parent which we want to reflect back to 
4745         wxSpinCtrl 
*spin 
= wxSpinCtrl::GetSpinForTextCtrl(control
); 
4746         if ( spin 
&& spin
->ProcessTextCommand(cmd
, id
) ) 
4748 #endif // wxUSE_SPINCTRL 
4750 #if wxUSE_CHOICE && defined(__SMARTPHONE__) 
4751         // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND 
4752         // notifications to its parent which we want to reflect back to 
4754         wxChoice 
*choice 
= wxChoice::GetChoiceForListBox(control
); 
4755         if ( choice 
&& choice
->MSWCommand(cmd
, id
) ) 
4763 // --------------------------------------------------------------------------- 
4765 // --------------------------------------------------------------------------- 
4767 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
, 
4771     // our client coords are not quite the same as Windows ones 
4772     wxPoint pt 
= GetClientAreaOrigin(); 
4773     event
.m_x 
= x 
- pt
.x
; 
4774     event
.m_y 
= y 
- pt
.y
; 
4776     event
.m_shiftDown 
= (flags 
& MK_SHIFT
) != 0; 
4777     event
.m_controlDown 
= (flags 
& MK_CONTROL
) != 0; 
4778     event
.m_leftDown 
= (flags 
& MK_LBUTTON
) != 0; 
4779     event
.m_middleDown 
= (flags 
& MK_MBUTTON
) != 0; 
4780     event
.m_rightDown 
= (flags 
& MK_RBUTTON
) != 0; 
4781     event
.m_altDown 
= ::GetKeyState(VK_MENU
) < 0; 
4784     event
.SetTimestamp(::GetMessageTime()); 
4787     event
.SetEventObject(this); 
4788     event
.SetId(GetId()); 
4790 #if wxUSE_MOUSEEVENT_HACK 
4791     gs_lastMouseEvent
.pos 
= ClientToScreen(wxPoint(x
, y
)); 
4792     gs_lastMouseEvent
.type 
= event
.GetEventType(); 
4793 #endif // wxUSE_MOUSEEVENT_HACK 
4797 // Windows doesn't send the mouse events to the static controls (which are 
4798 // transparent in the sense that their WM_NCHITTEST handler returns 
4799 // HTTRANSPARENT) at all but we want all controls to receive the mouse events 
4800 // and so we manually check if we don't have a child window under mouse and if 
4801 // we do, send the event to it instead of the window Windows had sent WM_XXX 
4804 // Notice that this is not done for the mouse move events because this could 
4805 // (would?) be too slow, but only for clicks which means that the static texts 
4806 // still don't get move, enter nor leave events. 
4807 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
) 
4809     wxCHECK_MSG( x 
&& y
, win
, _T("NULL pointer in FindWindowForMouseEvent") ); 
4811     // first try to find a non transparent child: this allows us to send events 
4812     // to a static text which is inside a static box, for example 
4813     POINT pt 
= { *x
, *y 
}; 
4814     HWND hwnd 
= GetHwndOf(win
), 
4818     hwndUnderMouse 
= ::ChildWindowFromPoint
 
4824     hwndUnderMouse 
= ::ChildWindowFromPointEx
 
4834     if ( !hwndUnderMouse 
|| hwndUnderMouse 
== hwnd 
) 
4836         // now try any child window at all 
4837         hwndUnderMouse 
= ::ChildWindowFromPoint(hwnd
, pt
); 
4840     // check that we have a child window which is susceptible to receive mouse 
4841     // events: for this it must be shown and enabled 
4842     if ( hwndUnderMouse 
&& 
4843             hwndUnderMouse 
!= hwnd 
&& 
4844                 ::IsWindowVisible(hwndUnderMouse
) && 
4845                     ::IsWindowEnabled(hwndUnderMouse
) ) 
4847         wxWindow 
*winUnderMouse 
= wxFindWinFromHandle((WXHWND
)hwndUnderMouse
); 
4848         if ( winUnderMouse 
) 
4850             // translate the mouse coords to the other window coords 
4851             win
->ClientToScreen(x
, y
); 
4852             winUnderMouse
->ScreenToClient(x
, y
); 
4854             win 
= winUnderMouse
; 
4860 #endif // __WXWINCE__ 
4862 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4864     // the mouse events take consecutive IDs from WM_MOUSEFIRST to 
4865     // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST 
4866     // from the message id and take the value in the table to get wxWin event 
4868     static const wxEventType eventsMouse
[] = 
4882     wxMouseEvent 
event(eventsMouse
[msg 
- WM_MOUSEMOVE
]); 
4883     InitMouseEvent(event
, x
, y
, flags
); 
4885     return GetEventHandler()->ProcessEvent(event
); 
4888 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
) 
4890     if ( !m_mouseInWindow 
) 
4892         // it would be wrong to assume that just because we get a mouse move 
4893         // event that the mouse is inside the window: although this is usually 
4894         // true, it is not if we had captured the mouse, so we need to check 
4895         // the mouse coordinates here 
4896         if ( !HasCapture() || IsMouseInWindow() ) 
4898             // Generate an ENTER event 
4899             m_mouseInWindow 
= true; 
4901 #ifdef HAVE_TRACKMOUSEEVENT 
4902             typedef BOOL (WINAPI 
*_TrackMouseEvent_t
)(LPTRACKMOUSEEVENT
); 
4904             static const _TrackMouseEvent_t
 
4905                 s_pfn_TrackMouseEvent 
= _TrackMouseEvent
; 
4906 #else // !__WXWINCE__ 
4907             static _TrackMouseEvent_t s_pfn_TrackMouseEvent
; 
4908             static bool s_initDone 
= false; 
4913                 wxDynamicLibrary 
dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM
); 
4914                 if ( dllComCtl32
.IsLoaded() ) 
4916                     s_pfn_TrackMouseEvent 
= (_TrackMouseEvent_t
) 
4917                         dllComCtl32
.GetSymbol(_T("_TrackMouseEvent")); 
4922                 // notice that it's ok to unload comctl32.dll here as it won't 
4923                 // be really unloaded, being still in use because we link to it 
4927             if ( s_pfn_TrackMouseEvent 
) 
4928 #endif // __WXWINCE__/!__WXWINCE__ 
4930                 WinStruct
<TRACKMOUSEEVENT
> trackinfo
; 
4932                 trackinfo
.dwFlags 
= TME_LEAVE
; 
4933                 trackinfo
.hwndTrack 
= GetHwnd(); 
4935                 (*s_pfn_TrackMouseEvent
)(&trackinfo
); 
4937 #endif // HAVE_TRACKMOUSEEVENT 
4939             wxMouseEvent 
event(wxEVT_ENTER_WINDOW
); 
4940             InitMouseEvent(event
, x
, y
, flags
); 
4942             (void)GetEventHandler()->ProcessEvent(event
); 
4945 #ifdef HAVE_TRACKMOUSEEVENT 
4946     else // mouse not in window 
4948         // Check if we need to send a LEAVE event 
4949         // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so 
4950         // send it here if we are using native mouse leave tracking 
4951         if ( HasCapture() && !IsMouseInWindow() ) 
4953             GenerateMouseLeave(); 
4956 #endif // HAVE_TRACKMOUSEEVENT 
4958 #if wxUSE_MOUSEEVENT_HACK 
4959     // Windows often generates mouse events even if mouse position hasn't 
4960     // changed (http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/66576) 
4962     // Filter this out as it can result in unexpected behaviour compared to 
4964     if ( gs_lastMouseEvent
.type 
== wxEVT_RIGHT_DOWN 
|| 
4965          gs_lastMouseEvent
.type 
== wxEVT_LEFT_DOWN 
|| 
4966          gs_lastMouseEvent
.type 
== wxEVT_MIDDLE_DOWN 
|| 
4967          gs_lastMouseEvent
.type 
== wxEVT_MOTION 
) 
4969         if ( ClientToScreen(wxPoint(x
, y
)) == gs_lastMouseEvent
.pos 
) 
4971             gs_lastMouseEvent
.type 
= wxEVT_MOTION
; 
4976 #endif // wxUSE_MOUSEEVENT_HACK 
4978     return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
); 
4982 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
) 
4984 #if wxUSE_MOUSEWHEEL 
4985     // notice that WM_MOUSEWHEEL position is in screen coords (as it's 
4986     // forwarded up to the parent by DefWindowProc()) and not in the client 
4987     // ones as all the other messages, translate them to the client coords for 
4990         pt 
= ScreenToClient(wxPoint(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
))); 
4991     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
4992     InitMouseEvent(event
, pt
.x
, pt
.y
, LOWORD(wParam
)); 
4993     event
.m_wheelRotation 
= (short)HIWORD(wParam
); 
4994     event
.m_wheelDelta 
= WHEEL_DELTA
; 
4996     static int s_linesPerRotation 
= -1; 
4997     if ( s_linesPerRotation 
== -1 ) 
4999         if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, 
5000                                      &s_linesPerRotation
, 0)) 
5002             // this is not supposed to happen 
5003             wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)")); 
5005             // the default is 3, so use it if SystemParametersInfo() failed 
5006             s_linesPerRotation 
= 3; 
5010     event
.m_linesPerAction 
= s_linesPerRotation
; 
5011     return GetEventHandler()->ProcessEvent(event
); 
5013 #else // !wxUSE_MOUSEWHEEL 
5014     wxUnusedVar(wParam
); 
5015     wxUnusedVar(lParam
); 
5018 #endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL 
5021 void wxWindowMSW::GenerateMouseLeave() 
5023     m_mouseInWindow 
= false; 
5026     if ( wxIsShiftDown() ) 
5028     if ( wxIsCtrlDown() ) 
5029         state 
|= MK_CONTROL
; 
5031     // Only the high-order bit should be tested 
5032     if ( GetKeyState( VK_LBUTTON 
) & (1<<15) ) 
5033         state 
|= MK_LBUTTON
; 
5034     if ( GetKeyState( VK_MBUTTON 
) & (1<<15) ) 
5035         state 
|= MK_MBUTTON
; 
5036     if ( GetKeyState( VK_RBUTTON 
) & (1<<15) ) 
5037         state 
|= MK_RBUTTON
; 
5041     if ( !::GetCursorPosWinCE(&pt
) ) 
5043     if ( !::GetCursorPos(&pt
) ) 
5046         wxLogLastError(_T("GetCursorPos")); 
5049     // we need to have client coordinates here for symmetry with 
5050     // wxEVT_ENTER_WINDOW 
5051     RECT rect 
= wxGetWindowRect(GetHwnd()); 
5055     wxMouseEvent 
event(wxEVT_LEAVE_WINDOW
); 
5056     InitMouseEvent(event
, pt
.x
, pt
.y
, state
); 
5058     (void)GetEventHandler()->ProcessEvent(event
); 
5061 // --------------------------------------------------------------------------- 
5062 // keyboard handling 
5063 // --------------------------------------------------------------------------- 
5065 // create the key event of the given type for the given key - used by 
5066 // HandleChar and HandleKeyDown/Up 
5067 wxKeyEvent 
wxWindowMSW::CreateKeyEvent(wxEventType evType
, 
5070                                        WXWPARAM wParam
) const 
5072     wxKeyEvent 
event(evType
); 
5073     event
.SetId(GetId()); 
5074     event
.m_shiftDown 
= wxIsShiftDown(); 
5075     event
.m_controlDown 
= wxIsCtrlDown(); 
5076     event
.m_altDown 
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
; 
5078     event
.SetEventObject((wxWindow 
*)this); // const_cast 
5079     event
.m_keyCode 
= id
; 
5081     event
.m_uniChar 
= (wxChar
) wParam
; 
5083     event
.m_rawCode 
= (wxUint32
) wParam
; 
5084     event
.m_rawFlags 
= (wxUint32
) lParam
; 
5086     event
.SetTimestamp(::GetMessageTime()); 
5089     // translate the position to client coords 
5092     GetCursorPosWinCE(&pt
); 
5097     GetWindowRect(GetHwnd(),&rect
); 
5107 // isASCII is true only when we're called from WM_CHAR handler and not from 
5109 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
) 
5116     else // we're called from WM_KEYDOWN 
5118         // don't pass lParam to wxCharCodeMSWToWX() here because we don't want 
5119         // to get numpad key codes: CHAR events should use the logical keys 
5120         // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events 
5121         id 
= wxCharCodeMSWToWX(wParam
); 
5124             // it's ASCII and will be processed here only when called from 
5125             // WM_CHAR (i.e. when isASCII = true), don't process it now 
5130     wxKeyEvent 
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
)); 
5132     // the alphanumeric keys produced by pressing AltGr+something on European 
5133     // keyboards have both Ctrl and Alt modifiers which may confuse the user 
5134     // code as, normally, keys with Ctrl and/or Alt don't result in anything 
5135     // alphanumeric, so pretend that there are no modifiers at all (the 
5136     // KEY_DOWN event would still have the correct modifiers if they're really 
5138     if ( event
.m_controlDown 
&& event
.m_altDown 
&& 
5139             (id 
>= 32 && id 
< 256) ) 
5141         event
.m_controlDown 
= 
5142         event
.m_altDown 
= false; 
5145     return GetEventHandler()->ProcessEvent(event
); 
5148 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
) 
5150     int id 
= wxCharCodeMSWToWX(wParam
, lParam
); 
5154         // normal ASCII char 
5158     wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
)); 
5159     return GetEventHandler()->ProcessEvent(event
); 
5162 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
) 
5164     int id 
= wxCharCodeMSWToWX(wParam
, lParam
); 
5168         // normal ASCII char 
5172     wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
)); 
5173     return GetEventHandler()->ProcessEvent(event
); 
5176 int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel
), 
5177                                 WXLPARAM 
WXUNUSED_IN_WINCE(lParam
)) 
5179     // FIXME: implement GetMenuItemCount for WinCE, possibly 
5180     // in terms of GetMenuItemInfo 
5182     const HMENU hmenu 
= (HMENU
)lParam
; 
5186     mii
.cbSize 
= sizeof(MENUITEMINFO
); 
5188     // we could use MIIM_FTYPE here as we only need to know if the item is 
5189     // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but 
5190     // MIIM_FTYPE is not supported under Win95 
5191     mii
.fMask 
= MIIM_TYPE 
| MIIM_DATA
; 
5193     // find if we have this letter in any owner drawn item 
5194     const int count 
= ::GetMenuItemCount(hmenu
); 
5195     for ( int i 
= 0; i 
< count
; i
++ ) 
5197         // previous loop iteration could modify it, reset it back before 
5198         // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData 
5201         if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) ) 
5203             if ( mii
.fType 
== MFT_OWNERDRAW 
) 
5205                 //  dwItemData member of the MENUITEMINFO is a 
5206                 //  pointer to the associated wxMenuItem -- see the 
5207                 //  menu creation code 
5208                 wxMenuItem 
*item 
= (wxMenuItem
*)mii
.dwItemData
; 
5210                 const wxChar 
*p 
= wxStrchr(item
->GetText(), _T('&')); 
5213                     if ( *p 
== _T('&') ) 
5215                         // this is not the accel char, find the real one 
5216                         p 
= wxStrchr(p 
+ 1, _T('&')); 
5218                     else // got the accel char 
5220                         // FIXME-UNICODE: this comparison doesn't risk to work 
5221                         // for non ASCII accelerator characters I'm afraid, but 
5223                         if ( (wchar_t)wxToupper(*p
) == (wchar_t)chAccel 
) 
5229                             // this one doesn't match 
5236         else // failed to get the menu text? 
5238             // it's not fatal, so don't show error, but still log it 
5239             wxLogLastError(_T("GetMenuItemInfo")); 
5246 bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg 
) 
5248     const wxEventType type 
= ( nMsg 
== WM_CUT 
) ? wxEVT_COMMAND_TEXT_CUT 
: 
5249                              ( nMsg 
== WM_COPY 
) ? wxEVT_COMMAND_TEXT_COPY 
: 
5250                            /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE
; 
5251     wxClipboardTextEvent 
evt(type
, GetId()); 
5253     evt
.SetEventObject(this); 
5255     return GetEventHandler()->ProcessEvent(evt
); 
5258 // --------------------------------------------------------------------------- 
5260 // --------------------------------------------------------------------------- 
5262 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
5266     if ( flags 
& JOY_BUTTON1CHG 
) 
5267         change 
= wxJOY_BUTTON1
; 
5268     if ( flags 
& JOY_BUTTON2CHG 
) 
5269         change 
= wxJOY_BUTTON2
; 
5270     if ( flags 
& JOY_BUTTON3CHG 
) 
5271         change 
= wxJOY_BUTTON3
; 
5272     if ( flags 
& JOY_BUTTON4CHG 
) 
5273         change 
= wxJOY_BUTTON4
; 
5276     if ( flags 
& JOY_BUTTON1 
) 
5277         buttons 
|= wxJOY_BUTTON1
; 
5278     if ( flags 
& JOY_BUTTON2 
) 
5279         buttons 
|= wxJOY_BUTTON2
; 
5280     if ( flags 
& JOY_BUTTON3 
) 
5281         buttons 
|= wxJOY_BUTTON3
; 
5282     if ( flags 
& JOY_BUTTON4 
) 
5283         buttons 
|= wxJOY_BUTTON4
; 
5285     // the event ids aren't consecutive so we can't use table based lookup 
5287     wxEventType eventType
; 
5292             eventType 
= wxEVT_JOY_MOVE
; 
5297             eventType 
= wxEVT_JOY_MOVE
; 
5302             eventType 
= wxEVT_JOY_ZMOVE
; 
5307             eventType 
= wxEVT_JOY_ZMOVE
; 
5310         case MM_JOY1BUTTONDOWN
: 
5312             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
5315         case MM_JOY2BUTTONDOWN
: 
5317             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
5320         case MM_JOY1BUTTONUP
: 
5322             eventType 
= wxEVT_JOY_BUTTON_UP
; 
5325         case MM_JOY2BUTTONUP
: 
5327             eventType 
= wxEVT_JOY_BUTTON_UP
; 
5331             wxFAIL_MSG(wxT("no such joystick event")); 
5336     wxJoystickEvent 
event(eventType
, buttons
, joystick
, change
); 
5337     event
.SetPosition(wxPoint(x
, y
)); 
5338     event
.SetEventObject(this); 
5340     return GetEventHandler()->ProcessEvent(event
); 
5350 // --------------------------------------------------------------------------- 
5352 // --------------------------------------------------------------------------- 
5354 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
, 
5355                               WXWORD pos
, WXHWND control
) 
5357     if ( control 
&& control 
!= m_hWnd 
) // Prevent infinite recursion 
5359         wxWindow 
*child 
= wxFindWinFromHandle(control
); 
5361             return child
->MSWOnScroll(orientation
, wParam
, pos
, control
); 
5364     wxScrollWinEvent event
; 
5365     event
.SetPosition(pos
); 
5366     event
.SetOrientation(orientation
); 
5367     event
.SetEventObject(this); 
5372         event
.SetEventType(wxEVT_SCROLLWIN_TOP
); 
5376         event
.SetEventType(wxEVT_SCROLLWIN_BOTTOM
); 
5380         event
.SetEventType(wxEVT_SCROLLWIN_LINEUP
); 
5384         event
.SetEventType(wxEVT_SCROLLWIN_LINEDOWN
); 
5388         event
.SetEventType(wxEVT_SCROLLWIN_PAGEUP
); 
5392         event
.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN
); 
5395     case SB_THUMBPOSITION
: 
5397         // under Win32, the scrollbar range and position are 32 bit integers, 
5398         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must 
5399         // explicitly query the scrollbar for the correct position (this must 
5400         // be done only for these two SB_ events as they are the only one 
5401         // carrying the scrollbar position) 
5403             WinStruct
<SCROLLINFO
> scrollInfo
; 
5404             scrollInfo
.fMask 
= SIF_TRACKPOS
; 
5406             if ( !::GetScrollInfo(GetHwnd(), 
5407                                   orientation 
== wxHORIZONTAL 
? SB_HORZ
 
5411                 // Not necessarily an error, if there are no scrollbars yet. 
5412                 // wxLogLastError(_T("GetScrollInfo")); 
5415             event
.SetPosition(scrollInfo
.nTrackPos
); 
5418         event
.SetEventType( wParam 
== SB_THUMBPOSITION
 
5419                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
 
5420                                 : wxEVT_SCROLLWIN_THUMBTRACK 
); 
5427     return GetEventHandler()->ProcessEvent(event
); 
5430 // =========================================================================== 
5432 // =========================================================================== 
5434 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
& the_font
) 
5437     HDC dc 
= ::GetDC((HWND
) wnd
); 
5440     //    the_font.UseResource(); 
5441     //    the_font.RealizeResource(); 
5442     HFONT fnt 
= (HFONT
)the_font
.GetResourceHandle(); // const_cast 
5444         was 
= (HFONT
) SelectObject(dc
,fnt
); 
5446     GetTextMetrics(dc
, &tm
); 
5449         SelectObject(dc
,was
); 
5451     ReleaseDC((HWND
)wnd
, dc
); 
5454         *x 
= tm
.tmAveCharWidth
; 
5456         *y 
= tm
.tmHeight 
+ tm
.tmExternalLeading
; 
5458     //   the_font.ReleaseResource(); 
5461 // use the "extended" bit (24) of lParam to distinguish extended keys 
5462 // from normal keys as the same key is sent 
5464 int ChooseNormalOrExtended(int lParam
, int keyNormal
, int keyExtended
) 
5466     // except that if lParam is 0, it means we don't have real lParam from 
5467     // WM_KEYDOWN but are just translating just a VK constant (e.g. done from 
5468     // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a 
5469     // non-numpad (hence extended) key as this is a more common case 
5470     return !lParam 
|| (lParam 
& (1 << 24)) ? keyExtended 
: keyNormal
; 
5473 // this array contains the Windows virtual key codes which map one to one to 
5474 // WXK_xxx constants and is used in wxCharCodeMSWToWX/WXToMSW() below 
5476 // note that keys having a normal and numpad version (e.g. WXK_HOME and 
5477 // WXK_NUMPAD_HOME) are not included in this table as the mapping is not 1-to-1 
5478 static const struct wxKeyMapping
 
5482 } gs_specialKeys
[] = 
5484     { VK_CANCEL
,        WXK_CANCEL 
}, 
5485     { VK_BACK
,          WXK_BACK 
}, 
5486     { VK_TAB
,           WXK_TAB 
}, 
5487     { VK_CLEAR
,         WXK_CLEAR 
}, 
5488     { VK_SHIFT
,         WXK_SHIFT 
}, 
5489     { VK_CONTROL
,       WXK_CONTROL 
}, 
5490     { VK_MENU 
,         WXK_ALT 
}, 
5491     { VK_PAUSE
,         WXK_PAUSE 
}, 
5492     { VK_CAPITAL
,       WXK_CAPITAL 
}, 
5493     { VK_SPACE
,         WXK_SPACE 
}, 
5494     { VK_ESCAPE
,        WXK_ESCAPE 
}, 
5495     { VK_SELECT
,        WXK_SELECT 
}, 
5496     { VK_PRINT
,         WXK_PRINT 
}, 
5497     { VK_EXECUTE
,       WXK_EXECUTE 
}, 
5498     { VK_SNAPSHOT
,      WXK_SNAPSHOT 
}, 
5499     { VK_HELP
,          WXK_HELP 
}, 
5501     { VK_NUMPAD0
,       WXK_NUMPAD0 
}, 
5502     { VK_NUMPAD1
,       WXK_NUMPAD1 
}, 
5503     { VK_NUMPAD2
,       WXK_NUMPAD2 
}, 
5504     { VK_NUMPAD3
,       WXK_NUMPAD3 
}, 
5505     { VK_NUMPAD4
,       WXK_NUMPAD4 
}, 
5506     { VK_NUMPAD5
,       WXK_NUMPAD5 
}, 
5507     { VK_NUMPAD6
,       WXK_NUMPAD6 
}, 
5508     { VK_NUMPAD7
,       WXK_NUMPAD7 
}, 
5509     { VK_NUMPAD8
,       WXK_NUMPAD8 
}, 
5510     { VK_NUMPAD9
,       WXK_NUMPAD9 
}, 
5511     { VK_MULTIPLY
,      WXK_NUMPAD_MULTIPLY 
}, 
5512     { VK_ADD
,           WXK_NUMPAD_ADD 
}, 
5513     { VK_SUBTRACT
,      WXK_NUMPAD_SUBTRACT 
}, 
5514     { VK_DECIMAL
,       WXK_NUMPAD_DECIMAL 
}, 
5515     { VK_DIVIDE
,        WXK_NUMPAD_DIVIDE 
}, 
5526     { VK_F10
,           WXK_F10 
}, 
5527     { VK_F11
,           WXK_F11 
}, 
5528     { VK_F12
,           WXK_F12 
}, 
5529     { VK_F13
,           WXK_F13 
}, 
5530     { VK_F14
,           WXK_F14 
}, 
5531     { VK_F15
,           WXK_F15 
}, 
5532     { VK_F16
,           WXK_F16 
}, 
5533     { VK_F17
,           WXK_F17 
}, 
5534     { VK_F18
,           WXK_F18 
}, 
5535     { VK_F19
,           WXK_F19 
}, 
5536     { VK_F20
,           WXK_F20 
}, 
5537     { VK_F21
,           WXK_F21 
}, 
5538     { VK_F22
,           WXK_F22 
}, 
5539     { VK_F23
,           WXK_F23 
}, 
5540     { VK_F24
,           WXK_F24 
}, 
5542     { VK_NUMLOCK
,       WXK_NUMLOCK 
}, 
5543     { VK_SCROLL
,        WXK_SCROLL 
}, 
5546     { VK_LWIN
,          WXK_WINDOWS_LEFT 
}, 
5547     { VK_RWIN
,          WXK_WINDOWS_RIGHT 
}, 
5548     { VK_APPS
,          WXK_WINDOWS_MENU 
}, 
5549 #endif // VK_APPS defined 
5552 // Returns 0 if was a normal ASCII value, not a special key. This indicates that 
5553 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. 
5554 int wxCharCodeMSWToWX(int vk
, WXLPARAM lParam
) 
5556     // check the table first 
5557     for ( size_t n 
= 0; n 
< WXSIZEOF(gs_specialKeys
); n
++ ) 
5559         if ( gs_specialKeys
[n
].vk 
== vk 
) 
5560             return gs_specialKeys
[n
].wxk
; 
5563     // keys requiring special handling 
5567         // the mapping for these keys may be incorrect on non-US keyboards so 
5568         // maybe we shouldn't map them to ASCII values at all 
5569         case VK_OEM_1
:      wxk 
= ';'; break; 
5570         case VK_OEM_PLUS
:   wxk 
= '+'; break; 
5571         case VK_OEM_COMMA
:  wxk 
= ','; break; 
5572         case VK_OEM_MINUS
:  wxk 
= '-'; break; 
5573         case VK_OEM_PERIOD
: wxk 
= '.'; break; 
5574         case VK_OEM_2
:      wxk 
= '/'; break; 
5575         case VK_OEM_3
:      wxk 
= '~'; break; 
5576         case VK_OEM_4
:      wxk 
= '['; break; 
5577         case VK_OEM_5
:      wxk 
= '\\'; break; 
5578         case VK_OEM_6
:      wxk 
= ']'; break; 
5579         case VK_OEM_7
:      wxk 
= '\''; break; 
5581         // handle extended keys 
5583             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_PAGEUP
, WXK_PAGEUP
); 
5587             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_PAGEDOWN
, WXK_PAGEDOWN
); 
5591             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_END
, WXK_END
); 
5595             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_HOME
, WXK_HOME
); 
5599             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_LEFT
, WXK_LEFT
); 
5603             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_UP
, WXK_UP
); 
5607             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_RIGHT
, WXK_RIGHT
); 
5611             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_DOWN
, WXK_DOWN
); 
5615             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_INSERT
, WXK_INSERT
); 
5619             wxk 
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_DELETE
, WXK_DELETE
); 
5623             // don't use ChooseNormalOrExtended() here as the keys are reversed 
5624             // here: numpad enter is the extended one 
5625             wxk 
= lParam 
&& (lParam 
& (1 << 24)) ? WXK_NUMPAD_ENTER 
: WXK_RETURN
; 
5635 WXWORD 
wxCharCodeWXToMSW(int wxk
, bool *isVirtual
) 
5640     // check the table first 
5641     for ( size_t n 
= 0; n 
< WXSIZEOF(gs_specialKeys
); n
++ ) 
5643         if ( gs_specialKeys
[n
].wxk 
== wxk 
) 
5644             return gs_specialKeys
[n
].vk
; 
5647     // and then check for special keys not included in the table 
5652         case WXK_NUMPAD_PAGEUP
: 
5657         case WXK_NUMPAD_PAGEDOWN
: 
5662         case WXK_NUMPAD_END
: 
5667         case WXK_NUMPAD_HOME
: 
5672         case WXK_NUMPAD_LEFT
: 
5682         case WXK_NUMPAD_RIGHT
: 
5687         case WXK_NUMPAD_DOWN
: 
5692         case WXK_NUMPAD_INSERT
: 
5697         case WXK_NUMPAD_DELETE
: 
5711 #ifndef SM_SWAPBUTTON 
5712     #define SM_SWAPBUTTON 23 
5715 // small helper for wxGetKeyState() and wxGetMouseState() 
5716 static inline bool wxIsKeyDown(WXWORD vk
) 
5721             if (GetSystemMetrics(SM_SWAPBUTTON
)) vk 
= VK_RBUTTON
; 
5724             if (GetSystemMetrics(SM_SWAPBUTTON
)) vk 
= VK_LBUTTON
; 
5727     // the low order bit indicates whether the key was pressed since the last 
5728     // call and the high order one indicates whether it is down right now and 
5729     // we only want that one 
5730     return (GetAsyncKeyState(vk
) & (1<<15)) != 0; 
5733 bool wxGetKeyState(wxKeyCode key
) 
5735     // although this does work under Windows, it is not supported under other 
5736     // platforms so don't allow it, you must use wxGetMouseState() instead 
5737     wxASSERT_MSG( key 
!= VK_LBUTTON 
&& 
5738                     key 
!= VK_RBUTTON 
&& 
5740                     wxT("can't use wxGetKeyState() for mouse buttons") ); 
5742     const WXWORD vk 
= wxCharCodeWXToMSW(key
); 
5744     // if the requested key is a LED key, return true if the led is pressed 
5745     if ( key 
== WXK_NUMLOCK 
|| key 
== WXK_CAPITAL 
|| key 
== WXK_SCROLL 
) 
5747         // low order bit means LED is highlighted and high order one means the 
5748         // key is down; for compatibility with the other ports return true if 
5749         // either one is set 
5750         return GetKeyState(vk
) != 0; 
5755         return wxIsKeyDown(vk
); 
5760 wxMouseState 
wxGetMouseState() 
5764     GetCursorPos( &pt 
); 
5768     ms
.SetLeftDown(wxIsKeyDown(VK_LBUTTON
)); 
5769     ms
.SetMiddleDown(wxIsKeyDown(VK_MBUTTON
)); 
5770     ms
.SetRightDown(wxIsKeyDown(VK_RBUTTON
)); 
5772     ms
.SetControlDown(wxIsKeyDown(VK_CONTROL
)); 
5773     ms
.SetShiftDown(wxIsKeyDown(VK_SHIFT
)); 
5774     ms
.SetAltDown(wxIsKeyDown(VK_MENU
)); 
5775 //    ms.SetMetaDown(); 
5781 wxWindow 
*wxGetActiveWindow() 
5783     HWND hWnd 
= GetActiveWindow(); 
5786         return wxFindWinFromHandle((WXHWND
) hWnd
); 
5791 extern wxWindow 
*wxGetWindowFromHWND(WXHWND hWnd
) 
5793     HWND hwnd 
= (HWND
)hWnd
; 
5795     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set 
5796     // by code in msw/radiobox.cpp), for all the others we just search up the 
5798     wxWindow 
*win 
= (wxWindow 
*)NULL
; 
5801         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
5805             // native radiobuttons return DLGC_RADIOBUTTON here and for any 
5806             // wxWindow class which overrides WM_GETDLGCODE processing to 
5807             // do it as well, win would be already non NULL 
5808             if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON 
) 
5810                 win 
= (wxWindow 
*)wxGetWindowUserData(hwnd
); 
5812             //else: it's a wxRadioButton, not a radiobutton from wxRadioBox 
5813 #endif // wxUSE_RADIOBOX 
5815             // spin control text buddy window should be mapped to spin ctrl 
5816             // itself so try it too 
5817 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
5820                 win 
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
); 
5822 #endif // wxUSE_SPINCTRL 
5826     while ( hwnd 
&& !win 
) 
5828         // this is a really ugly hack needed to avoid mistakenly returning the 
5829         // parent frame wxWindow for the find/replace modeless dialog HWND - 
5830         // this, in turn, is needed to call IsDialogMessage() from 
5831         // wxApp::ProcessMessage() as for this we must return NULL from here 
5833         // FIXME: this is clearly not the best way to do it but I think we'll 
5834         //        need to change HWND <-> wxWindow code more heavily than I can 
5835         //        do it now to fix it 
5836 #ifndef __WXMICROWIN__ 
5837         if ( ::GetWindow(hwnd
, GW_OWNER
) ) 
5839             // it's a dialog box, don't go upwards 
5844         hwnd 
= ::GetParent(hwnd
); 
5845         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
5851 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
5853 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE 
5854 // in active frames and dialogs, regardless of where the focus is. 
5855 static HHOOK wxTheKeyboardHook 
= 0; 
5856 static FARPROC wxTheKeyboardHookProc 
= 0; 
5857 int APIENTRY _EXPORT
 
5858 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
); 
5860 void wxSetKeyboardHook(bool doIt
) 
5864         wxTheKeyboardHookProc 
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance()); 
5865         wxTheKeyboardHook 
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(), 
5867             GetCurrentThreadId() 
5868         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? 
5873         UnhookWindowsHookEx(wxTheKeyboardHook
); 
5877 int APIENTRY _EXPORT
 
5878 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
) 
5880     DWORD hiWord 
= HIWORD(lParam
); 
5881     if ( nCode 
!= HC_NOREMOVE 
&& ((hiWord 
& KF_UP
) == 0) ) 
5883         int id 
= wxCharCodeMSWToWX(wParam
, lParam
); 
5886             wxKeyEvent 
event(wxEVT_CHAR_HOOK
); 
5887             if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
5888                 event
.m_altDown 
= true; 
5890             event
.SetEventObject(NULL
); 
5891             event
.m_keyCode 
= id
; 
5892             event
.m_shiftDown 
= wxIsShiftDown(); 
5893             event
.m_controlDown 
= wxIsCtrlDown(); 
5895             event
.SetTimestamp(::GetMessageTime()); 
5897             wxWindow 
*win 
= wxGetActiveWindow(); 
5898             wxEvtHandler 
*handler
; 
5901                 handler 
= win
->GetEventHandler(); 
5902                 event
.SetId(win
->GetId()); 
5907                 event
.SetId(wxID_ANY
); 
5910             if ( handler 
&& handler
->ProcessEvent(event
) ) 
5918     return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
); 
5921 #endif // !__WXMICROWIN__ 
5924 const wxChar 
*wxGetMessageName(int message
) 
5928         case 0x0000: return wxT("WM_NULL"); 
5929         case 0x0001: return wxT("WM_CREATE"); 
5930         case 0x0002: return wxT("WM_DESTROY"); 
5931         case 0x0003: return wxT("WM_MOVE"); 
5932         case 0x0005: return wxT("WM_SIZE"); 
5933         case 0x0006: return wxT("WM_ACTIVATE"); 
5934         case 0x0007: return wxT("WM_SETFOCUS"); 
5935         case 0x0008: return wxT("WM_KILLFOCUS"); 
5936         case 0x000A: return wxT("WM_ENABLE"); 
5937         case 0x000B: return wxT("WM_SETREDRAW"); 
5938         case 0x000C: return wxT("WM_SETTEXT"); 
5939         case 0x000D: return wxT("WM_GETTEXT"); 
5940         case 0x000E: return wxT("WM_GETTEXTLENGTH"); 
5941         case 0x000F: return wxT("WM_PAINT"); 
5942         case 0x0010: return wxT("WM_CLOSE"); 
5943         case 0x0011: return wxT("WM_QUERYENDSESSION"); 
5944         case 0x0012: return wxT("WM_QUIT"); 
5945         case 0x0013: return wxT("WM_QUERYOPEN"); 
5946         case 0x0014: return wxT("WM_ERASEBKGND"); 
5947         case 0x0015: return wxT("WM_SYSCOLORCHANGE"); 
5948         case 0x0016: return wxT("WM_ENDSESSION"); 
5949         case 0x0017: return wxT("WM_SYSTEMERROR"); 
5950         case 0x0018: return wxT("WM_SHOWWINDOW"); 
5951         case 0x0019: return wxT("WM_CTLCOLOR"); 
5952         case 0x001A: return wxT("WM_WININICHANGE"); 
5953         case 0x001B: return wxT("WM_DEVMODECHANGE"); 
5954         case 0x001C: return wxT("WM_ACTIVATEAPP"); 
5955         case 0x001D: return wxT("WM_FONTCHANGE"); 
5956         case 0x001E: return wxT("WM_TIMECHANGE"); 
5957         case 0x001F: return wxT("WM_CANCELMODE"); 
5958         case 0x0020: return wxT("WM_SETCURSOR"); 
5959         case 0x0021: return wxT("WM_MOUSEACTIVATE"); 
5960         case 0x0022: return wxT("WM_CHILDACTIVATE"); 
5961         case 0x0023: return wxT("WM_QUEUESYNC"); 
5962         case 0x0024: return wxT("WM_GETMINMAXINFO"); 
5963         case 0x0026: return wxT("WM_PAINTICON"); 
5964         case 0x0027: return wxT("WM_ICONERASEBKGND"); 
5965         case 0x0028: return wxT("WM_NEXTDLGCTL"); 
5966         case 0x002A: return wxT("WM_SPOOLERSTATUS"); 
5967         case 0x002B: return wxT("WM_DRAWITEM"); 
5968         case 0x002C: return wxT("WM_MEASUREITEM"); 
5969         case 0x002D: return wxT("WM_DELETEITEM"); 
5970         case 0x002E: return wxT("WM_VKEYTOITEM"); 
5971         case 0x002F: return wxT("WM_CHARTOITEM"); 
5972         case 0x0030: return wxT("WM_SETFONT"); 
5973         case 0x0031: return wxT("WM_GETFONT"); 
5974         case 0x0037: return wxT("WM_QUERYDRAGICON"); 
5975         case 0x0039: return wxT("WM_COMPAREITEM"); 
5976         case 0x0041: return wxT("WM_COMPACTING"); 
5977         case 0x0044: return wxT("WM_COMMNOTIFY"); 
5978         case 0x0046: return wxT("WM_WINDOWPOSCHANGING"); 
5979         case 0x0047: return wxT("WM_WINDOWPOSCHANGED"); 
5980         case 0x0048: return wxT("WM_POWER"); 
5982         case 0x004A: return wxT("WM_COPYDATA"); 
5983         case 0x004B: return wxT("WM_CANCELJOURNAL"); 
5984         case 0x004E: return wxT("WM_NOTIFY"); 
5985         case 0x0050: return wxT("WM_INPUTLANGCHANGEREQUEST"); 
5986         case 0x0051: return wxT("WM_INPUTLANGCHANGE"); 
5987         case 0x0052: return wxT("WM_TCARD"); 
5988         case 0x0053: return wxT("WM_HELP"); 
5989         case 0x0054: return wxT("WM_USERCHANGED"); 
5990         case 0x0055: return wxT("WM_NOTIFYFORMAT"); 
5991         case 0x007B: return wxT("WM_CONTEXTMENU"); 
5992         case 0x007C: return wxT("WM_STYLECHANGING"); 
5993         case 0x007D: return wxT("WM_STYLECHANGED"); 
5994         case 0x007E: return wxT("WM_DISPLAYCHANGE"); 
5995         case 0x007F: return wxT("WM_GETICON"); 
5996         case 0x0080: return wxT("WM_SETICON"); 
5998         case 0x0081: return wxT("WM_NCCREATE"); 
5999         case 0x0082: return wxT("WM_NCDESTROY"); 
6000         case 0x0083: return wxT("WM_NCCALCSIZE"); 
6001         case 0x0084: return wxT("WM_NCHITTEST"); 
6002         case 0x0085: return wxT("WM_NCPAINT"); 
6003         case 0x0086: return wxT("WM_NCACTIVATE"); 
6004         case 0x0087: return wxT("WM_GETDLGCODE"); 
6005         case 0x00A0: return wxT("WM_NCMOUSEMOVE"); 
6006         case 0x00A1: return wxT("WM_NCLBUTTONDOWN"); 
6007         case 0x00A2: return wxT("WM_NCLBUTTONUP"); 
6008         case 0x00A3: return wxT("WM_NCLBUTTONDBLCLK"); 
6009         case 0x00A4: return wxT("WM_NCRBUTTONDOWN"); 
6010         case 0x00A5: return wxT("WM_NCRBUTTONUP"); 
6011         case 0x00A6: return wxT("WM_NCRBUTTONDBLCLK"); 
6012         case 0x00A7: return wxT("WM_NCMBUTTONDOWN"); 
6013         case 0x00A8: return wxT("WM_NCMBUTTONUP"); 
6014         case 0x00A9: return wxT("WM_NCMBUTTONDBLCLK"); 
6016         case 0x00B0: return wxT("EM_GETSEL"); 
6017         case 0x00B1: return wxT("EM_SETSEL"); 
6018         case 0x00B2: return wxT("EM_GETRECT"); 
6019         case 0x00B3: return wxT("EM_SETRECT"); 
6020         case 0x00B4: return wxT("EM_SETRECTNP"); 
6021         case 0x00B5: return wxT("EM_SCROLL"); 
6022         case 0x00B6: return wxT("EM_LINESCROLL"); 
6023         case 0x00B7: return wxT("EM_SCROLLCARET"); 
6024         case 0x00B8: return wxT("EM_GETMODIFY"); 
6025         case 0x00B9: return wxT("EM_SETMODIFY"); 
6026         case 0x00BA: return wxT("EM_GETLINECOUNT"); 
6027         case 0x00BB: return wxT("EM_LINEINDEX"); 
6028         case 0x00BC: return wxT("EM_SETHANDLE"); 
6029         case 0x00BD: return wxT("EM_GETHANDLE"); 
6030         case 0x00BE: return wxT("EM_GETTHUMB"); 
6031         case 0x00C1: return wxT("EM_LINELENGTH"); 
6032         case 0x00C2: return wxT("EM_REPLACESEL"); 
6033         case 0x00C4: return wxT("EM_GETLINE"); 
6034         case 0x00C5: return wxT("EM_LIMITTEXT/EM_SETLIMITTEXT"); /* ;win40 Name change */ 
6035         case 0x00C6: return wxT("EM_CANUNDO"); 
6036         case 0x00C7: return wxT("EM_UNDO"); 
6037         case 0x00C8: return wxT("EM_FMTLINES"); 
6038         case 0x00C9: return wxT("EM_LINEFROMCHAR"); 
6039         case 0x00CB: return wxT("EM_SETTABSTOPS"); 
6040         case 0x00CC: return wxT("EM_SETPASSWORDCHAR"); 
6041         case 0x00CD: return wxT("EM_EMPTYUNDOBUFFER"); 
6042         case 0x00CE: return wxT("EM_GETFIRSTVISIBLELINE"); 
6043         case 0x00CF: return wxT("EM_SETREADONLY"); 
6044         case 0x00D0: return wxT("EM_SETWORDBREAKPROC"); 
6045         case 0x00D1: return wxT("EM_GETWORDBREAKPROC"); 
6046         case 0x00D2: return wxT("EM_GETPASSWORDCHAR"); 
6047         case 0x00D3: return wxT("EM_SETMARGINS"); 
6048         case 0x00D4: return wxT("EM_GETMARGINS"); 
6049         case 0x00D5: return wxT("EM_GETLIMITTEXT"); 
6050         case 0x00D6: return wxT("EM_POSFROMCHAR"); 
6051         case 0x00D7: return wxT("EM_CHARFROMPOS"); 
6052         case 0x00D8: return wxT("EM_SETIMESTATUS"); 
6053         case 0x00D9: return wxT("EM_GETIMESTATUS"); 
6055         case 0x0100: return wxT("WM_KEYDOWN"); 
6056         case 0x0101: return wxT("WM_KEYUP"); 
6057         case 0x0102: return wxT("WM_CHAR"); 
6058         case 0x0103: return wxT("WM_DEADCHAR"); 
6059         case 0x0104: return wxT("WM_SYSKEYDOWN"); 
6060         case 0x0105: return wxT("WM_SYSKEYUP"); 
6061         case 0x0106: return wxT("WM_SYSCHAR"); 
6062         case 0x0107: return wxT("WM_SYSDEADCHAR"); 
6063         case 0x0108: return wxT("WM_KEYLAST"); 
6065         case 0x010D: return wxT("WM_IME_STARTCOMPOSITION"); 
6066         case 0x010E: return wxT("WM_IME_ENDCOMPOSITION"); 
6067         case 0x010F: return wxT("WM_IME_COMPOSITION"); 
6069         case 0x0110: return wxT("WM_INITDIALOG"); 
6070         case 0x0111: return wxT("WM_COMMAND"); 
6071         case 0x0112: return wxT("WM_SYSCOMMAND"); 
6072         case 0x0113: return wxT("WM_TIMER"); 
6073         case 0x0114: return wxT("WM_HSCROLL"); 
6074         case 0x0115: return wxT("WM_VSCROLL"); 
6075         case 0x0116: return wxT("WM_INITMENU"); 
6076         case 0x0117: return wxT("WM_INITMENUPOPUP"); 
6077         case 0x011F: return wxT("WM_MENUSELECT"); 
6078         case 0x0120: return wxT("WM_MENUCHAR"); 
6079         case 0x0121: return wxT("WM_ENTERIDLE"); 
6081         case 0x0132: return wxT("WM_CTLCOLORMSGBOX"); 
6082         case 0x0133: return wxT("WM_CTLCOLOREDIT"); 
6083         case 0x0134: return wxT("WM_CTLCOLORLISTBOX"); 
6084         case 0x0135: return wxT("WM_CTLCOLORBTN"); 
6085         case 0x0136: return wxT("WM_CTLCOLORDLG"); 
6086         case 0x0137: return wxT("WM_CTLCOLORSCROLLBAR"); 
6087         case 0x0138: return wxT("WM_CTLCOLORSTATIC"); 
6088         case 0x01E1: return wxT("MN_GETHMENU"); 
6090         case 0x0200: return wxT("WM_MOUSEMOVE"); 
6091         case 0x0201: return wxT("WM_LBUTTONDOWN"); 
6092         case 0x0202: return wxT("WM_LBUTTONUP"); 
6093         case 0x0203: return wxT("WM_LBUTTONDBLCLK"); 
6094         case 0x0204: return wxT("WM_RBUTTONDOWN"); 
6095         case 0x0205: return wxT("WM_RBUTTONUP"); 
6096         case 0x0206: return wxT("WM_RBUTTONDBLCLK"); 
6097         case 0x0207: return wxT("WM_MBUTTONDOWN"); 
6098         case 0x0208: return wxT("WM_MBUTTONUP"); 
6099         case 0x0209: return wxT("WM_MBUTTONDBLCLK"); 
6100         case 0x020A: return wxT("WM_MOUSEWHEEL"); 
6101         case 0x0210: return wxT("WM_PARENTNOTIFY"); 
6102         case 0x0211: return wxT("WM_ENTERMENULOOP"); 
6103         case 0x0212: return wxT("WM_EXITMENULOOP"); 
6105         case 0x0213: return wxT("WM_NEXTMENU"); 
6106         case 0x0214: return wxT("WM_SIZING"); 
6107         case 0x0215: return wxT("WM_CAPTURECHANGED"); 
6108         case 0x0216: return wxT("WM_MOVING"); 
6109         case 0x0218: return wxT("WM_POWERBROADCAST"); 
6110         case 0x0219: return wxT("WM_DEVICECHANGE"); 
6112         case 0x0220: return wxT("WM_MDICREATE"); 
6113         case 0x0221: return wxT("WM_MDIDESTROY"); 
6114         case 0x0222: return wxT("WM_MDIACTIVATE"); 
6115         case 0x0223: return wxT("WM_MDIRESTORE"); 
6116         case 0x0224: return wxT("WM_MDINEXT"); 
6117         case 0x0225: return wxT("WM_MDIMAXIMIZE"); 
6118         case 0x0226: return wxT("WM_MDITILE"); 
6119         case 0x0227: return wxT("WM_MDICASCADE"); 
6120         case 0x0228: return wxT("WM_MDIICONARRANGE"); 
6121         case 0x0229: return wxT("WM_MDIGETACTIVE"); 
6122         case 0x0230: return wxT("WM_MDISETMENU"); 
6123         case 0x0233: return wxT("WM_DROPFILES"); 
6125         case 0x0281: return wxT("WM_IME_SETCONTEXT"); 
6126         case 0x0282: return wxT("WM_IME_NOTIFY"); 
6127         case 0x0283: return wxT("WM_IME_CONTROL"); 
6128         case 0x0284: return wxT("WM_IME_COMPOSITIONFULL"); 
6129         case 0x0285: return wxT("WM_IME_SELECT"); 
6130         case 0x0286: return wxT("WM_IME_CHAR"); 
6131         case 0x0290: return wxT("WM_IME_KEYDOWN"); 
6132         case 0x0291: return wxT("WM_IME_KEYUP"); 
6134         case 0x02A0: return wxT("WM_NCMOUSEHOVER"); 
6135         case 0x02A1: return wxT("WM_MOUSEHOVER"); 
6136         case 0x02A2: return wxT("WM_NCMOUSELEAVE"); 
6137         case 0x02A3: return wxT("WM_MOUSELEAVE"); 
6139         case 0x0300: return wxT("WM_CUT"); 
6140         case 0x0301: return wxT("WM_COPY"); 
6141         case 0x0302: return wxT("WM_PASTE"); 
6142         case 0x0303: return wxT("WM_CLEAR"); 
6143         case 0x0304: return wxT("WM_UNDO"); 
6144         case 0x0305: return wxT("WM_RENDERFORMAT"); 
6145         case 0x0306: return wxT("WM_RENDERALLFORMATS"); 
6146         case 0x0307: return wxT("WM_DESTROYCLIPBOARD"); 
6147         case 0x0308: return wxT("WM_DRAWCLIPBOARD"); 
6148         case 0x0309: return wxT("WM_PAINTCLIPBOARD"); 
6149         case 0x030A: return wxT("WM_VSCROLLCLIPBOARD"); 
6150         case 0x030B: return wxT("WM_SIZECLIPBOARD"); 
6151         case 0x030C: return wxT("WM_ASKCBFORMATNAME"); 
6152         case 0x030D: return wxT("WM_CHANGECBCHAIN"); 
6153         case 0x030E: return wxT("WM_HSCROLLCLIPBOARD"); 
6154         case 0x030F: return wxT("WM_QUERYNEWPALETTE"); 
6155         case 0x0310: return wxT("WM_PALETTEISCHANGING"); 
6156         case 0x0311: return wxT("WM_PALETTECHANGED"); 
6157         case 0x0312: return wxT("WM_HOTKEY"); 
6159         case 0x0317: return wxT("WM_PRINT"); 
6160         case 0x0318: return wxT("WM_PRINTCLIENT"); 
6162         // common controls messages - although they're not strictly speaking 
6163         // standard, it's nice to decode them nevertheless 
6166         case 0x1000 + 0: return wxT("LVM_GETBKCOLOR"); 
6167         case 0x1000 + 1: return wxT("LVM_SETBKCOLOR"); 
6168         case 0x1000 + 2: return wxT("LVM_GETIMAGELIST"); 
6169         case 0x1000 + 3: return wxT("LVM_SETIMAGELIST"); 
6170         case 0x1000 + 4: return wxT("LVM_GETITEMCOUNT"); 
6171         case 0x1000 + 5: return wxT("LVM_GETITEMA"); 
6172         case 0x1000 + 75: return wxT("LVM_GETITEMW"); 
6173         case 0x1000 + 6: return wxT("LVM_SETITEMA"); 
6174         case 0x1000 + 76: return wxT("LVM_SETITEMW"); 
6175         case 0x1000 + 7: return wxT("LVM_INSERTITEMA"); 
6176         case 0x1000 + 77: return wxT("LVM_INSERTITEMW"); 
6177         case 0x1000 + 8: return wxT("LVM_DELETEITEM"); 
6178         case 0x1000 + 9: return wxT("LVM_DELETEALLITEMS"); 
6179         case 0x1000 + 10: return wxT("LVM_GETCALLBACKMASK"); 
6180         case 0x1000 + 11: return wxT("LVM_SETCALLBACKMASK"); 
6181         case 0x1000 + 12: return wxT("LVM_GETNEXTITEM"); 
6182         case 0x1000 + 13: return wxT("LVM_FINDITEMA"); 
6183         case 0x1000 + 83: return wxT("LVM_FINDITEMW"); 
6184         case 0x1000 + 14: return wxT("LVM_GETITEMRECT"); 
6185         case 0x1000 + 15: return wxT("LVM_SETITEMPOSITION"); 
6186         case 0x1000 + 16: return wxT("LVM_GETITEMPOSITION"); 
6187         case 0x1000 + 17: return wxT("LVM_GETSTRINGWIDTHA"); 
6188         case 0x1000 + 87: return wxT("LVM_GETSTRINGWIDTHW"); 
6189         case 0x1000 + 18: return wxT("LVM_HITTEST"); 
6190         case 0x1000 + 19: return wxT("LVM_ENSUREVISIBLE"); 
6191         case 0x1000 + 20: return wxT("LVM_SCROLL"); 
6192         case 0x1000 + 21: return wxT("LVM_REDRAWITEMS"); 
6193         case 0x1000 + 22: return wxT("LVM_ARRANGE"); 
6194         case 0x1000 + 23: return wxT("LVM_EDITLABELA"); 
6195         case 0x1000 + 118: return wxT("LVM_EDITLABELW"); 
6196         case 0x1000 + 24: return wxT("LVM_GETEDITCONTROL"); 
6197         case 0x1000 + 25: return wxT("LVM_GETCOLUMNA"); 
6198         case 0x1000 + 95: return wxT("LVM_GETCOLUMNW"); 
6199         case 0x1000 + 26: return wxT("LVM_SETCOLUMNA"); 
6200         case 0x1000 + 96: return wxT("LVM_SETCOLUMNW"); 
6201         case 0x1000 + 27: return wxT("LVM_INSERTCOLUMNA"); 
6202         case 0x1000 + 97: return wxT("LVM_INSERTCOLUMNW"); 
6203         case 0x1000 + 28: return wxT("LVM_DELETECOLUMN"); 
6204         case 0x1000 + 29: return wxT("LVM_GETCOLUMNWIDTH"); 
6205         case 0x1000 + 30: return wxT("LVM_SETCOLUMNWIDTH"); 
6206         case 0x1000 + 31: return wxT("LVM_GETHEADER"); 
6207         case 0x1000 + 33: return wxT("LVM_CREATEDRAGIMAGE"); 
6208         case 0x1000 + 34: return wxT("LVM_GETVIEWRECT"); 
6209         case 0x1000 + 35: return wxT("LVM_GETTEXTCOLOR"); 
6210         case 0x1000 + 36: return wxT("LVM_SETTEXTCOLOR"); 
6211         case 0x1000 + 37: return wxT("LVM_GETTEXTBKCOLOR"); 
6212         case 0x1000 + 38: return wxT("LVM_SETTEXTBKCOLOR"); 
6213         case 0x1000 + 39: return wxT("LVM_GETTOPINDEX"); 
6214         case 0x1000 + 40: return wxT("LVM_GETCOUNTPERPAGE"); 
6215         case 0x1000 + 41: return wxT("LVM_GETORIGIN"); 
6216         case 0x1000 + 42: return wxT("LVM_UPDATE"); 
6217         case 0x1000 + 43: return wxT("LVM_SETITEMSTATE"); 
6218         case 0x1000 + 44: return wxT("LVM_GETITEMSTATE"); 
6219         case 0x1000 + 45: return wxT("LVM_GETITEMTEXTA"); 
6220         case 0x1000 + 115: return wxT("LVM_GETITEMTEXTW"); 
6221         case 0x1000 + 46: return wxT("LVM_SETITEMTEXTA"); 
6222         case 0x1000 + 116: return wxT("LVM_SETITEMTEXTW"); 
6223         case 0x1000 + 47: return wxT("LVM_SETITEMCOUNT"); 
6224         case 0x1000 + 48: return wxT("LVM_SORTITEMS"); 
6225         case 0x1000 + 49: return wxT("LVM_SETITEMPOSITION32"); 
6226         case 0x1000 + 50: return wxT("LVM_GETSELECTEDCOUNT"); 
6227         case 0x1000 + 51: return wxT("LVM_GETITEMSPACING"); 
6228         case 0x1000 + 52: return wxT("LVM_GETISEARCHSTRINGA"); 
6229         case 0x1000 + 117: return wxT("LVM_GETISEARCHSTRINGW"); 
6230         case 0x1000 + 53: return wxT("LVM_SETICONSPACING"); 
6231         case 0x1000 + 54: return wxT("LVM_SETEXTENDEDLISTVIEWSTYLE"); 
6232         case 0x1000 + 55: return wxT("LVM_GETEXTENDEDLISTVIEWSTYLE"); 
6233         case 0x1000 + 56: return wxT("LVM_GETSUBITEMRECT"); 
6234         case 0x1000 + 57: return wxT("LVM_SUBITEMHITTEST"); 
6235         case 0x1000 + 58: return wxT("LVM_SETCOLUMNORDERARRAY"); 
6236         case 0x1000 + 59: return wxT("LVM_GETCOLUMNORDERARRAY"); 
6237         case 0x1000 + 60: return wxT("LVM_SETHOTITEM"); 
6238         case 0x1000 + 61: return wxT("LVM_GETHOTITEM"); 
6239         case 0x1000 + 62: return wxT("LVM_SETHOTCURSOR"); 
6240         case 0x1000 + 63: return wxT("LVM_GETHOTCURSOR"); 
6241         case 0x1000 + 64: return wxT("LVM_APPROXIMATEVIEWRECT"); 
6242         case 0x1000 + 65: return wxT("LVM_SETWORKAREA"); 
6245         case 0x1100 + 0: return wxT("TVM_INSERTITEMA"); 
6246         case 0x1100 + 50: return wxT("TVM_INSERTITEMW"); 
6247         case 0x1100 + 1: return wxT("TVM_DELETEITEM"); 
6248         case 0x1100 + 2: return wxT("TVM_EXPAND"); 
6249         case 0x1100 + 4: return wxT("TVM_GETITEMRECT"); 
6250         case 0x1100 + 5: return wxT("TVM_GETCOUNT"); 
6251         case 0x1100 + 6: return wxT("TVM_GETINDENT"); 
6252         case 0x1100 + 7: return wxT("TVM_SETINDENT"); 
6253         case 0x1100 + 8: return wxT("TVM_GETIMAGELIST"); 
6254         case 0x1100 + 9: return wxT("TVM_SETIMAGELIST"); 
6255         case 0x1100 + 10: return wxT("TVM_GETNEXTITEM"); 
6256         case 0x1100 + 11: return wxT("TVM_SELECTITEM"); 
6257         case 0x1100 + 12: return wxT("TVM_GETITEMA"); 
6258         case 0x1100 + 62: return wxT("TVM_GETITEMW"); 
6259         case 0x1100 + 13: return wxT("TVM_SETITEMA"); 
6260         case 0x1100 + 63: return wxT("TVM_SETITEMW"); 
6261         case 0x1100 + 14: return wxT("TVM_EDITLABELA"); 
6262         case 0x1100 + 65: return wxT("TVM_EDITLABELW"); 
6263         case 0x1100 + 15: return wxT("TVM_GETEDITCONTROL"); 
6264         case 0x1100 + 16: return wxT("TVM_GETVISIBLECOUNT"); 
6265         case 0x1100 + 17: return wxT("TVM_HITTEST"); 
6266         case 0x1100 + 18: return wxT("TVM_CREATEDRAGIMAGE"); 
6267         case 0x1100 + 19: return wxT("TVM_SORTCHILDREN"); 
6268         case 0x1100 + 20: return wxT("TVM_ENSUREVISIBLE"); 
6269         case 0x1100 + 21: return wxT("TVM_SORTCHILDRENCB"); 
6270         case 0x1100 + 22: return wxT("TVM_ENDEDITLABELNOW"); 
6271         case 0x1100 + 23: return wxT("TVM_GETISEARCHSTRINGA"); 
6272         case 0x1100 + 64: return wxT("TVM_GETISEARCHSTRINGW"); 
6273         case 0x1100 + 24: return wxT("TVM_SETTOOLTIPS"); 
6274         case 0x1100 + 25: return wxT("TVM_GETTOOLTIPS"); 
6277         case 0x1200 + 0: return wxT("HDM_GETITEMCOUNT"); 
6278         case 0x1200 + 1: return wxT("HDM_INSERTITEMA"); 
6279         case 0x1200 + 10: return wxT("HDM_INSERTITEMW"); 
6280         case 0x1200 + 2: return wxT("HDM_DELETEITEM"); 
6281         case 0x1200 + 3: return wxT("HDM_GETITEMA"); 
6282         case 0x1200 + 11: return wxT("HDM_GETITEMW"); 
6283         case 0x1200 + 4: return wxT("HDM_SETITEMA"); 
6284         case 0x1200 + 12: return wxT("HDM_SETITEMW"); 
6285         case 0x1200 + 5: return wxT("HDM_LAYOUT"); 
6286         case 0x1200 + 6: return wxT("HDM_HITTEST"); 
6287         case 0x1200 + 7: return wxT("HDM_GETITEMRECT"); 
6288         case 0x1200 + 8: return wxT("HDM_SETIMAGELIST"); 
6289         case 0x1200 + 9: return wxT("HDM_GETIMAGELIST"); 
6290         case 0x1200 + 15: return wxT("HDM_ORDERTOINDEX"); 
6291         case 0x1200 + 16: return wxT("HDM_CREATEDRAGIMAGE"); 
6292         case 0x1200 + 17: return wxT("HDM_GETORDERARRAY"); 
6293         case 0x1200 + 18: return wxT("HDM_SETORDERARRAY"); 
6294         case 0x1200 + 19: return wxT("HDM_SETHOTDIVIDER"); 
6297         case 0x1300 + 2: return wxT("TCM_GETIMAGELIST"); 
6298         case 0x1300 + 3: return wxT("TCM_SETIMAGELIST"); 
6299         case 0x1300 + 4: return wxT("TCM_GETITEMCOUNT"); 
6300         case 0x1300 + 5: return wxT("TCM_GETITEMA"); 
6301         case 0x1300 + 60: return wxT("TCM_GETITEMW"); 
6302         case 0x1300 + 6: return wxT("TCM_SETITEMA"); 
6303         case 0x1300 + 61: return wxT("TCM_SETITEMW"); 
6304         case 0x1300 + 7: return wxT("TCM_INSERTITEMA"); 
6305         case 0x1300 + 62: return wxT("TCM_INSERTITEMW"); 
6306         case 0x1300 + 8: return wxT("TCM_DELETEITEM"); 
6307         case 0x1300 + 9: return wxT("TCM_DELETEALLITEMS"); 
6308         case 0x1300 + 10: return wxT("TCM_GETITEMRECT"); 
6309         case 0x1300 + 11: return wxT("TCM_GETCURSEL"); 
6310         case 0x1300 + 12: return wxT("TCM_SETCURSEL"); 
6311         case 0x1300 + 13: return wxT("TCM_HITTEST"); 
6312         case 0x1300 + 14: return wxT("TCM_SETITEMEXTRA"); 
6313         case 0x1300 + 40: return wxT("TCM_ADJUSTRECT"); 
6314         case 0x1300 + 41: return wxT("TCM_SETITEMSIZE"); 
6315         case 0x1300 + 42: return wxT("TCM_REMOVEIMAGE"); 
6316         case 0x1300 + 43: return wxT("TCM_SETPADDING"); 
6317         case 0x1300 + 44: return wxT("TCM_GETROWCOUNT"); 
6318         case 0x1300 + 45: return wxT("TCM_GETTOOLTIPS"); 
6319         case 0x1300 + 46: return wxT("TCM_SETTOOLTIPS"); 
6320         case 0x1300 + 47: return wxT("TCM_GETCURFOCUS"); 
6321         case 0x1300 + 48: return wxT("TCM_SETCURFOCUS"); 
6322         case 0x1300 + 49: return wxT("TCM_SETMINTABWIDTH"); 
6323         case 0x1300 + 50: return wxT("TCM_DESELECTALL"); 
6326         case WM_USER
+1: return wxT("TB_ENABLEBUTTON"); 
6327         case WM_USER
+2: return wxT("TB_CHECKBUTTON"); 
6328         case WM_USER
+3: return wxT("TB_PRESSBUTTON"); 
6329         case WM_USER
+4: return wxT("TB_HIDEBUTTON"); 
6330         case WM_USER
+5: return wxT("TB_INDETERMINATE"); 
6331         case WM_USER
+9: return wxT("TB_ISBUTTONENABLED"); 
6332         case WM_USER
+10: return wxT("TB_ISBUTTONCHECKED"); 
6333         case WM_USER
+11: return wxT("TB_ISBUTTONPRESSED"); 
6334         case WM_USER
+12: return wxT("TB_ISBUTTONHIDDEN"); 
6335         case WM_USER
+13: return wxT("TB_ISBUTTONINDETERMINATE"); 
6336         case WM_USER
+17: return wxT("TB_SETSTATE"); 
6337         case WM_USER
+18: return wxT("TB_GETSTATE"); 
6338         case WM_USER
+19: return wxT("TB_ADDBITMAP"); 
6339         case WM_USER
+20: return wxT("TB_ADDBUTTONS"); 
6340         case WM_USER
+21: return wxT("TB_INSERTBUTTON"); 
6341         case WM_USER
+22: return wxT("TB_DELETEBUTTON"); 
6342         case WM_USER
+23: return wxT("TB_GETBUTTON"); 
6343         case WM_USER
+24: return wxT("TB_BUTTONCOUNT"); 
6344         case WM_USER
+25: return wxT("TB_COMMANDTOINDEX"); 
6345         case WM_USER
+26: return wxT("TB_SAVERESTOREA"); 
6346         case WM_USER
+76: return wxT("TB_SAVERESTOREW"); 
6347         case WM_USER
+27: return wxT("TB_CUSTOMIZE"); 
6348         case WM_USER
+28: return wxT("TB_ADDSTRINGA"); 
6349         case WM_USER
+77: return wxT("TB_ADDSTRINGW"); 
6350         case WM_USER
+29: return wxT("TB_GETITEMRECT"); 
6351         case WM_USER
+30: return wxT("TB_BUTTONSTRUCTSIZE"); 
6352         case WM_USER
+31: return wxT("TB_SETBUTTONSIZE"); 
6353         case WM_USER
+32: return wxT("TB_SETBITMAPSIZE"); 
6354         case WM_USER
+33: return wxT("TB_AUTOSIZE"); 
6355         case WM_USER
+35: return wxT("TB_GETTOOLTIPS"); 
6356         case WM_USER
+36: return wxT("TB_SETTOOLTIPS"); 
6357         case WM_USER
+37: return wxT("TB_SETPARENT"); 
6358         case WM_USER
+39: return wxT("TB_SETROWS"); 
6359         case WM_USER
+40: return wxT("TB_GETROWS"); 
6360         case WM_USER
+42: return wxT("TB_SETCMDID"); 
6361         case WM_USER
+43: return wxT("TB_CHANGEBITMAP"); 
6362         case WM_USER
+44: return wxT("TB_GETBITMAP"); 
6363         case WM_USER
+45: return wxT("TB_GETBUTTONTEXTA"); 
6364         case WM_USER
+75: return wxT("TB_GETBUTTONTEXTW"); 
6365         case WM_USER
+46: return wxT("TB_REPLACEBITMAP"); 
6366         case WM_USER
+47: return wxT("TB_SETINDENT"); 
6367         case WM_USER
+48: return wxT("TB_SETIMAGELIST"); 
6368         case WM_USER
+49: return wxT("TB_GETIMAGELIST"); 
6369         case WM_USER
+50: return wxT("TB_LOADIMAGES"); 
6370         case WM_USER
+51: return wxT("TB_GETRECT"); 
6371         case WM_USER
+52: return wxT("TB_SETHOTIMAGELIST"); 
6372         case WM_USER
+53: return wxT("TB_GETHOTIMAGELIST"); 
6373         case WM_USER
+54: return wxT("TB_SETDISABLEDIMAGELIST"); 
6374         case WM_USER
+55: return wxT("TB_GETDISABLEDIMAGELIST"); 
6375         case WM_USER
+56: return wxT("TB_SETSTYLE"); 
6376         case WM_USER
+57: return wxT("TB_GETSTYLE"); 
6377         case WM_USER
+58: return wxT("TB_GETBUTTONSIZE"); 
6378         case WM_USER
+59: return wxT("TB_SETBUTTONWIDTH"); 
6379         case WM_USER
+60: return wxT("TB_SETMAXTEXTROWS"); 
6380         case WM_USER
+61: return wxT("TB_GETTEXTROWS"); 
6381         case WM_USER
+41: return wxT("TB_GETBITMAPFLAGS"); 
6384             static wxString s_szBuf
; 
6385             s_szBuf
.Printf(wxT("<unknown message = %d>"), message
); 
6386             return s_szBuf
.c_str(); 
6389 #endif //__WXDEBUG__ 
6391 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
) 
6395     HWND hwnd 
= GetHwndOf(win
); 
6396     HDC hdc 
= ::GetDC(hwnd
); 
6398 #if !wxDIALOG_UNIT_COMPATIBILITY 
6399     // and select the current font into it 
6400     HFONT hfont 
= GetHfontOf(win
->GetFont()); 
6403         hfont 
= (HFONT
)::SelectObject(hdc
, hfont
); 
6407     // finally retrieve the text metrics from it 
6408     GetTextMetrics(hdc
, &tm
); 
6410 #if !wxDIALOG_UNIT_COMPATIBILITY 
6414         (void)::SelectObject(hdc
, hfont
); 
6418     ::ReleaseDC(hwnd
, hdc
); 
6423 // Find the wxWindow at the current mouse position, returning the mouse 
6425 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
6427     pt 
= wxGetMousePosition(); 
6428     return wxFindWindowAtPoint(pt
); 
6431 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
6437     HWND hWnd 
= ::WindowFromPoint(pt2
); 
6439     return wxGetWindowFromHWND((WXHWND
)hWnd
); 
6442 // Get the current mouse position. 
6443 wxPoint 
wxGetMousePosition() 
6447     GetCursorPosWinCE(&pt
); 
6449     GetCursorPos( & pt 
); 
6452     return wxPoint(pt
.x
, pt
.y
); 
6457 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
6458 static void WinCEUnregisterHotKey(int modifiers
, int id
) 
6460     // Register hotkeys for the hardware buttons 
6462     typedef BOOL (WINAPI 
*UnregisterFunc1Proc
)(UINT
, UINT
); 
6464     UnregisterFunc1Proc procUnregisterFunc
; 
6465     hCoreDll 
= LoadLibrary(_T("coredll.dll")); 
6468         procUnregisterFunc 
= (UnregisterFunc1Proc
)GetProcAddress(hCoreDll
, _T("UnregisterFunc1")); 
6469         if (procUnregisterFunc
) 
6470             procUnregisterFunc(modifiers
, id
); 
6471         FreeLibrary(hCoreDll
); 
6476 bool wxWindowMSW::RegisterHotKey(int hotkeyId
, int modifiers
, int keycode
) 
6478     UINT win_modifiers
=0; 
6479     if ( modifiers 
& wxMOD_ALT 
) 
6480         win_modifiers 
|= MOD_ALT
; 
6481     if ( modifiers 
& wxMOD_SHIFT 
) 
6482         win_modifiers 
|= MOD_SHIFT
; 
6483     if ( modifiers 
& wxMOD_CONTROL 
) 
6484         win_modifiers 
|= MOD_CONTROL
; 
6485     if ( modifiers 
& wxMOD_WIN 
) 
6486         win_modifiers 
|= MOD_WIN
; 
6488 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
6489     // Required for PPC and Smartphone hardware buttons 
6490     if (keycode 
>= WXK_SPECIAL1 
&& keycode 
<= WXK_SPECIAL20
) 
6491         WinCEUnregisterHotKey(win_modifiers
, hotkeyId
); 
6494     if ( !::RegisterHotKey(GetHwnd(), hotkeyId
, win_modifiers
, keycode
) ) 
6496         wxLogLastError(_T("RegisterHotKey")); 
6504 bool wxWindowMSW::UnregisterHotKey(int hotkeyId
) 
6506 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
6507     WinCEUnregisterHotKey(MOD_WIN
, hotkeyId
); 
6510     if ( !::UnregisterHotKey(GetHwnd(), hotkeyId
) ) 
6512         wxLogLastError(_T("UnregisterHotKey")); 
6522 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam
, WXLPARAM lParam
) 
6524     int hotkeyId 
= wParam
; 
6525     int virtualKey 
= HIWORD(lParam
); 
6526     int win_modifiers 
= LOWORD(lParam
); 
6528     wxKeyEvent 
event(CreateKeyEvent(wxEVT_HOTKEY
, virtualKey
, wParam
, lParam
)); 
6529     event
.SetId(hotkeyId
); 
6530     event
.m_shiftDown 
= (win_modifiers 
& MOD_SHIFT
) != 0; 
6531     event
.m_controlDown 
= (win_modifiers 
& MOD_CONTROL
) != 0; 
6532     event
.m_altDown 
= (win_modifiers 
& MOD_ALT
) != 0; 
6533     event
.m_metaDown 
= (win_modifiers 
& MOD_WIN
) != 0; 
6535     return GetEventHandler()->ProcessEvent(event
); 
6538 #endif // wxUSE_ACCEL 
6540 #endif // wxUSE_HOTKEY 
6542 // Not tested under WinCE 
6545 // this class installs a message hook which really wakes up our idle processing 
6546 // each time a WM_NULL is received (wxWakeUpIdle does this), even if we're 
6547 // sitting inside a local modal loop (e.g. a menu is opened or scrollbar is 
6548 // being dragged or even inside ::MessageBox()) and so don't control message 
6549 // dispatching otherwise 
6550 class wxIdleWakeUpModule 
: public wxModule
 
6553     virtual bool OnInit() 
6555         ms_hMsgHookProc 
= ::SetWindowsHookEx
 
6558                              &wxIdleWakeUpModule::MsgHookProc
, 
6560                              GetCurrentThreadId() 
6563         if ( !ms_hMsgHookProc 
) 
6565             wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)")); 
6573     virtual void OnExit() 
6575         ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc
); 
6578     static LRESULT CALLBACK 
MsgHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
) 
6580         MSG 
*msg 
= (MSG
*)lParam
; 
6582         // only process the message if it is actually going to be removed from 
6583         // the message queue, this prevents that the same event from being 
6584         // processed multiple times if now someone just called PeekMessage() 
6585         if ( msg
->message 
== WM_NULL 
&& wParam 
== PM_REMOVE 
) 
6587             wxTheApp
->ProcessPendingEvents(); 
6590         return CallNextHookEx(ms_hMsgHookProc
, nCode
, wParam
, lParam
); 
6594     static HHOOK ms_hMsgHookProc
; 
6596     DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule
) 
6599 HHOOK 
wxIdleWakeUpModule::ms_hMsgHookProc 
= 0; 
6601 IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule
, wxModule
) 
6603 #endif // __WXWINCE__ 
6608 static void wxAdjustZOrder(wxWindow
* parent
) 
6610     if (parent
->IsKindOf(CLASSINFO(wxStaticBox
))) 
6612         // Set the z-order correctly 
6613         SetWindowPos((HWND
) parent
->GetHWND(), HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
); 
6616     wxWindowList::compatibility_iterator current 
= parent
->GetChildren().GetFirst(); 
6619         wxWindow 
*childWin 
= current
->GetData(); 
6620         wxAdjustZOrder(childWin
); 
6621         current 
= current
->GetNext(); 
6626 // We need to adjust the z-order of static boxes in WinCE, to 
6627 // make 'contained' controls visible 
6628 void wxWindowMSW::OnInitDialog( wxInitDialogEvent
& event 
) 
6631     wxAdjustZOrder(this);