1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/windows.cpp 
   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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "window.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  32     #include "wx/msw/wrapwin.h" 
  33     #include "wx/window.h" 
  38     #include "wx/dcclient.h" 
  39     #include "wx/dcmemory.h" 
  42     #include "wx/layout.h" 
  43     #include "wx/dialog.h" 
  45     #include "wx/listbox.h" 
  46     #include "wx/button.h" 
  47     #include "wx/msgdlg.h" 
  48     #include "wx/settings.h" 
  49     #include "wx/statbox.h" 
  52 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__) 
  53     #include "wx/ownerdrw.h" 
  56 #if wxUSE_DRAG_AND_DROP 
  60 #if wxUSE_ACCESSIBILITY 
  61     #include "wx/access.h" 
  65         #define WM_GETOBJECT 0x003D 
  68         #define OBJID_CLIENT 0xFFFFFFFC 
  72 #include "wx/menuitem.h" 
  75 #include "wx/msw/private.h" 
  78     #include "wx/tooltip.h" 
  86     #include "wx/spinctrl.h" 
  87 #endif // wxUSE_SPINCTRL 
  92 #include "wx/textctrl.h" 
  93 #include "wx/notebook.h" 
  94 #include "wx/listctrl.h" 
  98 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__) 
 100     #include <mmsystem.h> 
 104     #include <windowsx.h> 
 107 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__) 
 109         #include <commctrl.h> 
 111 #elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler 
 112     #include "wx/msw/gnuwin32/extra.h" 
 115 #if defined(__GNUG__) 
 116 #include "wx/msw/missing.h" 
 119 #if defined(__WXWINCE__) 
 120 #include "wx/msw/wince/missing.h" 
 123 // ---------------------------------------------------------------------------- 
 124 // standard constants not available with all compilers/headers 
 125 // ---------------------------------------------------------------------------- 
 127 // This didn't appear in mingw until 2.95.2 
 129 #define SIF_TRACKPOS 16 
 133     #ifndef WM_MOUSEWHEEL 
 134         #define WM_MOUSEWHEEL           0x020A 
 137         #define WHEEL_DELTA             120 
 139     #ifndef SPI_GETWHEELSCROLLLINES 
 140         #define SPI_GETWHEELSCROLLLINES 104 
 142 #endif // wxUSE_MOUSEWHEEL 
 145     #define VK_OEM_1        0xBA 
 146     #define VK_OEM_2        0xBF 
 147     #define VK_OEM_3        0xC0 
 148     #define VK_OEM_4        0xDB 
 149     #define VK_OEM_5        0xDC 
 150     #define VK_OEM_6        0xDD 
 151     #define VK_OEM_7        0xDE 
 155     #define VK_OEM_PLUS     0xBB 
 156     #define VK_OEM_COMMA    0xBC 
 157     #define VK_OEM_MINUS    0xBD 
 158     #define VK_OEM_PERIOD   0xBE 
 161 // --------------------------------------------------------------------------- 
 163 // --------------------------------------------------------------------------- 
 165 #if wxUSE_MENUS_NATIVE 
 166 wxMenu 
*wxCurrentPopupMenu 
= NULL
; 
 167 #endif // wxUSE_MENUS_NATIVE 
 169 extern const wxChar 
*wxCanvasClassName
; 
 171 // true if we had already created the std colour map, used by 
 172 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT) 
 173 static bool gs_hasStdCmap 
= FALSE
; 
 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 char *wxGetMessageName(int message
); 
 188 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 189 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 190 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
); 
 192 // this magical function is used to translate VK_APPS key presses to right 
 194 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
 195                                      int *x
, int *y
, WPARAM 
*flags
); 
 197 // get the text metrics for the current font 
 198 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
); 
 200 // find the window for the mouse event at the specified position 
 201 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
); //TW:REQ:Univ 
 203 // wrapper around BringWindowToTop() API 
 204 static inline void wxBringWindowToTop(HWND hwnd
) 
 206 #ifdef __WXMICROWIN__ 
 207     // It seems that MicroWindows brings the _parent_ of the window to the top, 
 208     // which can be the wrong one. 
 210     // activate (set focus to) specified window 
 214     // raise top level parent to top of z order 
 215     if (!::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE 
| SWP_NOSIZE
)) 
 217         wxLogLastError(_T("SetWindowPos")); 
 221 // ensure that all our parent windows have WS_EX_CONTROLPARENT style 
 222 static void EnsureParentHasControlParentStyle(wxWindow 
*parent
) 
 225        If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our 
 226        parent as well as otherwise several Win32 functions using 
 227        GetNextDlgTabItem() to iterate over all controls such as 
 228        IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, 
 229        all of them iterate over all the controls starting from the currently 
 230        focused one and stop iterating when they get back to the focus but 
 231        unless all parents have WS_EX_CONTROLPARENT bit set, they would never 
 232        get back to the initial (focused) window: as we do have this style, 
 233        GetNextDlgTabItem() will leave this window and continue in its parent, 
 234        but if the parent doesn't have it, it wouldn't recurse inside it later 
 235        on and so wouldn't have a chance of getting back to this window neither. 
 238     while ( parent 
&& !parent
->IsTopLevel() ) 
 240         LONG exStyle 
= ::GetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
); 
 241         if ( !(exStyle 
& WS_EX_CONTROLPARENT
) ) 
 243             // force the parent to have this style 
 244             ::SetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
, 
 245                             exStyle 
| WS_EX_CONTROLPARENT
); 
 248         parent 
= parent
->GetParent(); 
 250 #endif // !__WXWINCE__ 
 253 // --------------------------------------------------------------------------- 
 255 // --------------------------------------------------------------------------- 
 257 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
 259 #ifdef __WXUNIVERSAL__ 
 260     IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
) 
 262 #if wxUSE_EXTENDED_RTTI 
 264 // windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls 
 265 // must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as 
 266 // windows with negative ids never can be recreated anyway 
 268 bool wxWindowStreamingCallback( const wxObject 
*object
, wxWriter 
* , wxPersister 
* , wxxVariantArray 
& ) 
 270     const wxWindow 
* win 
= dynamic_cast<const wxWindow
*>(object
) ; 
 271     if ( win 
&& win
->GetId() < 0 ) 
 276 IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow
, wxWindowBase
,"wx/window.h", wxWindowStreamingCallback
) 
 278 // make wxWindowList known before the property is used 
 280 wxCOLLECTION_TYPE_INFO( wxWindow
* , wxWindowList 
) ; 
 282 template<> void wxCollectionToVariantArray( wxWindowList 
const &theList
, wxxVariantArray 
&value
) 
 284     wxListCollectionToVariantArray
<wxWindowList::compatibility_iterator
>( theList 
, value 
) ; 
 287 WX_DEFINE_FLAGS( wxWindowStyle 
) 
 289 wxBEGIN_FLAGS( wxWindowStyle 
) 
 290     // new style border flags, we put them first to 
 291     // use them for streaming out 
 293     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
 294     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
 295     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
 296     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
 297     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
 298     wxFLAGS_MEMBER(wxBORDER_NONE
) 
 300     // old style border flags 
 301     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
 302     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
 303     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
 304     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
 305     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
 306     wxFLAGS_MEMBER(wxNO_BORDER
) 
 308     // standard window styles 
 309     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
 310     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
 311     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
 312     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
 313     wxFLAGS_MEMBER(wxNO_FULL_REPAINT_ON_RESIZE
) 
 314     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
 315     wxFLAGS_MEMBER(wxVSCROLL
) 
 316     wxFLAGS_MEMBER(wxHSCROLL
) 
 318 wxEND_FLAGS( wxWindowStyle 
) 
 320 wxBEGIN_PROPERTIES_TABLE(wxWindow
) 
 321         wxEVENT_PROPERTY( Close 
, wxEVT_CLOSE_WINDOW 
, wxCloseEvent
) 
 322         wxEVENT_PROPERTY( Create 
, wxEVT_CREATE 
, wxWindowCreateEvent 
) 
 323         wxEVENT_PROPERTY( Destroy 
, wxEVT_DESTROY 
, wxWindowDestroyEvent 
) 
 324     // Always constructor Properties first 
 326     wxREADONLY_PROPERTY( Parent
,wxWindow
*, GetParent
,  , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 327         wxPROPERTY( Id
,wxWindowID
, SetId
, GetId
, -1, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
 328         wxPROPERTY( Position
,wxPoint
, SetPosition 
, GetPosition
, wxPoint(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos 
 329         wxPROPERTY( Size
,wxSize
, SetSize
, GetSize
, wxSize(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size 
 330     wxPROPERTY( WindowStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
 332     // Then all relations of the object graph 
 334     wxREADONLY_PROPERTY_COLLECTION( Children 
, wxWindowList 
, wxWindowBase
* , GetWindowChildren 
, wxPROP_OBJECT_GRAPH 
/*flags*/ , wxT("Helpstring") , wxT("group")) 
 336    // and finally all other properties 
 338         wxPROPERTY( ExtraStyle 
, long , SetExtraStyle 
, GetExtraStyle 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle 
 339         wxPROPERTY( BackgroundColour 
, wxColour 
, SetBackgroundColour 
, GetBackgroundColour 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg 
 340         wxPROPERTY( ForegroundColour 
, wxColour 
, SetForegroundColour 
, GetForegroundColour 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg 
 341         wxPROPERTY( Enabled 
, bool , Enable 
, IsEnabled 
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 342         wxPROPERTY( Shown 
, bool , Show 
, IsShown 
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 344     // possible property candidates (not in xrc) or not valid in all subclasses 
 345         wxPROPERTY( Title
,wxString
, SetTitle
, GetTitle
, wxT("") ) 
 346         wxPROPERTY( Font 
, wxFont 
, SetFont 
, GetWindowFont  
, ) 
 347         wxPROPERTY( Label
,wxString
, SetLabel
, GetLabel
, wxT("") ) 
 348         // MaxHeight, Width , MinHeight , Width 
 349         // TODO switch label to control and title to toplevels 
 351         wxPROPERTY( ThemeEnabled 
, bool , SetThemeEnabled 
, GetThemeEnabled 
, ) 
 352         //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , ) 
 353         // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , ) 
 354         wxPROPERTY( AutoLayout 
, bool , SetAutoLayout 
, GetAutoLayout 
, ) 
 359 wxEND_PROPERTIES_TABLE() 
 361 wxBEGIN_HANDLERS_TABLE(wxWindow
) 
 362 wxEND_HANDLERS_TABLE() 
 364 wxCONSTRUCTOR_DUMMY(wxWindow
) 
 367     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
 369 #endif // __WXUNIVERSAL__/__WXMSW__ 
 371 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
) 
 372     EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
) 
 373     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
) 
 374     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
) 
 377 // =========================================================================== 
 379 // =========================================================================== 
 381 // --------------------------------------------------------------------------- 
 382 // wxWindow utility functions 
 383 // --------------------------------------------------------------------------- 
 385 // Find an item given the MS Windows id 
 386 wxWindow 
*wxWindowMSW::FindItem(long id
) const 
 389     wxControl 
*item 
= wxDynamicCastThis(wxControl
); 
 392         // is it we or one of our "internal" children? 
 393         if ( item
->GetId() == id
 
 394 #ifndef __WXUNIVERSAL__ 
 395                 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
) 
 396 #endif // __WXUNIVERSAL__ 
 402 #endif // wxUSE_CONTROLS 
 404     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 407         wxWindow 
*childWin 
= current
->GetData(); 
 409         wxWindow 
*wnd 
= childWin
->FindItem(id
); 
 413         current 
= current
->GetNext(); 
 419 // Find an item given the MS Windows handle 
 420 wxWindow 
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const 
 422     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 425         wxWindow 
*parent 
= current
->GetData(); 
 427         // Do a recursive search. 
 428         wxWindow 
*wnd 
= parent
->FindItemByHWND(hWnd
); 
 434                 || parent
->IsKindOf(CLASSINFO(wxControl
)) 
 435 #endif // wxUSE_CONTROLS 
 438             wxWindow 
*item 
= current
->GetData(); 
 439             if ( item
->GetHWND() == hWnd 
) 
 443                 if ( item
->ContainsHWND(hWnd
) ) 
 448         current 
= current
->GetNext(); 
 453 // Default command handler 
 454 bool wxWindowMSW::MSWCommand(WXUINT 
WXUNUSED(param
), WXWORD 
WXUNUSED(id
)) 
 459 // ---------------------------------------------------------------------------- 
 460 // constructors and such 
 461 // ---------------------------------------------------------------------------- 
 463 void wxWindowMSW::Init() 
 469     m_isBeingDeleted 
= FALSE
; 
 471     m_mouseInWindow 
= FALSE
; 
 472     m_lastKeydownProcessed 
= FALSE
; 
 474     m_childrenDisabled 
= NULL
; 
 484     // as all windows are created with WS_VISIBLE style... 
 487 #if wxUSE_MOUSEEVENT_HACK 
 490     m_lastMouseEvent 
= -1; 
 491 #endif // wxUSE_MOUSEEVENT_HACK 
 495 wxWindowMSW::~wxWindowMSW() 
 497     m_isBeingDeleted 
= TRUE
; 
 499 #ifndef __WXUNIVERSAL__ 
 500     // VS: make sure there's no wxFrame with last focus set to us: 
 501     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
 503         wxTopLevelWindow 
*frame 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 506             if ( frame
->GetLastFocus() == this ) 
 508                 frame
->SetLastFocus(NULL
); 
 513 #endif // __WXUNIVERSAL__ 
 515     // VS: destroy children first and _then_ detach *this from its parent. 
 516     //     If we'd do it the other way around, children wouldn't be able 
 517     //     find their parent frame (see above). 
 522         // VZ: test temp removed to understand what really happens here 
 523         //if (::IsWindow(GetHwnd())) 
 525             if ( !::DestroyWindow(GetHwnd()) ) 
 526                 wxLogLastError(wxT("DestroyWindow")); 
 529         // remove hWnd <-> wxWindow association 
 530         wxRemoveHandleAssociation(this); 
 533     delete m_childrenDisabled
; 
 536 // real construction (Init() must have been called before!) 
 537 bool wxWindowMSW::Create(wxWindow 
*parent
, 
 542                          const wxString
& name
) 
 544     wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") ); 
 546     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 549     parent
->AddChild(this); 
 552     DWORD msflags 
= MSWGetCreateWindowFlags(&exstyle
); 
 554 #ifdef __WXUNIVERSAL__ 
 555     // no borders, we draw them ourselves 
 556     exstyle 
&= ~(WS_EX_DLGMODALFRAME 
| 
 560     msflags 
&= ~WS_BORDER
; 
 561 #endif // wxUniversal 
 563     // all windows are created visible by default except popup ones (which are 
 564     // like the wxTopLevelWindows in this aspect) 
 565     if ( style 
& wxPOPUP_WINDOW 
) 
 567         msflags 
&= ~WS_VISIBLE
; 
 572         msflags 
|= WS_VISIBLE
; 
 575     return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
); 
 578 // --------------------------------------------------------------------------- 
 580 // --------------------------------------------------------------------------- 
 582 void wxWindowMSW::SetFocus() 
 584     HWND hWnd 
= GetHwnd(); 
 585     wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") ); 
 587 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
 591     if ( !::SetFocus(hWnd
) ) 
 593 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__) 
 594         // was there really an error? 
 595         DWORD dwRes 
= ::GetLastError(); 
 598             HWND hwndFocus 
= ::GetFocus(); 
 599             if ( hwndFocus 
!= hWnd 
) 
 601                 wxLogApiError(_T("SetFocus"), dwRes
); 
 608 void wxWindowMSW::SetFocusFromKbd() 
 610     // when the focus is given to the control with DLGC_HASSETSEL style from 
 611     // keyboard its contents should be entirely selected: this is what 
 612     // ::IsDialogMessage() does and so we should do it as well to provide the 
 613     // same LNF as the native programs 
 614     if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL 
) 
 616         ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1); 
 619     // do this after (maybe) setting the selection as like this when 
 620     // wxEVT_SET_FOCUS handler is called, the selection would have been already 
 621     // set correctly -- this may be important 
 622     wxWindowBase::SetFocusFromKbd(); 
 625 // Get the window with the focus 
 626 wxWindow 
*wxWindowBase::FindFocus() 
 628     HWND hWnd 
= ::GetFocus(); 
 631         return wxGetWindowFromHWND((WXHWND
)hWnd
); 
 637 bool wxWindowMSW::Enable(bool enable
) 
 639     if ( !wxWindowBase::Enable(enable
) ) 
 642     HWND hWnd 
= GetHwnd(); 
 644         ::EnableWindow(hWnd
, (BOOL
)enable
); 
 646     // the logic below doesn't apply to the top level windows -- otherwise 
 647     // showing a modal dialog would result in total greying out (and ungreying 
 648     // out later) of everything which would be really ugly 
 652     // when the parent is disabled, all of its children should be disabled as 
 653     // well but when it is enabled back, only those of the children which 
 654     // hadn't been already disabled in the beginning should be enabled again, 
 655     // so we have to keep the list of those children 
 656     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
 658           node 
= node
->GetNext() ) 
 660         wxWindow 
*child 
= node
->GetData(); 
 661         if ( child
->IsTopLevel() ) 
 663             // the logic below doesn't apply to top level children 
 669             // enable the child back unless it had been disabled before us 
 670             if ( !m_childrenDisabled 
|| !m_childrenDisabled
->Find(child
) ) 
 673         else // we're being disabled 
 675             if ( child
->IsEnabled() ) 
 677                 // disable it as children shouldn't stay enabled while the 
 681             else // child already disabled, remember it 
 683                 // have we created the list of disabled children already? 
 684                 if ( !m_childrenDisabled 
) 
 685                     m_childrenDisabled 
= new wxWindowList
; 
 687                 m_childrenDisabled
->Append(child
); 
 692     if ( enable 
&& m_childrenDisabled 
) 
 694         // we don't need this list any more, don't keep unused memory 
 695         delete m_childrenDisabled
; 
 696         m_childrenDisabled 
= NULL
; 
 702 bool wxWindowMSW::Show(bool show
) 
 704     if ( !wxWindowBase::Show(show
) ) 
 707     HWND hWnd 
= GetHwnd(); 
 708     int cshow 
= show 
? SW_SHOW 
: SW_HIDE
; 
 709     ::ShowWindow(hWnd
, cshow
); 
 711     if ( show 
&& IsTopLevel() ) 
 713         wxBringWindowToTop(hWnd
); 
 719 // Raise the window to the top of the Z order 
 720 void wxWindowMSW::Raise() 
 722     wxBringWindowToTop(GetHwnd()); 
 725 // Lower the window to the bottom of the Z order 
 726 void wxWindowMSW::Lower() 
 728     ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0, 
 729                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
 732 void wxWindowMSW::SetTitle( const wxString
& title
) 
 734     SetWindowText(GetHwnd(), title
.c_str()); 
 737 wxString 
wxWindowMSW::GetTitle() const 
 739     return wxGetWindowText(GetHWND()); 
 742 void wxWindowMSW::DoCaptureMouse() 
 744     HWND hWnd 
= GetHwnd(); 
 751 void wxWindowMSW::DoReleaseMouse() 
 753     if ( !::ReleaseCapture() ) 
 755         wxLogLastError(_T("ReleaseCapture")); 
 759 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 761     HWND hwnd 
= ::GetCapture(); 
 762     return hwnd 
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow 
*)NULL
; 
 765 bool wxWindowMSW::SetFont(const wxFont
& font
) 
 767     if ( !wxWindowBase::SetFont(font
) ) 
 773     HWND hWnd 
= GetHwnd(); 
 776         WXHANDLE hFont 
= m_font
.GetResourceHandle(); 
 778         wxASSERT_MSG( hFont
, wxT("should have valid font") ); 
 780         ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0)); 
 785 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
) 
 787     if ( !wxWindowBase::SetCursor(cursor
) ) 
 795         HWND hWnd 
= GetHwnd(); 
 797         // Change the cursor NOW if we're within the correct window 
 799         ::GetCursorPos(&point
); 
 801         RECT rect 
= wxGetWindowRect(hWnd
); 
 803         if ( ::PtInRect(&rect
, point
) && !wxIsBusy() ) 
 804             ::SetCursor(GetHcursorOf(m_cursor
)); 
 810 void wxWindowMSW::WarpPointer (int x
, int y
) 
 812     ClientToScreen(&x
, &y
); 
 814     if ( !::SetCursorPos(x
, y
) ) 
 816         wxLogLastError(_T("SetCursorPos")); 
 820 // --------------------------------------------------------------------------- 
 822 // --------------------------------------------------------------------------- 
 824 // convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT 
 825 static inline int wxDirToWinStyle(int orient
) 
 827     return orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
; 
 830 inline int GetScrollPosition(HWND hWnd
, int wOrient
) 
 832 #ifdef __WXMICROWIN__ 
 833     return ::GetScrollPosWX(hWnd
, wOrient
); 
 835     WinStruct
<SCROLLINFO
> scrollInfo
; 
 836     scrollInfo
.cbSize 
= sizeof(SCROLLINFO
); 
 837     scrollInfo
.fMask 
= SIF_POS
; 
 838     if ( !::GetScrollInfo(hWnd
, 
 842         // Not neccessarily an error, if there are no scrollbars yet. 
 843         // wxLogLastError(_T("GetScrollInfo")); 
 845     return scrollInfo
.nPos
; 
 846 //    return ::GetScrollPos(hWnd, wOrient); 
 850 int wxWindowMSW::GetScrollPos(int orient
) const 
 852     HWND hWnd 
= GetHwnd(); 
 853     wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") ); 
 855     return GetScrollPosition(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
); 
 858 // This now returns the whole range, not just the number 
 859 // of positions that we can scroll. 
 860 int wxWindowMSW::GetScrollRange(int orient
) const 
 863     HWND hWnd 
= GetHwnd(); 
 867     ::GetScrollRange(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 870     WinStruct
<SCROLLINFO
> scrollInfo
; 
 871     scrollInfo
.fMask 
= SIF_RANGE
; 
 872     if ( !::GetScrollInfo(hWnd
, 
 873                           orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 876         // Most of the time this is not really an error, since the return 
 877         // value can also be zero when there is no scrollbar yet. 
 878         // wxLogLastError(_T("GetScrollInfo")); 
 880     maxPos 
= scrollInfo
.nMax
; 
 882     // undo "range - 1" done in SetScrollbar() 
 886 int wxWindowMSW::GetScrollThumb(int orient
) const 
 888     return orient 
== wxHORIZONTAL 
? m_xThumbSize 
: m_yThumbSize
; 
 891 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
) 
 893     HWND hWnd 
= GetHwnd(); 
 894     wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") ); 
 896     WinStruct
<SCROLLINFO
> info
; 
 900     info
.fMask 
= SIF_POS
; 
 901     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 903         // disable scrollbar instead of removing it then 
 904         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 907     ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 911 // New function that will replace some of the above. 
 912 void wxWindowMSW::SetScrollbar(int orient
, 
 918     WinStruct
<SCROLLINFO
> info
; 
 919     info
.nPage 
= pageSize
; 
 920     info
.nMin 
= 0;              // range is nMax - nMin + 1 
 921     info
.nMax 
= range 
- 1;      //  as both nMax and nMax are inclusive 
 923     info
.fMask 
= SIF_RANGE 
| SIF_PAGE 
| SIF_POS
; 
 924     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 926         // disable scrollbar instead of removing it then 
 927         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 930     HWND hWnd 
= GetHwnd(); 
 933         ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 937     *(orient 
== wxHORIZONTAL 
? &m_xThumbSize 
: &m_yThumbSize
) = pageSize
; 
 940 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect 
*prect
) 
 946         rect
.left 
= prect
->x
; 
 948         rect
.right 
= prect
->x 
+ prect
->width
; 
 949         rect
.bottom 
= prect
->y 
+ prect
->height
; 
 958     // FIXME: is this the exact equivalent of the line below? 
 959     ::ScrollWindowEx(GetHwnd(), dx
, dy
, pr
, pr
, 0, 0, SW_ERASE
|SW_INVALIDATE
); 
 961     ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
); 
 965 static bool ScrollVertically(HWND hwnd
, int kind
, int count
) 
 967     int posStart 
= GetScrollPosition(hwnd
, SB_VERT
); 
 970     for ( int n 
= 0; n 
< count
; n
++ ) 
 972         ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0); 
 974         int posNew 
= GetScrollPosition(hwnd
, SB_VERT
); 
 977             // don't bother to continue, we're already at top/bottom 
 984     return pos 
!= posStart
; 
 987 bool wxWindowMSW::ScrollLines(int lines
) 
 989     bool down 
= lines 
> 0; 
 991     return ScrollVertically(GetHwnd(), 
 992                             down 
? SB_LINEDOWN 
: SB_LINEUP
, 
 993                             down 
? lines 
: -lines
); 
 996 bool wxWindowMSW::ScrollPages(int pages
) 
 998     bool down 
= pages 
> 0; 
1000     return ScrollVertically(GetHwnd(), 
1001                             down 
? SB_PAGEDOWN 
: SB_PAGEUP
, 
1002                             down 
? pages 
: -pages
); 
1005 // --------------------------------------------------------------------------- 
1007 // --------------------------------------------------------------------------- 
1009 void wxWindowMSW::SubclassWin(WXHWND hWnd
) 
1011     wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") ); 
1013     HWND hwnd 
= (HWND
)hWnd
; 
1014     wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") ); 
1016     wxAssociateWinWithHandle(hwnd
, this); 
1018     m_oldWndProc 
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
); 
1020     // we don't need to subclass the window of our own class (in the Windows 
1021     // sense of the word) 
1022         if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) ) 
1024         ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
); 
1028         // don't bother restoring it neither: this also makes it easy to 
1029         // implement IsOfStandardClass() method which returns TRUE for the 
1030         // standard controls and FALSE for the wxWindows own windows as it can 
1031         // simply check m_oldWndProc 
1032         m_oldWndProc 
= NULL
; 
1036 void wxWindowMSW::UnsubclassWin() 
1038     wxRemoveHandleAssociation(this); 
1040     // Restore old Window proc 
1041     HWND hwnd 
= GetHwnd(); 
1046         wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") ); 
1050             if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) ) 
1052                 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
); 
1055             m_oldWndProc 
= NULL
; 
1060 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
) 
1062     // Unicows note: the code below works, but only because WNDCLASS contains 
1063     // original window handler rather that the unicows fake one. This may not 
1064     // be on purpose, though; if it stops working with future versions of 
1065     // unicows.dll, we can override unicows hooks by setting 
1066     // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own 
1067     // versions that keep track of fake<->real wnd proc mapping. 
1069         // On WinCE (at least), the wndproc comparison doesn't work, 
1070         // so have to use something like this. 
1072         extern const wxChar 
*wxCanvasClassName
; 
1073         extern const wxChar 
*wxCanvasClassNameNR
; 
1074         extern const wxChar 
*wxMDIFrameClassName
; 
1075         extern const wxChar 
*wxMDIFrameClassNameNoRedraw
; 
1076         extern const wxChar 
*wxMDIChildFrameClassName
; 
1077         extern const wxChar 
*wxMDIChildFrameClassNameNoRedraw
; 
1078         wxString 
str(wxGetWindowClass(hWnd
)); 
1079         if (str 
== wxCanvasClassName 
|| 
1080                 str 
== wxCanvasClassNameNR 
|| 
1081                 str 
== wxMDIFrameClassName 
|| 
1082                 str 
== wxMDIFrameClassNameNoRedraw 
|| 
1083                 str 
== wxMDIChildFrameClassName 
|| 
1084                 str 
== wxMDIChildFrameClassNameNoRedraw 
|| 
1085                 str 
== _T("wxTLWHiddenParent")) 
1086                 return TRUE
; // Effectively means don't subclass 
1091     if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd
), &cls
) ) 
1093         wxLogLastError(_T("GetClassInfo")); 
1098     return wndProc 
== (WXFARPROC
)cls
.lpfnWndProc
; 
1102 // ---------------------------------------------------------------------------- 
1104 // ---------------------------------------------------------------------------- 
1106 void wxWindowMSW::SetWindowStyleFlag(long flags
) 
1108     long flagsOld 
= GetWindowStyleFlag(); 
1109     if ( flags 
== flagsOld 
) 
1112     // update the internal variable 
1113     wxWindowBase::SetWindowStyleFlag(flags
); 
1115     // now update the Windows style as well if needed - and if the window had 
1116     // been already created 
1120     WXDWORD exstyle
, exstyleOld
; 
1121     long style 
= MSWGetStyle(flags
, &exstyle
), 
1122          styleOld 
= MSWGetStyle(flagsOld
, &exstyleOld
); 
1124     if ( style 
!= styleOld 
) 
1126         // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by 
1127         // this function so instead of simply setting the style to the new 
1128         // value we clear the bits which were set in styleOld but are set in 
1129         // the new one and set the ones which were not set before 
1130         long styleReal 
= ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
1131         styleReal 
&= ~styleOld
; 
1134         ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
); 
1137     // and the extended style 
1138     if ( exstyle 
!= exstyleOld 
) 
1140         long exstyleReal 
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1141         exstyleReal 
&= ~exstyleOld
; 
1142         exstyleReal 
|= exstyle
; 
1144         ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
); 
1146         // we must call SetWindowPos() to flash the cached extended style and 
1147         // also to make the change to wxSTAY_ON_TOP style take effect: just 
1148         // setting the style simply doesn't work 
1149         if ( !::SetWindowPos(GetHwnd(), 
1150                              exstyleReal 
& WS_EX_TOPMOST 
? HWND_TOPMOST
 
1153                              SWP_NOMOVE 
| SWP_NOSIZE
) ) 
1155             wxLogLastError(_T("SetWindowPos")); 
1160 WXDWORD 
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD 
*exstyle
) const 
1162     // translate the style 
1163     WXDWORD style 
= WS_CHILD 
| WS_VISIBLE
; 
1165     if ( flags 
& wxCLIP_CHILDREN 
) 
1166         style 
|= WS_CLIPCHILDREN
; 
1168     if ( flags 
& wxCLIP_SIBLINGS 
) 
1169         style 
|= WS_CLIPSIBLINGS
; 
1171     if ( flags 
& wxVSCROLL 
) 
1172         style 
|= WS_VSCROLL
; 
1174     if ( flags 
& wxHSCROLL 
) 
1175         style 
|= WS_HSCROLL
; 
1177     const wxBorder border 
= GetBorder(flags
); 
1179     // WS_BORDER is only required for wxBORDER_SIMPLE 
1180     if ( border 
== wxBORDER_SIMPLE 
) 
1183     // now deal with ext style if the caller wants it 
1189         if ( flags 
& wxTRANSPARENT_WINDOW 
) 
1190             *exstyle 
|= WS_EX_TRANSPARENT
; 
1196             case wxBORDER_DEFAULT
: 
1197                 wxFAIL_MSG( _T("unknown border style") ); 
1201             case wxBORDER_SIMPLE
: 
1204             case wxBORDER_STATIC
: 
1205                 *exstyle 
|= WS_EX_STATICEDGE
; 
1208             case wxBORDER_RAISED
: 
1209                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1212             case wxBORDER_SUNKEN
: 
1213                 *exstyle 
|= WS_EX_CLIENTEDGE
; 
1214                 style 
&= ~WS_BORDER
; 
1217             case wxBORDER_DOUBLE
: 
1218                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1222         // wxUniv doesn't use Windows dialog navigation functions at all 
1223 #if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__) 
1224         // to make the dialog navigation work with the nested panels we must 
1225         // use this style (top level windows such as dialogs don't need it) 
1226         if ( (flags 
& wxTAB_TRAVERSAL
) && !IsTopLevel() ) 
1228             *exstyle 
|= WS_EX_CONTROLPARENT
; 
1230 #endif // __WXUNIVERSAL__ 
1236 // Setup background and foreground colours correctly 
1237 void wxWindowMSW::SetupColours() 
1240         SetBackgroundColour(GetParent()->GetBackgroundColour()); 
1243 bool wxWindowMSW::IsMouseInWindow() const 
1245     // get the mouse position 
1247     ::GetCursorPos(&pt
); 
1249     // find the window which currently has the cursor and go up the window 
1250     // chain until we find this window - or exhaust it 
1251     HWND hwnd 
= ::WindowFromPoint(pt
); 
1252     while ( hwnd 
&& (hwnd 
!= GetHwnd()) ) 
1253         hwnd 
= ::GetParent(hwnd
); 
1255     return hwnd 
!= NULL
; 
1258 void wxWindowMSW::OnInternalIdle() 
1260     // Check if we need to send a LEAVE event 
1261     if ( m_mouseInWindow 
) 
1263         // note that we should generate the leave event whether the window has 
1264         // or doesn't have mouse capture 
1265         if ( !IsMouseInWindow() ) 
1267             // Generate a LEAVE event 
1268             m_mouseInWindow 
= FALSE
; 
1270             // Unfortunately the mouse button and keyboard state may have 
1271             // changed by the time the OnInternalIdle function is called, so 'state' 
1272             // may be meaningless. 
1274             if ( wxIsShiftDown() ) 
1276             if ( wxIsCtrlDown() ) 
1277                 state 
|= MK_CONTROL
; 
1278             if ( GetKeyState( VK_LBUTTON 
) ) 
1279                 state 
|= MK_LBUTTON
; 
1280             if ( GetKeyState( VK_MBUTTON 
) ) 
1281                 state 
|= MK_MBUTTON
; 
1282             if ( GetKeyState( VK_RBUTTON 
) ) 
1283                 state 
|= MK_RBUTTON
; 
1286             if ( !::GetCursorPos(&pt
) ) 
1288                 wxLogLastError(_T("GetCursorPos")); 
1291             // we need to have client coordinates here for symmetry with 
1292             // wxEVT_ENTER_WINDOW 
1293             RECT rect 
= wxGetWindowRect(GetHwnd()); 
1297             wxMouseEvent 
event2(wxEVT_LEAVE_WINDOW
); 
1298             InitMouseEvent(event2
, pt
.x
, pt
.y
, state
); 
1300             (void)GetEventHandler()->ProcessEvent(event2
); 
1304     if (wxUpdateUIEvent::CanUpdate(this)) 
1305         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
1308 // Set this window to be the child of 'parent'. 
1309 bool wxWindowMSW::Reparent(wxWindowBase 
*parent
) 
1311     if ( !wxWindowBase::Reparent(parent
) ) 
1314     HWND hWndChild 
= GetHwnd(); 
1315     HWND hWndParent 
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0; 
1317     ::SetParent(hWndChild
, hWndParent
); 
1320     if ( ::GetWindowLong(hWndChild
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
1322         EnsureParentHasControlParentStyle(GetParent()); 
1324 #endif // !__WXWINCE__ 
1329 static inline void SendSetRedraw(HWND hwnd
, bool on
) 
1331 #ifndef __WXMICROWIN__ 
1332     ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0); 
1336 void wxWindowMSW::Freeze() 
1338     SendSetRedraw(GetHwnd(), FALSE
); 
1341 void wxWindowMSW::Thaw() 
1343     SendSetRedraw(GetHwnd(), TRUE
); 
1345     // we need to refresh everything or otherwise he invalidated area is not 
1350 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1352     HWND hWnd 
= GetHwnd(); 
1358             mswRect
.left 
= rect
->x
; 
1359             mswRect
.top 
= rect
->y
; 
1360             mswRect
.right 
= rect
->x 
+ rect
->width
; 
1361             mswRect
.bottom 
= rect
->y 
+ rect
->height
; 
1363             ::InvalidateRect(hWnd
, &mswRect
, eraseBack
); 
1366             ::InvalidateRect(hWnd
, NULL
, eraseBack
); 
1370 void wxWindowMSW::Update() 
1372     if ( !::UpdateWindow(GetHwnd()) ) 
1374         wxLogLastError(_T("UpdateWindow")); 
1377 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
1378     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT 
1379     // handler needs to be really drawn right now 
1384 // --------------------------------------------------------------------------- 
1386 // --------------------------------------------------------------------------- 
1389 #if wxUSE_DRAG_AND_DROP 
1390 void wxWindowMSW::SetDropTarget(wxDropTarget 
*pDropTarget
) 
1392     if ( m_dropTarget 
!= 0 ) { 
1393         m_dropTarget
->Revoke(m_hWnd
); 
1394         delete m_dropTarget
; 
1397     m_dropTarget 
= pDropTarget
; 
1398     if ( m_dropTarget 
!= 0 ) 
1399         m_dropTarget
->Register(m_hWnd
); 
1401 #endif // wxUSE_DRAG_AND_DROP 
1403 // old style file-manager drag&drop support: we retain the old-style 
1404 // DragAcceptFiles in parallel with SetDropTarget. 
1405 void wxWindowMSW::DragAcceptFiles(bool accept
) 
1407 #if !defined(__WXWINCE__) 
1408     HWND hWnd 
= GetHwnd(); 
1410         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
1414 // ---------------------------------------------------------------------------- 
1416 // ---------------------------------------------------------------------------- 
1420 void wxWindowMSW::DoSetToolTip(wxToolTip 
*tooltip
) 
1422     wxWindowBase::DoSetToolTip(tooltip
); 
1425         m_tooltip
->SetWindow((wxWindow 
*)this); 
1428 #endif // wxUSE_TOOLTIPS 
1430 // --------------------------------------------------------------------------- 
1431 // moving and resizing 
1432 // --------------------------------------------------------------------------- 
1435 void wxWindowMSW::DoGetSize(int *x
, int *y
) const 
1437     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1440         *x 
= rect
.right 
- rect
.left
; 
1442         *y 
= rect
.bottom 
- rect
.top
; 
1445 // Get size *available for subwindows* i.e. excluding menu bar etc. 
1446 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const 
1448     RECT rect 
= wxGetClientRect(GetHwnd()); 
1456 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const 
1458     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1461     point
.x 
= rect
.left
; 
1464     // we do the adjustments with respect to the parent only for the "real" 
1465     // children, not for the dialogs/frames 
1466     if ( !IsTopLevel() ) 
1468         HWND hParentWnd 
= 0; 
1469         wxWindow 
*parent 
= GetParent(); 
1471             hParentWnd 
= GetWinHwnd(parent
); 
1473         // Since we now have the absolute screen coords, if there's a parent we 
1474         // must subtract its top left corner 
1477             ::ScreenToClient(hParentWnd
, &point
); 
1482             // We may be faking the client origin. So a window that's really at (0, 
1483             // 30) may appear (to wxWin apps) to be at (0, 0). 
1484             wxPoint 
pt(parent
->GetClientAreaOrigin()); 
1496 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const 
1504     ::ScreenToClient(GetHwnd(), &pt
); 
1512 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const 
1520     ::ClientToScreen(GetHwnd(), &pt
); 
1528 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
) 
1530     // TODO: is this consistent with other platforms? 
1531     // Still, negative width or height shouldn't be allowed 
1536     if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) ) 
1538         wxLogLastError(wxT("MoveWindow")); 
1542 // set the size of the window: if the dimensions are positive, just use them, 
1543 // but if any of them is equal to -1, it means that we must find the value for 
1544 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
1545 // which case -1 is a valid value for x and y) 
1547 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
1548 // the width/height to best suit our contents, otherwise we reuse the current 
1550 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
1552     // get the current size and position... 
1553     int currentX
, currentY
; 
1554     GetPosition(¤tX
, ¤tY
); 
1555     int currentW
,currentH
; 
1556     GetSize(¤tW
, ¤tH
); 
1558     // ... and don't do anything (avoiding flicker) if it's already ok 
1559     if ( x 
== currentX 
&& y 
== currentY 
&& 
1560          width 
== currentW 
&& height 
== currentH 
) 
1565     if ( x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1567     if ( y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1570     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
1572     wxSize 
size(-1, -1); 
1575         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
1577             size 
= DoGetBestSize(); 
1582             // just take the current one 
1589         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
1593                 size 
= DoGetBestSize(); 
1595             //else: already called DoGetBestSize() above 
1601             // just take the current one 
1606     DoMoveWindow(x
, y
, width
, height
); 
1609 void wxWindowMSW::DoSetClientSize(int width
, int height
) 
1611     // setting the client size is less obvious than it it could have been 
1612     // because in the result of changing the total size the window scrollbar 
1613     // may [dis]appear and/or its menubar may [un]wrap and so the client size 
1614     // will not be correct as the difference between the total and client size 
1615     // changes - so we keep changing it until we get it right 
1617     // normally this loop shouldn't take more than 3 iterations (usually 1 but 
1618     // if scrollbars [dis]appear as the result of the first call, then 2 and it 
1619     // may become 3 if the window had 0 size originally and so we didn't 
1620     // calculate the scrollbar correction correctly during the first iteration) 
1621     // but just to be on the safe side we check for it instead of making it an 
1622     // "infinite" loop (i.e. leaving break inside as the only way to get out) 
1623     for ( int i 
= 0; i 
< 4; i
++ ) 
1626         ::GetClientRect(GetHwnd(), &rectClient
); 
1628         // if the size is already ok, stop here (rectClient.left = top = 0) 
1629         if ( (rectClient
.right 
== width 
|| width 
== -1) && 
1630              (rectClient
.bottom 
== height 
|| height 
== -1) ) 
1635         int widthClient 
= width
, 
1636             heightClient 
= height
; 
1638         // Find the difference between the entire window (title bar and all) 
1639         // and the client area; add this to the new client size to move the 
1642         ::GetWindowRect(GetHwnd(), &rectWin
); 
1644         widthClient 
+= rectWin
.right 
- rectWin
.left 
- rectClient
.right
; 
1645         heightClient 
+= rectWin
.bottom 
- rectWin
.top 
- rectClient
.bottom
; 
1648         point
.x 
= rectWin
.left
; 
1649         point
.y 
= rectWin
.top
; 
1651         // MoveWindow positions the child windows relative to the parent, so 
1652         // adjust if necessary 
1653         if ( !IsTopLevel() ) 
1655             wxWindow 
*parent 
= GetParent(); 
1658                 ::ScreenToClient(GetHwndOf(parent
), &point
); 
1662         DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
); 
1666 // For implementation purposes - sometimes decorations make the client area 
1668 wxPoint 
wxWindowMSW::GetClientAreaOrigin() const 
1670     return wxPoint(0, 0); 
1673 // --------------------------------------------------------------------------- 
1675 // --------------------------------------------------------------------------- 
1677 int wxWindowMSW::GetCharHeight() const 
1679     return wxGetTextMetrics(this).tmHeight
; 
1682 int wxWindowMSW::GetCharWidth() const 
1684     // +1 is needed because Windows apparently adds it when calculating the 
1685     // dialog units size in pixels 
1686 #if wxDIALOG_UNIT_COMPATIBILITY 
1687     return wxGetTextMetrics(this).tmAveCharWidth
; 
1689     return wxGetTextMetrics(this).tmAveCharWidth 
+ 1; 
1693 void wxWindowMSW::GetTextExtent(const wxString
& string
, 
1695                              int *descent
, int *externalLeading
, 
1696                              const wxFont 
*theFont
) const 
1698     const wxFont 
*fontToUse 
= theFont
; 
1700         fontToUse 
= &m_font
; 
1702     HWND hWnd 
= GetHwnd(); 
1703     HDC dc 
= ::GetDC(hWnd
); 
1707     if ( fontToUse 
&& fontToUse
->Ok() ) 
1709         fnt 
= (HFONT
)((wxFont 
*)fontToUse
)->GetResourceHandle(); // const_cast 
1711             hfontOld 
= (HFONT
)SelectObject(dc
,fnt
); 
1716     GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
); 
1717     GetTextMetrics(dc
, &tm
); 
1719     if ( fontToUse 
&& fnt 
&& hfontOld 
) 
1720         SelectObject(dc
, hfontOld
); 
1722     ReleaseDC(hWnd
, dc
); 
1729         *descent 
= tm
.tmDescent
; 
1730     if ( externalLeading 
) 
1731         *externalLeading 
= tm
.tmExternalLeading
; 
1734 // --------------------------------------------------------------------------- 
1736 // --------------------------------------------------------------------------- 
1738 #if wxUSE_MENUS_NATIVE 
1740 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue 
1741 // immediately, without waiting for the next event loop iteration 
1743 // NB: this function should probably be made public later as it can almost 
1744 //     surely replace wxYield() elsewhere as well 
1745 static void wxYieldForCommandsOnly() 
1747     // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't 
1748     // want to process it here) 
1750     while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) ) 
1752         if ( msg
.message 
== WM_QUIT 
) 
1754             // if we retrieved a WM_QUIT, insert back into the message queue. 
1755             ::PostQuitMessage(0); 
1759         // luckily (as we don't have access to wxEventLoopImpl method from here 
1760         // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it 
1762         ::TranslateMessage(&msg
); 
1763         ::DispatchMessage(&msg
); 
1767 bool wxWindowMSW::DoPopupMenu(wxMenu 
*menu
, int x
, int y
) 
1769     menu
->SetInvokingWindow(this); 
1772     HWND hWnd 
= GetHwnd(); 
1773     HMENU hMenu 
= GetHmenuOf(menu
); 
1777     ::ClientToScreen(hWnd
, &point
); 
1778     wxCurrentPopupMenu 
= menu
; 
1780 #if !defined(__WXWINCE__) 
1781     flags 
= TPM_RIGHTBUTTON
; 
1783     ::TrackPopupMenu(hMenu
, flags
, point
.x
, point
.y
, 0, hWnd
, NULL
); 
1785     // we need to do it righ now as otherwise the events are never going to be 
1786     // sent to wxCurrentPopupMenu from HandleCommand() 
1788     // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't 
1789     // help and we'd still need wxYieldForCommandsOnly() as the menu may be 
1790     // destroyed as soon as we return (it can be a local variable in the caller 
1791     // for example) and so we do need to process the event immediately 
1792     wxYieldForCommandsOnly(); 
1794     wxCurrentPopupMenu 
= NULL
; 
1796     menu
->SetInvokingWindow(NULL
); 
1801 #endif // wxUSE_MENUS_NATIVE 
1803 // =========================================================================== 
1804 // pre/post message processing 
1805 // =========================================================================== 
1807 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
1810         return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
1812         return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
); 
1815 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
) 
1817     // wxUniversal implements tab traversal itself 
1818 #ifndef __WXUNIVERSAL__ 
1819     if ( m_hWnd 
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) ) 
1821         // intercept dialog navigation keys 
1822         MSG 
*msg 
= (MSG 
*)pMsg
; 
1824         // here we try to do all the job which ::IsDialogMessage() usually does 
1827         if ( msg
->message 
== WM_KEYDOWN 
) 
1829             bool bCtrlDown 
= wxIsCtrlDown(); 
1830             bool bShiftDown 
= wxIsShiftDown(); 
1832             // WM_GETDLGCODE: ask the control if it wants the key for itself, 
1833             // don't process it if it's the case (except for Ctrl-Tab/Enter 
1834             // combinations which are always processed) 
1838                 lDlgCode 
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0); 
1840                 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the 
1841                 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, 
1842                 // it, of course, implies them 
1843                 if ( lDlgCode 
& DLGC_WANTALLKEYS 
) 
1845                     lDlgCode 
|= DLGC_WANTTAB 
| DLGC_WANTARROWS
; 
1849             bool bForward 
= TRUE
, 
1850                  bWindowChange 
= FALSE
; 
1852             // should we process this message specially? 
1853             bool bProcess 
= TRUE
; 
1854             switch ( msg
->wParam 
) 
1857                     // assume that nobody wants Shift-TAB for himself - if we 
1858                     // don't do it there is no easy way for a control to grab 
1859                     // TABs but still let Shift-TAB work as navugation key 
1860                     if ( (lDlgCode 
& DLGC_WANTTAB
) && !bShiftDown 
) { 
1864                         // Ctrl-Tab cycles thru notebook pages 
1865                         bWindowChange 
= bCtrlDown
; 
1866                         bForward 
= !bShiftDown
; 
1872                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1880                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1886                         if ( (lDlgCode 
& DLGC_WANTMESSAGE
) && !bCtrlDown 
) 
1888                             // control wants to process Enter itself, don't 
1889                             // call IsDialogMessage() which would interpret 
1893                         else if ( lDlgCode 
& DLGC_BUTTON 
) 
1895                             // let IsDialogMessage() handle this for all 
1896                             // buttons except the owner-drawn ones which it 
1897                             // just seems to ignore 
1898                             long style 
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
); 
1899                             if ( (style 
& BS_OWNERDRAW
) == BS_OWNERDRAW 
) 
1901                                 // emulate the button click 
1902                                 wxWindow 
*btn 
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
); 
1904                                     btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1909                         // FIXME: this should be handled by 
1910                         //        wxNavigationKeyEvent handler and not here!! 
1914                             wxButton 
*btn 
= wxDynamicCast(GetDefaultItem(), 
1916                             if ( btn 
&& btn
->IsEnabled() ) 
1918                                 // if we do have a default button, do press it 
1919                                 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1923                             else // no default button 
1925 #endif // wxUSE_BUTTON 
1926                                 // this is a quick and dirty test for a text 
1928                                 if ( !(lDlgCode 
& DLGC_HASSETSEL
) ) 
1930                                     // don't process Enter, the control might 
1931                                     // need it for itself and don't let 
1932                                     // ::IsDialogMessage() have it as it can 
1933                                     // eat the Enter events sometimes 
1936                                 else if (!IsTopLevel()) 
1938                                     // if not a top level window, let parent 
1942                                 //else: treat Enter as TAB: pass to the next 
1943                                 //      control as this is the best thing to do 
1944                                 //      if the text doesn't handle Enter itself 
1956                 wxNavigationKeyEvent event
; 
1957                 event
.SetDirection(bForward
); 
1958                 event
.SetWindowChange(bWindowChange
); 
1959                 event
.SetEventObject(this); 
1961                 if ( GetEventHandler()->ProcessEvent(event
) ) 
1968         // let ::IsDialogMessage() do almost everything and handle just the 
1969         // things it doesn't here: Ctrl-TAB for switching notebook pages 
1970         if ( msg
->message 
== WM_KEYDOWN 
) 
1972             // don't process system keys here 
1973             if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) ) 
1975                 if ( (msg
->wParam 
== VK_TAB
) && wxIsCtrlDown() ) 
1977                     // find the first notebook parent and change its page 
1978                     wxWindow 
*win 
= this; 
1979                     wxNotebook 
*nbook 
= NULL
; 
1980                     while ( win 
&& !nbook 
) 
1982                         nbook 
= wxDynamicCast(win
, wxNotebook
); 
1983                         win 
= win
->GetParent(); 
1988                         bool forward 
= !wxIsShiftDown(); 
1990                         nbook
->AdvanceSelection(forward
); 
1997         // we handle VK_ESCAPE ourselves in wxDialog::OnCharHook() and we 
1998         // shouldn't let IsDialogMessage() get it as it _always_ eats the 
1999         // message even when there is no cancel button and when the message is 
2000         // needed by the control itself: in particular, it prevents the tree in 
2001         // place edit control from being closed with Escape in a dialog 
2002         if ( msg
->message 
!= WM_KEYDOWN 
|| msg
->wParam 
!= VK_ESCAPE 
) 
2004             // ::IsDialogMessage() is broken and may sometimes hang the 
2005             // application by going into an infinite loop, so we try to detect 
2006             // [some of] the situatations when this may happen and not call it 
2009             // assume we can call it by default 
2010             bool canSafelyCallIsDlgMsg 
= TRUE
; 
2012             HWND hwndFocus 
= ::GetFocus(); 
2014             // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter 
2015             // an infinite loop, because it will recursively check the child 
2016             // windows but not the window itself and so if none of the children 
2017             // accepts focus it loops forever (as it only stops when it gets 
2018             // back to the window it started from) 
2020             // while it is very unusual that a window with WS_EX_CONTROLPARENT 
2021             // style has the focus, it can happen. One such possibility is if 
2022             // all windows are either toplevel, wxDialog, wxPanel or static 
2023             // controls and no window can actually accept keyboard input. 
2024 #if !defined(__WXWINCE__) 
2025             if ( ::GetWindowLong(hwndFocus
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
2027                 // passimistic by default 
2028                 canSafelyCallIsDlgMsg 
= FALSE
; 
2029                 for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
2031                       node 
= node
->GetNext() ) 
2033                     wxWindow 
* const win 
= node
->GetData(); 
2034                     if ( win
->AcceptsFocus() && 
2035                             !(::GetWindowLong(GetHwndOf(win
), GWL_EXSTYLE
) & 
2036                                 WS_EX_CONTROLPARENT
) ) 
2038                         // it shouldn't hang... 
2039                         canSafelyCallIsDlgMsg 
= TRUE
; 
2045 #endif // !__WXWINCE__ 
2047             if ( canSafelyCallIsDlgMsg 
) 
2049                 // ::IsDialogMessage() can enter in an infinite loop when the 
2050                 // currently focused window is disabled or hidden and its 
2051                 // parent has WS_EX_CONTROLPARENT style, so don't call it in 
2055                     if ( !::IsWindowEnabled(hwndFocus
) || 
2056                             !::IsWindowVisible(hwndFocus
) ) 
2058                         // it would enter an infinite loop if we do this! 
2059                         canSafelyCallIsDlgMsg 
= FALSE
; 
2064                     if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) ) 
2066                         // it's a top level window, don't go further -- e.g. even 
2067                         // if the parent of a dialog is disabled, this doesn't 
2068                         // break navigation inside the dialog 
2072                     hwndFocus 
= ::GetParent(hwndFocus
); 
2076             // let IsDialogMessage() have the message if it's safe to call it 
2077             if ( canSafelyCallIsDlgMsg 
&& ::IsDialogMessage(GetHwnd(), msg
) ) 
2079                 // IsDialogMessage() did something... 
2084 #endif // __WXUNIVERSAL__ 
2089         // relay mouse move events to the tooltip control 
2090         MSG 
*msg 
= (MSG 
*)pMsg
; 
2091         if ( msg
->message 
== WM_MOUSEMOVE 
) 
2092             m_tooltip
->RelayEvent(pMsg
); 
2094 #endif // wxUSE_TOOLTIPS 
2099 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
) 
2101 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__) 
2102     return m_acceleratorTable
.Translate(this, pMsg
); 
2106 #endif // wxUSE_ACCEL 
2109 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
)) 
2111     // preprocess all messages by default 
2115 // --------------------------------------------------------------------------- 
2116 // message params unpackers 
2117 // --------------------------------------------------------------------------- 
2119 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2120                              WORD 
*id
, WXHWND 
*hwnd
, WORD 
*cmd
) 
2122     *id 
= LOWORD(wParam
); 
2123     *hwnd 
= (WXHWND
)lParam
; 
2124     *cmd 
= HIWORD(wParam
); 
2127 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2128                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2130     *state 
= LOWORD(wParam
); 
2131     *minimized 
= HIWORD(wParam
); 
2132     *hwnd 
= (WXHWND
)lParam
; 
2135 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2136                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2138     *code 
= LOWORD(wParam
); 
2139     *pos 
= HIWORD(wParam
); 
2140     *hwnd 
= (WXHWND
)lParam
; 
2143 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2144                               WXWORD 
*nCtlColor
, WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2146 #ifndef __WXMICROWIN__ 
2147     *nCtlColor 
= CTLCOLOR_BTN
; 
2148     *hwnd 
= (WXHWND
)lParam
; 
2149     *hdc 
= (WXHDC
)wParam
; 
2153 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2154                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2156     *item 
= (WXWORD
)wParam
; 
2157     *flags 
= HIWORD(wParam
); 
2158     *hmenu 
= (WXHMENU
)lParam
; 
2161 // --------------------------------------------------------------------------- 
2162 // Main wxWindows window proc and the window proc for wxWindow 
2163 // --------------------------------------------------------------------------- 
2165 // Hook for new window just as it's being created, when the window isn't yet 
2166 // associated with the handle 
2167 static wxWindowMSW 
*gs_winBeingCreated 
= NULL
; 
2169 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the 
2170 // window being created and insures that it's always unset back later 
2171 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW 
*winBeingCreated
) 
2173     gs_winBeingCreated 
= winBeingCreated
; 
2176 wxWindowCreationHook::~wxWindowCreationHook() 
2178     gs_winBeingCreated 
= NULL
; 
2182 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) 
2184     // trace all messages - useful for the debugging 
2186     wxLogTrace(wxTraceMessages
, 
2187                wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"), 
2188                wxGetMessageName(message
), (long)hWnd
, (long)wParam
, lParam
); 
2189 #endif // __WXDEBUG__ 
2191     wxWindowMSW 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2193     // when we get the first message for the HWND we just created, we associate 
2194     // it with wxWindow stored in gs_winBeingCreated 
2195     if ( !wnd 
&& gs_winBeingCreated 
) 
2197         wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
); 
2198         wnd 
= gs_winBeingCreated
; 
2199         gs_winBeingCreated 
= NULL
; 
2200         wnd
->SetHWND((WXHWND
)hWnd
); 
2206         rc 
= wnd
->MSWWindowProc(message
, wParam
, lParam
); 
2208         rc 
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
); 
2213 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
2215     // did we process the message? 
2216     bool processed 
= FALSE
; 
2227     // for most messages we should return 0 when we do process the message 
2235                 processed 
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
); 
2238                     // return 0 to allow window creation 
2239                     rc
.result 
= mayCreate 
? 0 : -1; 
2245             // never set processed to TRUE and *always* pass WM_DESTROY to 
2246             // DefWindowProc() as Windows may do some internal cleanup when 
2247             // processing it and failing to pass the message along may cause 
2248             // memory and resource leaks! 
2249             (void)HandleDestroy(); 
2253             processed 
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2256 #if !defined(__WXWINCE__) 
2259                 LPRECT pRect 
= (LPRECT
)lParam
; 
2261                 rc
.SetLeft(pRect
->left
); 
2262                 rc
.SetTop(pRect
->top
); 
2263                 rc
.SetRight(pRect
->right
); 
2264                 rc
.SetBottom(pRect
->bottom
); 
2265                 processed 
= HandleMoving(rc
); 
2267                     pRect
->left 
= rc
.GetLeft(); 
2268                     pRect
->top 
= rc
.GetTop(); 
2269                     pRect
->right 
= rc
.GetRight(); 
2270                     pRect
->bottom 
= rc
.GetBottom(); 
2281                     // we're not interested in these messages at all 
2284                 case SIZE_MINIMIZED
: 
2285                     // we shouldn't send sizev events for these messages as the 
2286                     // client size may be negative which breaks existing code 
2288                     // OTOH we might send another (wxMinimizedEvent?) one or 
2289                     // add an additional parameter to wxSizeEvent if this is 
2290                     // useful to anybody 
2294                     wxFAIL_MSG( _T("unexpected WM_SIZE parameter") ); 
2295                     // fall through nevertheless 
2297                 case SIZE_MAXIMIZED
: 
2299                     processed 
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), 
2304 #if !defined(__WXWINCE__) 
2307                 LPRECT pRect 
= (LPRECT
)lParam
; 
2309                 rc
.SetLeft(pRect
->left
); 
2310                 rc
.SetTop(pRect
->top
); 
2311                 rc
.SetRight(pRect
->right
); 
2312                 rc
.SetBottom(pRect
->bottom
); 
2313                 processed 
= HandleSizing(rc
); 
2315                     pRect
->left 
= rc
.GetLeft(); 
2316                     pRect
->top 
= rc
.GetTop(); 
2317                     pRect
->right 
= rc
.GetRight(); 
2318                     pRect
->bottom 
= rc
.GetBottom(); 
2324 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
2325         case WM_ACTIVATEAPP
: 
2326             wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
2332                 WXWORD state
, minimized
; 
2334                 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
); 
2336                 processed 
= HandleActivate(state
, minimized 
!= 0, (WXHWND
)hwnd
); 
2341             processed 
= HandleSetFocus((WXHWND
)(HWND
)wParam
); 
2345             processed 
= HandleKillFocus((WXHWND
)(HWND
)wParam
); 
2352                     // cast to wxWindow is needed for wxUniv 
2353                     wxPaintDCEx 
dc((wxWindow 
*)this, (WXHDC
)wParam
); 
2354                     processed 
= HandlePaint(); 
2358                     processed 
= HandlePaint(); 
2366                 // Don't call the wx handlers in this case 
2367                 if ( wxIsKindOf(this, wxListCtrl
) ) 
2370                 if ( lParam 
& PRF_ERASEBKGND 
) 
2371                     HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
2373                 wxPaintDCEx 
dc((wxWindow 
*)this, (WXHDC
)wParam
); 
2374                 processed 
= HandlePaint(); 
2380 #ifdef __WXUNIVERSAL__ 
2381             // Universal uses its own wxFrame/wxDialog, so we don't receive 
2382             // close events unless we have this. 
2387             // don't let the DefWindowProc() destroy our window - we'll do it 
2388             // ourselves in ~wxWindow 
2395             processed 
= HandleShow(wParam 
!= 0, (int)lParam
); 
2399             processed 
= HandleMouseMove(GET_X_LPARAM(lParam
), 
2400                                         GET_Y_LPARAM(lParam
), 
2404 #if wxUSE_MOUSEWHEEL 
2406             processed 
= HandleMouseWheel(wParam
, lParam
); 
2410         case WM_LBUTTONDOWN
: 
2412         case WM_LBUTTONDBLCLK
: 
2413         case WM_RBUTTONDOWN
: 
2415         case WM_RBUTTONDBLCLK
: 
2416         case WM_MBUTTONDOWN
: 
2418         case WM_MBUTTONDBLCLK
: 
2420 #ifdef __WXMICROWIN__ 
2421                 // MicroWindows seems to ignore the fact that a window is 
2422                 // disabled. So catch mouse events and throw them away if 
2424                 wxWindowMSW
* win 
= this; 
2427                     if (!win
->IsEnabled()) 
2433                     win 
= win
->GetParent(); 
2434                     if ( !win 
|| win
->IsTopLevel() ) 
2441 #endif // __WXMICROWIN__ 
2442                 int x 
= GET_X_LPARAM(lParam
), 
2443                     y 
= GET_Y_LPARAM(lParam
); 
2445                 // redirect the event to a static control if necessary by 
2446                 // finding one under mouse 
2448                 if ( GetCapture() == this ) 
2450                     // but don't do it if the mouse is captured by this window 
2451                     // because then it should really get this event itself 
2456                     win 
= FindWindowForMouseEvent(this, &x
, &y
); 
2458                     // this should never happen 
2459                     wxCHECK_MSG( win
, 0, 
2460                                  _T("FindWindowForMouseEvent() returned NULL") ); 
2462                     // for the standard classes their WndProc sets the focus to 
2463                     // them anyhow and doing it from here results in some weird 
2464                     // problems, but for our windows we want them to acquire 
2465                     // focus when clicked 
2466                     if ( !win
->IsOfStandardClass() ) 
2468                         if ( message 
== WM_LBUTTONDOWN 
&& win
->AcceptsFocus() ) 
2473                 processed 
= win
->HandleMouseEvent(message
, x
, y
, wParam
); 
2482         case MM_JOY1BUTTONDOWN
: 
2483         case MM_JOY2BUTTONDOWN
: 
2484         case MM_JOY1BUTTONUP
: 
2485         case MM_JOY2BUTTONUP
: 
2486             processed 
= HandleJoystickEvent(message
, 
2487                                             GET_X_LPARAM(lParam
), 
2488                                             GET_Y_LPARAM(lParam
), 
2491 #endif // __WXMICROWIN__ 
2494             processed 
= HandleSysCommand(wParam
, lParam
); 
2501                 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
); 
2503                 processed 
= HandleCommand(id
, cmd
, hwnd
); 
2508             processed 
= HandleNotify((int)wParam
, lParam
, &rc
.result
); 
2511             // for these messages we must return TRUE if process the message 
2514         case WM_MEASUREITEM
: 
2516                 int idCtrl 
= (UINT
)wParam
; 
2517                 if ( message 
== WM_DRAWITEM 
) 
2519                     processed 
= MSWOnDrawItem(idCtrl
, 
2520                                               (WXDRAWITEMSTRUCT 
*)lParam
); 
2524                     processed 
= MSWOnMeasureItem(idCtrl
, 
2525                                                  (WXMEASUREITEMSTRUCT 
*)lParam
); 
2532 #endif // defined(WM_DRAWITEM) 
2535             if ( !IsOfStandardClass() ) 
2537                 // we always want to get the char events 
2538                 rc
.result 
= DLGC_WANTCHARS
; 
2540                 if ( GetWindowStyleFlag() & wxWANTS_CHARS 
) 
2542                     // in fact, we want everything 
2543                     rc
.result 
|= DLGC_WANTARROWS 
| 
2550             //else: get the dlg code from the DefWindowProc() 
2555             // If this has been processed by an event handler, return 0 now 
2556             // (we've handled it). 
2557             m_lastKeydownProcessed 
= HandleKeyDown((WORD
) wParam
, lParam
); 
2558             if ( m_lastKeydownProcessed 
) 
2567                     // we consider these message "not interesting" to OnChar, so 
2568                     // just don't do anything more with them 
2578                     // avoid duplicate messages to OnChar for these ASCII keys: 
2579                     // they will be translated by TranslateMessage() and received 
2601                         // but set processed to FALSE, not TRUE to still pass them 
2602                         // to the control's default window proc - otherwise 
2603                         // built-in keyboard handling won't work 
2608                     // special case of VK_APPS: treat it the same as right mouse 
2609                     // click because both usually pop up a context menu 
2615                             TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2616                             processed 
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
); 
2622                         // do generate a CHAR event 
2623                         processed 
= HandleChar((WORD
)wParam
, lParam
); 
2626             if (message 
== WM_SYSKEYDOWN
)  // Let Windows still handle the SYSKEYs 
2633             // special case of VK_APPS: treat it the same as right mouse button 
2634             if ( wParam 
== VK_APPS 
) 
2639                 TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2640                 processed 
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
); 
2645                 processed 
= HandleKeyUp((WORD
) wParam
, lParam
); 
2650         case WM_CHAR
: // Always an ASCII character 
2651             if ( m_lastKeydownProcessed 
) 
2653                 // The key was handled in the EVT_KEY_DOWN and handling 
2654                 // a key in an EVT_KEY_DOWN handler is meant, by 
2655                 // design, to prevent EVT_CHARs from happening 
2656                 m_lastKeydownProcessed 
= FALSE
; 
2661                 processed 
= HandleChar((WORD
)wParam
, lParam
, TRUE
); 
2667             processed 
= HandleHotKey((WORD
)wParam
, lParam
); 
2669 #endif // wxUSE_HOTKEY 
2676                 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
); 
2678                 processed 
= MSWOnScroll(message 
== WM_HSCROLL 
? wxHORIZONTAL
 
2684         // CTLCOLOR messages are sent by children to query the parent for their 
2685         // colors#ifndef __WXMICROWIN__ 
2686 #ifndef __WXMICROWIN__ 
2687         case WM_CTLCOLORMSGBOX
: 
2688         case WM_CTLCOLOREDIT
: 
2689         case WM_CTLCOLORLISTBOX
: 
2690         case WM_CTLCOLORBTN
: 
2691         case WM_CTLCOLORDLG
: 
2692         case WM_CTLCOLORSCROLLBAR
: 
2693         case WM_CTLCOLORSTATIC
: 
2698                 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
); 
2700                 processed 
= HandleCtlColor(&rc
.hBrush
, 
2709 #endif // !__WXMICROWIN__ 
2711         case WM_SYSCOLORCHANGE
: 
2712             // the return value for this message is ignored 
2713             processed 
= HandleSysColorChange(); 
2716 #if !defined(__WXWINCE__) 
2717         case WM_DISPLAYCHANGE
: 
2718             processed 
= HandleDisplayChange(); 
2722         case WM_PALETTECHANGED
: 
2723             processed 
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
); 
2726         case WM_CAPTURECHANGED
: 
2727             processed 
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
); 
2730         case WM_QUERYNEWPALETTE
: 
2731             processed 
= HandleQueryNewPalette(); 
2735             processed 
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
2738                 // we processed the message, i.e. erased the background 
2743 #if !defined(__WXWINCE__) 
2745             processed 
= HandleDropFiles(wParam
); 
2750             processed 
= HandleInitDialog((WXHWND
)(HWND
)wParam
); 
2754                 // we never set focus from here 
2759 #if !defined(__WXWINCE__) 
2760         case WM_QUERYENDSESSION
: 
2761             processed 
= HandleQueryEndSession(lParam
, &rc
.allow
); 
2765             processed 
= HandleEndSession(wParam 
!= 0, lParam
); 
2768         case WM_GETMINMAXINFO
: 
2769             processed 
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
); 
2774             processed 
= HandleSetCursor((WXHWND
)(HWND
)wParam
, 
2775                                         LOWORD(lParam
),     // hit test 
2776                                         HIWORD(lParam
));    // mouse msg 
2780                 // returning TRUE stops the DefWindowProc() from further 
2781                 // processing this message - exactly what we need because we've 
2782                 // just set the cursor. 
2787 #if wxUSE_ACCESSIBILITY 
2790                 //WPARAM dwFlags = (WPARAM) (DWORD) wParam; 
2791                 LPARAM dwObjId 
= (LPARAM
) (DWORD
) lParam
; 
2793                 if (dwObjId 
== (LPARAM
)OBJID_CLIENT 
&& GetOrCreateAccessible()) 
2795                     return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible()); 
2801 #if defined(WM_HELP) 
2804                 // HELPINFO doesn't seem to be supported on WinCE. 
2806                 HELPINFO
* info 
= (HELPINFO
*) lParam
; 
2807                 // Don't yet process menu help events, just windows 
2808                 if (info
->iContextType 
== HELPINFO_WINDOW
) 
2811                     wxWindowMSW
* subjectOfHelp 
= this; 
2812                     bool eventProcessed 
= FALSE
; 
2813                     while (subjectOfHelp 
&& !eventProcessed
) 
2815                         wxHelpEvent 
helpEvent(wxEVT_HELP
, 
2816                                               subjectOfHelp
->GetId(), 
2820                                               wxPoint(info
->MousePos
.x
, info
->MousePos
.y
) 
2824                         helpEvent
.SetEventObject(this); 
2826                             GetEventHandler()->ProcessEvent(helpEvent
); 
2828                         // Go up the window hierarchy until the event is 
2830                         subjectOfHelp 
= subjectOfHelp
->GetParent(); 
2833                     processed 
= eventProcessed
; 
2836                 else if (info
->iContextType 
== HELPINFO_MENUITEM
) 
2838                     wxHelpEvent 
helpEvent(wxEVT_HELP
, info
->iCtrlId
); 
2839                     helpEvent
.SetEventObject(this); 
2840                     processed 
= GetEventHandler()->ProcessEvent(helpEvent
); 
2843                 //else: processed is already FALSE 
2849 #if !defined(__WXWINCE__) 
2850         case WM_CONTEXTMENU
: 
2852                 // we don't convert from screen to client coordinates as 
2853                 // the event may be handled by a parent window 
2854                 wxPoint 
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2856                 wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
2857                 evtCtx
.SetEventObject(this); 
2858                 processed 
= GetEventHandler()->ProcessEvent(evtCtx
); 
2864             // we're only interested in our own menus, not MF_SYSMENU 
2865             if ( HIWORD(wParam
) == MF_POPUP 
) 
2867                 // handle menu chars for ownerdrawn menu items 
2868                 int i 
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
); 
2869                 if ( i 
!= wxNOT_FOUND 
) 
2871                     rc
.result 
= MAKELRESULT(i
, MNC_EXECUTE
); 
2881         wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."), 
2882                    wxGetMessageName(message
)); 
2883 #endif // __WXDEBUG__ 
2884         rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
2890 // ---------------------------------------------------------------------------- 
2891 // wxWindow <-> HWND map 
2892 // ---------------------------------------------------------------------------- 
2894 wxWinHashTable 
*wxWinHandleHash 
= NULL
; 
2896 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
) 
2898     return wxWinHandleHash
->Get((long)hWnd
); 
2901 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
) 
2903     // adding NULL hWnd is (first) surely a result of an error and 
2904     // (secondly) breaks menu command processing 
2905     wxCHECK_RET( hWnd 
!= (HWND
)NULL
, 
2906                  wxT("attempt to add a NULL hWnd to window list ignored") ); 
2908     wxWindow 
*oldWin 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2910     if ( oldWin 
&& (oldWin 
!= win
) ) 
2912         wxLogDebug(wxT("HWND %X already associated with another window (%s)"), 
2913                    (int) hWnd
, win
->GetClassInfo()->GetClassName()); 
2916 #endif // __WXDEBUG__ 
2919         wxWinHandleHash
->Put((long)hWnd
, (wxWindow 
*)win
); 
2923 void wxRemoveHandleAssociation(wxWindowMSW 
*win
) 
2925     wxWinHandleHash
->Delete((long)win
->GetHWND()); 
2928 // ---------------------------------------------------------------------------- 
2929 // various MSW speciic class dependent functions 
2930 // ---------------------------------------------------------------------------- 
2932 // Default destroyer - override if you destroy it in some other way 
2933 // (e.g. with MDI child windows) 
2934 void wxWindowMSW::MSWDestroyWindow() 
2938 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
, 
2941                                            int& w
, int& h
) const 
2943     static const int DEFAULT_Y 
= 200; 
2944     static const int DEFAULT_H 
= 250; 
2946     bool nonDefault 
= FALSE
; 
2950         // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can 
2951         // just as well set it to CW_USEDEFAULT as well 
2957         // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it 
2958         // neither because it is not handled as a special value by Windows then 
2959         // and so we have to choose some default value for it 
2961         y 
= pos
.y 
== -1 ? DEFAULT_Y 
: pos
.y
; 
2967       NB: there used to be some code here which set the initial size of the 
2968           window to the client size of the parent if no explicit size was 
2969           specified. This was wrong because wxWindows programs often assume 
2970           that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke 
2971           it. To see why, you should understand that Windows sends WM_SIZE from 
2972           inside ::CreateWindow() anyhow. However, ::CreateWindow() is called 
2973           from some base class ctor and so this WM_SIZE is not processed in the 
2974           real class' OnSize() (because it's not fully constructed yet and the 
2975           event goes to some base class OnSize() instead). So the WM_SIZE we 
2976           rely on is the one sent when the parent frame resizes its children 
2977           but here is the problem: if the child already has just the right 
2978           size, nothing will happen as both wxWindows and Windows check for 
2979           this and ignore any attempts to change the window size to the size it 
2980           already has - so no WM_SIZE would be sent. 
2984         // as above, h is not used at all in this case anyhow 
2990         // and, again as above, we can't set the height to CW_USEDEFAULT here 
2992         h 
= size
.y 
== -1 ? DEFAULT_H  
: size
.y
; 
3000 WXHWND 
wxWindowMSW::MSWGetParent() const 
3002     return m_parent 
? m_parent
->GetHWND() : WXHWND(NULL
); 
3005 bool wxWindowMSW::MSWCreate(const wxChar 
*wclass
, 
3006                             const wxChar 
*title
, 
3010                             WXDWORD extendedStyle
) 
3012     // choose the position/size for the new window 
3014     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
3016     // controlId is menu handle for the top level windows, so set it to 0 
3017     // unless we're creating a child window 
3018     int controlId 
= style 
& WS_CHILD 
? GetId() : 0; 
3020     // for each class "Foo" we have we also have "FooNR" ("no repaint") class 
3021     // which is the same but without CS_[HV]REDRAW class styles so using it 
3022     // ensures that the window is not fully repainted on each resize 
3023     wxString 
className(wclass
); 
3024     if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE 
) 
3026         className 
+= wxT("NR"); 
3029     // do create the window 
3030     wxWindowCreationHook 
hook(this); 
3033     if (extendedStyle 
== 0) 
3035         m_hWnd 
= (WXHWND
)::CreateWindow
 
3038             title 
? title 
: wxEmptyString
, 
3041             (HWND
)MSWGetParent(), 
3044             NULL                        
// no extra data 
3050         m_hWnd 
= (WXHWND
)::CreateWindowEx
 
3054             title 
? title 
: wxEmptyString
, 
3057             (HWND
)MSWGetParent(), 
3060             NULL                        
// no extra data 
3066         wxLogSysError(_("Can't create window of class %s"), wclass
); 
3071     SubclassWin(m_hWnd
); 
3073     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
3078 // =========================================================================== 
3079 // MSW message handlers 
3080 // =========================================================================== 
3082 // --------------------------------------------------------------------------- 
3084 // --------------------------------------------------------------------------- 
3088 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
3090 #ifndef __WXMICROWIN__ 
3091     LPNMHDR hdr 
= (LPNMHDR
)lParam
; 
3092     HWND hWnd 
= hdr
->hwndFrom
; 
3093     wxWindow 
*win 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
3095     // if the control is one of our windows, let it handle the message itself 
3098         return win
->MSWOnNotify(idCtrl
, lParam
, result
); 
3101     // VZ: why did we do it? normally this is unnecessary and, besides, it 
3102     //     breaks the message processing for the toolbars because the tooltip 
3103     //     notifications were being forwarded to the toolbar child controls 
3104     //     (if it had any) before being passed to the toolbar itself, so in my 
3105     //     example the tooltip for the combobox was always shown instead of the 
3106     //     correct button tooltips 
3108     // try all our children 
3109     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3112         wxWindow 
*child 
= node
->GetData(); 
3113         if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) ) 
3118         node 
= node
->GetNext(); 
3122     // by default, handle it ourselves 
3123     return MSWOnNotify(idCtrl
, lParam
, result
); 
3124 #else // __WXMICROWIN__ 
3131 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
, 
3133                                       const wxString
& ttip
) 
3135     // I don't know why it happens, but the versions of comctl32.dll starting 
3136     // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally, 
3137     // this message is supposed to be sent to Unicode programs only) -- hence 
3138     // we need to handle it as well, otherwise no tooltips will be shown in 
3141     if ( !(code 
== (WXUINT
) TTN_NEEDTEXTA 
|| code 
== (WXUINT
) TTN_NEEDTEXTW
) || ttip
.empty() ) 
3143         // not a tooltip message or no tooltip to show anyhow 
3148     LPTOOLTIPTEXT ttText 
= (LPTOOLTIPTEXT
)lParam
; 
3151     if ( code 
== (WXUINT
) TTN_NEEDTEXTA 
) 
3153         // we pass just the pointer as we store the string internally anyhow 
3154         ttText
->lpszText 
= (char *)ttip
.c_str(); 
3156     else // TTN_NEEDTEXTW 
3160         // in Unicode mode this is just what we need 
3161         ttText
->lpszText 
= (wxChar 
*)ttip
.c_str(); 
3164         MultiByteToWideChar(CP_ACP, 0, ttip, ttip.length()+1, 
3165                             (wchar_t *)ttText->szText, 
3166                             sizeof(ttText->szText) / sizeof(wchar_t)); 
3168         // Fix by dimitrishortcut: see patch 771772 
3170         // FIXME: szText has a max of 80 bytes, so limit the tooltip string 
3171         // length accordingly. Ideally lpszText should be used, but who 
3172         // would be responsible for freeing the buffer? 
3174         // Maximum length of a tip is 39 characters. 39 is 80/2 minus 1 byte 
3175         // needed for NULL character. 
3176         size_t tipLength 
= wxMin(ttip
.Len(), 39); 
3178         // Convert to WideChar without adding the NULL character. The NULL 
3179         // character is added afterwards (Could have used ttip.Left(tipLength) 
3180         // and a cchMultiByte parameter of tipLength+1, but this is more 
3182         ::MultiByteToWideChar(CP_ACP
, 0, ttip
, tipLength
, 
3183                              (wchar_t *)ttText
->szText
, 
3184                              sizeof(ttText
->szText
) / sizeof(wchar_t)); 
3186         // Add the NULL character. 
3187         ttText
->szText
[tipLength
*2+0] = '\0'; 
3188         ttText
->szText
[tipLength
*2+1] = '\0'; 
3190 #endif // Unicode/!Unicode 
3196 #endif // wxUSE_TOOLTIPS 
3198 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
), 
3200                               WXLPARAM
* WXUNUSED(result
)) 
3205         NMHDR
* hdr 
= (NMHDR 
*)lParam
; 
3206         if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip())) 
3212 #endif // wxUSE_TOOLTIPS 
3219 // --------------------------------------------------------------------------- 
3220 // end session messages 
3221 // --------------------------------------------------------------------------- 
3223 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
) 
3226     wxCloseEvent 
event(wxEVT_QUERY_END_SESSION
, -1); 
3227     event
.SetEventObject(wxTheApp
); 
3228     event
.SetCanVeto(TRUE
); 
3229     event
.SetLoggingOff(logOff 
== (long)ENDSESSION_LOGOFF
); 
3231     bool rc 
= wxTheApp
->ProcessEvent(event
); 
3235         // we may end only if the app didn't veto session closing (double 
3237         *mayEnd 
= !event
.GetVeto(); 
3246 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
) 
3249     // do nothing if the session isn't ending 
3254     if ( (this != wxTheApp
->GetTopWindow()) ) 
3257     wxCloseEvent 
event(wxEVT_END_SESSION
, -1); 
3258     event
.SetEventObject(wxTheApp
); 
3259     event
.SetCanVeto(FALSE
); 
3260     event
.SetLoggingOff( (logOff 
== (long)ENDSESSION_LOGOFF
) ); 
3262     return wxTheApp
->ProcessEvent(event
); 
3268 // --------------------------------------------------------------------------- 
3269 // window creation/destruction 
3270 // --------------------------------------------------------------------------- 
3272 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs
, bool *mayCreate
) 
3274     // VZ: why is this commented out for WinCE? If it doesn't support 
3275     //     WS_EX_CONTROLPARENT at all it should be somehow handled globally, 
3276     //     not with multiple #ifdef's! 
3278     if ( ((CREATESTRUCT 
*)cs
)->dwExStyle 
& WS_EX_CONTROLPARENT 
) 
3279         EnsureParentHasControlParentStyle(GetParent()); 
3280 #endif // !__WXWINCE__ 
3282     // TODO: should generate this event from WM_NCCREATE 
3283     wxWindowCreateEvent 
event((wxWindow 
*)this); 
3284     (void)GetEventHandler()->ProcessEvent(event
); 
3291 bool wxWindowMSW::HandleDestroy() 
3295     // delete our drop target if we've got one 
3296 #if wxUSE_DRAG_AND_DROP 
3297     if ( m_dropTarget 
!= NULL 
) 
3299         m_dropTarget
->Revoke(m_hWnd
); 
3301         delete m_dropTarget
; 
3302         m_dropTarget 
= NULL
; 
3304 #endif // wxUSE_DRAG_AND_DROP 
3306     // WM_DESTROY handled 
3310 // --------------------------------------------------------------------------- 
3312 // --------------------------------------------------------------------------- 
3314 bool wxWindowMSW::HandleActivate(int state
, 
3315                               bool WXUNUSED(minimized
), 
3316                               WXHWND 
WXUNUSED(activate
)) 
3318     wxActivateEvent 
event(wxEVT_ACTIVATE
, 
3319                           (state 
== WA_ACTIVE
) || (state 
== WA_CLICKACTIVE
), 
3321     event
.SetEventObject(this); 
3323     return GetEventHandler()->ProcessEvent(event
); 
3326 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
) 
3328     // notify the parent keeping track of focus for the kbd navigation 
3329     // purposes that we got it 
3330     wxChildFocusEvent 
eventFocus((wxWindow 
*)this); 
3331     (void)GetEventHandler()->ProcessEvent(eventFocus
); 
3337         m_caret
->OnSetFocus(); 
3339 #endif // wxUSE_CARET 
3342     // If it's a wxTextCtrl don't send the event as it will be done 
3343     // after the control gets to process it from EN_FOCUS handler 
3344     if ( wxDynamicCastThis(wxTextCtrl
) ) 
3348 #endif // wxUSE_TEXTCTRL 
3350     wxFocusEvent 
event(wxEVT_SET_FOCUS
, m_windowId
); 
3351     event
.SetEventObject(this); 
3353     // wxFindWinFromHandle() may return NULL, it is ok 
3354     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3356     return GetEventHandler()->ProcessEvent(event
); 
3359 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
) 
3365         m_caret
->OnKillFocus(); 
3367 #endif // wxUSE_CARET 
3370     // If it's a wxTextCtrl don't send the event as it will be done 
3371     // after the control gets to process it. 
3372     wxTextCtrl 
*ctrl 
= wxDynamicCastThis(wxTextCtrl
); 
3379     // Don't send the event when in the process of being deleted.  This can 
3380     // only cause problems if the event handler tries to access the object. 
3381     if ( m_isBeingDeleted 
) 
3386     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, m_windowId
); 
3387     event
.SetEventObject(this); 
3389     // wxFindWinFromHandle() may return NULL, it is ok 
3390     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3392     return GetEventHandler()->ProcessEvent(event
); 
3395 // --------------------------------------------------------------------------- 
3397 // --------------------------------------------------------------------------- 
3399 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
)) 
3401     wxShowEvent 
event(GetId(), show
); 
3402     event
.m_eventObject 
= this; 
3404     return GetEventHandler()->ProcessEvent(event
); 
3407 bool wxWindowMSW::HandleInitDialog(WXHWND 
WXUNUSED(hWndFocus
)) 
3409     wxInitDialogEvent 
event(GetId()); 
3410     event
.m_eventObject 
= this; 
3412     return GetEventHandler()->ProcessEvent(event
); 
3415 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
) 
3417 #if defined (__WXMICROWIN__) || defined(__WXWINCE__) 
3419 #else // __WXMICROWIN__ 
3420     HDROP hFilesInfo 
= (HDROP
) wParam
; 
3422     // Get the total number of files dropped 
3423     UINT gwFilesDropped 
= ::DragQueryFile
 
3431     wxString 
*files 
= new wxString
[gwFilesDropped
]; 
3432     for ( UINT wIndex 
= 0; wIndex 
< gwFilesDropped
; wIndex
++ ) 
3434         // first get the needed buffer length (+1 for terminating NUL) 
3435         size_t len 
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1; 
3437         // and now get the file name 
3438         ::DragQueryFile(hFilesInfo
, wIndex
, 
3439                         wxStringBuffer(files
[wIndex
], len
), len
); 
3441     DragFinish (hFilesInfo
); 
3443     wxDropFilesEvent 
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
); 
3444     event
.m_eventObject 
= this; 
3447     DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
); 
3448     event
.m_pos
.x 
= dropPoint
.x
; 
3449     event
.m_pos
.y 
= dropPoint
.y
; 
3451     return GetEventHandler()->ProcessEvent(event
); 
3456 bool wxWindowMSW::HandleSetCursor(WXHWND 
WXUNUSED(hWnd
), 
3458                                   int WXUNUSED(mouseMsg
)) 
3460 #ifndef __WXMICROWIN__ 
3461     // the logic is as follows: 
3462     // -1. don't set cursor for non client area, including but not limited to 
3463     //     the title bar, scrollbars, &c 
3464     //  0. allow the user to override default behaviour by using EVT_SET_CURSOR 
3465     //  1. if we have the cursor set it unless wxIsBusy() 
3466     //  2. if we're a top level window, set some cursor anyhow 
3467     //  3. if wxIsBusy(), set the busy cursor, otherwise the global one 
3469     if ( nHitTest 
!= HTCLIENT 
) 
3474     HCURSOR hcursor 
= 0; 
3476     // first ask the user code - it may wish to set the cursor in some very 
3477     // specific way (for example, depending on the current position) 
3479     if ( !::GetCursorPos(&pt
) ) 
3481         wxLogLastError(wxT("GetCursorPos")); 
3486     ScreenToClient(&x
, &y
); 
3487     wxSetCursorEvent 
event(x
, y
); 
3489     bool processedEvtSetCursor 
= GetEventHandler()->ProcessEvent(event
); 
3490     if ( processedEvtSetCursor 
&& event
.HasCursor() ) 
3492         hcursor 
= GetHcursorOf(event
.GetCursor()); 
3497         bool isBusy 
= wxIsBusy(); 
3499         // the test for processedEvtSetCursor is here to prevent using m_cursor 
3500         // if the user code caught EVT_SET_CURSOR() and returned nothing from 
3501         // it - this is a way to say that our cursor shouldn't be used for this 
3503         if ( !processedEvtSetCursor 
&& m_cursor
.Ok() ) 
3505             hcursor 
= GetHcursorOf(m_cursor
); 
3512                 hcursor 
= wxGetCurrentBusyCursor(); 
3514             else if ( !hcursor 
) 
3516                 const wxCursor 
*cursor 
= wxGetGlobalCursor(); 
3517                 if ( cursor 
&& cursor
->Ok() ) 
3519                     hcursor 
= GetHcursorOf(*cursor
); 
3527 //        wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor); 
3529         ::SetCursor(hcursor
); 
3531         // cursor set, stop here 
3534 #endif // __WXMICROWIN__ 
3536     // pass up the window chain 
3540 // --------------------------------------------------------------------------- 
3541 // owner drawn stuff 
3542 // --------------------------------------------------------------------------- 
3544 #if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \ 
3545         (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)) 
3546     #define WXUNUSED_UNLESS_ODRAWN(param) param 
3548     #define WXUNUSED_UNLESS_ODRAWN(param) 
3552 wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id
), 
3553                            WXDRAWITEMSTRUCT 
* WXUNUSED_UNLESS_ODRAWN(itemStruct
)) 
3555 #if wxUSE_OWNER_DRAWN 
3557 #if wxUSE_MENUS_NATIVE 
3558     // is it a menu item? 
3559     DRAWITEMSTRUCT 
*pDrawStruct 
= (DRAWITEMSTRUCT 
*)itemStruct
; 
3560     if ( id 
== 0 && pDrawStruct
->CtlType 
== ODT_MENU 
) 
3562         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pDrawStruct
->itemData
); 
3564         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE 
); 
3566         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent 
3567         // the DC from being released 
3568         wxDCTemp 
dc((WXHDC
)pDrawStruct
->hDC
); 
3569         wxRect 
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
, 
3570                     pDrawStruct
->rcItem
.right 
- pDrawStruct
->rcItem
.left
, 
3571                     pDrawStruct
->rcItem
.bottom 
- pDrawStruct
->rcItem
.top
); 
3573         return pMenuItem
->OnDrawItem
 
3577                 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
, 
3578                 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
 
3581 #endif // wxUSE_MENUS_NATIVE 
3583 #endif // USE_OWNER_DRAWN 
3585 #if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) 
3587 #if wxUSE_OWNER_DRAWN 
3588     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
3589 #else // !wxUSE_OWNER_DRAWN 
3590     // we may still have owner-drawn buttons internally because we have to make 
3591     // them owner-drawn to support colour change 
3592     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxButton
); 
3593 #endif // USE_OWNER_DRAWN 
3597         return item
->MSWOnDraw(itemStruct
); 
3600 #endif // wxUSE_CONTROLS 
3606 wxWindowMSW::MSWOnMeasureItem(int WXUNUSED_UNLESS_ODRAWN(id
), 
3607                               WXMEASUREITEMSTRUCT 
* 
3608                                   WXUNUSED_UNLESS_ODRAWN(itemStruct
)) 
3610 #if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE 
3611     // is it a menu item? 
3612     MEASUREITEMSTRUCT 
*pMeasureStruct 
= (MEASUREITEMSTRUCT 
*)itemStruct
; 
3613     if ( id 
== 0 && pMeasureStruct
->CtlType 
== ODT_MENU 
) 
3615         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pMeasureStruct
->itemData
); 
3617         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE 
); 
3619         return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
, 
3620                                         &pMeasureStruct
->itemHeight
); 
3623     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
3626         return item
->MSWOnMeasure(itemStruct
); 
3628 #endif // wxUSE_OWNER_DRAWN 
3633 // --------------------------------------------------------------------------- 
3634 // colours and palettes 
3635 // --------------------------------------------------------------------------- 
3637 bool wxWindowMSW::HandleSysColorChange() 
3639     wxSysColourChangedEvent event
; 
3640     event
.SetEventObject(this); 
3642     (void)GetEventHandler()->ProcessEvent(event
); 
3644     // always let the system carry on the default processing to allow the 
3645     // native controls to react to the colours update 
3649 bool wxWindowMSW::HandleDisplayChange() 
3651     wxDisplayChangedEvent event
; 
3652     event
.SetEventObject(this); 
3654     return GetEventHandler()->ProcessEvent(event
); 
3657 bool wxWindowMSW::HandleCtlColor(WXHBRUSH 
*brush
, 
3665 #ifndef __WXMICROWIN__ 
3666     WXHBRUSH hBrush 
= 0; 
3671     if ( nCtlColor 
== CTLCOLOR_DLG 
) 
3674         hBrush 
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3679         wxControl 
*item 
= (wxControl 
*)FindItemByHWND(pWnd
, TRUE
); 
3681             hBrush 
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3683 #endif // wxUSE_CONTROLS 
3689 #else // __WXMICROWIN__ 
3694 // Define for each class of dialog and control 
3695 WXHBRUSH 
wxWindowMSW::OnCtlColor(WXHDC 
WXUNUSED(hDC
), 
3696                                  WXHWND 
WXUNUSED(hWnd
), 
3697                                  WXUINT 
WXUNUSED(nCtlColor
), 
3698                                  WXUINT 
WXUNUSED(message
), 
3699                                  WXWPARAM 
WXUNUSED(wParam
), 
3700                                  WXLPARAM 
WXUNUSED(lParam
)) 
3705 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
) 
3708     // same as below except we don't respond to our own messages 
3709     if ( hWndPalChange 
!= GetHWND() ) 
3711         // check to see if we our our parents have a custom palette 
3712         wxWindowMSW 
*win 
= this; 
3713         while ( win 
&& !win
->HasCustomPalette() ) 
3715             win 
= win
->GetParent(); 
3718         if ( win 
&& win
->HasCustomPalette() ) 
3720             // realize the palette to see whether redrawing is needed 
3721             HDC hdc 
= ::GetDC((HWND
) hWndPalChange
); 
3722             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3723                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3725             int result 
= ::RealizePalette(hdc
); 
3727             // restore the palette (before releasing the DC) 
3728             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3729                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3730             ::RealizePalette(hdc
); 
3731             ::ReleaseDC((HWND
) hWndPalChange
, hdc
); 
3733             // now check for the need to redraw 
3735                 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
); 
3739 #endif // wxUSE_PALETTE 
3741     wxPaletteChangedEvent 
event(GetId()); 
3742     event
.SetEventObject(this); 
3743     event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
)); 
3745     return GetEventHandler()->ProcessEvent(event
); 
3748 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
) 
3750     wxMouseCaptureChangedEvent 
event(GetId(), wxFindWinFromHandle(hWndGainedCapture
)); 
3751     event
.SetEventObject(this); 
3753     return GetEventHandler()->ProcessEvent(event
); 
3756 bool wxWindowMSW::HandleQueryNewPalette() 
3760     // check to see if we our our parents have a custom palette 
3761     wxWindowMSW 
*win 
= this; 
3762     while (!win
->HasCustomPalette() && win
->GetParent()) win 
= win
->GetParent(); 
3763     if (win
->HasCustomPalette()) { 
3764         /* realize the palette to see whether redrawing is needed */ 
3765         HDC hdc 
= GetDC((HWND
) GetHWND()); 
3766         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3767              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) ); 
3769         int result 
= ::RealizePalette(hdc
); 
3770         /* restore the palette (before releasing the DC) */ 
3771         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3772              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) ); 
3773         ::RealizePalette(hdc
); 
3774         ::ReleaseDC((HWND
) GetHWND(), hdc
); 
3775         /* now check for the need to redraw */ 
3777             ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
); 
3779 #endif // wxUSE_PALETTE 
3781     wxQueryNewPaletteEvent 
event(GetId()); 
3782     event
.SetEventObject(this); 
3784     return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized(); 
3787 // Responds to colour changes: passes event on to children. 
3788 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
3790     // the top level window also reset the standard colour map as it might have 
3791     // changed (there is no need to do it for the non top level windows as we 
3792     // only have to do it once) 
3796         gs_hasStdCmap 
= FALSE
; 
3798     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3801         // Only propagate to non-top-level windows because Windows already 
3802         // sends this event to all top-level ones 
3803         wxWindow 
*win 
= node
->GetData(); 
3804         if ( !win
->IsTopLevel() ) 
3806             // we need to send the real WM_SYSCOLORCHANGE and not just trigger 
3807             // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for 
3808             // the standard controls 
3809             ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0); 
3812         node 
= node
->GetNext(); 
3815     // update the colours we use if they were not set explicitly by the user: 
3816     // this must be done or OnCtlColor() would continue to use the old colours 
3819         m_foregroundColour 
= wxSystemSettings:: 
3820                                 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
); 
3825         m_backgroundColour 
= wxSystemSettings:: 
3826                                 GetSystemColour(wxSYS_COLOUR_BTNFACE
); 
3830 extern wxCOLORMAP 
*wxGetStdColourMap() 
3832     static COLORREF s_stdColours
[wxSTD_COL_MAX
]; 
3833     static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
]; 
3835     if ( !gs_hasStdCmap 
) 
3837         static bool s_coloursInit 
= FALSE
; 
3839         if ( !s_coloursInit 
) 
3841             // When a bitmap is loaded, the RGB values can change (apparently 
3842             // because Windows adjusts them to care for the old programs always 
3843             // using 0xc0c0c0 while the transparent colour for the new Windows 
3844             // versions is different). But we do this adjustment ourselves so 
3845             // we want to avoid Windows' "help" and for this we need to have a 
3846             // reference bitmap which can tell us what the RGB values change 
3848             wxBitmap 
stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); 
3849             if ( stdColourBitmap
.Ok() ) 
3851                 // the pixels in the bitmap must correspond to wxSTD_COL_XXX! 
3852                 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
, 
3853                               _T("forgot to update wxBITMAP_STD_COLOURS!") ); 
3856                 memDC
.SelectObject(stdColourBitmap
); 
3859                 for ( size_t i 
= 0; i 
< WXSIZEOF(s_stdColours
); i
++ ) 
3861                     memDC
.GetPixel(i
, 0, &colour
); 
3862                     s_stdColours
[i
] = wxColourToRGB(colour
); 
3865             else // wxBITMAP_STD_COLOURS couldn't be loaded 
3867                 s_stdColours
[0] = RGB(000,000,000);     // black 
3868                 s_stdColours
[1] = RGB(128,128,128);     // dark grey 
3869                 s_stdColours
[2] = RGB(192,192,192);     // light grey 
3870                 s_stdColours
[3] = RGB(255,255,255);     // white 
3871                 //s_stdColours[4] = RGB(000,000,255);     // blue 
3872                 //s_stdColours[5] = RGB(255,000,255);     // magenta 
3875             s_coloursInit 
= TRUE
; 
3878         gs_hasStdCmap 
= TRUE
; 
3880         // create the colour map 
3881 #define INIT_CMAP_ENTRY(col) \ 
3882             s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \ 
3883             s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col) 
3885         INIT_CMAP_ENTRY(BTNTEXT
); 
3886         INIT_CMAP_ENTRY(BTNSHADOW
); 
3887         INIT_CMAP_ENTRY(BTNFACE
); 
3888         INIT_CMAP_ENTRY(BTNHIGHLIGHT
); 
3890 #undef INIT_CMAP_ENTRY 
3896 // --------------------------------------------------------------------------- 
3898 // --------------------------------------------------------------------------- 
3900 bool wxWindowMSW::HandlePaint() 
3902 //    if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) 
3905     HRGN hRegion 
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle 
3907         wxLogLastError(wxT("CreateRectRgn")); 
3908     if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR 
) 
3909         wxLogLastError(wxT("GetUpdateRgn")); 
3911     m_updateRegion 
= wxRegion((WXHRGN
) hRegion
); 
3913     wxPaintEvent 
event(m_windowId
); 
3914     event
.SetEventObject(this); 
3916     bool processed 
= GetEventHandler()->ProcessEvent(event
); 
3918     // note that we must generate NC event after the normal one as otherwise 
3919     // BeginPaint() will happily overwrite our decorations with the background 
3921     wxNcPaintEvent 
eventNc(m_windowId
); 
3922     eventNc
.SetEventObject(this); 
3923     GetEventHandler()->ProcessEvent(eventNc
); 
3928 // Can be called from an application's OnPaint handler 
3929 void wxWindowMSW::OnPaint(wxPaintEvent
& event
) 
3931 #ifdef __WXUNIVERSAL__ 
3934     HDC hDC 
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject()); 
3937         MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0); 
3942 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
) 
3944     // Prevents flicker when dragging 
3945     if ( ::IsIconic(GetHwnd()) ) 
3949     if (GetParent() && GetParent()->GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND
) 
3954     if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND
) 
3956         if (wxUxThemeEngine::Get()) 
3958             WXHTHEME hTheme 
= wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L
"TAB"); 
3962                 ::GetClientRect((HWND
) GetHWND(), (RECT
*) & rect
); 
3963                 wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme
, hdc
, 10 /* TABP_BODY */, 0, &rect
, &rect
); 
3964                 wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme
); 
3974     dc
.SetWindow((wxWindow 
*)this); 
3977     wxEraseEvent 
event(m_windowId
, &dc
); 
3978     event
.SetEventObject(this); 
3979     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
3983     // must be called manually as ~wxDC doesn't do anything for wxDCTemp 
3984     dc
.SelectOldObjects(hdc
); 
3989 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
) 
3992     ::GetClientRect(GetHwnd(), &rect
); 
3994     COLORREF ref 
= PALETTERGB(m_backgroundColour
.Red(), 
3995                               m_backgroundColour
.Green(), 
3996                               m_backgroundColour
.Blue()); 
3997     HBRUSH hBrush 
= ::CreateSolidBrush(ref
); 
3999         wxLogLastError(wxT("CreateSolidBrush")); 
4001     HDC hdc 
= (HDC
)event
.GetDC()->GetHDC(); 
4004     int mode 
= ::SetMapMode(hdc
, MM_TEXT
); 
4007     ::FillRect(hdc
, &rect
, hBrush
); 
4008     ::DeleteObject(hBrush
); 
4011     ::SetMapMode(hdc
, mode
); 
4015 // --------------------------------------------------------------------------- 
4016 // moving and resizing 
4017 // --------------------------------------------------------------------------- 
4019 bool wxWindowMSW::HandleMinimize() 
4021     wxIconizeEvent 
event(m_windowId
); 
4022     event
.SetEventObject(this); 
4024     return GetEventHandler()->ProcessEvent(event
); 
4027 bool wxWindowMSW::HandleMaximize() 
4029     wxMaximizeEvent 
event(m_windowId
); 
4030     event
.SetEventObject(this); 
4032     return GetEventHandler()->ProcessEvent(event
); 
4035 bool wxWindowMSW::HandleMove(int x
, int y
) 
4037     wxMoveEvent 
event(wxPoint(x
, y
), m_windowId
); 
4038     event
.SetEventObject(this); 
4040     return GetEventHandler()->ProcessEvent(event
); 
4043 bool wxWindowMSW::HandleMoving(wxRect
& rect
) 
4045     wxMoveEvent 
event(rect
, m_windowId
); 
4046     event
.SetEventObject(this); 
4048     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4050         rect 
= event
.GetRect(); 
4054 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), 
4055                              WXUINT 
WXUNUSED(flag
)) 
4057     // don't use w and h parameters as they specify the client size while 
4058     // according to the docs EVT_SIZE handler is supposed to receive the total 
4060     wxSizeEvent 
event(GetSize(), m_windowId
); 
4061     event
.SetEventObject(this); 
4063     return GetEventHandler()->ProcessEvent(event
); 
4066 bool wxWindowMSW::HandleSizing(wxRect
& rect
) 
4068     wxSizeEvent 
event(rect
, m_windowId
); 
4069     event
.SetEventObject(this); 
4071     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4073         rect 
= event
.GetRect(); 
4077 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
) 
4082     MINMAXINFO 
*info 
= (MINMAXINFO 
*)mmInfo
; 
4086     int minWidth 
= GetMinWidth(), 
4087         minHeight 
= GetMinHeight(), 
4088         maxWidth 
= GetMaxWidth(), 
4089         maxHeight 
= GetMaxHeight(); 
4091     if ( minWidth 
!= -1 ) 
4093         info
->ptMinTrackSize
.x 
= minWidth
; 
4097     if ( minHeight 
!= -1 ) 
4099         info
->ptMinTrackSize
.y 
= minHeight
; 
4103     if ( maxWidth 
!= -1 ) 
4105         info
->ptMaxTrackSize
.x 
= maxWidth
; 
4109     if ( maxHeight 
!= -1 ) 
4111         info
->ptMaxTrackSize
.y 
= maxHeight
; 
4119 // --------------------------------------------------------------------------- 
4121 // --------------------------------------------------------------------------- 
4123 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
) 
4125 #if wxUSE_MENUS_NATIVE 
4126     if ( !cmd 
&& wxCurrentPopupMenu 
) 
4128         wxMenu 
*popupMenu 
= wxCurrentPopupMenu
; 
4129         wxCurrentPopupMenu 
= NULL
; 
4131         return popupMenu
->MSWCommand(cmd
, id
); 
4133 #endif // wxUSE_MENUS_NATIVE 
4135     wxWindow 
*win 
= NULL
; 
4137     // first try to find it from HWND - this works even with the broken 
4138     // programs using the same ids for different controls 
4141         win 
= wxFindWinFromHandle(control
); 
4147         // must cast to a signed type before comparing with other ids! 
4148         win 
= FindItem((signed short)id
); 
4153         return win
->MSWCommand(cmd
, id
); 
4156     // the messages sent from the in-place edit control used by the treectrl 
4157     // for label editing have id == 0, but they should _not_ be treated as menu 
4158     // messages (they are EN_XXX ones, in fact) so don't translate anything 
4159     // coming from a control to wxEVT_COMMAND_MENU_SELECTED 
4162         // If no child window, it may be an accelerator, e.g. for a popup menu 
4165         wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
); 
4166         event
.SetEventObject(this); 
4170         return GetEventHandler()->ProcessEvent(event
); 
4172 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
4175         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND 
4176         // notifications to its parent which we want to reflect back to 
4178         wxSpinCtrl 
*spin 
= wxSpinCtrl::GetSpinForTextCtrl(control
); 
4179         if ( spin 
&& spin
->ProcessTextCommand(cmd
, id
) ) 
4182 #endif // wxUSE_SPINCTRL 
4187 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM 
WXUNUSED(lParam
)) 
4190     // 4 bits are reserved 
4191     switch ( wParam 
& 0xFFFFFFF0 ) 
4194             return HandleMaximize(); 
4197             return HandleMinimize(); 
4204 // --------------------------------------------------------------------------- 
4206 // --------------------------------------------------------------------------- 
4208 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
, 
4212     // our client coords are not quite the same as Windows ones 
4213     wxPoint pt 
= GetClientAreaOrigin(); 
4214     event
.m_x 
= x 
- pt
.x
; 
4215     event
.m_y 
= y 
- pt
.y
; 
4217     event
.m_shiftDown 
= (flags 
& MK_SHIFT
) != 0; 
4218     event
.m_controlDown 
= (flags 
& MK_CONTROL
) != 0; 
4219     event
.m_leftDown 
= (flags 
& MK_LBUTTON
) != 0; 
4220     event
.m_middleDown 
= (flags 
& MK_MBUTTON
) != 0; 
4221     event
.m_rightDown 
= (flags 
& MK_RBUTTON
) != 0; 
4222  //   event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; 
4223     // Returns different negative values on WinME and WinNT, 
4224     // so simply test for negative value. 
4225     event
.m_altDown 
= ::GetKeyState(VK_MENU
) < 0; 
4228     event
.SetTimestamp(::GetMessageTime()); 
4231     event
.m_eventObject 
= this; 
4232     event
.SetId(GetId()); 
4234 #if wxUSE_MOUSEEVENT_HACK 
4237     m_lastMouseEvent 
= event
.GetEventType(); 
4238 #endif // wxUSE_MOUSEEVENT_HACK 
4241 // Windows doesn't send the mouse events to the static controls (which are 
4242 // transparent in the sense that their WM_NCHITTEST handler returns 
4243 // HTTRANSPARENT) at all but we want all controls to receive the mouse events 
4244 // and so we manually check if we don't have a child window under mouse and if 
4245 // we do, send the event to it instead of the window Windows had sent WM_XXX 
4248 // Notice that this is not done for the mouse move events because this could 
4249 // (would?) be too slow, but only for clicks which means that the static texts 
4250 // still don't get move, enter nor leave events. 
4251 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
) //TW:REQ:Univ 
4253     wxCHECK_MSG( x 
&& y
, win
, _T("NULL pointer in FindWindowForMouseEvent") ); 
4255     // first try to find a non transparent child: this allows us to send events 
4256     // to a static text which is inside a static box, for example 
4257     POINT pt 
= { *x
, *y 
}; 
4258     HWND hwnd 
= GetHwndOf(win
), 
4262     hwndUnderMouse 
= ::ChildWindowFromPoint
 
4268     hwndUnderMouse 
= ::ChildWindowFromPointEx
 
4278     if ( !hwndUnderMouse 
|| hwndUnderMouse 
== hwnd 
) 
4280         // now try any child window at all 
4281         hwndUnderMouse 
= ::ChildWindowFromPoint(hwnd
, pt
); 
4284     // check that we have a child window which is susceptible to receive mouse 
4285     // events: for this it must be shown and enabled 
4286     if ( hwndUnderMouse 
&& 
4287             hwndUnderMouse 
!= hwnd 
&& 
4288                 ::IsWindowVisible(hwndUnderMouse
) && 
4289                     ::IsWindowEnabled(hwndUnderMouse
) ) 
4291         wxWindow 
*winUnderMouse 
= wxFindWinFromHandle((WXHWND
)hwndUnderMouse
); 
4292         if ( winUnderMouse 
) 
4294             // translate the mouse coords to the other window coords 
4295             win
->ClientToScreen(x
, y
); 
4296             winUnderMouse
->ScreenToClient(x
, y
); 
4298             win 
= winUnderMouse
; 
4305 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4307     // the mouse events take consecutive IDs from WM_MOUSEFIRST to 
4308     // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST 
4309     // from the message id and take the value in the table to get wxWin event 
4311     static const wxEventType eventsMouse
[] = 
4325     wxMouseEvent 
event(eventsMouse
[msg 
- WM_MOUSEMOVE
]); 
4326     InitMouseEvent(event
, x
, y
, flags
); 
4328     return GetEventHandler()->ProcessEvent(event
); 
4331 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
) 
4333     if ( !m_mouseInWindow 
) 
4335         // it would be wrong to assume that just because we get a mouse move 
4336         // event that the mouse is inside the window: although this is usually 
4337         // true, it is not if we had captured the mouse, so we need to check 
4338         // the mouse coordinates here 
4339         if ( !HasCapture() || IsMouseInWindow() ) 
4341             // Generate an ENTER event 
4342             m_mouseInWindow 
= TRUE
; 
4344             wxMouseEvent 
event(wxEVT_ENTER_WINDOW
); 
4345             InitMouseEvent(event
, x
, y
, flags
); 
4347             (void)GetEventHandler()->ProcessEvent(event
); 
4351 #if wxUSE_MOUSEEVENT_HACK 
4352     // Window gets a click down message followed by a mouse move message even 
4353     // if position isn't changed!  We want to discard the trailing move event 
4354     // if x and y are the same. 
4355     if ( (m_lastMouseEvent 
== wxEVT_RIGHT_DOWN 
|| 
4356           m_lastMouseEvent 
== wxEVT_LEFT_DOWN 
|| 
4357           m_lastMouseEvent 
== wxEVT_MIDDLE_DOWN
) && 
4358          (m_lastMouseX 
== x 
&& m_lastMouseY 
== y
) ) 
4360         m_lastMouseEvent 
= wxEVT_MOTION
; 
4364 #endif // wxUSE_MOUSEEVENT_HACK 
4366     return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
); 
4370 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
) 
4372 #if wxUSE_MOUSEWHEEL 
4373     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
4374     InitMouseEvent(event
, 
4375                    GET_X_LPARAM(lParam
), 
4376                    GET_Y_LPARAM(lParam
), 
4378     event
.m_wheelRotation 
= (short)HIWORD(wParam
); 
4379     event
.m_wheelDelta 
= WHEEL_DELTA
; 
4381     static int s_linesPerRotation 
= -1; 
4382     if ( s_linesPerRotation 
== -1 ) 
4384         if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, 
4385                                      &s_linesPerRotation
, 0)) 
4387             // this is not supposed to happen 
4388             wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)")); 
4390             // the default is 3, so use it if SystemParametersInfo() failed 
4391             s_linesPerRotation 
= 3; 
4395     event
.m_linesPerAction 
= s_linesPerRotation
; 
4396     return GetEventHandler()->ProcessEvent(event
); 
4407 // --------------------------------------------------------------------------- 
4408 // keyboard handling 
4409 // --------------------------------------------------------------------------- 
4411 // create the key event of the given type for the given key - used by 
4412 // HandleChar and HandleKeyDown/Up 
4413 wxKeyEvent 
wxWindowMSW::CreateKeyEvent(wxEventType evType
, 
4416                                        WXWPARAM wParam
) const 
4418     wxKeyEvent 
event(evType
); 
4419     event
.SetId(GetId()); 
4420     event
.m_shiftDown 
= wxIsShiftDown(); 
4421     event
.m_controlDown 
= wxIsCtrlDown(); 
4422     event
.m_altDown 
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
; 
4424     event
.m_eventObject 
= (wxWindow 
*)this; // const_cast 
4425     event
.m_keyCode 
= id
; 
4426     event
.m_rawCode 
= (wxUint32
) wParam
; 
4427     event
.m_rawFlags 
= (wxUint32
) lParam
; 
4429     event
.SetTimestamp(::GetMessageTime()); 
4432     // translate the position to client coords 
4436     GetWindowRect(GetHwnd(),&rect
); 
4446 // isASCII is TRUE only when we're called from WM_CHAR handler and not from 
4448 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
) 
4453         // If 1 -> 26, translate to either special keycode or just set 
4454         // ctrlDown.  IOW, Ctrl-C should result in keycode == 3 and 
4455         // ControlDown() == TRUE. 
4457         if ( (id 
> 0) && (id 
< 27) ) 
4479     else // we're called from WM_KEYDOWN 
4481         id 
= wxCharCodeMSWToWX(wParam
); 
4484             // it's ASCII and will be processed here only when called from 
4485             // WM_CHAR (i.e. when isASCII = TRUE), don't process it now 
4490     wxKeyEvent 
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
)); 
4492     // the alphanumeric keys produced by pressing AltGr+something on European 
4493     // keyboards have both Ctrl and Alt modifiers which may confuse the user 
4494     // code as, normally, keys with Ctrl and/or Alt don't result in anything 
4495     // alphanumeric, so pretend that there are no modifiers at all (the 
4496     // KEY_DOWN event would still have the correct modifiers if they're really 
4498     if ( event
.m_controlDown 
&& event
.m_altDown 
&& 
4499             (id 
>= 32 && id 
< 256) ) 
4501         event
.m_controlDown 
= 
4502         event
.m_altDown 
= FALSE
; 
4505     return GetEventHandler()->ProcessEvent(event
); 
4508 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
) 
4510     int id 
= wxCharCodeMSWToWX(wParam
); 
4514         // normal ASCII char 
4518     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4520         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
)); 
4521         if ( GetEventHandler()->ProcessEvent(event
) ) 
4530 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
) 
4532     int id 
= wxCharCodeMSWToWX(wParam
); 
4536         // normal ASCII char 
4540     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4542         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
)); 
4543         if ( GetEventHandler()->ProcessEvent(event
) ) 
4550 int wxWindowMSW::HandleMenuChar(int chAccel
, WXLPARAM lParam
) 
4552     // FIXME: implement GetMenuItemCount for WinCE, possibly 
4553     // in terms of GetMenuItemInfo 
4555     const HMENU hmenu 
= (HMENU
)lParam
; 
4559     mii
.cbSize 
= sizeof(MENUITEMINFO
); 
4560     mii
.fMask 
= MIIM_TYPE 
| MIIM_DATA
; 
4562     // find if we have this letter in any owner drawn item 
4563     const int count 
= ::GetMenuItemCount(hmenu
); 
4564     for ( int i 
= 0; i 
< count
; i
++ ) 
4566         if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) ) 
4568             if ( mii
.fType 
== MFT_OWNERDRAW 
) 
4570                 //  dwItemData member of the MENUITEMINFO is a 
4571                 //  pointer to the associated wxMenuItem -- see the 
4572                 //  menu creation code 
4573                 wxMenuItem 
*item 
= (wxMenuItem
*)mii
.dwItemData
; 
4575                 const wxChar 
*p 
= wxStrchr(item
->GetText(), _T('&')); 
4578                     if ( *p 
== _T('&') ) 
4580                         // this is not the accel char, find the real one 
4581                         p 
= wxStrchr(p 
+ 1, _T('&')); 
4583                     else // got the accel char 
4585                         // FIXME-UNICODE: this comparison doesn't risk to work 
4586                         // for non ASCII accelerator characters I'm afraid, but 
4588                         if ( wxToupper(*p
) == chAccel 
) 
4594                             // this one doesn't match 
4601         else // failed to get the menu text? 
4603             // it's not fatal, so don't show error, but still log 
4605             wxLogLastError(_T("GetMenuItemInfo")); 
4612 // --------------------------------------------------------------------------- 
4614 // --------------------------------------------------------------------------- 
4616 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4620     if ( flags 
& JOY_BUTTON1CHG 
) 
4621         change 
= wxJOY_BUTTON1
; 
4622     if ( flags 
& JOY_BUTTON2CHG 
) 
4623         change 
= wxJOY_BUTTON2
; 
4624     if ( flags 
& JOY_BUTTON3CHG 
) 
4625         change 
= wxJOY_BUTTON3
; 
4626     if ( flags 
& JOY_BUTTON4CHG 
) 
4627         change 
= wxJOY_BUTTON4
; 
4630     if ( flags 
& JOY_BUTTON1 
) 
4631         buttons 
|= wxJOY_BUTTON1
; 
4632     if ( flags 
& JOY_BUTTON2 
) 
4633         buttons 
|= wxJOY_BUTTON2
; 
4634     if ( flags 
& JOY_BUTTON3 
) 
4635         buttons 
|= wxJOY_BUTTON3
; 
4636     if ( flags 
& JOY_BUTTON4 
) 
4637         buttons 
|= wxJOY_BUTTON4
; 
4639     // the event ids aren't consecutive so we can't use table based lookup 
4641     wxEventType eventType
; 
4646             eventType 
= wxEVT_JOY_MOVE
; 
4651             eventType 
= wxEVT_JOY_MOVE
; 
4656             eventType 
= wxEVT_JOY_ZMOVE
; 
4661             eventType 
= wxEVT_JOY_ZMOVE
; 
4664         case MM_JOY1BUTTONDOWN
: 
4666             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4669         case MM_JOY2BUTTONDOWN
: 
4671             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4674         case MM_JOY1BUTTONUP
: 
4676             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4679         case MM_JOY2BUTTONUP
: 
4681             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4685             wxFAIL_MSG(wxT("no such joystick event")); 
4690     wxJoystickEvent 
event(eventType
, buttons
, joystick
, change
); 
4691     event
.SetPosition(wxPoint(x
, y
)); 
4692     event
.SetEventObject(this); 
4694     return GetEventHandler()->ProcessEvent(event
); 
4700 // --------------------------------------------------------------------------- 
4702 // --------------------------------------------------------------------------- 
4704 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
, 
4705                               WXWORD pos
, WXHWND control
) 
4709         wxWindow 
*child 
= wxFindWinFromHandle(control
); 
4711             return child
->MSWOnScroll(orientation
, wParam
, pos
, control
); 
4714     wxScrollWinEvent event
; 
4715     event
.SetPosition(pos
); 
4716     event
.SetOrientation(orientation
); 
4717     event
.m_eventObject 
= this; 
4722         event
.m_eventType 
= wxEVT_SCROLLWIN_TOP
; 
4726         event
.m_eventType 
= wxEVT_SCROLLWIN_BOTTOM
; 
4730         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEUP
; 
4734         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEDOWN
; 
4738         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEUP
; 
4742         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEDOWN
; 
4745     case SB_THUMBPOSITION
: 
4747         // under Win32, the scrollbar range and position are 32 bit integers, 
4748         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must 
4749         // explicitly query the scrollbar for the correct position (this must 
4750         // be done only for these two SB_ events as they are the only one 
4751         // carrying the scrollbar position) 
4753             WinStruct
<SCROLLINFO
> scrollInfo
; 
4754             scrollInfo
.fMask 
= SIF_TRACKPOS
; 
4756             if ( !::GetScrollInfo(GetHwnd(), 
4757                                   orientation 
== wxHORIZONTAL 
? SB_HORZ
 
4761                 // Not neccessarily an error, if there are no scrollbars yet. 
4762                 // wxLogLastError(_T("GetScrollInfo")); 
4765             event
.SetPosition(scrollInfo
.nTrackPos
); 
4768         event
.m_eventType 
= wParam 
== SB_THUMBPOSITION
 
4769                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
 
4770                                 : wxEVT_SCROLLWIN_THUMBTRACK
; 
4777     return GetEventHandler()->ProcessEvent(event
); 
4780 // =========================================================================== 
4782 // =========================================================================== 
4784 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont 
*the_font
) 
4787     HDC dc 
= ::GetDC((HWND
) wnd
); 
4792         //    the_font->UseResource(); 
4793         //    the_font->RealizeResource(); 
4794         fnt 
= (HFONT
)((wxFont 
*)the_font
)->GetResourceHandle(); // const_cast 
4796             was 
= (HFONT
) SelectObject(dc
,fnt
); 
4798     GetTextMetrics(dc
, &tm
); 
4799     if ( the_font 
&& fnt 
&& was 
) 
4801         SelectObject(dc
,was
); 
4803     ReleaseDC((HWND
)wnd
, dc
); 
4806         *x 
= tm
.tmAveCharWidth
; 
4808         *y 
= tm
.tmHeight 
+ tm
.tmExternalLeading
; 
4811     //    the_font->ReleaseResource(); 
4814 // Returns 0 if was a normal ASCII value, not a special key. This indicates that 
4815 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. 
4816 int wxCharCodeMSWToWX(int keySym
) 
4821         case VK_CANCEL
:     id 
= WXK_CANCEL
; break; 
4822         case VK_BACK
:       id 
= WXK_BACK
; break; 
4823         case VK_TAB
:        id 
= WXK_TAB
; break; 
4824         case VK_CLEAR
:      id 
= WXK_CLEAR
; break; 
4825         case VK_RETURN
:     id 
= WXK_RETURN
; break; 
4826         case VK_SHIFT
:      id 
= WXK_SHIFT
; break; 
4827         case VK_CONTROL
:    id 
= WXK_CONTROL
; break; 
4828         case VK_MENU 
:      id 
= WXK_MENU
; break; 
4829         case VK_PAUSE
:      id 
= WXK_PAUSE
; break; 
4830         case VK_CAPITAL
:    id 
= WXK_CAPITAL
; break; 
4831         case VK_SPACE
:      id 
= WXK_SPACE
; break; 
4832         case VK_ESCAPE
:     id 
= WXK_ESCAPE
; break; 
4833         case VK_PRIOR
:      id 
= WXK_PRIOR
; break; 
4834         case VK_NEXT 
:      id 
= WXK_NEXT
; break; 
4835         case VK_END
:        id 
= WXK_END
; break; 
4836         case VK_HOME 
:      id 
= WXK_HOME
; break; 
4837         case VK_LEFT 
:      id 
= WXK_LEFT
; break; 
4838         case VK_UP
:         id 
= WXK_UP
; break; 
4839         case VK_RIGHT
:      id 
= WXK_RIGHT
; break; 
4840         case VK_DOWN 
:      id 
= WXK_DOWN
; break; 
4841         case VK_SELECT
:     id 
= WXK_SELECT
; break; 
4842         case VK_PRINT
:      id 
= WXK_PRINT
; break; 
4843         case VK_EXECUTE
:    id 
= WXK_EXECUTE
; break; 
4844         case VK_INSERT
:     id 
= WXK_INSERT
; break; 
4845         case VK_DELETE
:     id 
= WXK_DELETE
; break; 
4846         case VK_HELP 
:      id 
= WXK_HELP
; break; 
4847         case VK_NUMPAD0
:    id 
= WXK_NUMPAD0
; break; 
4848         case VK_NUMPAD1
:    id 
= WXK_NUMPAD1
; break; 
4849         case VK_NUMPAD2
:    id 
= WXK_NUMPAD2
; break; 
4850         case VK_NUMPAD3
:    id 
= WXK_NUMPAD3
; break; 
4851         case VK_NUMPAD4
:    id 
= WXK_NUMPAD4
; break; 
4852         case VK_NUMPAD5
:    id 
= WXK_NUMPAD5
; break; 
4853         case VK_NUMPAD6
:    id 
= WXK_NUMPAD6
; break; 
4854         case VK_NUMPAD7
:    id 
= WXK_NUMPAD7
; break; 
4855         case VK_NUMPAD8
:    id 
= WXK_NUMPAD8
; break; 
4856         case VK_NUMPAD9
:    id 
= WXK_NUMPAD9
; break; 
4857         case VK_MULTIPLY
:   id 
= WXK_NUMPAD_MULTIPLY
; break; 
4858         case VK_ADD
:        id 
= WXK_NUMPAD_ADD
; break; 
4859         case VK_SUBTRACT
:   id 
= WXK_NUMPAD_SUBTRACT
; break; 
4860         case VK_DECIMAL
:    id 
= WXK_NUMPAD_DECIMAL
; break; 
4861         case VK_DIVIDE
:     id 
= WXK_NUMPAD_DIVIDE
; break; 
4862         case VK_F1
:         id 
= WXK_F1
; break; 
4863         case VK_F2
:         id 
= WXK_F2
; break; 
4864         case VK_F3
:         id 
= WXK_F3
; break; 
4865         case VK_F4
:         id 
= WXK_F4
; break; 
4866         case VK_F5
:         id 
= WXK_F5
; break; 
4867         case VK_F6
:         id 
= WXK_F6
; break; 
4868         case VK_F7
:         id 
= WXK_F7
; break; 
4869         case VK_F8
:         id 
= WXK_F8
; break; 
4870         case VK_F9
:         id 
= WXK_F9
; break; 
4871         case VK_F10
:        id 
= WXK_F10
; break; 
4872         case VK_F11
:        id 
= WXK_F11
; break; 
4873         case VK_F12
:        id 
= WXK_F12
; break; 
4874         case VK_F13
:        id 
= WXK_F13
; break; 
4875         case VK_F14
:        id 
= WXK_F14
; break; 
4876         case VK_F15
:        id 
= WXK_F15
; break; 
4877         case VK_F16
:        id 
= WXK_F16
; break; 
4878         case VK_F17
:        id 
= WXK_F17
; break; 
4879         case VK_F18
:        id 
= WXK_F18
; break; 
4880         case VK_F19
:        id 
= WXK_F19
; break; 
4881         case VK_F20
:        id 
= WXK_F20
; break; 
4882         case VK_F21
:        id 
= WXK_F21
; break; 
4883         case VK_F22
:        id 
= WXK_F22
; break; 
4884         case VK_F23
:        id 
= WXK_F23
; break; 
4885         case VK_F24
:        id 
= WXK_F24
; break; 
4886         case VK_NUMLOCK
:    id 
= WXK_NUMLOCK
; break; 
4887         case VK_SCROLL
:     id 
= WXK_SCROLL
; break; 
4889         case VK_OEM_1
:      id 
= ';'; break; 
4890         case VK_OEM_PLUS
:   id 
= '+'; break; 
4891         case VK_OEM_COMMA
:  id 
= ','; break; 
4892         case VK_OEM_MINUS
:  id 
= '-'; break; 
4893         case VK_OEM_PERIOD
: id 
= '.'; break; 
4894         case VK_OEM_2
:      id 
= '/'; break; 
4895         case VK_OEM_3
:      id 
= '~'; break; 
4896         case VK_OEM_4
:      id 
= '['; break; 
4897         case VK_OEM_5
:      id 
= '\\'; break; 
4898         case VK_OEM_6
:      id 
= ']'; break; 
4899         case VK_OEM_7
:      id 
= '\''; break; 
4902         case VK_LWIN
:       id 
= WXK_WINDOWS_LEFT
; break; 
4903         case VK_RWIN
:       id 
= WXK_WINDOWS_RIGHT
; break; 
4904         case VK_APPS
:       id 
= WXK_WINDOWS_MENU
; break; 
4905 #endif // VK_APPS defined 
4914 int wxCharCodeWXToMSW(int id
, bool *isVirtual
) 
4920     case WXK_CANCEL
:    keySym 
= VK_CANCEL
; break; 
4921     case WXK_CLEAR
:     keySym 
= VK_CLEAR
; break; 
4922     case WXK_SHIFT
:     keySym 
= VK_SHIFT
; break; 
4923     case WXK_CONTROL
:   keySym 
= VK_CONTROL
; break; 
4924     case WXK_MENU 
:     keySym 
= VK_MENU
; break; 
4925     case WXK_PAUSE
:     keySym 
= VK_PAUSE
; break; 
4926     case WXK_PRIOR
:     keySym 
= VK_PRIOR
; break; 
4927     case WXK_NEXT 
:     keySym 
= VK_NEXT
; break; 
4928     case WXK_END
:       keySym 
= VK_END
; break; 
4929     case WXK_HOME 
:     keySym 
= VK_HOME
; break; 
4930     case WXK_LEFT 
:     keySym 
= VK_LEFT
; break; 
4931     case WXK_UP
:        keySym 
= VK_UP
; break; 
4932     case WXK_RIGHT
:     keySym 
= VK_RIGHT
; break; 
4933     case WXK_DOWN 
:     keySym 
= VK_DOWN
; break; 
4934     case WXK_SELECT
:    keySym 
= VK_SELECT
; break; 
4935     case WXK_PRINT
:     keySym 
= VK_PRINT
; break; 
4936     case WXK_EXECUTE
:   keySym 
= VK_EXECUTE
; break; 
4937     case WXK_INSERT
:    keySym 
= VK_INSERT
; break; 
4938     case WXK_DELETE
:    keySym 
= VK_DELETE
; break; 
4939     case WXK_HELP 
:     keySym 
= VK_HELP
; break; 
4940     case WXK_NUMPAD0
:   keySym 
= VK_NUMPAD0
; break; 
4941     case WXK_NUMPAD1
:   keySym 
= VK_NUMPAD1
; break; 
4942     case WXK_NUMPAD2
:   keySym 
= VK_NUMPAD2
; break; 
4943     case WXK_NUMPAD3
:   keySym 
= VK_NUMPAD3
; break; 
4944     case WXK_NUMPAD4
:   keySym 
= VK_NUMPAD4
; break; 
4945     case WXK_NUMPAD5
:   keySym 
= VK_NUMPAD5
; break; 
4946     case WXK_NUMPAD6
:   keySym 
= VK_NUMPAD6
; break; 
4947     case WXK_NUMPAD7
:   keySym 
= VK_NUMPAD7
; break; 
4948     case WXK_NUMPAD8
:   keySym 
= VK_NUMPAD8
; break; 
4949     case WXK_NUMPAD9
:   keySym 
= VK_NUMPAD9
; break; 
4950     case WXK_NUMPAD_MULTIPLY
:  keySym 
= VK_MULTIPLY
; break; 
4951     case WXK_NUMPAD_ADD
:       keySym 
= VK_ADD
; break; 
4952     case WXK_NUMPAD_SUBTRACT
:  keySym 
= VK_SUBTRACT
; break; 
4953     case WXK_NUMPAD_DECIMAL
:   keySym 
= VK_DECIMAL
; break; 
4954     case WXK_NUMPAD_DIVIDE
:    keySym 
= VK_DIVIDE
; break; 
4955     case WXK_F1
:        keySym 
= VK_F1
; break; 
4956     case WXK_F2
:        keySym 
= VK_F2
; break; 
4957     case WXK_F3
:        keySym 
= VK_F3
; break; 
4958     case WXK_F4
:        keySym 
= VK_F4
; break; 
4959     case WXK_F5
:        keySym 
= VK_F5
; break; 
4960     case WXK_F6
:        keySym 
= VK_F6
; break; 
4961     case WXK_F7
:        keySym 
= VK_F7
; break; 
4962     case WXK_F8
:        keySym 
= VK_F8
; break; 
4963     case WXK_F9
:        keySym 
= VK_F9
; break; 
4964     case WXK_F10
:       keySym 
= VK_F10
; break; 
4965     case WXK_F11
:       keySym 
= VK_F11
; break; 
4966     case WXK_F12
:       keySym 
= VK_F12
; break; 
4967     case WXK_F13
:       keySym 
= VK_F13
; break; 
4968     case WXK_F14
:       keySym 
= VK_F14
; break; 
4969     case WXK_F15
:       keySym 
= VK_F15
; break; 
4970     case WXK_F16
:       keySym 
= VK_F16
; break; 
4971     case WXK_F17
:       keySym 
= VK_F17
; break; 
4972     case WXK_F18
:       keySym 
= VK_F18
; break; 
4973     case WXK_F19
:       keySym 
= VK_F19
; break; 
4974     case WXK_F20
:       keySym 
= VK_F20
; break; 
4975     case WXK_F21
:       keySym 
= VK_F21
; break; 
4976     case WXK_F22
:       keySym 
= VK_F22
; break; 
4977     case WXK_F23
:       keySym 
= VK_F23
; break; 
4978     case WXK_F24
:       keySym 
= VK_F24
; break; 
4979     case WXK_NUMLOCK
:   keySym 
= VK_NUMLOCK
; break; 
4980     case WXK_SCROLL
:    keySym 
= VK_SCROLL
; break; 
4991 wxWindow 
*wxGetActiveWindow() 
4993     HWND hWnd 
= GetActiveWindow(); 
4996         return wxFindWinFromHandle((WXHWND
) hWnd
); 
5001 extern wxWindow 
*wxGetWindowFromHWND(WXHWND hWnd
) 
5003     HWND hwnd 
= (HWND
)hWnd
; 
5005     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set 
5006     // by code in msw/radiobox.cpp), for all the others we just search up the 
5008     wxWindow 
*win 
= (wxWindow 
*)NULL
; 
5011         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
5015             // native radiobuttons return DLGC_RADIOBUTTON here and for any 
5016             // wxWindow class which overrides WM_GETDLGCODE processing to 
5017             // do it as well, win would be already non NULL 
5018             if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON 
) 
5020                 win 
= (wxWindow 
*)::GetWindowLong(hwnd
, GWL_USERDATA
); 
5022             //else: it's a wxRadioButton, not a radiobutton from wxRadioBox 
5023 #endif // wxUSE_RADIOBOX 
5025             // spin control text buddy window should be mapped to spin ctrl 
5026             // itself so try it too 
5027 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
5030                 win 
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
); 
5032 #endif // wxUSE_SPINCTRL 
5036     while ( hwnd 
&& !win 
) 
5038         // this is a really ugly hack needed to avoid mistakenly returning the 
5039         // parent frame wxWindow for the find/replace modeless dialog HWND - 
5040         // this, in turn, is needed to call IsDialogMessage() from 
5041         // wxApp::ProcessMessage() as for this we must return NULL from here 
5043         // FIXME: this is clearly not the best way to do it but I think we'll 
5044         //        need to change HWND <-> wxWindow code more heavily than I can 
5045         //        do it now to fix it 
5046 #ifndef __WXMICROWIN__ 
5047         if ( ::GetWindow(hwnd
, GW_OWNER
) ) 
5049             // it's a dialog box, don't go upwards 
5054         hwnd 
= ::GetParent(hwnd
); 
5055         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
5061 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
5063 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE 
5064 // in active frames and dialogs, regardless of where the focus is. 
5065 static HHOOK wxTheKeyboardHook 
= 0; 
5066 static FARPROC wxTheKeyboardHookProc 
= 0; 
5067 int APIENTRY _EXPORT
 
5068 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
); 
5070 void wxSetKeyboardHook(bool doIt
) 
5074         wxTheKeyboardHookProc 
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance()); 
5075         wxTheKeyboardHook 
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(), 
5077             GetCurrentThreadId() 
5078         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? 
5083         UnhookWindowsHookEx(wxTheKeyboardHook
); 
5087 int APIENTRY _EXPORT
 
5088 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
) 
5090     DWORD hiWord 
= HIWORD(lParam
); 
5091     if ( nCode 
!= HC_NOREMOVE 
&& ((hiWord 
& KF_UP
) == 0) ) 
5093         int id 
= wxCharCodeMSWToWX(wParam
); 
5096             wxKeyEvent 
event(wxEVT_CHAR_HOOK
); 
5097             if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
5098                 event
.m_altDown 
= TRUE
; 
5100             event
.m_eventObject 
= NULL
; 
5101             event
.m_keyCode 
= id
; 
5102             event
.m_shiftDown 
= wxIsShiftDown(); 
5103             event
.m_controlDown 
= wxIsCtrlDown(); 
5105             event
.SetTimestamp(::GetMessageTime()); 
5107             wxWindow 
*win 
= wxGetActiveWindow(); 
5108             wxEvtHandler 
*handler
; 
5111                 handler 
= win
->GetEventHandler(); 
5112                 event
.SetId(win
->GetId()); 
5120             if ( handler 
&& handler
->ProcessEvent(event
) ) 
5128     return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
); 
5131 #endif // !__WXMICROWIN__ 
5134 const char *wxGetMessageName(int message
) 
5138         case 0x0000: return "WM_NULL"; 
5139         case 0x0001: return "WM_CREATE"; 
5140         case 0x0002: return "WM_DESTROY"; 
5141         case 0x0003: return "WM_MOVE"; 
5142         case 0x0005: return "WM_SIZE"; 
5143         case 0x0006: return "WM_ACTIVATE"; 
5144         case 0x0007: return "WM_SETFOCUS"; 
5145         case 0x0008: return "WM_KILLFOCUS"; 
5146         case 0x000A: return "WM_ENABLE"; 
5147         case 0x000B: return "WM_SETREDRAW"; 
5148         case 0x000C: return "WM_SETTEXT"; 
5149         case 0x000D: return "WM_GETTEXT"; 
5150         case 0x000E: return "WM_GETTEXTLENGTH"; 
5151         case 0x000F: return "WM_PAINT"; 
5152         case 0x0010: return "WM_CLOSE"; 
5153         case 0x0011: return "WM_QUERYENDSESSION"; 
5154         case 0x0012: return "WM_QUIT"; 
5155         case 0x0013: return "WM_QUERYOPEN"; 
5156         case 0x0014: return "WM_ERASEBKGND"; 
5157         case 0x0015: return "WM_SYSCOLORCHANGE"; 
5158         case 0x0016: return "WM_ENDSESSION"; 
5159         case 0x0017: return "WM_SYSTEMERROR"; 
5160         case 0x0018: return "WM_SHOWWINDOW"; 
5161         case 0x0019: return "WM_CTLCOLOR"; 
5162         case 0x001A: return "WM_WININICHANGE"; 
5163         case 0x001B: return "WM_DEVMODECHANGE"; 
5164         case 0x001C: return "WM_ACTIVATEAPP"; 
5165         case 0x001D: return "WM_FONTCHANGE"; 
5166         case 0x001E: return "WM_TIMECHANGE"; 
5167         case 0x001F: return "WM_CANCELMODE"; 
5168         case 0x0020: return "WM_SETCURSOR"; 
5169         case 0x0021: return "WM_MOUSEACTIVATE"; 
5170         case 0x0022: return "WM_CHILDACTIVATE"; 
5171         case 0x0023: return "WM_QUEUESYNC"; 
5172         case 0x0024: return "WM_GETMINMAXINFO"; 
5173         case 0x0026: return "WM_PAINTICON"; 
5174         case 0x0027: return "WM_ICONERASEBKGND"; 
5175         case 0x0028: return "WM_NEXTDLGCTL"; 
5176         case 0x002A: return "WM_SPOOLERSTATUS"; 
5177         case 0x002B: return "WM_DRAWITEM"; 
5178         case 0x002C: return "WM_MEASUREITEM"; 
5179         case 0x002D: return "WM_DELETEITEM"; 
5180         case 0x002E: return "WM_VKEYTOITEM"; 
5181         case 0x002F: return "WM_CHARTOITEM"; 
5182         case 0x0030: return "WM_SETFONT"; 
5183         case 0x0031: return "WM_GETFONT"; 
5184         case 0x0037: return "WM_QUERYDRAGICON"; 
5185         case 0x0039: return "WM_COMPAREITEM"; 
5186         case 0x0041: return "WM_COMPACTING"; 
5187         case 0x0044: return "WM_COMMNOTIFY"; 
5188         case 0x0046: return "WM_WINDOWPOSCHANGING"; 
5189         case 0x0047: return "WM_WINDOWPOSCHANGED"; 
5190         case 0x0048: return "WM_POWER"; 
5192         case 0x004A: return "WM_COPYDATA"; 
5193         case 0x004B: return "WM_CANCELJOURNAL"; 
5194         case 0x004E: return "WM_NOTIFY"; 
5195         case 0x0050: return "WM_INPUTLANGCHANGEREQUEST"; 
5196         case 0x0051: return "WM_INPUTLANGCHANGE"; 
5197         case 0x0052: return "WM_TCARD"; 
5198         case 0x0053: return "WM_HELP"; 
5199         case 0x0054: return "WM_USERCHANGED"; 
5200         case 0x0055: return "WM_NOTIFYFORMAT"; 
5201         case 0x007B: return "WM_CONTEXTMENU"; 
5202         case 0x007C: return "WM_STYLECHANGING"; 
5203         case 0x007D: return "WM_STYLECHANGED"; 
5204         case 0x007E: return "WM_DISPLAYCHANGE"; 
5205         case 0x007F: return "WM_GETICON"; 
5206         case 0x0080: return "WM_SETICON"; 
5208         case 0x0081: return "WM_NCCREATE"; 
5209         case 0x0082: return "WM_NCDESTROY"; 
5210         case 0x0083: return "WM_NCCALCSIZE"; 
5211         case 0x0084: return "WM_NCHITTEST"; 
5212         case 0x0085: return "WM_NCPAINT"; 
5213         case 0x0086: return "WM_NCACTIVATE"; 
5214         case 0x0087: return "WM_GETDLGCODE"; 
5215         case 0x00A0: return "WM_NCMOUSEMOVE"; 
5216         case 0x00A1: return "WM_NCLBUTTONDOWN"; 
5217         case 0x00A2: return "WM_NCLBUTTONUP"; 
5218         case 0x00A3: return "WM_NCLBUTTONDBLCLK"; 
5219         case 0x00A4: return "WM_NCRBUTTONDOWN"; 
5220         case 0x00A5: return "WM_NCRBUTTONUP"; 
5221         case 0x00A6: return "WM_NCRBUTTONDBLCLK"; 
5222         case 0x00A7: return "WM_NCMBUTTONDOWN"; 
5223         case 0x00A8: return "WM_NCMBUTTONUP"; 
5224         case 0x00A9: return "WM_NCMBUTTONDBLCLK"; 
5225         case 0x0100: return "WM_KEYDOWN"; 
5226         case 0x0101: return "WM_KEYUP"; 
5227         case 0x0102: return "WM_CHAR"; 
5228         case 0x0103: return "WM_DEADCHAR"; 
5229         case 0x0104: return "WM_SYSKEYDOWN"; 
5230         case 0x0105: return "WM_SYSKEYUP"; 
5231         case 0x0106: return "WM_SYSCHAR"; 
5232         case 0x0107: return "WM_SYSDEADCHAR"; 
5233         case 0x0108: return "WM_KEYLAST"; 
5235         case 0x010D: return "WM_IME_STARTCOMPOSITION"; 
5236         case 0x010E: return "WM_IME_ENDCOMPOSITION"; 
5237         case 0x010F: return "WM_IME_COMPOSITION"; 
5239         case 0x0110: return "WM_INITDIALOG"; 
5240         case 0x0111: return "WM_COMMAND"; 
5241         case 0x0112: return "WM_SYSCOMMAND"; 
5242         case 0x0113: return "WM_TIMER"; 
5243         case 0x0114: return "WM_HSCROLL"; 
5244         case 0x0115: return "WM_VSCROLL"; 
5245         case 0x0116: return "WM_INITMENU"; 
5246         case 0x0117: return "WM_INITMENUPOPUP"; 
5247         case 0x011F: return "WM_MENUSELECT"; 
5248         case 0x0120: return "WM_MENUCHAR"; 
5249         case 0x0121: return "WM_ENTERIDLE"; 
5250         case 0x0200: return "WM_MOUSEMOVE"; 
5251         case 0x0201: return "WM_LBUTTONDOWN"; 
5252         case 0x0202: return "WM_LBUTTONUP"; 
5253         case 0x0203: return "WM_LBUTTONDBLCLK"; 
5254         case 0x0204: return "WM_RBUTTONDOWN"; 
5255         case 0x0205: return "WM_RBUTTONUP"; 
5256         case 0x0206: return "WM_RBUTTONDBLCLK"; 
5257         case 0x0207: return "WM_MBUTTONDOWN"; 
5258         case 0x0208: return "WM_MBUTTONUP"; 
5259         case 0x0209: return "WM_MBUTTONDBLCLK"; 
5260         case 0x020A: return "WM_MOUSEWHEEL"; 
5261         case 0x0210: return "WM_PARENTNOTIFY"; 
5262         case 0x0211: return "WM_ENTERMENULOOP"; 
5263         case 0x0212: return "WM_EXITMENULOOP"; 
5265         case 0x0213: return "WM_NEXTMENU"; 
5266         case 0x0214: return "WM_SIZING"; 
5267         case 0x0215: return "WM_CAPTURECHANGED"; 
5268         case 0x0216: return "WM_MOVING"; 
5269         case 0x0218: return "WM_POWERBROADCAST"; 
5270         case 0x0219: return "WM_DEVICECHANGE"; 
5272         case 0x0220: return "WM_MDICREATE"; 
5273         case 0x0221: return "WM_MDIDESTROY"; 
5274         case 0x0222: return "WM_MDIACTIVATE"; 
5275         case 0x0223: return "WM_MDIRESTORE"; 
5276         case 0x0224: return "WM_MDINEXT"; 
5277         case 0x0225: return "WM_MDIMAXIMIZE"; 
5278         case 0x0226: return "WM_MDITILE"; 
5279         case 0x0227: return "WM_MDICASCADE"; 
5280         case 0x0228: return "WM_MDIICONARRANGE"; 
5281         case 0x0229: return "WM_MDIGETACTIVE"; 
5282         case 0x0230: return "WM_MDISETMENU"; 
5283         case 0x0233: return "WM_DROPFILES"; 
5285         case 0x0281: return "WM_IME_SETCONTEXT"; 
5286         case 0x0282: return "WM_IME_NOTIFY"; 
5287         case 0x0283: return "WM_IME_CONTROL"; 
5288         case 0x0284: return "WM_IME_COMPOSITIONFULL"; 
5289         case 0x0285: return "WM_IME_SELECT"; 
5290         case 0x0286: return "WM_IME_CHAR"; 
5291         case 0x0290: return "WM_IME_KEYDOWN"; 
5292         case 0x0291: return "WM_IME_KEYUP"; 
5294         case 0x0300: return "WM_CUT"; 
5295         case 0x0301: return "WM_COPY"; 
5296         case 0x0302: return "WM_PASTE"; 
5297         case 0x0303: return "WM_CLEAR"; 
5298         case 0x0304: return "WM_UNDO"; 
5299         case 0x0305: return "WM_RENDERFORMAT"; 
5300         case 0x0306: return "WM_RENDERALLFORMATS"; 
5301         case 0x0307: return "WM_DESTROYCLIPBOARD"; 
5302         case 0x0308: return "WM_DRAWCLIPBOARD"; 
5303         case 0x0309: return "WM_PAINTCLIPBOARD"; 
5304         case 0x030A: return "WM_VSCROLLCLIPBOARD"; 
5305         case 0x030B: return "WM_SIZECLIPBOARD"; 
5306         case 0x030C: return "WM_ASKCBFORMATNAME"; 
5307         case 0x030D: return "WM_CHANGECBCHAIN"; 
5308         case 0x030E: return "WM_HSCROLLCLIPBOARD"; 
5309         case 0x030F: return "WM_QUERYNEWPALETTE"; 
5310         case 0x0310: return "WM_PALETTEISCHANGING"; 
5311         case 0x0311: return "WM_PALETTECHANGED"; 
5313         case 0x0312: return "WM_HOTKEY"; 
5316         // common controls messages - although they're not strictly speaking 
5317         // standard, it's nice to decode them nevertheless 
5320         case 0x1000 + 0: return "LVM_GETBKCOLOR"; 
5321         case 0x1000 + 1: return "LVM_SETBKCOLOR"; 
5322         case 0x1000 + 2: return "LVM_GETIMAGELIST"; 
5323         case 0x1000 + 3: return "LVM_SETIMAGELIST"; 
5324         case 0x1000 + 4: return "LVM_GETITEMCOUNT"; 
5325         case 0x1000 + 5: return "LVM_GETITEMA"; 
5326         case 0x1000 + 75: return "LVM_GETITEMW"; 
5327         case 0x1000 + 6: return "LVM_SETITEMA"; 
5328         case 0x1000 + 76: return "LVM_SETITEMW"; 
5329         case 0x1000 + 7: return "LVM_INSERTITEMA"; 
5330         case 0x1000 + 77: return "LVM_INSERTITEMW"; 
5331         case 0x1000 + 8: return "LVM_DELETEITEM"; 
5332         case 0x1000 + 9: return "LVM_DELETEALLITEMS"; 
5333         case 0x1000 + 10: return "LVM_GETCALLBACKMASK"; 
5334         case 0x1000 + 11: return "LVM_SETCALLBACKMASK"; 
5335         case 0x1000 + 12: return "LVM_GETNEXTITEM"; 
5336         case 0x1000 + 13: return "LVM_FINDITEMA"; 
5337         case 0x1000 + 83: return "LVM_FINDITEMW"; 
5338         case 0x1000 + 14: return "LVM_GETITEMRECT"; 
5339         case 0x1000 + 15: return "LVM_SETITEMPOSITION"; 
5340         case 0x1000 + 16: return "LVM_GETITEMPOSITION"; 
5341         case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA"; 
5342         case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW"; 
5343         case 0x1000 + 18: return "LVM_HITTEST"; 
5344         case 0x1000 + 19: return "LVM_ENSUREVISIBLE"; 
5345         case 0x1000 + 20: return "LVM_SCROLL"; 
5346         case 0x1000 + 21: return "LVM_REDRAWITEMS"; 
5347         case 0x1000 + 22: return "LVM_ARRANGE"; 
5348         case 0x1000 + 23: return "LVM_EDITLABELA"; 
5349         case 0x1000 + 118: return "LVM_EDITLABELW"; 
5350         case 0x1000 + 24: return "LVM_GETEDITCONTROL"; 
5351         case 0x1000 + 25: return "LVM_GETCOLUMNA"; 
5352         case 0x1000 + 95: return "LVM_GETCOLUMNW"; 
5353         case 0x1000 + 26: return "LVM_SETCOLUMNA"; 
5354         case 0x1000 + 96: return "LVM_SETCOLUMNW"; 
5355         case 0x1000 + 27: return "LVM_INSERTCOLUMNA"; 
5356         case 0x1000 + 97: return "LVM_INSERTCOLUMNW"; 
5357         case 0x1000 + 28: return "LVM_DELETECOLUMN"; 
5358         case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH"; 
5359         case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH"; 
5360         case 0x1000 + 31: return "LVM_GETHEADER"; 
5361         case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE"; 
5362         case 0x1000 + 34: return "LVM_GETVIEWRECT"; 
5363         case 0x1000 + 35: return "LVM_GETTEXTCOLOR"; 
5364         case 0x1000 + 36: return "LVM_SETTEXTCOLOR"; 
5365         case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR"; 
5366         case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR"; 
5367         case 0x1000 + 39: return "LVM_GETTOPINDEX"; 
5368         case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE"; 
5369         case 0x1000 + 41: return "LVM_GETORIGIN"; 
5370         case 0x1000 + 42: return "LVM_UPDATE"; 
5371         case 0x1000 + 43: return "LVM_SETITEMSTATE"; 
5372         case 0x1000 + 44: return "LVM_GETITEMSTATE"; 
5373         case 0x1000 + 45: return "LVM_GETITEMTEXTA"; 
5374         case 0x1000 + 115: return "LVM_GETITEMTEXTW"; 
5375         case 0x1000 + 46: return "LVM_SETITEMTEXTA"; 
5376         case 0x1000 + 116: return "LVM_SETITEMTEXTW"; 
5377         case 0x1000 + 47: return "LVM_SETITEMCOUNT"; 
5378         case 0x1000 + 48: return "LVM_SORTITEMS"; 
5379         case 0x1000 + 49: return "LVM_SETITEMPOSITION32"; 
5380         case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT"; 
5381         case 0x1000 + 51: return "LVM_GETITEMSPACING"; 
5382         case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA"; 
5383         case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW"; 
5384         case 0x1000 + 53: return "LVM_SETICONSPACING"; 
5385         case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE"; 
5386         case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE"; 
5387         case 0x1000 + 56: return "LVM_GETSUBITEMRECT"; 
5388         case 0x1000 + 57: return "LVM_SUBITEMHITTEST"; 
5389         case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY"; 
5390         case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY"; 
5391         case 0x1000 + 60: return "LVM_SETHOTITEM"; 
5392         case 0x1000 + 61: return "LVM_GETHOTITEM"; 
5393         case 0x1000 + 62: return "LVM_SETHOTCURSOR"; 
5394         case 0x1000 + 63: return "LVM_GETHOTCURSOR"; 
5395         case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT"; 
5396         case 0x1000 + 65: return "LVM_SETWORKAREA"; 
5399         case 0x1100 + 0: return "TVM_INSERTITEMA"; 
5400         case 0x1100 + 50: return "TVM_INSERTITEMW"; 
5401         case 0x1100 + 1: return "TVM_DELETEITEM"; 
5402         case 0x1100 + 2: return "TVM_EXPAND"; 
5403         case 0x1100 + 4: return "TVM_GETITEMRECT"; 
5404         case 0x1100 + 5: return "TVM_GETCOUNT"; 
5405         case 0x1100 + 6: return "TVM_GETINDENT"; 
5406         case 0x1100 + 7: return "TVM_SETINDENT"; 
5407         case 0x1100 + 8: return "TVM_GETIMAGELIST"; 
5408         case 0x1100 + 9: return "TVM_SETIMAGELIST"; 
5409         case 0x1100 + 10: return "TVM_GETNEXTITEM"; 
5410         case 0x1100 + 11: return "TVM_SELECTITEM"; 
5411         case 0x1100 + 12: return "TVM_GETITEMA"; 
5412         case 0x1100 + 62: return "TVM_GETITEMW"; 
5413         case 0x1100 + 13: return "TVM_SETITEMA"; 
5414         case 0x1100 + 63: return "TVM_SETITEMW"; 
5415         case 0x1100 + 14: return "TVM_EDITLABELA"; 
5416         case 0x1100 + 65: return "TVM_EDITLABELW"; 
5417         case 0x1100 + 15: return "TVM_GETEDITCONTROL"; 
5418         case 0x1100 + 16: return "TVM_GETVISIBLECOUNT"; 
5419         case 0x1100 + 17: return "TVM_HITTEST"; 
5420         case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE"; 
5421         case 0x1100 + 19: return "TVM_SORTCHILDREN"; 
5422         case 0x1100 + 20: return "TVM_ENSUREVISIBLE"; 
5423         case 0x1100 + 21: return "TVM_SORTCHILDRENCB"; 
5424         case 0x1100 + 22: return "TVM_ENDEDITLABELNOW"; 
5425         case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA"; 
5426         case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW"; 
5427         case 0x1100 + 24: return "TVM_SETTOOLTIPS"; 
5428         case 0x1100 + 25: return "TVM_GETTOOLTIPS"; 
5431         case 0x1200 + 0: return "HDM_GETITEMCOUNT"; 
5432         case 0x1200 + 1: return "HDM_INSERTITEMA"; 
5433         case 0x1200 + 10: return "HDM_INSERTITEMW"; 
5434         case 0x1200 + 2: return "HDM_DELETEITEM"; 
5435         case 0x1200 + 3: return "HDM_GETITEMA"; 
5436         case 0x1200 + 11: return "HDM_GETITEMW"; 
5437         case 0x1200 + 4: return "HDM_SETITEMA"; 
5438         case 0x1200 + 12: return "HDM_SETITEMW"; 
5439         case 0x1200 + 5: return "HDM_LAYOUT"; 
5440         case 0x1200 + 6: return "HDM_HITTEST"; 
5441         case 0x1200 + 7: return "HDM_GETITEMRECT"; 
5442         case 0x1200 + 8: return "HDM_SETIMAGELIST"; 
5443         case 0x1200 + 9: return "HDM_GETIMAGELIST"; 
5444         case 0x1200 + 15: return "HDM_ORDERTOINDEX"; 
5445         case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE"; 
5446         case 0x1200 + 17: return "HDM_GETORDERARRAY"; 
5447         case 0x1200 + 18: return "HDM_SETORDERARRAY"; 
5448         case 0x1200 + 19: return "HDM_SETHOTDIVIDER"; 
5451         case 0x1300 + 2: return "TCM_GETIMAGELIST"; 
5452         case 0x1300 + 3: return "TCM_SETIMAGELIST"; 
5453         case 0x1300 + 4: return "TCM_GETITEMCOUNT"; 
5454         case 0x1300 + 5: return "TCM_GETITEMA"; 
5455         case 0x1300 + 60: return "TCM_GETITEMW"; 
5456         case 0x1300 + 6: return "TCM_SETITEMA"; 
5457         case 0x1300 + 61: return "TCM_SETITEMW"; 
5458         case 0x1300 + 7: return "TCM_INSERTITEMA"; 
5459         case 0x1300 + 62: return "TCM_INSERTITEMW"; 
5460         case 0x1300 + 8: return "TCM_DELETEITEM"; 
5461         case 0x1300 + 9: return "TCM_DELETEALLITEMS"; 
5462         case 0x1300 + 10: return "TCM_GETITEMRECT"; 
5463         case 0x1300 + 11: return "TCM_GETCURSEL"; 
5464         case 0x1300 + 12: return "TCM_SETCURSEL"; 
5465         case 0x1300 + 13: return "TCM_HITTEST"; 
5466         case 0x1300 + 14: return "TCM_SETITEMEXTRA"; 
5467         case 0x1300 + 40: return "TCM_ADJUSTRECT"; 
5468         case 0x1300 + 41: return "TCM_SETITEMSIZE"; 
5469         case 0x1300 + 42: return "TCM_REMOVEIMAGE"; 
5470         case 0x1300 + 43: return "TCM_SETPADDING"; 
5471         case 0x1300 + 44: return "TCM_GETROWCOUNT"; 
5472         case 0x1300 + 45: return "TCM_GETTOOLTIPS"; 
5473         case 0x1300 + 46: return "TCM_SETTOOLTIPS"; 
5474         case 0x1300 + 47: return "TCM_GETCURFOCUS"; 
5475         case 0x1300 + 48: return "TCM_SETCURFOCUS"; 
5476         case 0x1300 + 49: return "TCM_SETMINTABWIDTH"; 
5477         case 0x1300 + 50: return "TCM_DESELECTALL"; 
5480         case WM_USER
+1: return "TB_ENABLEBUTTON"; 
5481         case WM_USER
+2: return "TB_CHECKBUTTON"; 
5482         case WM_USER
+3: return "TB_PRESSBUTTON"; 
5483         case WM_USER
+4: return "TB_HIDEBUTTON"; 
5484         case WM_USER
+5: return "TB_INDETERMINATE"; 
5485         case WM_USER
+9: return "TB_ISBUTTONENABLED"; 
5486         case WM_USER
+10: return "TB_ISBUTTONCHECKED"; 
5487         case WM_USER
+11: return "TB_ISBUTTONPRESSED"; 
5488         case WM_USER
+12: return "TB_ISBUTTONHIDDEN"; 
5489         case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE"; 
5490         case WM_USER
+17: return "TB_SETSTATE"; 
5491         case WM_USER
+18: return "TB_GETSTATE"; 
5492         case WM_USER
+19: return "TB_ADDBITMAP"; 
5493         case WM_USER
+20: return "TB_ADDBUTTONS"; 
5494         case WM_USER
+21: return "TB_INSERTBUTTON"; 
5495         case WM_USER
+22: return "TB_DELETEBUTTON"; 
5496         case WM_USER
+23: return "TB_GETBUTTON"; 
5497         case WM_USER
+24: return "TB_BUTTONCOUNT"; 
5498         case WM_USER
+25: return "TB_COMMANDTOINDEX"; 
5499         case WM_USER
+26: return "TB_SAVERESTOREA"; 
5500         case WM_USER
+76: return "TB_SAVERESTOREW"; 
5501         case WM_USER
+27: return "TB_CUSTOMIZE"; 
5502         case WM_USER
+28: return "TB_ADDSTRINGA"; 
5503         case WM_USER
+77: return "TB_ADDSTRINGW"; 
5504         case WM_USER
+29: return "TB_GETITEMRECT"; 
5505         case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE"; 
5506         case WM_USER
+31: return "TB_SETBUTTONSIZE"; 
5507         case WM_USER
+32: return "TB_SETBITMAPSIZE"; 
5508         case WM_USER
+33: return "TB_AUTOSIZE"; 
5509         case WM_USER
+35: return "TB_GETTOOLTIPS"; 
5510         case WM_USER
+36: return "TB_SETTOOLTIPS"; 
5511         case WM_USER
+37: return "TB_SETPARENT"; 
5512         case WM_USER
+39: return "TB_SETROWS"; 
5513         case WM_USER
+40: return "TB_GETROWS"; 
5514         case WM_USER
+42: return "TB_SETCMDID"; 
5515         case WM_USER
+43: return "TB_CHANGEBITMAP"; 
5516         case WM_USER
+44: return "TB_GETBITMAP"; 
5517         case WM_USER
+45: return "TB_GETBUTTONTEXTA"; 
5518         case WM_USER
+75: return "TB_GETBUTTONTEXTW"; 
5519         case WM_USER
+46: return "TB_REPLACEBITMAP"; 
5520         case WM_USER
+47: return "TB_SETINDENT"; 
5521         case WM_USER
+48: return "TB_SETIMAGELIST"; 
5522         case WM_USER
+49: return "TB_GETIMAGELIST"; 
5523         case WM_USER
+50: return "TB_LOADIMAGES"; 
5524         case WM_USER
+51: return "TB_GETRECT"; 
5525         case WM_USER
+52: return "TB_SETHOTIMAGELIST"; 
5526         case WM_USER
+53: return "TB_GETHOTIMAGELIST"; 
5527         case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST"; 
5528         case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST"; 
5529         case WM_USER
+56: return "TB_SETSTYLE"; 
5530         case WM_USER
+57: return "TB_GETSTYLE"; 
5531         case WM_USER
+58: return "TB_GETBUTTONSIZE"; 
5532         case WM_USER
+59: return "TB_SETBUTTONWIDTH"; 
5533         case WM_USER
+60: return "TB_SETMAXTEXTROWS"; 
5534         case WM_USER
+61: return "TB_GETTEXTROWS"; 
5535         case WM_USER
+41: return "TB_GETBITMAPFLAGS"; 
5538             static char s_szBuf
[128]; 
5539             sprintf(s_szBuf
, "<unknown message = %d>", message
); 
5543 #endif //__WXDEBUG__ 
5545 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
5546                                      int *x
, int *y
, WPARAM 
*flags
) 
5548     // construct the key mask 
5549     WPARAM
& fwKeys 
= *flags
; 
5551     fwKeys 
= MK_RBUTTON
; 
5552     if ( wxIsCtrlDown() ) 
5553         fwKeys 
|= MK_CONTROL
; 
5554     if ( wxIsShiftDown() ) 
5557     // simulate right mouse button click 
5558     DWORD dwPos 
= ::GetMessagePos(); 
5559     *x 
= GET_X_LPARAM(dwPos
); 
5560     *y 
= GET_Y_LPARAM(dwPos
); 
5562     win
->ScreenToClient(x
, y
); 
5565 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
) 
5569     HWND hwnd 
= GetHwndOf(win
); 
5570     HDC hdc 
= ::GetDC(hwnd
); 
5572 #if !wxDIALOG_UNIT_COMPATIBILITY 
5573     // and select the current font into it 
5574     HFONT hfont 
= GetHfontOf(win
->GetFont()); 
5577         hfont 
= (HFONT
)::SelectObject(hdc
, hfont
); 
5581     // finally retrieve the text metrics from it 
5582     GetTextMetrics(hdc
, &tm
); 
5584 #if !wxDIALOG_UNIT_COMPATIBILITY 
5588         (void)::SelectObject(hdc
, hfont
); 
5592     ::ReleaseDC(hwnd
, hdc
); 
5597 // Find the wxWindow at the current mouse position, returning the mouse 
5599 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
5601     pt 
= wxGetMousePosition(); 
5602     return wxFindWindowAtPoint(pt
); 
5605 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
5610     HWND hWndHit 
= ::WindowFromPoint(pt2
); 
5612     wxWindow
* win 
= wxFindWinFromHandle((WXHWND
) hWndHit
) ; 
5613     HWND hWnd 
= hWndHit
; 
5615     // Try to find a window with a wxWindow associated with it 
5616     while (!win 
&& (hWnd 
!= 0)) 
5618         hWnd 
= ::GetParent(hWnd
); 
5619         win 
= wxFindWinFromHandle((WXHWND
) hWnd
) ; 
5624 // Get the current mouse position. 
5625 wxPoint 
wxGetMousePosition() 
5628     GetCursorPos( & pt 
); 
5630     return wxPoint(pt
.x
, pt
.y
); 
5635 bool wxWindowMSW::RegisterHotKey(int hotkeyId
, int modifiers
, int keycode
) 
5637     UINT win_modifiers
=0; 
5638     if ( modifiers 
& wxMOD_ALT 
) 
5639         win_modifiers 
|= MOD_ALT
; 
5640     if ( modifiers 
& wxMOD_SHIFT 
) 
5641         win_modifiers 
|= MOD_SHIFT
; 
5642     if ( modifiers 
& wxMOD_CONTROL 
) 
5643         win_modifiers 
|= MOD_CONTROL
; 
5644     if ( modifiers 
& wxMOD_WIN 
) 
5645         win_modifiers 
|= MOD_WIN
; 
5647     if ( !::RegisterHotKey(GetHwnd(), hotkeyId
, win_modifiers
, keycode
) ) 
5649         wxLogLastError(_T("RegisterHotKey")); 
5657 bool wxWindowMSW::UnregisterHotKey(int hotkeyId
) 
5659     if ( !::UnregisterHotKey(GetHwnd(), hotkeyId
) ) 
5661         wxLogLastError(_T("UnregisterHotKey")); 
5669 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam
, WXLPARAM lParam
) 
5671     int hotkeyId 
= wParam
; 
5672     int virtualKey 
= HIWORD(lParam
); 
5673     int win_modifiers 
= LOWORD(lParam
); 
5675     wxKeyEvent 
event(CreateKeyEvent(wxEVT_HOTKEY
, virtualKey
, wParam
, lParam
)); 
5676     event
.SetId(hotkeyId
); 
5677     event
.m_shiftDown 
= (win_modifiers 
& MOD_SHIFT
) != 0; 
5678     event
.m_controlDown 
= (win_modifiers 
& MOD_CONTROL
) != 0; 
5679     event
.m_altDown 
= (win_modifiers 
& MOD_ALT
) != 0; 
5680     event
.m_metaDown 
= (win_modifiers 
& MOD_WIN
) != 0; 
5682     return GetEventHandler()->ProcessEvent(event
); 
5685 #endif // wxUSE_HOTKEY