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 #include "wx/module.h" 
  58 #if wxUSE_DRAG_AND_DROP 
  62 #if wxUSE_ACCESSIBILITY 
  63     #include "wx/access.h" 
  67         #define WM_GETOBJECT 0x003D 
  70         #define OBJID_CLIENT 0xFFFFFFFC 
  74 #include "wx/menuitem.h" 
  77 #include "wx/msw/private.h" 
  80     #include "wx/tooltip.h" 
  88     #include "wx/spinctrl.h" 
  89 #endif // wxUSE_SPINCTRL 
  94 #include "wx/textctrl.h" 
  95 #include "wx/notebook.h" 
  96 #include "wx/listctrl.h" 
 100 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__) 
 101     #include <shellapi.h> 
 102     #include <mmsystem.h> 
 106     #include <windowsx.h> 
 109 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__) 
 111         #include <commctrl.h> 
 113 #elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler 
 114     #include "wx/msw/gnuwin32/extra.h" 
 117 #include "wx/msw/missing.h" 
 119 #if defined(__WXWINCE__) 
 120 #include "wx/msw/wince/missing.h" 
 123 // --------------------------------------------------------------------------- 
 125 // --------------------------------------------------------------------------- 
 127 #if wxUSE_MENUS_NATIVE 
 128 wxMenu 
*wxCurrentPopupMenu 
= NULL
; 
 129 #endif // wxUSE_MENUS_NATIVE 
 131 extern const wxChar 
*wxCanvasClassName
; 
 133 // true if we had already created the std colour map, used by 
 134 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT) 
 135 static bool gs_hasStdCmap 
= false; 
 137 // --------------------------------------------------------------------------- 
 139 // --------------------------------------------------------------------------- 
 141 // the window proc for all our windows 
 142 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
 143                                    WPARAM wParam
, LPARAM lParam
); 
 147     const char *wxGetMessageName(int message
); 
 150 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 151 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 152 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
); 
 154 // this magical function is used to translate VK_APPS key presses to right 
 156 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
 157                                      int *x
, int *y
, WPARAM 
*flags
); 
 159 // get the text metrics for the current font 
 160 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
); 
 162 // find the window for the mouse event at the specified position 
 163 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
); //TW:REQ:Univ 
 165 // wrapper around BringWindowToTop() API 
 166 static inline void wxBringWindowToTop(HWND hwnd
) 
 168 #ifdef __WXMICROWIN__ 
 169     // It seems that MicroWindows brings the _parent_ of the window to the top, 
 170     // which can be the wrong one. 
 172     // activate (set focus to) specified window 
 176     // raise top level parent to top of z order 
 177     if (!::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE 
| SWP_NOSIZE
)) 
 179         wxLogLastError(_T("SetWindowPos")); 
 183 // ensure that all our parent windows have WS_EX_CONTROLPARENT style 
 184 static void EnsureParentHasControlParentStyle(wxWindow 
*parent
) 
 187        If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our 
 188        parent as well as otherwise several Win32 functions using 
 189        GetNextDlgTabItem() to iterate over all controls such as 
 190        IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, 
 191        all of them iterate over all the controls starting from the currently 
 192        focused one and stop iterating when they get back to the focus but 
 193        unless all parents have WS_EX_CONTROLPARENT bit set, they would never 
 194        get back to the initial (focused) window: as we do have this style, 
 195        GetNextDlgTabItem() will leave this window and continue in its parent, 
 196        but if the parent doesn't have it, it wouldn't recurse inside it later 
 197        on and so wouldn't have a chance of getting back to this window neither. 
 200     while ( parent 
&& !parent
->IsTopLevel() ) 
 202         LONG exStyle 
= ::GetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
); 
 203         if ( !(exStyle 
& WS_EX_CONTROLPARENT
) ) 
 205             // force the parent to have this style 
 206             ::SetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
, 
 207                             exStyle 
| WS_EX_CONTROLPARENT
); 
 210         parent 
= parent
->GetParent(); 
 212 #endif // !__WXWINCE__ 
 215 // --------------------------------------------------------------------------- 
 217 // --------------------------------------------------------------------------- 
 219 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
 221 #ifdef __WXUNIVERSAL__ 
 222     IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
) 
 224 #if wxUSE_EXTENDED_RTTI 
 226 // windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls 
 227 // must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as 
 228 // windows with negative ids never can be recreated anyway 
 230 bool wxWindowStreamingCallback( const wxObject 
*object
, wxWriter 
* , wxPersister 
* , wxxVariantArray 
& ) 
 232     const wxWindow 
* win 
= dynamic_cast<const wxWindow
*>(object
) ; 
 233     if ( win 
&& win
->GetId() < 0 ) 
 238 IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow
, wxWindowBase
,"wx/window.h", wxWindowStreamingCallback
) 
 240 // make wxWindowList known before the property is used 
 242 wxCOLLECTION_TYPE_INFO( wxWindow
* , wxWindowList 
) ; 
 244 template<> void wxCollectionToVariantArray( wxWindowList 
const &theList
, wxxVariantArray 
&value
) 
 246     wxListCollectionToVariantArray
<wxWindowList::compatibility_iterator
>( theList 
, value 
) ; 
 249 WX_DEFINE_FLAGS( wxWindowStyle 
) 
 251 wxBEGIN_FLAGS( wxWindowStyle 
) 
 252     // new style border flags, we put them first to 
 253     // use them for streaming out 
 255     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
 256     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
 257     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
 258     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
 259     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
 260     wxFLAGS_MEMBER(wxBORDER_NONE
) 
 262     // old style border flags 
 263     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
 264     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
 265     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
 266     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
 267     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
 268     wxFLAGS_MEMBER(wxBORDER
) 
 270     // standard window styles 
 271     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
 272     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
 273     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
 274     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
 275     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
 276     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
 277     wxFLAGS_MEMBER(wxVSCROLL
) 
 278     wxFLAGS_MEMBER(wxHSCROLL
) 
 280 wxEND_FLAGS( wxWindowStyle 
) 
 282 wxBEGIN_PROPERTIES_TABLE(wxWindow
) 
 283         wxEVENT_PROPERTY( Close 
, wxEVT_CLOSE_WINDOW 
, wxCloseEvent
) 
 284         wxEVENT_PROPERTY( Create 
, wxEVT_CREATE 
, wxWindowCreateEvent 
) 
 285         wxEVENT_PROPERTY( Destroy 
, wxEVT_DESTROY 
, wxWindowDestroyEvent 
) 
 286     // Always constructor Properties first 
 288     wxREADONLY_PROPERTY( Parent
,wxWindow
*, GetParent
,  , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 289         wxPROPERTY( Id
,wxWindowID
, SetId
, GetId
, -1, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
 290         wxPROPERTY( Position
,wxPoint
, SetPosition 
, GetPosition
, wxPoint(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos 
 291         wxPROPERTY( Size
,wxSize
, SetSize
, GetSize
, wxSize(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size 
 292     wxPROPERTY( WindowStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
 294     // Then all relations of the object graph 
 296     wxREADONLY_PROPERTY_COLLECTION( Children 
, wxWindowList 
, wxWindowBase
* , GetWindowChildren 
, wxPROP_OBJECT_GRAPH 
/*flags*/ , wxT("Helpstring") , wxT("group")) 
 298    // and finally all other properties 
 300         wxPROPERTY( ExtraStyle 
, long , SetExtraStyle 
, GetExtraStyle 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle 
 301         wxPROPERTY( BackgroundColour 
, wxColour 
, SetBackgroundColour 
, GetBackgroundColour 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg 
 302         wxPROPERTY( ForegroundColour 
, wxColour 
, SetForegroundColour 
, GetForegroundColour 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg 
 303         wxPROPERTY( Enabled 
, bool , Enable 
, IsEnabled 
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 304         wxPROPERTY( Shown 
, bool , Show 
, IsShown 
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
 306     // possible property candidates (not in xrc) or not valid in all subclasses 
 307         wxPROPERTY( Title
,wxString
, SetTitle
, GetTitle
, wxT("") ) 
 308         wxPROPERTY( Font 
, wxFont 
, SetFont 
, GetWindowFont  
, ) 
 309         wxPROPERTY( Label
,wxString
, SetLabel
, GetLabel
, wxT("") ) 
 310         // MaxHeight, Width , MinHeight , Width 
 311         // TODO switch label to control and title to toplevels 
 313         wxPROPERTY( ThemeEnabled 
, bool , SetThemeEnabled 
, GetThemeEnabled 
, ) 
 314         //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , ) 
 315         // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , ) 
 316         wxPROPERTY( AutoLayout 
, bool , SetAutoLayout 
, GetAutoLayout 
, ) 
 321 wxEND_PROPERTIES_TABLE() 
 323 wxBEGIN_HANDLERS_TABLE(wxWindow
) 
 324 wxEND_HANDLERS_TABLE() 
 326 wxCONSTRUCTOR_DUMMY(wxWindow
) 
 329     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
 331 #endif // __WXUNIVERSAL__/__WXMSW__ 
 333 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
) 
 334     EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
) 
 335     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
) 
 336     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
) 
 339 // =========================================================================== 
 341 // =========================================================================== 
 343 // --------------------------------------------------------------------------- 
 344 // wxWindow utility functions 
 345 // --------------------------------------------------------------------------- 
 347 // Find an item given the MS Windows id 
 348 wxWindow 
*wxWindowMSW::FindItem(long id
) const 
 351     wxControl 
*item 
= wxDynamicCastThis(wxControl
); 
 354         // is it we or one of our "internal" children? 
 355         if ( item
->GetId() == id
 
 356 #ifndef __WXUNIVERSAL__ 
 357                 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
) 
 358 #endif // __WXUNIVERSAL__ 
 364 #endif // wxUSE_CONTROLS 
 366     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 369         wxWindow 
*childWin 
= current
->GetData(); 
 371         wxWindow 
*wnd 
= childWin
->FindItem(id
); 
 375         current 
= current
->GetNext(); 
 381 // Find an item given the MS Windows handle 
 382 wxWindow 
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const 
 384     wxWindowList::compatibility_iterator current 
= GetChildren().GetFirst(); 
 387         wxWindow 
*parent 
= current
->GetData(); 
 389         // Do a recursive search. 
 390         wxWindow 
*wnd 
= parent
->FindItemByHWND(hWnd
); 
 396                 || parent
->IsKindOf(CLASSINFO(wxControl
)) 
 397 #endif // wxUSE_CONTROLS 
 400             wxWindow 
*item 
= current
->GetData(); 
 401             if ( item
->GetHWND() == hWnd 
) 
 405                 if ( item
->ContainsHWND(hWnd
) ) 
 410         current 
= current
->GetNext(); 
 415 // Default command handler 
 416 bool wxWindowMSW::MSWCommand(WXUINT 
WXUNUSED(param
), WXWORD 
WXUNUSED(id
)) 
 421 // ---------------------------------------------------------------------------- 
 422 // constructors and such 
 423 // ---------------------------------------------------------------------------- 
 425 void wxWindowMSW::Init() 
 428     m_isBeingDeleted 
= false; 
 430     m_mouseInWindow 
= false; 
 431     m_lastKeydownProcessed 
= false; 
 433     m_childrenDisabled 
= NULL
; 
 443     // as all windows are created with WS_VISIBLE style... 
 446 #if wxUSE_MOUSEEVENT_HACK 
 449     m_lastMouseEvent 
= -1; 
 450 #endif // wxUSE_MOUSEEVENT_HACK 
 454 wxWindowMSW::~wxWindowMSW() 
 456     m_isBeingDeleted 
= true; 
 458 #ifndef __WXUNIVERSAL__ 
 459     // VS: make sure there's no wxFrame with last focus set to us: 
 460     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
 462         wxTopLevelWindow 
*frame 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 465             if ( frame
->GetLastFocus() == this ) 
 467                 frame
->SetLastFocus(NULL
); 
 472 #endif // __WXUNIVERSAL__ 
 474     // VS: destroy children first and _then_ detach *this from its parent. 
 475     //     If we'd do it the other way around, children wouldn't be able 
 476     //     find their parent frame (see above). 
 481         // VZ: test temp removed to understand what really happens here 
 482         //if (::IsWindow(GetHwnd())) 
 484             if ( !::DestroyWindow(GetHwnd()) ) 
 485                 wxLogLastError(wxT("DestroyWindow")); 
 488         // remove hWnd <-> wxWindow association 
 489         wxRemoveHandleAssociation(this); 
 492     delete m_childrenDisabled
; 
 495 // real construction (Init() must have been called before!) 
 496 bool wxWindowMSW::Create(wxWindow 
*parent
, 
 501                          const wxString
& name
) 
 503     wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") ); 
 505     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 508     parent
->AddChild(this); 
 511     DWORD msflags 
= MSWGetCreateWindowFlags(&exstyle
); 
 513 #ifdef __WXUNIVERSAL__ 
 514     // no borders, we draw them ourselves 
 515     exstyle 
&= ~(WS_EX_DLGMODALFRAME 
| 
 519     msflags 
&= ~WS_BORDER
; 
 520 #endif // wxUniversal 
 522     // all windows are created visible by default except popup ones (which are 
 523     // like the wxTopLevelWindows in this aspect) 
 524     if ( style 
& wxPOPUP_WINDOW 
) 
 526         msflags 
&= ~WS_VISIBLE
; 
 531         msflags 
|= WS_VISIBLE
; 
 534     return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
); 
 537 // --------------------------------------------------------------------------- 
 539 // --------------------------------------------------------------------------- 
 541 void wxWindowMSW::SetFocus() 
 543     HWND hWnd 
= GetHwnd(); 
 544     wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") ); 
 546 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
 550     if ( !::SetFocus(hWnd
) ) 
 552 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__) 
 553         // was there really an error? 
 554         DWORD dwRes 
= ::GetLastError(); 
 557             HWND hwndFocus 
= ::GetFocus(); 
 558             if ( hwndFocus 
!= hWnd 
) 
 560                 wxLogApiError(_T("SetFocus"), dwRes
); 
 567 void wxWindowMSW::SetFocusFromKbd() 
 569     // when the focus is given to the control with DLGC_HASSETSEL style from 
 570     // keyboard its contents should be entirely selected: this is what 
 571     // ::IsDialogMessage() does and so we should do it as well to provide the 
 572     // same LNF as the native programs 
 573     if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL 
) 
 575         ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1); 
 578     // do this after (maybe) setting the selection as like this when 
 579     // wxEVT_SET_FOCUS handler is called, the selection would have been already 
 580     // set correctly -- this may be important 
 581     wxWindowBase::SetFocusFromKbd(); 
 584 // Get the window with the focus 
 585 wxWindow 
*wxWindowBase::FindFocus() 
 587     HWND hWnd 
= ::GetFocus(); 
 590         return wxGetWindowFromHWND((WXHWND
)hWnd
); 
 596 bool wxWindowMSW::Enable(bool enable
) 
 598     if ( !wxWindowBase::Enable(enable
) ) 
 601     HWND hWnd 
= GetHwnd(); 
 603         ::EnableWindow(hWnd
, (BOOL
)enable
); 
 605     // the logic below doesn't apply to the top level windows -- otherwise 
 606     // showing a modal dialog would result in total greying out (and ungreying 
 607     // out later) of everything which would be really ugly 
 611     // when the parent is disabled, all of its children should be disabled as 
 612     // well but when it is enabled back, only those of the children which 
 613     // hadn't been already disabled in the beginning should be enabled again, 
 614     // so we have to keep the list of those children 
 615     for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
 617           node 
= node
->GetNext() ) 
 619         wxWindow 
*child 
= node
->GetData(); 
 620         if ( child
->IsTopLevel() ) 
 622             // the logic below doesn't apply to top level children 
 628             // enable the child back unless it had been disabled before us 
 629             if ( !m_childrenDisabled 
|| !m_childrenDisabled
->Find(child
) ) 
 632         else // we're being disabled 
 634             if ( child
->IsEnabled() ) 
 636                 // disable it as children shouldn't stay enabled while the 
 640             else // child already disabled, remember it 
 642                 // have we created the list of disabled children already? 
 643                 if ( !m_childrenDisabled 
) 
 644                     m_childrenDisabled 
= new wxWindowList
; 
 646                 m_childrenDisabled
->Append(child
); 
 651     if ( enable 
&& m_childrenDisabled 
) 
 653         // we don't need this list any more, don't keep unused memory 
 654         delete m_childrenDisabled
; 
 655         m_childrenDisabled 
= NULL
; 
 661 bool wxWindowMSW::Show(bool show
) 
 663     if ( !wxWindowBase::Show(show
) ) 
 666     HWND hWnd 
= GetHwnd(); 
 667     int cshow 
= show 
? SW_SHOW 
: SW_HIDE
; 
 668     ::ShowWindow(hWnd
, cshow
); 
 670     if ( show 
&& IsTopLevel() ) 
 672         wxBringWindowToTop(hWnd
); 
 678 // Raise the window to the top of the Z order 
 679 void wxWindowMSW::Raise() 
 681     wxBringWindowToTop(GetHwnd()); 
 684 // Lower the window to the bottom of the Z order 
 685 void wxWindowMSW::Lower() 
 687     ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0, 
 688                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
 691 void wxWindowMSW::SetTitle( const wxString
& title
) 
 693     SetWindowText(GetHwnd(), title
.c_str()); 
 696 wxString 
wxWindowMSW::GetTitle() const 
 698     return wxGetWindowText(GetHWND()); 
 701 void wxWindowMSW::DoCaptureMouse() 
 703     HWND hWnd 
= GetHwnd(); 
 710 void wxWindowMSW::DoReleaseMouse() 
 712     if ( !::ReleaseCapture() ) 
 714         wxLogLastError(_T("ReleaseCapture")); 
 718 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 720     HWND hwnd 
= ::GetCapture(); 
 721     return hwnd 
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow 
*)NULL
; 
 724 bool wxWindowMSW::SetFont(const wxFont
& font
) 
 726     if ( !wxWindowBase::SetFont(font
) ) 
 732     HWND hWnd 
= GetHwnd(); 
 735         WXHANDLE hFont 
= m_font
.GetResourceHandle(); 
 737         wxASSERT_MSG( hFont
, wxT("should have valid font") ); 
 739         ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0)); 
 744 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
) 
 746     if ( !wxWindowBase::SetCursor(cursor
) ) 
 754         HWND hWnd 
= GetHwnd(); 
 756         // Change the cursor NOW if we're within the correct window 
 758         ::GetCursorPos(&point
); 
 760         RECT rect 
= wxGetWindowRect(hWnd
); 
 762         if ( ::PtInRect(&rect
, point
) && !wxIsBusy() ) 
 763             ::SetCursor(GetHcursorOf(m_cursor
)); 
 769 void wxWindowMSW::WarpPointer (int x
, int y
) 
 771     ClientToScreen(&x
, &y
); 
 773     if ( !::SetCursorPos(x
, y
) ) 
 775         wxLogLastError(_T("SetCursorPos")); 
 779 // --------------------------------------------------------------------------- 
 781 // --------------------------------------------------------------------------- 
 783 // convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT 
 784 static inline int wxDirToWinStyle(int orient
) 
 786     return orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
; 
 789 inline int GetScrollPosition(HWND hWnd
, int wOrient
) 
 791 #ifdef __WXMICROWIN__ 
 792     return ::GetScrollPosWX(hWnd
, wOrient
); 
 794     WinStruct
<SCROLLINFO
> scrollInfo
; 
 795     scrollInfo
.cbSize 
= sizeof(SCROLLINFO
); 
 796     scrollInfo
.fMask 
= SIF_POS
; 
 797     if ( !::GetScrollInfo(hWnd
, 
 801         // Not neccessarily an error, if there are no scrollbars yet. 
 802         // wxLogLastError(_T("GetScrollInfo")); 
 804     return scrollInfo
.nPos
; 
 805 //    return ::GetScrollPos(hWnd, wOrient); 
 809 int wxWindowMSW::GetScrollPos(int orient
) const 
 811     HWND hWnd 
= GetHwnd(); 
 812     wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") ); 
 814     return GetScrollPosition(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
); 
 817 // This now returns the whole range, not just the number 
 818 // of positions that we can scroll. 
 819 int wxWindowMSW::GetScrollRange(int orient
) const 
 822     HWND hWnd 
= GetHwnd(); 
 826     ::GetScrollRange(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 829     WinStruct
<SCROLLINFO
> scrollInfo
; 
 830     scrollInfo
.fMask 
= SIF_RANGE
; 
 831     if ( !::GetScrollInfo(hWnd
, 
 832                           orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 835         // Most of the time this is not really an error, since the return 
 836         // value can also be zero when there is no scrollbar yet. 
 837         // wxLogLastError(_T("GetScrollInfo")); 
 839     maxPos 
= scrollInfo
.nMax
; 
 841     // undo "range - 1" done in SetScrollbar() 
 845 int wxWindowMSW::GetScrollThumb(int orient
) const 
 847     return orient 
== wxHORIZONTAL 
? m_xThumbSize 
: m_yThumbSize
; 
 850 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
) 
 852     HWND hWnd 
= GetHwnd(); 
 853     wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") ); 
 855     WinStruct
<SCROLLINFO
> info
; 
 859     info
.fMask 
= SIF_POS
; 
 860     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 862         // disable scrollbar instead of removing it then 
 863         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 866     ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 870 // New function that will replace some of the above. 
 871 void wxWindowMSW::SetScrollbar(int orient
, 
 877     WinStruct
<SCROLLINFO
> info
; 
 878     info
.nPage 
= pageSize
; 
 879     info
.nMin 
= 0;              // range is nMax - nMin + 1 
 880     info
.nMax 
= range 
- 1;      //  as both nMax and nMax are inclusive 
 882     info
.fMask 
= SIF_RANGE 
| SIF_PAGE 
| SIF_POS
; 
 883     if ( HasFlag(wxALWAYS_SHOW_SB
) ) 
 885         // disable scrollbar instead of removing it then 
 886         info
.fMask 
|= SIF_DISABLENOSCROLL
; 
 889     HWND hWnd 
= GetHwnd(); 
 892         ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 896     *(orient 
== wxHORIZONTAL 
? &m_xThumbSize 
: &m_yThumbSize
) = pageSize
; 
 899 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect 
*prect
) 
 905         rect
.left 
= prect
->x
; 
 907         rect
.right 
= prect
->x 
+ prect
->width
; 
 908         rect
.bottom 
= prect
->y 
+ prect
->height
; 
 917     // FIXME: is this the exact equivalent of the line below? 
 918     ::ScrollWindowEx(GetHwnd(), dx
, dy
, pr
, pr
, 0, 0, SW_ERASE
|SW_INVALIDATE
); 
 920     ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
); 
 924 static bool ScrollVertically(HWND hwnd
, int kind
, int count
) 
 926     int posStart 
= GetScrollPosition(hwnd
, SB_VERT
); 
 929     for ( int n 
= 0; n 
< count
; n
++ ) 
 931         ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0); 
 933         int posNew 
= GetScrollPosition(hwnd
, SB_VERT
); 
 936             // don't bother to continue, we're already at top/bottom 
 943     return pos 
!= posStart
; 
 946 bool wxWindowMSW::ScrollLines(int lines
) 
 948     bool down 
= lines 
> 0; 
 950     return ScrollVertically(GetHwnd(), 
 951                             down 
? SB_LINEDOWN 
: SB_LINEUP
, 
 952                             down 
? lines 
: -lines
); 
 955 bool wxWindowMSW::ScrollPages(int pages
) 
 957     bool down 
= pages 
> 0; 
 959     return ScrollVertically(GetHwnd(), 
 960                             down 
? SB_PAGEDOWN 
: SB_PAGEUP
, 
 961                             down 
? pages 
: -pages
); 
 964 // --------------------------------------------------------------------------- 
 966 // --------------------------------------------------------------------------- 
 968 void wxWindowMSW::SubclassWin(WXHWND hWnd
) 
 970     wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") ); 
 972     HWND hwnd 
= (HWND
)hWnd
; 
 973     wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") ); 
 975     wxAssociateWinWithHandle(hwnd
, this); 
 977     m_oldWndProc 
= (WXFARPROC
)wxGetWindowProc((HWND
)hWnd
); 
 979     // we don't need to subclass the window of our own class (in the Windows 
 980     // sense of the word) 
 981         if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) ) 
 983         wxSetWindowProc(hwnd
, wxWndProc
); 
 987         // don't bother restoring it neither: this also makes it easy to 
 988         // implement IsOfStandardClass() method which returns true for the 
 989         // standard controls and false for the wxWindows own windows as it can 
 990         // simply check m_oldWndProc 
 995 void wxWindowMSW::UnsubclassWin() 
 997     wxRemoveHandleAssociation(this); 
 999     // Restore old Window proc 
1000     HWND hwnd 
= GetHwnd(); 
1005         wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") ); 
1009             if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) ) 
1011                 wxSetWindowProc(hwnd
, (WNDPROC
)m_oldWndProc
); 
1014             m_oldWndProc 
= NULL
; 
1019 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
) 
1021     // Unicows note: the code below works, but only because WNDCLASS contains 
1022     // original window handler rather that the unicows fake one. This may not 
1023     // be on purpose, though; if it stops working with future versions of 
1024     // unicows.dll, we can override unicows hooks by setting 
1025     // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own 
1026     // versions that keep track of fake<->real wnd proc mapping. 
1028         // On WinCE (at least), the wndproc comparison doesn't work, 
1029         // so have to use something like this. 
1031         extern const wxChar 
*wxCanvasClassName
; 
1032         extern const wxChar 
*wxCanvasClassNameNR
; 
1033         extern const wxChar 
*wxMDIFrameClassName
; 
1034         extern const wxChar 
*wxMDIFrameClassNameNoRedraw
; 
1035         extern const wxChar 
*wxMDIChildFrameClassName
; 
1036         extern const wxChar 
*wxMDIChildFrameClassNameNoRedraw
; 
1037         wxString 
str(wxGetWindowClass(hWnd
)); 
1038         if (str 
== wxCanvasClassName 
|| 
1039                 str 
== wxCanvasClassNameNR 
|| 
1040                 str 
== wxMDIFrameClassName 
|| 
1041                 str 
== wxMDIFrameClassNameNoRedraw 
|| 
1042                 str 
== wxMDIChildFrameClassName 
|| 
1043                 str 
== wxMDIChildFrameClassNameNoRedraw 
|| 
1044                 str 
== _T("wxTLWHiddenParent")) 
1045                 return true; // Effectively means don't subclass 
1050     if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd
), &cls
) ) 
1052         wxLogLastError(_T("GetClassInfo")); 
1057     return wndProc 
== (WXFARPROC
)cls
.lpfnWndProc
; 
1061 // ---------------------------------------------------------------------------- 
1063 // ---------------------------------------------------------------------------- 
1065 void wxWindowMSW::SetWindowStyleFlag(long flags
) 
1067     long flagsOld 
= GetWindowStyleFlag(); 
1068     if ( flags 
== flagsOld 
) 
1071     // update the internal variable 
1072     wxWindowBase::SetWindowStyleFlag(flags
); 
1074     // now update the Windows style as well if needed - and if the window had 
1075     // been already created 
1079     WXDWORD exstyle
, exstyleOld
; 
1080     long style 
= MSWGetStyle(flags
, &exstyle
), 
1081          styleOld 
= MSWGetStyle(flagsOld
, &exstyleOld
); 
1083     if ( style 
!= styleOld 
) 
1085         // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by 
1086         // this function so instead of simply setting the style to the new 
1087         // value we clear the bits which were set in styleOld but are set in 
1088         // the new one and set the ones which were not set before 
1089         long styleReal 
= ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
1090         styleReal 
&= ~styleOld
; 
1093         ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
); 
1096     // and the extended style 
1097     if ( exstyle 
!= exstyleOld 
) 
1099         long exstyleReal 
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1100         exstyleReal 
&= ~exstyleOld
; 
1101         exstyleReal 
|= exstyle
; 
1103         ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
); 
1105         // we must call SetWindowPos() to flash the cached extended style and 
1106         // also to make the change to wxSTAY_ON_TOP style take effect: just 
1107         // setting the style simply doesn't work 
1108         if ( !::SetWindowPos(GetHwnd(), 
1109                              exstyleReal 
& WS_EX_TOPMOST 
? HWND_TOPMOST
 
1112                              SWP_NOMOVE 
| SWP_NOSIZE
) ) 
1114             wxLogLastError(_T("SetWindowPos")); 
1119 WXDWORD 
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD 
*exstyle
) const 
1121     // translate the style 
1122     WXDWORD style 
= WS_CHILD 
| WS_VISIBLE
; 
1124     if ( flags 
& wxCLIP_CHILDREN 
) 
1125         style 
|= WS_CLIPCHILDREN
; 
1127     if ( flags 
& wxCLIP_SIBLINGS 
) 
1128         style 
|= WS_CLIPSIBLINGS
; 
1130     if ( flags 
& wxVSCROLL 
) 
1131         style 
|= WS_VSCROLL
; 
1133     if ( flags 
& wxHSCROLL 
) 
1134         style 
|= WS_HSCROLL
; 
1136     const wxBorder border 
= GetBorder(flags
); 
1138     // WS_BORDER is only required for wxBORDER_SIMPLE 
1139     if ( border 
== wxBORDER_SIMPLE 
) 
1142     // now deal with ext style if the caller wants it 
1148         if ( flags 
& wxTRANSPARENT_WINDOW 
) 
1149             *exstyle 
|= WS_EX_TRANSPARENT
; 
1155             case wxBORDER_DEFAULT
: 
1156                 wxFAIL_MSG( _T("unknown border style") ); 
1160             case wxBORDER_SIMPLE
: 
1163             case wxBORDER_STATIC
: 
1164                 *exstyle 
|= WS_EX_STATICEDGE
; 
1167             case wxBORDER_RAISED
: 
1168                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1171             case wxBORDER_SUNKEN
: 
1172                 *exstyle 
|= WS_EX_CLIENTEDGE
; 
1173                 style 
&= ~WS_BORDER
; 
1176             case wxBORDER_DOUBLE
: 
1177                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1181         // wxUniv doesn't use Windows dialog navigation functions at all 
1182 #if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__) 
1183         // to make the dialog navigation work with the nested panels we must 
1184         // use this style (top level windows such as dialogs don't need it) 
1185         if ( (flags 
& wxTAB_TRAVERSAL
) && !IsTopLevel() ) 
1187             *exstyle 
|= WS_EX_CONTROLPARENT
; 
1189 #endif // __WXUNIVERSAL__ 
1195 // Setup background and foreground colours correctly 
1196 void wxWindowMSW::SetupColours() 
1199         SetBackgroundColour(GetParent()->GetBackgroundColour()); 
1202 bool wxWindowMSW::IsMouseInWindow() const 
1204     // get the mouse position 
1206     ::GetCursorPos(&pt
); 
1208     // find the window which currently has the cursor and go up the window 
1209     // chain until we find this window - or exhaust it 
1210     HWND hwnd 
= ::WindowFromPoint(pt
); 
1211     while ( hwnd 
&& (hwnd 
!= GetHwnd()) ) 
1212         hwnd 
= ::GetParent(hwnd
); 
1214     return hwnd 
!= NULL
; 
1217 void wxWindowMSW::OnInternalIdle() 
1219     // Check if we need to send a LEAVE event 
1220     if ( m_mouseInWindow 
) 
1222         // note that we should generate the leave event whether the window has 
1223         // or doesn't have mouse capture 
1224         if ( !IsMouseInWindow() ) 
1226             // Generate a LEAVE event 
1227             m_mouseInWindow 
= false; 
1229             // Unfortunately the mouse button and keyboard state may have 
1230             // changed by the time the OnInternalIdle function is called, so 'state' 
1231             // may be meaningless. 
1233             if ( wxIsShiftDown() ) 
1235             if ( wxIsCtrlDown() ) 
1236                 state 
|= MK_CONTROL
; 
1237             if ( GetKeyState( VK_LBUTTON 
) ) 
1238                 state 
|= MK_LBUTTON
; 
1239             if ( GetKeyState( VK_MBUTTON 
) ) 
1240                 state 
|= MK_MBUTTON
; 
1241             if ( GetKeyState( VK_RBUTTON 
) ) 
1242                 state 
|= MK_RBUTTON
; 
1245             if ( !::GetCursorPos(&pt
) ) 
1247                 wxLogLastError(_T("GetCursorPos")); 
1250             // we need to have client coordinates here for symmetry with 
1251             // wxEVT_ENTER_WINDOW 
1252             RECT rect 
= wxGetWindowRect(GetHwnd()); 
1256             wxMouseEvent 
event2(wxEVT_LEAVE_WINDOW
); 
1257             InitMouseEvent(event2
, pt
.x
, pt
.y
, state
); 
1259             (void)GetEventHandler()->ProcessEvent(event2
); 
1263     if (wxUpdateUIEvent::CanUpdate(this)) 
1264         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
1267 // Set this window to be the child of 'parent'. 
1268 bool wxWindowMSW::Reparent(wxWindowBase 
*parent
) 
1270     if ( !wxWindowBase::Reparent(parent
) ) 
1273     HWND hWndChild 
= GetHwnd(); 
1274     HWND hWndParent 
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0; 
1276     ::SetParent(hWndChild
, hWndParent
); 
1279     if ( ::GetWindowLong(hWndChild
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
1281         EnsureParentHasControlParentStyle(GetParent()); 
1283 #endif // !__WXWINCE__ 
1288 static inline void SendSetRedraw(HWND hwnd
, bool on
) 
1290 #ifndef __WXMICROWIN__ 
1291     ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0); 
1295 void wxWindowMSW::Freeze() 
1297     SendSetRedraw(GetHwnd(), false); 
1300 void wxWindowMSW::Thaw() 
1302     SendSetRedraw(GetHwnd(), true); 
1304     // we need to refresh everything or otherwise he invalidated area is not 
1309 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1311     HWND hWnd 
= GetHwnd(); 
1317             mswRect
.left 
= rect
->x
; 
1318             mswRect
.top 
= rect
->y
; 
1319             mswRect
.right 
= rect
->x 
+ rect
->width
; 
1320             mswRect
.bottom 
= rect
->y 
+ rect
->height
; 
1322             ::InvalidateRect(hWnd
, &mswRect
, eraseBack
); 
1325             ::InvalidateRect(hWnd
, NULL
, eraseBack
); 
1329 void wxWindowMSW::Update() 
1331     if ( !::UpdateWindow(GetHwnd()) ) 
1333         wxLogLastError(_T("UpdateWindow")); 
1336 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
1337     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT 
1338     // handler needs to be really drawn right now 
1343 // --------------------------------------------------------------------------- 
1345 // --------------------------------------------------------------------------- 
1348 #if wxUSE_DRAG_AND_DROP 
1349 void wxWindowMSW::SetDropTarget(wxDropTarget 
*pDropTarget
) 
1351     if ( m_dropTarget 
!= 0 ) { 
1352         m_dropTarget
->Revoke(m_hWnd
); 
1353         delete m_dropTarget
; 
1356     m_dropTarget 
= pDropTarget
; 
1357     if ( m_dropTarget 
!= 0 ) 
1358         m_dropTarget
->Register(m_hWnd
); 
1360 #endif // wxUSE_DRAG_AND_DROP 
1362 // old style file-manager drag&drop support: we retain the old-style 
1363 // DragAcceptFiles in parallel with SetDropTarget. 
1364 void wxWindowMSW::DragAcceptFiles(bool accept
) 
1366 #if !defined(__WXWINCE__) 
1367     HWND hWnd 
= GetHwnd(); 
1369         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
1373 // ---------------------------------------------------------------------------- 
1375 // ---------------------------------------------------------------------------- 
1379 void wxWindowMSW::DoSetToolTip(wxToolTip 
*tooltip
) 
1381     wxWindowBase::DoSetToolTip(tooltip
); 
1384         m_tooltip
->SetWindow((wxWindow 
*)this); 
1387 #endif // wxUSE_TOOLTIPS 
1389 // --------------------------------------------------------------------------- 
1390 // moving and resizing 
1391 // --------------------------------------------------------------------------- 
1394 void wxWindowMSW::DoGetSize(int *x
, int *y
) const 
1396     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1399         *x 
= rect
.right 
- rect
.left
; 
1401         *y 
= rect
.bottom 
- rect
.top
; 
1404 // Get size *available for subwindows* i.e. excluding menu bar etc. 
1405 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const 
1407     RECT rect 
= wxGetClientRect(GetHwnd()); 
1415 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const 
1417     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1420     point
.x 
= rect
.left
; 
1423     // we do the adjustments with respect to the parent only for the "real" 
1424     // children, not for the dialogs/frames 
1425     if ( !IsTopLevel() ) 
1427         HWND hParentWnd 
= 0; 
1428         wxWindow 
*parent 
= GetParent(); 
1430             hParentWnd 
= GetWinHwnd(parent
); 
1432         // Since we now have the absolute screen coords, if there's a parent we 
1433         // must subtract its top left corner 
1436             ::ScreenToClient(hParentWnd
, &point
); 
1441             // We may be faking the client origin. So a window that's really at (0, 
1442             // 30) may appear (to wxWin apps) to be at (0, 0). 
1443             wxPoint 
pt(parent
->GetClientAreaOrigin()); 
1455 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const 
1463     ::ScreenToClient(GetHwnd(), &pt
); 
1471 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const 
1479     ::ClientToScreen(GetHwnd(), &pt
); 
1487 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
) 
1489     // TODO: is this consistent with other platforms? 
1490     // Still, negative width or height shouldn't be allowed 
1495     if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) ) 
1497         wxLogLastError(wxT("MoveWindow")); 
1501 // set the size of the window: if the dimensions are positive, just use them, 
1502 // but if any of them is equal to -1, it means that we must find the value for 
1503 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
1504 // which case -1 is a valid value for x and y) 
1506 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
1507 // the width/height to best suit our contents, otherwise we reuse the current 
1509 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
1511     // get the current size and position... 
1512     int currentX
, currentY
; 
1513     GetPosition(¤tX
, ¤tY
); 
1514     int currentW
,currentH
; 
1515     GetSize(¤tW
, ¤tH
); 
1517     // ... and don't do anything (avoiding flicker) if it's already ok 
1518     if ( x 
== currentX 
&& y 
== currentY 
&& 
1519          width 
== currentW 
&& height 
== currentH 
) 
1524     if ( x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1526     if ( y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1529     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
1531     wxSize 
size(-1, -1); 
1534         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
1536             size 
= DoGetBestSize(); 
1541             // just take the current one 
1548         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
1552                 size 
= DoGetBestSize(); 
1554             //else: already called DoGetBestSize() above 
1560             // just take the current one 
1565     DoMoveWindow(x
, y
, width
, height
); 
1568 void wxWindowMSW::DoSetClientSize(int width
, int height
) 
1570     // setting the client size is less obvious than it it could have been 
1571     // because in the result of changing the total size the window scrollbar 
1572     // may [dis]appear and/or its menubar may [un]wrap and so the client size 
1573     // will not be correct as the difference between the total and client size 
1574     // changes - so we keep changing it until we get it right 
1576     // normally this loop shouldn't take more than 3 iterations (usually 1 but 
1577     // if scrollbars [dis]appear as the result of the first call, then 2 and it 
1578     // may become 3 if the window had 0 size originally and so we didn't 
1579     // calculate the scrollbar correction correctly during the first iteration) 
1580     // but just to be on the safe side we check for it instead of making it an 
1581     // "infinite" loop (i.e. leaving break inside as the only way to get out) 
1582     for ( int i 
= 0; i 
< 4; i
++ ) 
1585         ::GetClientRect(GetHwnd(), &rectClient
); 
1587         // if the size is already ok, stop here (rectClient.left = top = 0) 
1588         if ( (rectClient
.right 
== width 
|| width 
== -1) && 
1589              (rectClient
.bottom 
== height 
|| height 
== -1) ) 
1594         int widthClient 
= width
, 
1595             heightClient 
= height
; 
1597         // Find the difference between the entire window (title bar and all) 
1598         // and the client area; add this to the new client size to move the 
1601         ::GetWindowRect(GetHwnd(), &rectWin
); 
1603         widthClient 
+= rectWin
.right 
- rectWin
.left 
- rectClient
.right
; 
1604         heightClient 
+= rectWin
.bottom 
- rectWin
.top 
- rectClient
.bottom
; 
1607         point
.x 
= rectWin
.left
; 
1608         point
.y 
= rectWin
.top
; 
1610         // MoveWindow positions the child windows relative to the parent, so 
1611         // adjust if necessary 
1612         if ( !IsTopLevel() ) 
1614             wxWindow 
*parent 
= GetParent(); 
1617                 ::ScreenToClient(GetHwndOf(parent
), &point
); 
1621         DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
); 
1625 // For implementation purposes - sometimes decorations make the client area 
1627 wxPoint 
wxWindowMSW::GetClientAreaOrigin() const 
1629     return wxPoint(0, 0); 
1632 // --------------------------------------------------------------------------- 
1634 // --------------------------------------------------------------------------- 
1636 int wxWindowMSW::GetCharHeight() const 
1638     return wxGetTextMetrics(this).tmHeight
; 
1641 int wxWindowMSW::GetCharWidth() const 
1643     // +1 is needed because Windows apparently adds it when calculating the 
1644     // dialog units size in pixels 
1645 #if wxDIALOG_UNIT_COMPATIBILITY 
1646     return wxGetTextMetrics(this).tmAveCharWidth
; 
1648     return wxGetTextMetrics(this).tmAveCharWidth 
+ 1; 
1652 void wxWindowMSW::GetTextExtent(const wxString
& string
, 
1654                              int *descent
, int *externalLeading
, 
1655                              const wxFont 
*theFont
) const 
1657     const wxFont 
*fontToUse 
= theFont
; 
1659         fontToUse 
= &m_font
; 
1661     HWND hWnd 
= GetHwnd(); 
1662     HDC dc 
= ::GetDC(hWnd
); 
1666     if ( fontToUse 
&& fontToUse
->Ok() ) 
1668         fnt 
= (HFONT
)((wxFont 
*)fontToUse
)->GetResourceHandle(); // const_cast 
1670             hfontOld 
= (HFONT
)SelectObject(dc
,fnt
); 
1675     GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
); 
1676     GetTextMetrics(dc
, &tm
); 
1678     if ( fontToUse 
&& fnt 
&& hfontOld 
) 
1679         SelectObject(dc
, hfontOld
); 
1681     ReleaseDC(hWnd
, dc
); 
1688         *descent 
= tm
.tmDescent
; 
1689     if ( externalLeading 
) 
1690         *externalLeading 
= tm
.tmExternalLeading
; 
1693 // --------------------------------------------------------------------------- 
1695 // --------------------------------------------------------------------------- 
1697 #if wxUSE_MENUS_NATIVE 
1699 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue 
1700 // immediately, without waiting for the next event loop iteration 
1702 // NB: this function should probably be made public later as it can almost 
1703 //     surely replace wxYield() elsewhere as well 
1704 static void wxYieldForCommandsOnly() 
1706     // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't 
1707     // want to process it here) 
1709     while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) ) 
1711         if ( msg
.message 
== WM_QUIT 
) 
1713             // if we retrieved a WM_QUIT, insert back into the message queue. 
1714             ::PostQuitMessage(0); 
1718         // luckily (as we don't have access to wxEventLoopImpl method from here 
1719         // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it 
1721         ::TranslateMessage(&msg
); 
1722         ::DispatchMessage(&msg
); 
1726 bool wxWindowMSW::DoPopupMenu(wxMenu 
*menu
, int x
, int y
) 
1728     menu
->SetInvokingWindow(this); 
1731     HWND hWnd 
= GetHwnd(); 
1732     HMENU hMenu 
= GetHmenuOf(menu
); 
1736     ::ClientToScreen(hWnd
, &point
); 
1737     wxCurrentPopupMenu 
= menu
; 
1739 #if !defined(__WXWINCE__) 
1740     flags 
= TPM_RIGHTBUTTON
; 
1742     ::TrackPopupMenu(hMenu
, flags
, point
.x
, point
.y
, 0, hWnd
, NULL
); 
1744     // we need to do it righ now as otherwise the events are never going to be 
1745     // sent to wxCurrentPopupMenu from HandleCommand() 
1747     // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't 
1748     // help and we'd still need wxYieldForCommandsOnly() as the menu may be 
1749     // destroyed as soon as we return (it can be a local variable in the caller 
1750     // for example) and so we do need to process the event immediately 
1751     wxYieldForCommandsOnly(); 
1753     wxCurrentPopupMenu 
= NULL
; 
1755     menu
->SetInvokingWindow(NULL
); 
1760 #endif // wxUSE_MENUS_NATIVE 
1762 // =========================================================================== 
1763 // pre/post message processing 
1764 // =========================================================================== 
1766 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
1769         return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
1771         return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
); 
1774 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
) 
1776     // wxUniversal implements tab traversal itself 
1777 #ifndef __WXUNIVERSAL__ 
1778     if ( m_hWnd 
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) ) 
1780         // intercept dialog navigation keys 
1781         MSG 
*msg 
= (MSG 
*)pMsg
; 
1783         // here we try to do all the job which ::IsDialogMessage() usually does 
1786         if ( msg
->message 
== WM_KEYDOWN 
) 
1788             bool bCtrlDown 
= wxIsCtrlDown(); 
1789             bool bShiftDown 
= wxIsShiftDown(); 
1791             // WM_GETDLGCODE: ask the control if it wants the key for itself, 
1792             // don't process it if it's the case (except for Ctrl-Tab/Enter 
1793             // combinations which are always processed) 
1797                 lDlgCode 
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0); 
1799                 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the 
1800                 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, 
1801                 // it, of course, implies them 
1802                 if ( lDlgCode 
& DLGC_WANTALLKEYS 
) 
1804                     lDlgCode 
|= DLGC_WANTTAB 
| DLGC_WANTARROWS
; 
1808             bool bForward 
= true, 
1809                  bWindowChange 
= false; 
1811             // should we process this message specially? 
1812             bool bProcess 
= true; 
1813             switch ( msg
->wParam 
) 
1816                     if ( lDlgCode 
& DLGC_WANTTAB 
) { 
1820                         // Ctrl-Tab cycles thru notebook pages 
1821                         bWindowChange 
= bCtrlDown
; 
1822                         bForward 
= !bShiftDown
; 
1828                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1836                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1843                         wxButton 
*btn 
= wxDynamicCast(FindWindow(wxID_CANCEL
), 
1845                         if ( btn 
&& btn
->IsEnabled() ) 
1847                             // if we do have a cancel button, do press it 
1848                             btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1850                             // we consumed the message 
1853 #endif // wxUSE_BUTTON 
1861                         if ( (lDlgCode 
& DLGC_WANTMESSAGE
) && !bCtrlDown 
) 
1863                             // control wants to process Enter itself, don't 
1864                             // call IsDialogMessage() which would interpret 
1868                         else if ( lDlgCode 
& DLGC_BUTTON 
) 
1870                             // let IsDialogMessage() handle this for all 
1871                             // buttons except the owner-drawn ones which it 
1872                             // just seems to ignore 
1873                             long style 
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
); 
1874                             if ( (style 
& BS_OWNERDRAW
) == BS_OWNERDRAW 
) 
1876                                 // emulate the button click 
1877                                 wxWindow 
*btn 
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
); 
1879                                     btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1884                         // FIXME: this should be handled by 
1885                         //        wxNavigationKeyEvent handler and not here!! 
1889                             wxButton 
*btn 
= wxDynamicCast(GetDefaultItem(), 
1891                             if ( btn 
&& btn
->IsEnabled() ) 
1893                                 // if we do have a default button, do press it 
1894                                 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1898                             else // no default button 
1900 #endif // wxUSE_BUTTON 
1901                                 // this is a quick and dirty test for a text 
1903                                 if ( !(lDlgCode 
& DLGC_HASSETSEL
) ) 
1905                                     // don't process Enter, the control might 
1906                                     // need it for itself and don't let 
1907                                     // ::IsDialogMessage() have it as it can 
1908                                     // eat the Enter events sometimes 
1911                                 else if (!IsTopLevel()) 
1913                                     // if not a top level window, let parent 
1917                                 //else: treat Enter as TAB: pass to the next 
1918                                 //      control as this is the best thing to do 
1919                                 //      if the text doesn't handle Enter itself 
1931                 wxNavigationKeyEvent event
; 
1932                 event
.SetDirection(bForward
); 
1933                 event
.SetWindowChange(bWindowChange
); 
1934                 event
.SetEventObject(this); 
1936                 if ( GetEventHandler()->ProcessEvent(event
) ) 
1943         // let ::IsDialogMessage() do almost everything and handle just the 
1944         // things it doesn't here: Ctrl-TAB for switching notebook pages 
1945         if ( msg
->message 
== WM_KEYDOWN 
) 
1947             // don't process system keys here 
1948             if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) ) 
1950                 if ( (msg
->wParam 
== VK_TAB
) && wxIsCtrlDown() ) 
1952                     // find the first notebook parent and change its page 
1953                     wxWindow 
*win 
= this; 
1954                     wxNotebook 
*nbook 
= NULL
; 
1955                     while ( win 
&& !nbook 
) 
1957                         nbook 
= wxDynamicCast(win
, wxNotebook
); 
1958                         win 
= win
->GetParent(); 
1963                         bool forward 
= !wxIsShiftDown(); 
1965                         nbook
->AdvanceSelection(forward
); 
1972         // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the 
1973         // message even when there is no cancel button and when the message is 
1974         // needed by the control itself: in particular, it prevents the tree in 
1975         // place edit control from being closed with Escape in a dialog 
1976         if ( msg
->message 
!= WM_KEYDOWN 
|| msg
->wParam 
!= VK_ESCAPE 
) 
1978             // ::IsDialogMessage() is broken and may sometimes hang the 
1979             // application by going into an infinite loop, so we try to detect 
1980             // [some of] the situatations when this may happen and not call it 
1983             // assume we can call it by default 
1984             bool canSafelyCallIsDlgMsg 
= true; 
1986             HWND hwndFocus 
= ::GetFocus(); 
1988             // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter 
1989             // an infinite loop, because it will recursively check the child 
1990             // windows but not the window itself and so if none of the children 
1991             // accepts focus it loops forever (as it only stops when it gets 
1992             // back to the window it started from) 
1994             // while it is very unusual that a window with WS_EX_CONTROLPARENT 
1995             // style has the focus, it can happen. One such possibility is if 
1996             // all windows are either toplevel, wxDialog, wxPanel or static 
1997             // controls and no window can actually accept keyboard input. 
1998 #if !defined(__WXWINCE__) 
1999             if ( ::GetWindowLong(hwndFocus
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT 
) 
2001                 // passimistic by default 
2002                 canSafelyCallIsDlgMsg 
= false; 
2003                 for ( wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
2005                       node 
= node
->GetNext() ) 
2007                     wxWindow 
* const win 
= node
->GetData(); 
2008                     if ( win
->AcceptsFocus() && 
2009                             !(::GetWindowLong(GetHwndOf(win
), GWL_EXSTYLE
) & 
2010                                 WS_EX_CONTROLPARENT
) ) 
2012                         // it shouldn't hang... 
2013                         canSafelyCallIsDlgMsg 
= true; 
2019 #endif // !__WXWINCE__ 
2021             if ( canSafelyCallIsDlgMsg 
) 
2023                 // ::IsDialogMessage() can enter in an infinite loop when the 
2024                 // currently focused window is disabled or hidden and its 
2025                 // parent has WS_EX_CONTROLPARENT style, so don't call it in 
2029                     if ( !::IsWindowEnabled(hwndFocus
) || 
2030                             !::IsWindowVisible(hwndFocus
) ) 
2032                         // it would enter an infinite loop if we do this! 
2033                         canSafelyCallIsDlgMsg 
= false; 
2038                     if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) ) 
2040                         // it's a top level window, don't go further -- e.g. even 
2041                         // if the parent of a dialog is disabled, this doesn't 
2042                         // break navigation inside the dialog 
2046                     hwndFocus 
= ::GetParent(hwndFocus
); 
2050             // let IsDialogMessage() have the message if it's safe to call it 
2051             if ( canSafelyCallIsDlgMsg 
&& ::IsDialogMessage(GetHwnd(), msg
) ) 
2053                 // IsDialogMessage() did something... 
2058 #endif // __WXUNIVERSAL__ 
2063         // relay mouse move events to the tooltip control 
2064         MSG 
*msg 
= (MSG 
*)pMsg
; 
2065         if ( msg
->message 
== WM_MOUSEMOVE 
) 
2066             m_tooltip
->RelayEvent(pMsg
); 
2068 #endif // wxUSE_TOOLTIPS 
2073 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
) 
2075 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__) 
2076     return m_acceleratorTable
.Translate(this, pMsg
); 
2080 #endif // wxUSE_ACCEL 
2083 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
)) 
2085     // preprocess all messages by default 
2089 // --------------------------------------------------------------------------- 
2090 // message params unpackers 
2091 // --------------------------------------------------------------------------- 
2093 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2094                              WORD 
*id
, WXHWND 
*hwnd
, WORD 
*cmd
) 
2096     *id 
= LOWORD(wParam
); 
2097     *hwnd 
= (WXHWND
)lParam
; 
2098     *cmd 
= HIWORD(wParam
); 
2101 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2102                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2104     *state 
= LOWORD(wParam
); 
2105     *minimized 
= HIWORD(wParam
); 
2106     *hwnd 
= (WXHWND
)lParam
; 
2109 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2110                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2112     *code 
= LOWORD(wParam
); 
2113     *pos 
= HIWORD(wParam
); 
2114     *hwnd 
= (WXHWND
)lParam
; 
2117 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2118                               WXWORD 
*nCtlColor
, WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2120 #ifndef __WXMICROWIN__ 
2121     *nCtlColor 
= CTLCOLOR_BTN
; 
2122     *hwnd 
= (WXHWND
)lParam
; 
2123     *hdc 
= (WXHDC
)wParam
; 
2127 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2128                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2130     *item 
= (WXWORD
)wParam
; 
2131     *flags 
= HIWORD(wParam
); 
2132     *hmenu 
= (WXHMENU
)lParam
; 
2135 // --------------------------------------------------------------------------- 
2136 // Main wxWindows window proc and the window proc for wxWindow 
2137 // --------------------------------------------------------------------------- 
2139 // Hook for new window just as it's being created, when the window isn't yet 
2140 // associated with the handle 
2141 static wxWindowMSW 
*gs_winBeingCreated 
= NULL
; 
2143 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the 
2144 // window being created and insures that it's always unset back later 
2145 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW 
*winBeingCreated
) 
2147     gs_winBeingCreated 
= winBeingCreated
; 
2150 wxWindowCreationHook::~wxWindowCreationHook() 
2152     gs_winBeingCreated 
= NULL
; 
2156 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) 
2158     // trace all messages - useful for the debugging 
2160     wxLogTrace(wxTraceMessages
, 
2161                wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"), 
2162                wxGetMessageName(message
), (long)hWnd
, (long)wParam
, lParam
); 
2163 #endif // __WXDEBUG__ 
2165     wxWindowMSW 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2167     // when we get the first message for the HWND we just created, we associate 
2168     // it with wxWindow stored in gs_winBeingCreated 
2169     if ( !wnd 
&& gs_winBeingCreated 
) 
2171         wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
); 
2172         wnd 
= gs_winBeingCreated
; 
2173         gs_winBeingCreated 
= NULL
; 
2174         wnd
->SetHWND((WXHWND
)hWnd
); 
2180         rc 
= wnd
->MSWWindowProc(message
, wParam
, lParam
); 
2182         rc 
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
); 
2187 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
2189     // did we process the message? 
2190     bool processed 
= false; 
2201     // for most messages we should return 0 when we do process the message 
2209                 processed 
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
); 
2212                     // return 0 to allow window creation 
2213                     rc
.result 
= mayCreate 
? 0 : -1; 
2219             // never set processed to true and *always* pass WM_DESTROY to 
2220             // DefWindowProc() as Windows may do some internal cleanup when 
2221             // processing it and failing to pass the message along may cause 
2222             // memory and resource leaks! 
2223             (void)HandleDestroy(); 
2227             processed 
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2230 #if !defined(__WXWINCE__) 
2233                 LPRECT pRect 
= (LPRECT
)lParam
; 
2235                 rc
.SetLeft(pRect
->left
); 
2236                 rc
.SetTop(pRect
->top
); 
2237                 rc
.SetRight(pRect
->right
); 
2238                 rc
.SetBottom(pRect
->bottom
); 
2239                 processed 
= HandleMoving(rc
); 
2241                     pRect
->left 
= rc
.GetLeft(); 
2242                     pRect
->top 
= rc
.GetTop(); 
2243                     pRect
->right 
= rc
.GetRight(); 
2244                     pRect
->bottom 
= rc
.GetBottom(); 
2255                     // we're not interested in these messages at all 
2258                 case SIZE_MINIMIZED
: 
2259                     // we shouldn't send sizev events for these messages as the 
2260                     // client size may be negative which breaks existing code 
2262                     // OTOH we might send another (wxMinimizedEvent?) one or 
2263                     // add an additional parameter to wxSizeEvent if this is 
2264                     // useful to anybody 
2268                     wxFAIL_MSG( _T("unexpected WM_SIZE parameter") ); 
2269                     // fall through nevertheless 
2271                 case SIZE_MAXIMIZED
: 
2273                     processed 
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), 
2278 #if !defined(__WXWINCE__) 
2281                 LPRECT pRect 
= (LPRECT
)lParam
; 
2283                 rc
.SetLeft(pRect
->left
); 
2284                 rc
.SetTop(pRect
->top
); 
2285                 rc
.SetRight(pRect
->right
); 
2286                 rc
.SetBottom(pRect
->bottom
); 
2287                 processed 
= HandleSizing(rc
); 
2289                     pRect
->left 
= rc
.GetLeft(); 
2290                     pRect
->top 
= rc
.GetTop(); 
2291                     pRect
->right 
= rc
.GetRight(); 
2292                     pRect
->bottom 
= rc
.GetBottom(); 
2298 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
2299         case WM_ACTIVATEAPP
: 
2300             wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
2306                 WXWORD state
, minimized
; 
2308                 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
); 
2310                 processed 
= HandleActivate(state
, minimized 
!= 0, (WXHWND
)hwnd
); 
2315             processed 
= HandleSetFocus((WXHWND
)(HWND
)wParam
); 
2319             processed 
= HandleKillFocus((WXHWND
)(HWND
)wParam
); 
2326                     // cast to wxWindow is needed for wxUniv 
2327                     wxPaintDCEx 
dc((wxWindow 
*)this, (WXHDC
)wParam
); 
2328                     processed 
= HandlePaint(); 
2332                     processed 
= HandlePaint(); 
2340                 // Don't call the wx handlers in this case 
2341                 if ( wxIsKindOf(this, wxListCtrl
) ) 
2344                 if ( lParam 
& PRF_ERASEBKGND 
) 
2345                     HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
2347                 wxPaintDCEx 
dc((wxWindow 
*)this, (WXHDC
)wParam
); 
2348                 processed 
= HandlePaint(); 
2354 #ifdef __WXUNIVERSAL__ 
2355             // Universal uses its own wxFrame/wxDialog, so we don't receive 
2356             // close events unless we have this. 
2361             // don't let the DefWindowProc() destroy our window - we'll do it 
2362             // ourselves in ~wxWindow 
2369             processed 
= HandleShow(wParam 
!= 0, (int)lParam
); 
2373             processed 
= HandleMouseMove(GET_X_LPARAM(lParam
), 
2374                                         GET_Y_LPARAM(lParam
), 
2378             // Seems to be broken currently 
2379 #if 0 // ndef __WXWINCE__ 
2382             wxASSERT_MSG( !m_mouseInWindow
, wxT("the mouse should be in a window to generate this event!") ); 
2384             // only process this message if the mouse is not in the window, 
2385             // This can also check for children in composite windows.  
2386             // however, this may mean the the wxEVT_LEAVE_WINDOW is never sent 
2387             // if the mouse does not enter the window from it's child before  
2388             // leaving the scope of the window. ( perhaps this can be picked 
2389             // up in the OnIdle code as before, for this special case ) 
2390             if ( /*IsComposite() && */ !IsMouseInWindow() ) 
2392                 m_mouseInWindow 
= false; 
2394                 // Unfortunately no mouse state is passed with a WM_MOUSE_LEAVE  
2396                 if ( wxIsShiftDown() ) 
2398                 if ( wxIsCtrlDown() ) 
2399                     state 
|= MK_CONTROL
; 
2400                 if ( GetKeyState( VK_LBUTTON 
) ) 
2401                     state 
|= MK_LBUTTON
; 
2402                 if ( GetKeyState( VK_MBUTTON 
) ) 
2403                     state 
|= MK_MBUTTON
; 
2404                 if ( GetKeyState( VK_RBUTTON 
) ) 
2405                     state 
|= MK_RBUTTON
; 
2408                 if ( !::GetCursorPos(&pt
) ) 
2410                     wxLogLastError(_T("GetCursorPos")); 
2413                 // we need to have client coordinates here for symmetry with 
2414                 // wxEVT_ENTER_WINDOW 
2415                 RECT rect 
= wxGetWindowRect(GetHwnd()); 
2419                 wxMouseEvent 
event2(wxEVT_LEAVE_WINDOW
); 
2420                 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
); 
2422                 (void)GetEventHandler()->ProcessEvent(event2
); 
2424             // always pass processed back as false, this allows the window 
2425             // manager to process the message too.  This is needed to ensure 
2426             // windows XP themes work properly as the mouse moves over widgets 
2434 #if wxUSE_MOUSEWHEEL 
2436             processed 
= HandleMouseWheel(wParam
, lParam
); 
2440         case WM_LBUTTONDOWN
: 
2442         case WM_LBUTTONDBLCLK
: 
2443         case WM_RBUTTONDOWN
: 
2445         case WM_RBUTTONDBLCLK
: 
2446         case WM_MBUTTONDOWN
: 
2448         case WM_MBUTTONDBLCLK
: 
2450 #ifdef __WXMICROWIN__ 
2451                 // MicroWindows seems to ignore the fact that a window is 
2452                 // disabled. So catch mouse events and throw them away if 
2454                 wxWindowMSW
* win 
= this; 
2457                     if (!win
->IsEnabled()) 
2463                     win 
= win
->GetParent(); 
2464                     if ( !win 
|| win
->IsTopLevel() ) 
2471 #endif // __WXMICROWIN__ 
2472                 int x 
= GET_X_LPARAM(lParam
), 
2473                     y 
= GET_Y_LPARAM(lParam
); 
2475                 // redirect the event to a static control if necessary by 
2476                 // finding one under mouse 
2478                 if ( GetCapture() == this ) 
2480                     // but don't do it if the mouse is captured by this window 
2481                     // because then it should really get this event itself 
2486                     win 
= FindWindowForMouseEvent(this, &x
, &y
); 
2488                     // this should never happen 
2489                     wxCHECK_MSG( win
, 0, 
2490                                  _T("FindWindowForMouseEvent() returned NULL") ); 
2492                     // for the standard classes their WndProc sets the focus to 
2493                     // them anyhow and doing it from here results in some weird 
2494                     // problems, but for our windows we want them to acquire 
2495                     // focus when clicked 
2496                     if ( !win
->IsOfStandardClass() ) 
2498                         if ( message 
== WM_LBUTTONDOWN 
&& win
->AcceptsFocus() ) 
2503                 processed 
= win
->HandleMouseEvent(message
, x
, y
, wParam
); 
2512         case MM_JOY1BUTTONDOWN
: 
2513         case MM_JOY2BUTTONDOWN
: 
2514         case MM_JOY1BUTTONUP
: 
2515         case MM_JOY2BUTTONUP
: 
2516             processed 
= HandleJoystickEvent(message
, 
2517                                             GET_X_LPARAM(lParam
), 
2518                                             GET_Y_LPARAM(lParam
), 
2521 #endif // __WXMICROWIN__ 
2524             processed 
= HandleSysCommand(wParam
, lParam
); 
2531                 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
); 
2533                 processed 
= HandleCommand(id
, cmd
, hwnd
); 
2538             processed 
= HandleNotify((int)wParam
, lParam
, &rc
.result
); 
2541             // for these messages we must return true if process the message 
2544         case WM_MEASUREITEM
: 
2546                 int idCtrl 
= (UINT
)wParam
; 
2547                 if ( message 
== WM_DRAWITEM 
) 
2549                     processed 
= MSWOnDrawItem(idCtrl
, 
2550                                               (WXDRAWITEMSTRUCT 
*)lParam
); 
2554                     processed 
= MSWOnMeasureItem(idCtrl
, 
2555                                                  (WXMEASUREITEMSTRUCT 
*)lParam
); 
2562 #endif // defined(WM_DRAWITEM) 
2565             if ( !IsOfStandardClass() ) 
2567                 // we always want to get the char events 
2568                 rc
.result 
= DLGC_WANTCHARS
; 
2570                 if ( GetWindowStyleFlag() & wxWANTS_CHARS 
) 
2572                     // in fact, we want everything 
2573                     rc
.result 
|= DLGC_WANTARROWS 
| 
2580             //else: get the dlg code from the DefWindowProc() 
2585             // If this has been processed by an event handler, return 0 now 
2586             // (we've handled it). 
2587             m_lastKeydownProcessed 
= HandleKeyDown((WORD
) wParam
, lParam
); 
2588             if ( m_lastKeydownProcessed 
) 
2597                     // we consider these message "not interesting" to OnChar, so 
2598                     // just don't do anything more with them 
2608                     // avoid duplicate messages to OnChar for these ASCII keys: 
2609                     // they will be translated by TranslateMessage() and received 
2631                         // but set processed to false, not true to still pass them 
2632                         // to the control's default window proc - otherwise 
2633                         // built-in keyboard handling won't work 
2638                     // special case of VK_APPS: treat it the same as right mouse 
2639                     // click because both usually pop up a context menu 
2645                             TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2646                             processed 
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
); 
2652                         // do generate a CHAR event 
2653                         processed 
= HandleChar((WORD
)wParam
, lParam
); 
2656             if (message 
== WM_SYSKEYDOWN
)  // Let Windows still handle the SYSKEYs 
2663             // special case of VK_APPS: treat it the same as right mouse button 
2664             if ( wParam 
== VK_APPS 
) 
2669                 TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2670                 processed 
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
); 
2675                 processed 
= HandleKeyUp((WORD
) wParam
, lParam
); 
2680         case WM_CHAR
: // Always an ASCII character 
2681             if ( m_lastKeydownProcessed 
) 
2683                 // The key was handled in the EVT_KEY_DOWN and handling 
2684                 // a key in an EVT_KEY_DOWN handler is meant, by 
2685                 // design, to prevent EVT_CHARs from happening 
2686                 m_lastKeydownProcessed 
= false; 
2691                 processed 
= HandleChar((WORD
)wParam
, lParam
, true); 
2697             processed 
= HandleHotKey((WORD
)wParam
, lParam
); 
2699 #endif // wxUSE_HOTKEY 
2706                 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
); 
2708                 processed 
= MSWOnScroll(message 
== WM_HSCROLL 
? wxHORIZONTAL
 
2714         // CTLCOLOR messages are sent by children to query the parent for their 
2715         // colors#ifndef __WXMICROWIN__ 
2716 #ifndef __WXMICROWIN__ 
2717         case WM_CTLCOLORMSGBOX
: 
2718         case WM_CTLCOLOREDIT
: 
2719         case WM_CTLCOLORLISTBOX
: 
2720         case WM_CTLCOLORBTN
: 
2721         case WM_CTLCOLORDLG
: 
2722         case WM_CTLCOLORSCROLLBAR
: 
2723         case WM_CTLCOLORSTATIC
: 
2728                 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
); 
2730                 processed 
= HandleCtlColor(&rc
.hBrush
, 
2739 #endif // !__WXMICROWIN__ 
2741         case WM_SYSCOLORCHANGE
: 
2742             // the return value for this message is ignored 
2743             processed 
= HandleSysColorChange(); 
2746 #if !defined(__WXWINCE__) 
2747         case WM_DISPLAYCHANGE
: 
2748             processed 
= HandleDisplayChange(); 
2752         case WM_PALETTECHANGED
: 
2753             processed 
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
); 
2756         case WM_CAPTURECHANGED
: 
2757             processed 
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
); 
2760         case WM_QUERYNEWPALETTE
: 
2761             processed 
= HandleQueryNewPalette(); 
2765             processed 
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
2768                 // we processed the message, i.e. erased the background 
2773 #if !defined(__WXWINCE__) 
2775             processed 
= HandleDropFiles(wParam
); 
2780             processed 
= HandleInitDialog((WXHWND
)(HWND
)wParam
); 
2784                 // we never set focus from here 
2789 #if !defined(__WXWINCE__) 
2790         case WM_QUERYENDSESSION
: 
2791             processed 
= HandleQueryEndSession(lParam
, &rc
.allow
); 
2795             processed 
= HandleEndSession(wParam 
!= 0, lParam
); 
2798         case WM_GETMINMAXINFO
: 
2799             processed 
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
); 
2804             processed 
= HandleSetCursor((WXHWND
)(HWND
)wParam
, 
2805                                         LOWORD(lParam
),     // hit test 
2806                                         HIWORD(lParam
));    // mouse msg 
2810                 // returning TRUE stops the DefWindowProc() from further 
2811                 // processing this message - exactly what we need because we've 
2812                 // just set the cursor. 
2817 #if wxUSE_ACCESSIBILITY 
2820                 //WPARAM dwFlags = (WPARAM) (DWORD) wParam; 
2821                 LPARAM dwObjId 
= (LPARAM
) (DWORD
) lParam
; 
2823                 if (dwObjId 
== (LPARAM
)OBJID_CLIENT 
&& GetOrCreateAccessible()) 
2825                     return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible()); 
2831 #if defined(WM_HELP) 
2834                 // HELPINFO doesn't seem to be supported on WinCE. 
2836                 HELPINFO
* info 
= (HELPINFO
*) lParam
; 
2837                 // Don't yet process menu help events, just windows 
2838                 if (info
->iContextType 
== HELPINFO_WINDOW
) 
2841                     wxWindowMSW
* subjectOfHelp 
= this; 
2842                     bool eventProcessed 
= false; 
2843                     while (subjectOfHelp 
&& !eventProcessed
) 
2845                         wxHelpEvent 
helpEvent(wxEVT_HELP
, 
2846                                               subjectOfHelp
->GetId(), 
2850                                               wxPoint(info
->MousePos
.x
, info
->MousePos
.y
) 
2854                         helpEvent
.SetEventObject(this); 
2856                             GetEventHandler()->ProcessEvent(helpEvent
); 
2858                         // Go up the window hierarchy until the event is 
2860                         subjectOfHelp 
= subjectOfHelp
->GetParent(); 
2863                     processed 
= eventProcessed
; 
2866                 else if (info
->iContextType 
== HELPINFO_MENUITEM
) 
2868                     wxHelpEvent 
helpEvent(wxEVT_HELP
, info
->iCtrlId
); 
2869                     helpEvent
.SetEventObject(this); 
2870                     processed 
= GetEventHandler()->ProcessEvent(helpEvent
); 
2873                 //else: processed is already false 
2879 #if !defined(__WXWINCE__) 
2880         case WM_CONTEXTMENU
: 
2882                 // we don't convert from screen to client coordinates as 
2883                 // the event may be handled by a parent window 
2884                 wxPoint 
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2886                 wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
2888                 // we could have got an event from our child, reflect it back 
2889                 // to it if this is the case 
2890                 wxWindowMSW 
*win 
= NULL
; 
2891                 if ( wParam 
!= m_hWnd 
) 
2893                     win 
= FindItemByHWND((WXHWND
)wParam
); 
2899                 evtCtx
.SetEventObject(win
); 
2900                 processed 
= win
->GetEventHandler()->ProcessEvent(evtCtx
); 
2906             // we're only interested in our own menus, not MF_SYSMENU 
2907             if ( HIWORD(wParam
) == MF_POPUP 
) 
2909                 // handle menu chars for ownerdrawn menu items 
2910                 int i 
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
); 
2911                 if ( i 
!= wxNOT_FOUND 
) 
2913                     rc
.result 
= MAKELRESULT(i
, MNC_EXECUTE
); 
2923         wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."), 
2924                    wxGetMessageName(message
)); 
2925 #endif // __WXDEBUG__ 
2926         rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
2932 // ---------------------------------------------------------------------------- 
2933 // wxWindow <-> HWND map 
2934 // ---------------------------------------------------------------------------- 
2936 wxWinHashTable 
*wxWinHandleHash 
= NULL
; 
2938 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
) 
2940     return wxWinHandleHash
->Get((long)hWnd
); 
2943 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
) 
2945     // adding NULL hWnd is (first) surely a result of an error and 
2946     // (secondly) breaks menu command processing 
2947     wxCHECK_RET( hWnd 
!= (HWND
)NULL
, 
2948                  wxT("attempt to add a NULL hWnd to window list ignored") ); 
2950     wxWindow 
*oldWin 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2952     if ( oldWin 
&& (oldWin 
!= win
) ) 
2954         wxLogDebug(wxT("HWND %X already associated with another window (%s)"), 
2955                    (int) hWnd
, win
->GetClassInfo()->GetClassName()); 
2958 #endif // __WXDEBUG__ 
2961         wxWinHandleHash
->Put((long)hWnd
, (wxWindow 
*)win
); 
2965 void wxRemoveHandleAssociation(wxWindowMSW 
*win
) 
2967     wxWinHandleHash
->Delete((long)win
->GetHWND()); 
2970 // ---------------------------------------------------------------------------- 
2971 // various MSW speciic class dependent functions 
2972 // ---------------------------------------------------------------------------- 
2974 // Default destroyer - override if you destroy it in some other way 
2975 // (e.g. with MDI child windows) 
2976 void wxWindowMSW::MSWDestroyWindow() 
2980 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
, 
2983                                            int& w
, int& h
) const 
2985     // yes, those are just some arbitrary hardcoded numbers 
2986     static const int DEFAULT_Y 
= 200; 
2987     static const int DEFAULT_W 
= 400; 
2988     static const int DEFAULT_H 
= 250; 
2990     bool nonDefault 
= false; 
2994         // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we 
2995         // can just as well set it to CW_USEDEFAULT as well 
3001         // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it 
3002         // neither because it is not handled as a special value by Windows then 
3003         // and so we have to choose some default value for it 
3005         y 
= pos
.y 
== -1 ? DEFAULT_Y 
: pos
.y
; 
3011       NB: there used to be some code here which set the initial size of the 
3012           window to the client size of the parent if no explicit size was 
3013           specified. This was wrong because wxWindows programs often assume 
3014           that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke 
3015           it. To see why, you should understand that Windows sends WM_SIZE from 
3016           inside ::CreateWindow() anyhow. However, ::CreateWindow() is called 
3017           from some base class ctor and so this WM_SIZE is not processed in the 
3018           real class' OnSize() (because it's not fully constructed yet and the 
3019           event goes to some base class OnSize() instead). So the WM_SIZE we 
3020           rely on is the one sent when the parent frame resizes its children 
3021           but here is the problem: if the child already has just the right 
3022           size, nothing will happen as both wxWindows and Windows check for 
3023           this and ignore any attempts to change the window size to the size it 
3024           already has - so no WM_SIZE would be sent. 
3028         // we don't use CW_USEDEFAULT here for several reasons: 
3030         //  1. it results in huge frames on modern screens (1000*800 is not 
3031         //     uncommon on my 1280*1024 screen) which is way too big for a half 
3032         //     empty frame of most of wxWindows samples for example) 
3034         //  2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which 
3035         //     the default is for whatever reason 8*8 which breaks client <-> 
3036         //     window size calculations (it would be nice if it didn't, but it 
3037         //     does and the simplest way to fix it seemed to change the broken 
3038         //     default size anyhow) 
3040         //  3. there is just no advantage in doing it: with x and y it is 
3041         //     possible that [future versions of] Windows position the new top 
3042         //     level window in some smart way which we can't do, but we can 
3043         //     guess a reasonably good size for a new window just as well 
3050         // and, again as above, we can't set the height to CW_USEDEFAULT here 
3052         h 
= size
.y 
== -1 ? DEFAULT_H  
: size
.y
; 
3057     AdjustForParentClientOrigin(x
, y
); 
3062 WXHWND 
wxWindowMSW::MSWGetParent() const 
3064     return m_parent 
? m_parent
->GetHWND() : WXHWND(NULL
); 
3067 bool wxWindowMSW::MSWCreate(const wxChar 
*wclass
, 
3068                             const wxChar 
*title
, 
3072                             WXDWORD extendedStyle
) 
3074     // choose the position/size for the new window 
3076     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
3078     // controlId is menu handle for the top level windows, so set it to 0 
3079     // unless we're creating a child window 
3080     int controlId 
= style 
& WS_CHILD 
? GetId() : 0; 
3082     // for each class "Foo" we have we also have "FooNR" ("no repaint") class 
3083     // which is the same but without CS_[HV]REDRAW class styles so using it 
3084     // ensures that the window is not fully repainted on each resize 
3085     wxString 
className(wclass
); 
3086     if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE
) ) 
3088         className 
+= wxT("NR"); 
3091     // do create the window 
3092     wxWindowCreationHook 
hook(this); 
3095     if (extendedStyle 
== 0) 
3097         m_hWnd 
= (WXHWND
)::CreateWindow
 
3100             title 
? title 
: wxEmptyString
, 
3103             (HWND
)MSWGetParent(), 
3106             NULL                        
// no extra data 
3112         m_hWnd 
= (WXHWND
)::CreateWindowEx
 
3116             title 
? title 
: wxEmptyString
, 
3119             (HWND
)MSWGetParent(), 
3122             NULL                        
// no extra data 
3128         wxLogSysError(_("Can't create window of class %s"), wclass
); 
3133     SubclassWin(m_hWnd
); 
3135     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
3140 // =========================================================================== 
3141 // MSW message handlers 
3142 // =========================================================================== 
3144 // --------------------------------------------------------------------------- 
3146 // --------------------------------------------------------------------------- 
3150 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
3152 #ifndef __WXMICROWIN__ 
3153     LPNMHDR hdr 
= (LPNMHDR
)lParam
; 
3154     HWND hWnd 
= hdr
->hwndFrom
; 
3155     wxWindow 
*win 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
3157     // if the control is one of our windows, let it handle the message itself 
3160         return win
->MSWOnNotify(idCtrl
, lParam
, result
); 
3163     // VZ: why did we do it? normally this is unnecessary and, besides, it 
3164     //     breaks the message processing for the toolbars because the tooltip 
3165     //     notifications were being forwarded to the toolbar child controls 
3166     //     (if it had any) before being passed to the toolbar itself, so in my 
3167     //     example the tooltip for the combobox was always shown instead of the 
3168     //     correct button tooltips 
3170     // try all our children 
3171     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3174         wxWindow 
*child 
= node
->GetData(); 
3175         if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) ) 
3180         node 
= node
->GetNext(); 
3184     // by default, handle it ourselves 
3185     return MSWOnNotify(idCtrl
, lParam
, result
); 
3186 #else // __WXMICROWIN__ 
3193 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
, 
3195                                       const wxString
& ttip
) 
3197     // I don't know why it happens, but the versions of comctl32.dll starting 
3198     // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally, 
3199     // this message is supposed to be sent to Unicode programs only) -- hence 
3200     // we need to handle it as well, otherwise no tooltips will be shown in 
3203     if ( !(code 
== (WXUINT
) TTN_NEEDTEXTA 
|| code 
== (WXUINT
) TTN_NEEDTEXTW
) || ttip
.empty() ) 
3205         // not a tooltip message or no tooltip to show anyhow 
3210     LPTOOLTIPTEXT ttText 
= (LPTOOLTIPTEXT
)lParam
; 
3213     if ( code 
== (WXUINT
) TTN_NEEDTEXTA 
) 
3215         // we pass just the pointer as we store the string internally anyhow 
3216         ttText
->lpszText 
= (char *)ttip
.c_str(); 
3218     else // TTN_NEEDTEXTW 
3222         // in Unicode mode this is just what we need 
3223         ttText
->lpszText 
= (wxChar 
*)ttip
.c_str(); 
3225         // Convert tooltip from multi byte to Unicode. 
3227         // We don't want to use the szText buffer because it has a limit of 80 
3228         // bytes, for now use our own static buffer with a higher fixed max 
3230         // Preferably a dynamic buffer should be used, but who frees the buffer? 
3232         static const int MAX_LENGTH 
= 512; 
3233         static wchar_t buf
[MAX_LENGTH
+1]; 
3235         ttText
->lpszText 
= (LPSTR
) buf
; 
3237         // Truncate tooltip length if needed 
3238         size_t tipLength 
= wxMin(ttip
.Len(), MAX_LENGTH
); 
3240         // Convert to WideChar without adding the NULL character. The NULL 
3241         // character is added afterwards (this is more efficient). 
3242         ::MultiByteToWideChar(CP_ACP
, 0, ttip
, tipLength
, buf
, MAX_LENGTH
); 
3244         buf
[tipLength
] = '\0'; 
3246 #endif // Unicode/!Unicode 
3252 #endif // wxUSE_TOOLTIPS 
3254 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
), 
3256                               WXLPARAM
* WXUNUSED(result
)) 
3261         NMHDR
* hdr 
= (NMHDR 
*)lParam
; 
3262         if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip())) 
3268 #endif // wxUSE_TOOLTIPS 
3275 // --------------------------------------------------------------------------- 
3276 // end session messages 
3277 // --------------------------------------------------------------------------- 
3279 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
) 
3282     wxCloseEvent 
event(wxEVT_QUERY_END_SESSION
, -1); 
3283     event
.SetEventObject(wxTheApp
); 
3284     event
.SetCanVeto(true); 
3285     event
.SetLoggingOff(logOff 
== (long)ENDSESSION_LOGOFF
); 
3287     bool rc 
= wxTheApp
->ProcessEvent(event
); 
3291         // we may end only if the app didn't veto session closing (double 
3293         *mayEnd 
= !event
.GetVeto(); 
3302 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
) 
3305     // do nothing if the session isn't ending 
3310     if ( (this != wxTheApp
->GetTopWindow()) ) 
3313     wxCloseEvent 
event(wxEVT_END_SESSION
, -1); 
3314     event
.SetEventObject(wxTheApp
); 
3315     event
.SetCanVeto(false); 
3316     event
.SetLoggingOff( (logOff 
== (long)ENDSESSION_LOGOFF
) ); 
3318     return wxTheApp
->ProcessEvent(event
); 
3324 // --------------------------------------------------------------------------- 
3325 // window creation/destruction 
3326 // --------------------------------------------------------------------------- 
3328 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs
, bool *mayCreate
) 
3330     // VZ: why is this commented out for WinCE? If it doesn't support 
3331     //     WS_EX_CONTROLPARENT at all it should be somehow handled globally, 
3332     //     not with multiple #ifdef's! 
3334     if ( ((CREATESTRUCT 
*)cs
)->dwExStyle 
& WS_EX_CONTROLPARENT 
) 
3335         EnsureParentHasControlParentStyle(GetParent()); 
3336 #endif // !__WXWINCE__ 
3338     // TODO: should generate this event from WM_NCCREATE 
3339     wxWindowCreateEvent 
event((wxWindow 
*)this); 
3340     (void)GetEventHandler()->ProcessEvent(event
); 
3347 bool wxWindowMSW::HandleDestroy() 
3351     // delete our drop target if we've got one 
3352 #if wxUSE_DRAG_AND_DROP 
3353     if ( m_dropTarget 
!= NULL 
) 
3355         m_dropTarget
->Revoke(m_hWnd
); 
3357         delete m_dropTarget
; 
3358         m_dropTarget 
= NULL
; 
3360 #endif // wxUSE_DRAG_AND_DROP 
3362     // WM_DESTROY handled 
3366 // --------------------------------------------------------------------------- 
3368 // --------------------------------------------------------------------------- 
3370 bool wxWindowMSW::HandleActivate(int state
, 
3371                               bool WXUNUSED(minimized
), 
3372                               WXHWND 
WXUNUSED(activate
)) 
3374     wxActivateEvent 
event(wxEVT_ACTIVATE
, 
3375                           (state 
== WA_ACTIVE
) || (state 
== WA_CLICKACTIVE
), 
3377     event
.SetEventObject(this); 
3379     return GetEventHandler()->ProcessEvent(event
); 
3382 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
) 
3384     // notify the parent keeping track of focus for the kbd navigation 
3385     // purposes that we got it 
3386     wxChildFocusEvent 
eventFocus((wxWindow 
*)this); 
3387     (void)GetEventHandler()->ProcessEvent(eventFocus
); 
3393         m_caret
->OnSetFocus(); 
3395 #endif // wxUSE_CARET 
3398     // If it's a wxTextCtrl don't send the event as it will be done 
3399     // after the control gets to process it from EN_FOCUS handler 
3400     if ( wxDynamicCastThis(wxTextCtrl
) ) 
3404 #endif // wxUSE_TEXTCTRL 
3406     wxFocusEvent 
event(wxEVT_SET_FOCUS
, m_windowId
); 
3407     event
.SetEventObject(this); 
3409     // wxFindWinFromHandle() may return NULL, it is ok 
3410     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3412     return GetEventHandler()->ProcessEvent(event
); 
3415 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
) 
3421         m_caret
->OnKillFocus(); 
3423 #endif // wxUSE_CARET 
3426     // If it's a wxTextCtrl don't send the event as it will be done 
3427     // after the control gets to process it. 
3428     wxTextCtrl 
*ctrl 
= wxDynamicCastThis(wxTextCtrl
); 
3435     // Don't send the event when in the process of being deleted.  This can 
3436     // only cause problems if the event handler tries to access the object. 
3437     if ( m_isBeingDeleted 
) 
3442     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, m_windowId
); 
3443     event
.SetEventObject(this); 
3445     // wxFindWinFromHandle() may return NULL, it is ok 
3446     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3448     return GetEventHandler()->ProcessEvent(event
); 
3451 // --------------------------------------------------------------------------- 
3453 // --------------------------------------------------------------------------- 
3455 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
)) 
3457     wxShowEvent 
event(GetId(), show
); 
3458     event
.m_eventObject 
= this; 
3460     return GetEventHandler()->ProcessEvent(event
); 
3463 bool wxWindowMSW::HandleInitDialog(WXHWND 
WXUNUSED(hWndFocus
)) 
3465     wxInitDialogEvent 
event(GetId()); 
3466     event
.m_eventObject 
= this; 
3468     return GetEventHandler()->ProcessEvent(event
); 
3471 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
) 
3473 #if defined (__WXMICROWIN__) || defined(__WXWINCE__) 
3475 #else // __WXMICROWIN__ 
3476     HDROP hFilesInfo 
= (HDROP
) wParam
; 
3478     // Get the total number of files dropped 
3479     UINT gwFilesDropped 
= ::DragQueryFile
 
3487     wxString 
*files 
= new wxString
[gwFilesDropped
]; 
3488     for ( UINT wIndex 
= 0; wIndex 
< gwFilesDropped
; wIndex
++ ) 
3490         // first get the needed buffer length (+1 for terminating NUL) 
3491         size_t len 
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1; 
3493         // and now get the file name 
3494         ::DragQueryFile(hFilesInfo
, wIndex
, 
3495                         wxStringBuffer(files
[wIndex
], len
), len
); 
3497     DragFinish (hFilesInfo
); 
3499     wxDropFilesEvent 
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
); 
3500     event
.m_eventObject 
= this; 
3503     DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
); 
3504     event
.m_pos
.x 
= dropPoint
.x
; 
3505     event
.m_pos
.y 
= dropPoint
.y
; 
3507     return GetEventHandler()->ProcessEvent(event
); 
3512 bool wxWindowMSW::HandleSetCursor(WXHWND 
WXUNUSED(hWnd
), 
3514                                   int WXUNUSED(mouseMsg
)) 
3516 #ifndef __WXMICROWIN__ 
3517     // the logic is as follows: 
3518     // -1. don't set cursor for non client area, including but not limited to 
3519     //     the title bar, scrollbars, &c 
3520     //  0. allow the user to override default behaviour by using EVT_SET_CURSOR 
3521     //  1. if we have the cursor set it unless wxIsBusy() 
3522     //  2. if we're a top level window, set some cursor anyhow 
3523     //  3. if wxIsBusy(), set the busy cursor, otherwise the global one 
3525     if ( nHitTest 
!= HTCLIENT 
) 
3530     HCURSOR hcursor 
= 0; 
3532     // first ask the user code - it may wish to set the cursor in some very 
3533     // specific way (for example, depending on the current position) 
3535     if ( !::GetCursorPos(&pt
) ) 
3537         wxLogLastError(wxT("GetCursorPos")); 
3542     ScreenToClient(&x
, &y
); 
3543     wxSetCursorEvent 
event(x
, y
); 
3545     bool processedEvtSetCursor 
= GetEventHandler()->ProcessEvent(event
); 
3546     if ( processedEvtSetCursor 
&& event
.HasCursor() ) 
3548         hcursor 
= GetHcursorOf(event
.GetCursor()); 
3553         bool isBusy 
= wxIsBusy(); 
3555         // the test for processedEvtSetCursor is here to prevent using m_cursor 
3556         // if the user code caught EVT_SET_CURSOR() and returned nothing from 
3557         // it - this is a way to say that our cursor shouldn't be used for this 
3559         if ( !processedEvtSetCursor 
&& m_cursor
.Ok() ) 
3561             hcursor 
= GetHcursorOf(m_cursor
); 
3568                 hcursor 
= wxGetCurrentBusyCursor(); 
3570             else if ( !hcursor 
) 
3572                 const wxCursor 
*cursor 
= wxGetGlobalCursor(); 
3573                 if ( cursor 
&& cursor
->Ok() ) 
3575                     hcursor 
= GetHcursorOf(*cursor
); 
3583 //        wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor); 
3585         ::SetCursor(hcursor
); 
3587         // cursor set, stop here 
3590 #endif // __WXMICROWIN__ 
3592     // pass up the window chain 
3596 // --------------------------------------------------------------------------- 
3597 // owner drawn stuff 
3598 // --------------------------------------------------------------------------- 
3600 #if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \ 
3601         (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)) 
3602     #define WXUNUSED_UNLESS_ODRAWN(param) param 
3604     #define WXUNUSED_UNLESS_ODRAWN(param) 
3608 wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id
), 
3609                            WXDRAWITEMSTRUCT 
* WXUNUSED_UNLESS_ODRAWN(itemStruct
)) 
3611 #if wxUSE_OWNER_DRAWN 
3613 #if wxUSE_MENUS_NATIVE 
3614     // is it a menu item? 
3615     DRAWITEMSTRUCT 
*pDrawStruct 
= (DRAWITEMSTRUCT 
*)itemStruct
; 
3616     if ( id 
== 0 && pDrawStruct
->CtlType 
== ODT_MENU 
) 
3618         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pDrawStruct
->itemData
); 
3620         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), false ); 
3622         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent 
3623         // the DC from being released 
3624         wxDCTemp 
dc((WXHDC
)pDrawStruct
->hDC
); 
3625         wxRect 
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
, 
3626                     pDrawStruct
->rcItem
.right 
- pDrawStruct
->rcItem
.left
, 
3627                     pDrawStruct
->rcItem
.bottom 
- pDrawStruct
->rcItem
.top
); 
3629         return pMenuItem
->OnDrawItem
 
3633                 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
, 
3634                 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
 
3637 #endif // wxUSE_MENUS_NATIVE 
3639 #endif // USE_OWNER_DRAWN 
3641 #if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) 
3643 #if wxUSE_OWNER_DRAWN 
3644     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
3645 #else // !wxUSE_OWNER_DRAWN 
3646     // we may still have owner-drawn buttons internally because we have to make 
3647     // them owner-drawn to support colour change 
3648     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxButton
); 
3649 #endif // USE_OWNER_DRAWN 
3653         return item
->MSWOnDraw(itemStruct
); 
3656 #endif // wxUSE_CONTROLS 
3662 wxWindowMSW::MSWOnMeasureItem(int WXUNUSED_UNLESS_ODRAWN(id
), 
3663                               WXMEASUREITEMSTRUCT 
* 
3664                                   WXUNUSED_UNLESS_ODRAWN(itemStruct
)) 
3666 #if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE 
3667     // is it a menu item? 
3668     MEASUREITEMSTRUCT 
*pMeasureStruct 
= (MEASUREITEMSTRUCT 
*)itemStruct
; 
3669     if ( id 
== 0 && pMeasureStruct
->CtlType 
== ODT_MENU 
) 
3671         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pMeasureStruct
->itemData
); 
3673         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), false ); 
3676         bool rc 
= pMenuItem
->OnMeasureItem(&w
, &h
); 
3678         pMeasureStruct
->itemWidth 
= w
; 
3679         pMeasureStruct
->itemHeight 
= h
; 
3684     wxControl 
*item 
= wxDynamicCast(FindItem(id
), wxControl
); 
3687         return item
->MSWOnMeasure(itemStruct
); 
3689 #endif // wxUSE_OWNER_DRAWN 
3694 // --------------------------------------------------------------------------- 
3695 // colours and palettes 
3696 // --------------------------------------------------------------------------- 
3698 bool wxWindowMSW::HandleSysColorChange() 
3700     wxSysColourChangedEvent event
; 
3701     event
.SetEventObject(this); 
3703     (void)GetEventHandler()->ProcessEvent(event
); 
3705     // always let the system carry on the default processing to allow the 
3706     // native controls to react to the colours update 
3710 bool wxWindowMSW::HandleDisplayChange() 
3712     wxDisplayChangedEvent event
; 
3713     event
.SetEventObject(this); 
3715     return GetEventHandler()->ProcessEvent(event
); 
3718 bool wxWindowMSW::HandleCtlColor(WXHBRUSH 
*brush
, 
3726 #ifndef __WXMICROWIN__ 
3727     WXHBRUSH hBrush 
= 0; 
3732     if ( nCtlColor 
== CTLCOLOR_DLG 
) 
3735         hBrush 
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3740         wxControl 
*item 
= (wxControl 
*)FindItemByHWND(pWnd
, true); 
3742             hBrush 
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3744 #endif // wxUSE_CONTROLS 
3750 #else // __WXMICROWIN__ 
3755 // Define for each class of dialog and control 
3756 WXHBRUSH 
wxWindowMSW::OnCtlColor(WXHDC 
WXUNUSED(hDC
), 
3757                                  WXHWND 
WXUNUSED(hWnd
), 
3758                                  WXUINT 
WXUNUSED(nCtlColor
), 
3759                                  WXUINT 
WXUNUSED(message
), 
3760                                  WXWPARAM 
WXUNUSED(wParam
), 
3761                                  WXLPARAM 
WXUNUSED(lParam
)) 
3766 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
) 
3769     // same as below except we don't respond to our own messages 
3770     if ( hWndPalChange 
!= GetHWND() ) 
3772         // check to see if we our our parents have a custom palette 
3773         wxWindowMSW 
*win 
= this; 
3774         while ( win 
&& !win
->HasCustomPalette() ) 
3776             win 
= win
->GetParent(); 
3779         if ( win 
&& win
->HasCustomPalette() ) 
3781             // realize the palette to see whether redrawing is needed 
3782             HDC hdc 
= ::GetDC((HWND
) hWndPalChange
); 
3783             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3784                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3786             int result 
= ::RealizePalette(hdc
); 
3788             // restore the palette (before releasing the DC) 
3789             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3790                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3791             ::RealizePalette(hdc
); 
3792             ::ReleaseDC((HWND
) hWndPalChange
, hdc
); 
3794             // now check for the need to redraw 
3796                 ::InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
); 
3800 #endif // wxUSE_PALETTE 
3802     wxPaletteChangedEvent 
event(GetId()); 
3803     event
.SetEventObject(this); 
3804     event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
)); 
3806     return GetEventHandler()->ProcessEvent(event
); 
3809 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
) 
3811     wxMouseCaptureChangedEvent 
event(GetId(), wxFindWinFromHandle(hWndGainedCapture
)); 
3812     event
.SetEventObject(this); 
3814     return GetEventHandler()->ProcessEvent(event
); 
3817 bool wxWindowMSW::HandleQueryNewPalette() 
3821     // check to see if we our our parents have a custom palette 
3822     wxWindowMSW 
*win 
= this; 
3823     while (!win
->HasCustomPalette() && win
->GetParent()) win 
= win
->GetParent(); 
3824     if (win
->HasCustomPalette()) { 
3825         /* realize the palette to see whether redrawing is needed */ 
3826         HDC hdc 
= GetDC((HWND
) GetHWND()); 
3827         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3828              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) ); 
3830         int result 
= ::RealizePalette(hdc
); 
3831         /* restore the palette (before releasing the DC) */ 
3832         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3833              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) ); 
3834         ::RealizePalette(hdc
); 
3835         ::ReleaseDC((HWND
) GetHWND(), hdc
); 
3836         /* now check for the need to redraw */ 
3838             ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
); 
3840 #endif // wxUSE_PALETTE 
3842     wxQueryNewPaletteEvent 
event(GetId()); 
3843     event
.SetEventObject(this); 
3845     return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized(); 
3848 // Responds to colour changes: passes event on to children. 
3849 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
3851     // the top level window also reset the standard colour map as it might have 
3852     // changed (there is no need to do it for the non top level windows as we 
3853     // only have to do it once) 
3857         gs_hasStdCmap 
= false; 
3859     wxWindowList::compatibility_iterator node 
= GetChildren().GetFirst(); 
3862         // Only propagate to non-top-level windows because Windows already 
3863         // sends this event to all top-level ones 
3864         wxWindow 
*win 
= node
->GetData(); 
3865         if ( !win
->IsTopLevel() ) 
3867             // we need to send the real WM_SYSCOLORCHANGE and not just trigger 
3868             // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for 
3869             // the standard controls 
3870             ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0); 
3873         node 
= node
->GetNext(); 
3876     // update the colours we use if they were not set explicitly by the user: 
3877     // this must be done or OnCtlColor() would continue to use the old colours 
3880         m_foregroundColour 
= wxSystemSettings:: 
3881                                 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
); 
3886         m_backgroundColour 
= wxSystemSettings:: 
3887                                 GetSystemColour(wxSYS_COLOUR_BTNFACE
); 
3891 extern wxCOLORMAP 
*wxGetStdColourMap() 
3893     static COLORREF s_stdColours
[wxSTD_COL_MAX
]; 
3894     static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
]; 
3896     if ( !gs_hasStdCmap 
) 
3898         static bool s_coloursInit 
= false; 
3900         if ( !s_coloursInit 
) 
3902             // When a bitmap is loaded, the RGB values can change (apparently 
3903             // because Windows adjusts them to care for the old programs always 
3904             // using 0xc0c0c0 while the transparent colour for the new Windows 
3905             // versions is different). But we do this adjustment ourselves so 
3906             // we want to avoid Windows' "help" and for this we need to have a 
3907             // reference bitmap which can tell us what the RGB values change 
3909             wxBitmap 
stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); 
3910             if ( stdColourBitmap
.Ok() ) 
3912                 // the pixels in the bitmap must correspond to wxSTD_COL_XXX! 
3913                 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
, 
3914                               _T("forgot to update wxBITMAP_STD_COLOURS!") ); 
3917                 memDC
.SelectObject(stdColourBitmap
); 
3920                 for ( size_t i 
= 0; i 
< WXSIZEOF(s_stdColours
); i
++ ) 
3922                     memDC
.GetPixel(i
, 0, &colour
); 
3923                     s_stdColours
[i
] = wxColourToRGB(colour
); 
3926             else // wxBITMAP_STD_COLOURS couldn't be loaded 
3928                 s_stdColours
[0] = RGB(000,000,000);     // black 
3929                 s_stdColours
[1] = RGB(128,128,128);     // dark grey 
3930                 s_stdColours
[2] = RGB(192,192,192);     // light grey 
3931                 s_stdColours
[3] = RGB(255,255,255);     // white 
3932                 //s_stdColours[4] = RGB(000,000,255);     // blue 
3933                 //s_stdColours[5] = RGB(255,000,255);     // magenta 
3936             s_coloursInit 
= true; 
3939         gs_hasStdCmap 
= true; 
3941         // create the colour map 
3942 #define INIT_CMAP_ENTRY(col) \ 
3943             s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \ 
3944             s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col) 
3946         INIT_CMAP_ENTRY(BTNTEXT
); 
3947         INIT_CMAP_ENTRY(BTNSHADOW
); 
3948         INIT_CMAP_ENTRY(BTNFACE
); 
3949         INIT_CMAP_ENTRY(BTNHIGHLIGHT
); 
3951 #undef INIT_CMAP_ENTRY 
3957 // --------------------------------------------------------------------------- 
3959 // --------------------------------------------------------------------------- 
3961 bool wxWindowMSW::HandlePaint() 
3963 //    if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) 
3966     HRGN hRegion 
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle 
3968         wxLogLastError(wxT("CreateRectRgn")); 
3969     if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR 
) 
3970         wxLogLastError(wxT("GetUpdateRgn")); 
3972     m_updateRegion 
= wxRegion((WXHRGN
) hRegion
); 
3974     wxPaintEvent 
event(m_windowId
); 
3975     event
.SetEventObject(this); 
3977     bool processed 
= GetEventHandler()->ProcessEvent(event
); 
3979     // note that we must generate NC event after the normal one as otherwise 
3980     // BeginPaint() will happily overwrite our decorations with the background 
3982     wxNcPaintEvent 
eventNc(m_windowId
); 
3983     eventNc
.SetEventObject(this); 
3984     GetEventHandler()->ProcessEvent(eventNc
); 
3989 // Can be called from an application's OnPaint handler 
3990 void wxWindowMSW::OnPaint(wxPaintEvent
& event
) 
3992 #ifdef __WXUNIVERSAL__ 
3995     HDC hDC 
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject()); 
3998         MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0); 
4003 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
) 
4005     // Prevents flicker when dragging 
4006     if ( ::IsIconic(GetHwnd()) ) 
4010     if (GetParent() && GetParent()->GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND
) 
4015     if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND
) 
4017         if (wxUxThemeEngine::Get()) 
4019             WXHTHEME hTheme 
= wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L
"TAB"); 
4023                 ::GetClientRect((HWND
) GetHWND(), (RECT
*) & rect
); 
4024                 wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme
, hdc
, 10 /* TABP_BODY */, 0, &rect
, &rect
); 
4025                 wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme
); 
4035     dc
.SetWindow((wxWindow 
*)this); 
4038     wxEraseEvent 
event(m_windowId
, &dc
); 
4039     event
.SetEventObject(this); 
4040     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4044     // must be called manually as ~wxDC doesn't do anything for wxDCTemp 
4045     dc
.SelectOldObjects(hdc
); 
4050 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
) 
4053     ::GetClientRect(GetHwnd(), &rect
); 
4055     COLORREF ref 
= PALETTERGB(m_backgroundColour
.Red(), 
4056                               m_backgroundColour
.Green(), 
4057                               m_backgroundColour
.Blue()); 
4058     HBRUSH hBrush 
= ::CreateSolidBrush(ref
); 
4060         wxLogLastError(wxT("CreateSolidBrush")); 
4062     HDC hdc 
= (HDC
)event
.GetDC()->GetHDC(); 
4065     int mode 
= ::SetMapMode(hdc
, MM_TEXT
); 
4068     ::FillRect(hdc
, &rect
, hBrush
); 
4069     ::DeleteObject(hBrush
); 
4072     ::SetMapMode(hdc
, mode
); 
4076 // --------------------------------------------------------------------------- 
4077 // moving and resizing 
4078 // --------------------------------------------------------------------------- 
4080 bool wxWindowMSW::HandleMinimize() 
4082     wxIconizeEvent 
event(m_windowId
); 
4083     event
.SetEventObject(this); 
4085     return GetEventHandler()->ProcessEvent(event
); 
4088 bool wxWindowMSW::HandleMaximize() 
4090     wxMaximizeEvent 
event(m_windowId
); 
4091     event
.SetEventObject(this); 
4093     return GetEventHandler()->ProcessEvent(event
); 
4096 bool wxWindowMSW::HandleMove(int x
, int y
) 
4098     wxMoveEvent 
event(wxPoint(x
, y
), m_windowId
); 
4099     event
.SetEventObject(this); 
4101     return GetEventHandler()->ProcessEvent(event
); 
4104 bool wxWindowMSW::HandleMoving(wxRect
& rect
) 
4106     wxMoveEvent 
event(rect
, m_windowId
); 
4107     event
.SetEventObject(this); 
4109     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4111         rect 
= event
.GetRect(); 
4115 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), 
4116                              WXUINT 
WXUNUSED(flag
)) 
4118     // don't use w and h parameters as they specify the client size while 
4119     // according to the docs EVT_SIZE handler is supposed to receive the total 
4121     wxSizeEvent 
event(GetSize(), m_windowId
); 
4122     event
.SetEventObject(this); 
4124     return GetEventHandler()->ProcessEvent(event
); 
4127 bool wxWindowMSW::HandleSizing(wxRect
& rect
) 
4129     wxSizeEvent 
event(rect
, m_windowId
); 
4130     event
.SetEventObject(this); 
4132     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
4134         rect 
= event
.GetRect(); 
4138 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
) 
4143     MINMAXINFO 
*info 
= (MINMAXINFO 
*)mmInfo
; 
4147     int minWidth 
= GetMinWidth(), 
4148         minHeight 
= GetMinHeight(), 
4149         maxWidth 
= GetMaxWidth(), 
4150         maxHeight 
= GetMaxHeight(); 
4152     if ( minWidth 
!= -1 ) 
4154         info
->ptMinTrackSize
.x 
= minWidth
; 
4158     if ( minHeight 
!= -1 ) 
4160         info
->ptMinTrackSize
.y 
= minHeight
; 
4164     if ( maxWidth 
!= -1 ) 
4166         info
->ptMaxTrackSize
.x 
= maxWidth
; 
4170     if ( maxHeight 
!= -1 ) 
4172         info
->ptMaxTrackSize
.y 
= maxHeight
; 
4180 // --------------------------------------------------------------------------- 
4182 // --------------------------------------------------------------------------- 
4184 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
) 
4186 #if wxUSE_MENUS_NATIVE 
4187     if ( !cmd 
&& wxCurrentPopupMenu 
) 
4189         wxMenu 
*popupMenu 
= wxCurrentPopupMenu
; 
4190         wxCurrentPopupMenu 
= NULL
; 
4192         return popupMenu
->MSWCommand(cmd
, id
); 
4194 #endif // wxUSE_MENUS_NATIVE 
4196     wxWindow 
*win 
= NULL
; 
4198     // first try to find it from HWND - this works even with the broken 
4199     // programs using the same ids for different controls 
4202         win 
= wxFindWinFromHandle(control
); 
4208         // must cast to a signed type before comparing with other ids! 
4209         win 
= FindItem((signed short)id
); 
4214         return win
->MSWCommand(cmd
, id
); 
4217     // the messages sent from the in-place edit control used by the treectrl 
4218     // for label editing have id == 0, but they should _not_ be treated as menu 
4219     // messages (they are EN_XXX ones, in fact) so don't translate anything 
4220     // coming from a control to wxEVT_COMMAND_MENU_SELECTED 
4223         // If no child window, it may be an accelerator, e.g. for a popup menu 
4226         wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
); 
4227         event
.SetEventObject(this); 
4231         return GetEventHandler()->ProcessEvent(event
); 
4233 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
4236         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND 
4237         // notifications to its parent which we want to reflect back to 
4239         wxSpinCtrl 
*spin 
= wxSpinCtrl::GetSpinForTextCtrl(control
); 
4240         if ( spin 
&& spin
->ProcessTextCommand(cmd
, id
) ) 
4243 #endif // wxUSE_SPINCTRL 
4248 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM 
WXUNUSED(lParam
)) 
4251     // 4 bits are reserved 
4252     switch ( wParam 
& 0xFFFFFFF0 ) 
4255             return HandleMaximize(); 
4258             return HandleMinimize(); 
4265 // --------------------------------------------------------------------------- 
4267 // --------------------------------------------------------------------------- 
4269 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
, 
4273     // our client coords are not quite the same as Windows ones 
4274     wxPoint pt 
= GetClientAreaOrigin(); 
4275     event
.m_x 
= x 
- pt
.x
; 
4276     event
.m_y 
= y 
- pt
.y
; 
4278     event
.m_shiftDown 
= (flags 
& MK_SHIFT
) != 0; 
4279     event
.m_controlDown 
= (flags 
& MK_CONTROL
) != 0; 
4280     event
.m_leftDown 
= (flags 
& MK_LBUTTON
) != 0; 
4281     event
.m_middleDown 
= (flags 
& MK_MBUTTON
) != 0; 
4282     event
.m_rightDown 
= (flags 
& MK_RBUTTON
) != 0; 
4283  //   event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; 
4284     // Returns different negative values on WinME and WinNT, 
4285     // so simply test for negative value. 
4286     event
.m_altDown 
= ::GetKeyState(VK_MENU
) < 0; 
4289     event
.SetTimestamp(::GetMessageTime()); 
4292     event
.m_eventObject 
= this; 
4293     event
.SetId(GetId()); 
4295 #if wxUSE_MOUSEEVENT_HACK 
4298     m_lastMouseEvent 
= event
.GetEventType(); 
4299 #endif // wxUSE_MOUSEEVENT_HACK 
4302 // Windows doesn't send the mouse events to the static controls (which are 
4303 // transparent in the sense that their WM_NCHITTEST handler returns 
4304 // HTTRANSPARENT) at all but we want all controls to receive the mouse events 
4305 // and so we manually check if we don't have a child window under mouse and if 
4306 // we do, send the event to it instead of the window Windows had sent WM_XXX 
4309 // Notice that this is not done for the mouse move events because this could 
4310 // (would?) be too slow, but only for clicks which means that the static texts 
4311 // still don't get move, enter nor leave events. 
4312 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
) //TW:REQ:Univ 
4314     wxCHECK_MSG( x 
&& y
, win
, _T("NULL pointer in FindWindowForMouseEvent") ); 
4316     // first try to find a non transparent child: this allows us to send events 
4317     // to a static text which is inside a static box, for example 
4318     POINT pt 
= { *x
, *y 
}; 
4319     HWND hwnd 
= GetHwndOf(win
), 
4323     hwndUnderMouse 
= ::ChildWindowFromPoint
 
4329     hwndUnderMouse 
= ::ChildWindowFromPointEx
 
4339     if ( !hwndUnderMouse 
|| hwndUnderMouse 
== hwnd 
) 
4341         // now try any child window at all 
4342         hwndUnderMouse 
= ::ChildWindowFromPoint(hwnd
, pt
); 
4345     // check that we have a child window which is susceptible to receive mouse 
4346     // events: for this it must be shown and enabled 
4347     if ( hwndUnderMouse 
&& 
4348             hwndUnderMouse 
!= hwnd 
&& 
4349                 ::IsWindowVisible(hwndUnderMouse
) && 
4350                     ::IsWindowEnabled(hwndUnderMouse
) ) 
4352         wxWindow 
*winUnderMouse 
= wxFindWinFromHandle((WXHWND
)hwndUnderMouse
); 
4353         if ( winUnderMouse 
) 
4355             // translate the mouse coords to the other window coords 
4356             win
->ClientToScreen(x
, y
); 
4357             winUnderMouse
->ScreenToClient(x
, y
); 
4359             win 
= winUnderMouse
; 
4366 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4368     // the mouse events take consecutive IDs from WM_MOUSEFIRST to 
4369     // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST 
4370     // from the message id and take the value in the table to get wxWin event 
4372     static const wxEventType eventsMouse
[] = 
4386     wxMouseEvent 
event(eventsMouse
[msg 
- WM_MOUSEMOVE
]); 
4387     InitMouseEvent(event
, x
, y
, flags
); 
4389     return GetEventHandler()->ProcessEvent(event
); 
4392 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
) 
4394     if ( !m_mouseInWindow 
) 
4396         // it would be wrong to assume that just because we get a mouse move 
4397         // event that the mouse is inside the window: although this is usually 
4398         // true, it is not if we had captured the mouse, so we need to check 
4399         // the mouse coordinates here 
4400         if ( !HasCapture() || IsMouseInWindow() ) 
4402             // Generate an ENTER event 
4403             m_mouseInWindow 
= true; 
4404 #if _WIN32_WINNT >= 0x0400 
4406             TRACKMOUSEEVENT trackinfo
; 
4408             trackinfo
.cbSize 
= sizeof(trackinfo
); 
4409             trackinfo
.dwFlags 
= TME_LEAVE
; 
4410             trackinfo
.hwndTrack 
= GetHwnd(); 
4411             //Use the commctrl.h _TrackMouseEvent, which will call the 
4412             // appropriate TrackMouseEvent or emulate it ( win95 ) 
4413             // else we need _WIN32_WINNT >= 0x0400  
4414             _TrackMouseEvent(&trackinfo
); 
4417             wxMouseEvent 
event(wxEVT_ENTER_WINDOW
); 
4418             InitMouseEvent(event
, x
, y
, flags
); 
4420             (void)GetEventHandler()->ProcessEvent(event
); 
4424 #if wxUSE_MOUSEEVENT_HACK 
4425     // Window gets a click down message followed by a mouse move message even 
4426     // if position isn't changed!  We want to discard the trailing move event 
4427     // if x and y are the same. 
4428     if ( (m_lastMouseEvent 
== wxEVT_RIGHT_DOWN 
|| 
4429           m_lastMouseEvent 
== wxEVT_LEFT_DOWN 
|| 
4430           m_lastMouseEvent 
== wxEVT_MIDDLE_DOWN
) && 
4431          (m_lastMouseX 
== x 
&& m_lastMouseY 
== y
) ) 
4433         m_lastMouseEvent 
= wxEVT_MOTION
; 
4437 #endif // wxUSE_MOUSEEVENT_HACK 
4439     return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
); 
4443 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
) 
4445 #if wxUSE_MOUSEWHEEL 
4446     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
4447     InitMouseEvent(event
, 
4448                    GET_X_LPARAM(lParam
), 
4449                    GET_Y_LPARAM(lParam
), 
4451     event
.m_wheelRotation 
= (short)HIWORD(wParam
); 
4452     event
.m_wheelDelta 
= WHEEL_DELTA
; 
4454     static int s_linesPerRotation 
= -1; 
4455     if ( s_linesPerRotation 
== -1 ) 
4457         if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, 
4458                                      &s_linesPerRotation
, 0)) 
4460             // this is not supposed to happen 
4461             wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)")); 
4463             // the default is 3, so use it if SystemParametersInfo() failed 
4464             s_linesPerRotation 
= 3; 
4468     event
.m_linesPerAction 
= s_linesPerRotation
; 
4469     return GetEventHandler()->ProcessEvent(event
); 
4480 // --------------------------------------------------------------------------- 
4481 // keyboard handling 
4482 // --------------------------------------------------------------------------- 
4484 // create the key event of the given type for the given key - used by 
4485 // HandleChar and HandleKeyDown/Up 
4486 wxKeyEvent 
wxWindowMSW::CreateKeyEvent(wxEventType evType
, 
4489                                        WXWPARAM wParam
) const 
4491     wxKeyEvent 
event(evType
); 
4492     event
.SetId(GetId()); 
4493     event
.m_shiftDown 
= wxIsShiftDown(); 
4494     event
.m_controlDown 
= wxIsCtrlDown(); 
4495     event
.m_altDown 
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
; 
4497     event
.m_eventObject 
= (wxWindow 
*)this; // const_cast 
4498     event
.m_keyCode 
= id
; 
4499     event
.m_rawCode 
= (wxUint32
) wParam
; 
4500     event
.m_rawFlags 
= (wxUint32
) lParam
; 
4502     event
.SetTimestamp(::GetMessageTime()); 
4505     // translate the position to client coords 
4509     GetWindowRect(GetHwnd(),&rect
); 
4519 // isASCII is true only when we're called from WM_CHAR handler and not from 
4521 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
) 
4526         // If 1 -> 26, translate to either special keycode or just set 
4527         // ctrlDown.  IOW, Ctrl-C should result in keycode == 3 and 
4528         // ControlDown() == true. 
4530         if ( (id 
> 0) && (id 
< 27) ) 
4552     else // we're called from WM_KEYDOWN 
4554         id 
= wxCharCodeMSWToWX(wParam
); 
4557             // it's ASCII and will be processed here only when called from 
4558             // WM_CHAR (i.e. when isASCII = true), don't process it now 
4563     wxKeyEvent 
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
)); 
4565     // the alphanumeric keys produced by pressing AltGr+something on European 
4566     // keyboards have both Ctrl and Alt modifiers which may confuse the user 
4567     // code as, normally, keys with Ctrl and/or Alt don't result in anything 
4568     // alphanumeric, so pretend that there are no modifiers at all (the 
4569     // KEY_DOWN event would still have the correct modifiers if they're really 
4571     if ( event
.m_controlDown 
&& event
.m_altDown 
&& 
4572             (id 
>= 32 && id 
< 256) ) 
4574         event
.m_controlDown 
= 
4575         event
.m_altDown 
= false; 
4578     return GetEventHandler()->ProcessEvent(event
); 
4581 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
) 
4583     int id 
= wxCharCodeMSWToWX(wParam
); 
4587         // normal ASCII char 
4591     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4593         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
)); 
4594         if ( GetEventHandler()->ProcessEvent(event
) ) 
4603 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
) 
4605     int id 
= wxCharCodeMSWToWX(wParam
); 
4609         // normal ASCII char 
4613     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4615         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
)); 
4616         if ( GetEventHandler()->ProcessEvent(event
) ) 
4623 int wxWindowMSW::HandleMenuChar(int chAccel
, WXLPARAM lParam
) 
4625     // FIXME: implement GetMenuItemCount for WinCE, possibly 
4626     // in terms of GetMenuItemInfo 
4628     const HMENU hmenu 
= (HMENU
)lParam
; 
4632     mii
.cbSize 
= sizeof(MENUITEMINFO
); 
4633     mii
.fMask 
= MIIM_TYPE 
| MIIM_DATA
; 
4635     // find if we have this letter in any owner drawn item 
4636     const int count 
= ::GetMenuItemCount(hmenu
); 
4637     for ( int i 
= 0; i 
< count
; i
++ ) 
4639         if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) ) 
4641             if ( mii
.fType 
== MFT_OWNERDRAW 
) 
4643                 //  dwItemData member of the MENUITEMINFO is a 
4644                 //  pointer to the associated wxMenuItem -- see the 
4645                 //  menu creation code 
4646                 wxMenuItem 
*item 
= (wxMenuItem
*)mii
.dwItemData
; 
4648                 const wxChar 
*p 
= wxStrchr(item
->GetText(), _T('&')); 
4651                     if ( *p 
== _T('&') ) 
4653                         // this is not the accel char, find the real one 
4654                         p 
= wxStrchr(p 
+ 1, _T('&')); 
4656                     else // got the accel char 
4658                         // FIXME-UNICODE: this comparison doesn't risk to work 
4659                         // for non ASCII accelerator characters I'm afraid, but 
4661                         if ( wxToupper(*p
) == chAccel 
) 
4667                             // this one doesn't match 
4674         else // failed to get the menu text? 
4676             // it's not fatal, so don't show error, but still log 
4678             wxLogLastError(_T("GetMenuItemInfo")); 
4685 // --------------------------------------------------------------------------- 
4687 // --------------------------------------------------------------------------- 
4689 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4693     if ( flags 
& JOY_BUTTON1CHG 
) 
4694         change 
= wxJOY_BUTTON1
; 
4695     if ( flags 
& JOY_BUTTON2CHG 
) 
4696         change 
= wxJOY_BUTTON2
; 
4697     if ( flags 
& JOY_BUTTON3CHG 
) 
4698         change 
= wxJOY_BUTTON3
; 
4699     if ( flags 
& JOY_BUTTON4CHG 
) 
4700         change 
= wxJOY_BUTTON4
; 
4703     if ( flags 
& JOY_BUTTON1 
) 
4704         buttons 
|= wxJOY_BUTTON1
; 
4705     if ( flags 
& JOY_BUTTON2 
) 
4706         buttons 
|= wxJOY_BUTTON2
; 
4707     if ( flags 
& JOY_BUTTON3 
) 
4708         buttons 
|= wxJOY_BUTTON3
; 
4709     if ( flags 
& JOY_BUTTON4 
) 
4710         buttons 
|= wxJOY_BUTTON4
; 
4712     // the event ids aren't consecutive so we can't use table based lookup 
4714     wxEventType eventType
; 
4719             eventType 
= wxEVT_JOY_MOVE
; 
4724             eventType 
= wxEVT_JOY_MOVE
; 
4729             eventType 
= wxEVT_JOY_ZMOVE
; 
4734             eventType 
= wxEVT_JOY_ZMOVE
; 
4737         case MM_JOY1BUTTONDOWN
: 
4739             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4742         case MM_JOY2BUTTONDOWN
: 
4744             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4747         case MM_JOY1BUTTONUP
: 
4749             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4752         case MM_JOY2BUTTONUP
: 
4754             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4758             wxFAIL_MSG(wxT("no such joystick event")); 
4763     wxJoystickEvent 
event(eventType
, buttons
, joystick
, change
); 
4764     event
.SetPosition(wxPoint(x
, y
)); 
4765     event
.SetEventObject(this); 
4767     return GetEventHandler()->ProcessEvent(event
); 
4773 // --------------------------------------------------------------------------- 
4775 // --------------------------------------------------------------------------- 
4777 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
, 
4778                               WXWORD pos
, WXHWND control
) 
4780     if ( control 
&& control 
!= m_hWnd 
) // Prevent infinite recursion 
4782         wxWindow 
*child 
= wxFindWinFromHandle(control
); 
4784             return child
->MSWOnScroll(orientation
, wParam
, pos
, control
); 
4787     wxScrollWinEvent event
; 
4788     event
.SetPosition(pos
); 
4789     event
.SetOrientation(orientation
); 
4790     event
.m_eventObject 
= this; 
4795         event
.m_eventType 
= wxEVT_SCROLLWIN_TOP
; 
4799         event
.m_eventType 
= wxEVT_SCROLLWIN_BOTTOM
; 
4803         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEUP
; 
4807         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEDOWN
; 
4811         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEUP
; 
4815         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEDOWN
; 
4818     case SB_THUMBPOSITION
: 
4820         // under Win32, the scrollbar range and position are 32 bit integers, 
4821         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must 
4822         // explicitly query the scrollbar for the correct position (this must 
4823         // be done only for these two SB_ events as they are the only one 
4824         // carrying the scrollbar position) 
4826             WinStruct
<SCROLLINFO
> scrollInfo
; 
4827             scrollInfo
.fMask 
= SIF_TRACKPOS
; 
4829             if ( !::GetScrollInfo(GetHwnd(), 
4830                                   orientation 
== wxHORIZONTAL 
? SB_HORZ
 
4834                 // Not neccessarily an error, if there are no scrollbars yet. 
4835                 // wxLogLastError(_T("GetScrollInfo")); 
4838             event
.SetPosition(scrollInfo
.nTrackPos
); 
4841         event
.m_eventType 
= wParam 
== SB_THUMBPOSITION
 
4842                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
 
4843                                 : wxEVT_SCROLLWIN_THUMBTRACK
; 
4850     return GetEventHandler()->ProcessEvent(event
); 
4853 // =========================================================================== 
4855 // =========================================================================== 
4857 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont 
*the_font
) 
4860     HDC dc 
= ::GetDC((HWND
) wnd
); 
4865         //    the_font->UseResource(); 
4866         //    the_font->RealizeResource(); 
4867         fnt 
= (HFONT
)((wxFont 
*)the_font
)->GetResourceHandle(); // const_cast 
4869             was 
= (HFONT
) SelectObject(dc
,fnt
); 
4871     GetTextMetrics(dc
, &tm
); 
4872     if ( the_font 
&& fnt 
&& was 
) 
4874         SelectObject(dc
,was
); 
4876     ReleaseDC((HWND
)wnd
, dc
); 
4879         *x 
= tm
.tmAveCharWidth
; 
4881         *y 
= tm
.tmHeight 
+ tm
.tmExternalLeading
; 
4884     //    the_font->ReleaseResource(); 
4887 // Returns 0 if was a normal ASCII value, not a special key. This indicates that 
4888 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. 
4889 int wxCharCodeMSWToWX(int keySym
) 
4894         case VK_CANCEL
:     id 
= WXK_CANCEL
; break; 
4895         case VK_BACK
:       id 
= WXK_BACK
; break; 
4896         case VK_TAB
:        id 
= WXK_TAB
; break; 
4897         case VK_CLEAR
:      id 
= WXK_CLEAR
; break; 
4898         case VK_RETURN
:     id 
= WXK_RETURN
; break; 
4899         case VK_SHIFT
:      id 
= WXK_SHIFT
; break; 
4900         case VK_CONTROL
:    id 
= WXK_CONTROL
; break; 
4901         case VK_MENU 
:      id 
= WXK_MENU
; break; 
4902         case VK_PAUSE
:      id 
= WXK_PAUSE
; break; 
4903         case VK_CAPITAL
:    id 
= WXK_CAPITAL
; break; 
4904         case VK_SPACE
:      id 
= WXK_SPACE
; break; 
4905         case VK_ESCAPE
:     id 
= WXK_ESCAPE
; break; 
4906         case VK_PRIOR
:      id 
= WXK_PRIOR
; break; 
4907         case VK_NEXT 
:      id 
= WXK_NEXT
; break; 
4908         case VK_END
:        id 
= WXK_END
; break; 
4909         case VK_HOME 
:      id 
= WXK_HOME
; break; 
4910         case VK_LEFT 
:      id 
= WXK_LEFT
; break; 
4911         case VK_UP
:         id 
= WXK_UP
; break; 
4912         case VK_RIGHT
:      id 
= WXK_RIGHT
; break; 
4913         case VK_DOWN 
:      id 
= WXK_DOWN
; break; 
4914         case VK_SELECT
:     id 
= WXK_SELECT
; break; 
4915         case VK_PRINT
:      id 
= WXK_PRINT
; break; 
4916         case VK_EXECUTE
:    id 
= WXK_EXECUTE
; break; 
4917         case VK_INSERT
:     id 
= WXK_INSERT
; break; 
4918         case VK_DELETE
:     id 
= WXK_DELETE
; break; 
4919         case VK_HELP 
:      id 
= WXK_HELP
; break; 
4920         case VK_NUMPAD0
:    id 
= WXK_NUMPAD0
; break; 
4921         case VK_NUMPAD1
:    id 
= WXK_NUMPAD1
; break; 
4922         case VK_NUMPAD2
:    id 
= WXK_NUMPAD2
; break; 
4923         case VK_NUMPAD3
:    id 
= WXK_NUMPAD3
; break; 
4924         case VK_NUMPAD4
:    id 
= WXK_NUMPAD4
; break; 
4925         case VK_NUMPAD5
:    id 
= WXK_NUMPAD5
; break; 
4926         case VK_NUMPAD6
:    id 
= WXK_NUMPAD6
; break; 
4927         case VK_NUMPAD7
:    id 
= WXK_NUMPAD7
; break; 
4928         case VK_NUMPAD8
:    id 
= WXK_NUMPAD8
; break; 
4929         case VK_NUMPAD9
:    id 
= WXK_NUMPAD9
; break; 
4930         case VK_MULTIPLY
:   id 
= WXK_NUMPAD_MULTIPLY
; break; 
4931         case VK_ADD
:        id 
= WXK_NUMPAD_ADD
; break; 
4932         case VK_SUBTRACT
:   id 
= WXK_NUMPAD_SUBTRACT
; break; 
4933         case VK_DECIMAL
:    id 
= WXK_NUMPAD_DECIMAL
; break; 
4934         case VK_DIVIDE
:     id 
= WXK_NUMPAD_DIVIDE
; break; 
4935         case VK_F1
:         id 
= WXK_F1
; break; 
4936         case VK_F2
:         id 
= WXK_F2
; break; 
4937         case VK_F3
:         id 
= WXK_F3
; break; 
4938         case VK_F4
:         id 
= WXK_F4
; break; 
4939         case VK_F5
:         id 
= WXK_F5
; break; 
4940         case VK_F6
:         id 
= WXK_F6
; break; 
4941         case VK_F7
:         id 
= WXK_F7
; break; 
4942         case VK_F8
:         id 
= WXK_F8
; break; 
4943         case VK_F9
:         id 
= WXK_F9
; break; 
4944         case VK_F10
:        id 
= WXK_F10
; break; 
4945         case VK_F11
:        id 
= WXK_F11
; break; 
4946         case VK_F12
:        id 
= WXK_F12
; break; 
4947         case VK_F13
:        id 
= WXK_F13
; break; 
4948         case VK_F14
:        id 
= WXK_F14
; break; 
4949         case VK_F15
:        id 
= WXK_F15
; break; 
4950         case VK_F16
:        id 
= WXK_F16
; break; 
4951         case VK_F17
:        id 
= WXK_F17
; break; 
4952         case VK_F18
:        id 
= WXK_F18
; break; 
4953         case VK_F19
:        id 
= WXK_F19
; break; 
4954         case VK_F20
:        id 
= WXK_F20
; break; 
4955         case VK_F21
:        id 
= WXK_F21
; break; 
4956         case VK_F22
:        id 
= WXK_F22
; break; 
4957         case VK_F23
:        id 
= WXK_F23
; break; 
4958         case VK_F24
:        id 
= WXK_F24
; break; 
4959         case VK_NUMLOCK
:    id 
= WXK_NUMLOCK
; break; 
4960         case VK_SCROLL
:     id 
= WXK_SCROLL
; break; 
4962         case VK_OEM_1
:      id 
= ';'; break; 
4963         case VK_OEM_PLUS
:   id 
= '+'; break; 
4964         case VK_OEM_COMMA
:  id 
= ','; break; 
4965         case VK_OEM_MINUS
:  id 
= '-'; break; 
4966         case VK_OEM_PERIOD
: id 
= '.'; break; 
4967         case VK_OEM_2
:      id 
= '/'; break; 
4968         case VK_OEM_3
:      id 
= '~'; break; 
4969         case VK_OEM_4
:      id 
= '['; break; 
4970         case VK_OEM_5
:      id 
= '\\'; break; 
4971         case VK_OEM_6
:      id 
= ']'; break; 
4972         case VK_OEM_7
:      id 
= '\''; break; 
4975         case VK_LWIN
:       id 
= WXK_WINDOWS_LEFT
; break; 
4976         case VK_RWIN
:       id 
= WXK_WINDOWS_RIGHT
; break; 
4977         case VK_APPS
:       id 
= WXK_WINDOWS_MENU
; break; 
4978 #endif // VK_APPS defined 
4987 int wxCharCodeWXToMSW(int id
, bool *isVirtual
) 
4993     case WXK_CANCEL
:    keySym 
= VK_CANCEL
; break; 
4994     case WXK_CLEAR
:     keySym 
= VK_CLEAR
; break; 
4995     case WXK_SHIFT
:     keySym 
= VK_SHIFT
; break; 
4996     case WXK_CONTROL
:   keySym 
= VK_CONTROL
; break; 
4997     case WXK_MENU 
:     keySym 
= VK_MENU
; break; 
4998     case WXK_PAUSE
:     keySym 
= VK_PAUSE
; break; 
4999     case WXK_PRIOR
:     keySym 
= VK_PRIOR
; break; 
5000     case WXK_NEXT 
:     keySym 
= VK_NEXT
; break; 
5001     case WXK_END
:       keySym 
= VK_END
; break; 
5002     case WXK_HOME 
:     keySym 
= VK_HOME
; break; 
5003     case WXK_LEFT 
:     keySym 
= VK_LEFT
; break; 
5004     case WXK_UP
:        keySym 
= VK_UP
; break; 
5005     case WXK_RIGHT
:     keySym 
= VK_RIGHT
; break; 
5006     case WXK_DOWN 
:     keySym 
= VK_DOWN
; break; 
5007     case WXK_SELECT
:    keySym 
= VK_SELECT
; break; 
5008     case WXK_PRINT
:     keySym 
= VK_PRINT
; break; 
5009     case WXK_EXECUTE
:   keySym 
= VK_EXECUTE
; break; 
5010     case WXK_INSERT
:    keySym 
= VK_INSERT
; break; 
5011     case WXK_DELETE
:    keySym 
= VK_DELETE
; break; 
5012     case WXK_HELP 
:     keySym 
= VK_HELP
; break; 
5013     case WXK_NUMPAD0
:   keySym 
= VK_NUMPAD0
; break; 
5014     case WXK_NUMPAD1
:   keySym 
= VK_NUMPAD1
; break; 
5015     case WXK_NUMPAD2
:   keySym 
= VK_NUMPAD2
; break; 
5016     case WXK_NUMPAD3
:   keySym 
= VK_NUMPAD3
; break; 
5017     case WXK_NUMPAD4
:   keySym 
= VK_NUMPAD4
; break; 
5018     case WXK_NUMPAD5
:   keySym 
= VK_NUMPAD5
; break; 
5019     case WXK_NUMPAD6
:   keySym 
= VK_NUMPAD6
; break; 
5020     case WXK_NUMPAD7
:   keySym 
= VK_NUMPAD7
; break; 
5021     case WXK_NUMPAD8
:   keySym 
= VK_NUMPAD8
; break; 
5022     case WXK_NUMPAD9
:   keySym 
= VK_NUMPAD9
; break; 
5023     case WXK_NUMPAD_MULTIPLY
:  keySym 
= VK_MULTIPLY
; break; 
5024     case WXK_NUMPAD_ADD
:       keySym 
= VK_ADD
; break; 
5025     case WXK_NUMPAD_SUBTRACT
:  keySym 
= VK_SUBTRACT
; break; 
5026     case WXK_NUMPAD_DECIMAL
:   keySym 
= VK_DECIMAL
; break; 
5027     case WXK_NUMPAD_DIVIDE
:    keySym 
= VK_DIVIDE
; break; 
5028     case WXK_F1
:        keySym 
= VK_F1
; break; 
5029     case WXK_F2
:        keySym 
= VK_F2
; break; 
5030     case WXK_F3
:        keySym 
= VK_F3
; break; 
5031     case WXK_F4
:        keySym 
= VK_F4
; break; 
5032     case WXK_F5
:        keySym 
= VK_F5
; break; 
5033     case WXK_F6
:        keySym 
= VK_F6
; break; 
5034     case WXK_F7
:        keySym 
= VK_F7
; break; 
5035     case WXK_F8
:        keySym 
= VK_F8
; break; 
5036     case WXK_F9
:        keySym 
= VK_F9
; break; 
5037     case WXK_F10
:       keySym 
= VK_F10
; break; 
5038     case WXK_F11
:       keySym 
= VK_F11
; break; 
5039     case WXK_F12
:       keySym 
= VK_F12
; break; 
5040     case WXK_F13
:       keySym 
= VK_F13
; break; 
5041     case WXK_F14
:       keySym 
= VK_F14
; break; 
5042     case WXK_F15
:       keySym 
= VK_F15
; break; 
5043     case WXK_F16
:       keySym 
= VK_F16
; break; 
5044     case WXK_F17
:       keySym 
= VK_F17
; break; 
5045     case WXK_F18
:       keySym 
= VK_F18
; break; 
5046     case WXK_F19
:       keySym 
= VK_F19
; break; 
5047     case WXK_F20
:       keySym 
= VK_F20
; break; 
5048     case WXK_F21
:       keySym 
= VK_F21
; break; 
5049     case WXK_F22
:       keySym 
= VK_F22
; break; 
5050     case WXK_F23
:       keySym 
= VK_F23
; break; 
5051     case WXK_F24
:       keySym 
= VK_F24
; break; 
5052     case WXK_NUMLOCK
:   keySym 
= VK_NUMLOCK
; break; 
5053     case WXK_SCROLL
:    keySym 
= VK_SCROLL
; break; 
5064 bool wxGetKeyState(wxKeyCode key
) 
5067     int vkey 
= wxCharCodeWXToMSW(key
, &bVirtual
); 
5069     //there aren't WXK_ macros for non-virtual key codes 
5070     if (bVirtual 
== false) 
5073     return GetKeyState(vkey
) < 0; 
5076 wxWindow 
*wxGetActiveWindow() 
5078     HWND hWnd 
= GetActiveWindow(); 
5081         return wxFindWinFromHandle((WXHWND
) hWnd
); 
5086 extern wxWindow 
*wxGetWindowFromHWND(WXHWND hWnd
) 
5088     HWND hwnd 
= (HWND
)hWnd
; 
5090     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set 
5091     // by code in msw/radiobox.cpp), for all the others we just search up the 
5093     wxWindow 
*win 
= (wxWindow 
*)NULL
; 
5096         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
5100             // native radiobuttons return DLGC_RADIOBUTTON here and for any 
5101             // wxWindow class which overrides WM_GETDLGCODE processing to 
5102             // do it as well, win would be already non NULL 
5103             if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON 
) 
5105                 win 
= (wxWindow 
*)wxGetWindowUserData(hwnd
); 
5107             //else: it's a wxRadioButton, not a radiobutton from wxRadioBox 
5108 #endif // wxUSE_RADIOBOX 
5110             // spin control text buddy window should be mapped to spin ctrl 
5111             // itself so try it too 
5112 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
5115                 win 
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
); 
5117 #endif // wxUSE_SPINCTRL 
5121     while ( hwnd 
&& !win 
) 
5123         // this is a really ugly hack needed to avoid mistakenly returning the 
5124         // parent frame wxWindow for the find/replace modeless dialog HWND - 
5125         // this, in turn, is needed to call IsDialogMessage() from 
5126         // wxApp::ProcessMessage() as for this we must return NULL from here 
5128         // FIXME: this is clearly not the best way to do it but I think we'll 
5129         //        need to change HWND <-> wxWindow code more heavily than I can 
5130         //        do it now to fix it 
5131 #ifndef __WXMICROWIN__ 
5132         if ( ::GetWindow(hwnd
, GW_OWNER
) ) 
5134             // it's a dialog box, don't go upwards 
5139         hwnd 
= ::GetParent(hwnd
); 
5140         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
5146 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
5148 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE 
5149 // in active frames and dialogs, regardless of where the focus is. 
5150 static HHOOK wxTheKeyboardHook 
= 0; 
5151 static FARPROC wxTheKeyboardHookProc 
= 0; 
5152 int APIENTRY _EXPORT
 
5153 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
); 
5155 void wxSetKeyboardHook(bool doIt
) 
5159         wxTheKeyboardHookProc 
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance()); 
5160         wxTheKeyboardHook 
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(), 
5162             GetCurrentThreadId() 
5163         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? 
5168         UnhookWindowsHookEx(wxTheKeyboardHook
); 
5172 int APIENTRY _EXPORT
 
5173 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
) 
5175     DWORD hiWord 
= HIWORD(lParam
); 
5176     if ( nCode 
!= HC_NOREMOVE 
&& ((hiWord 
& KF_UP
) == 0) ) 
5178         int id 
= wxCharCodeMSWToWX(wParam
); 
5181             wxKeyEvent 
event(wxEVT_CHAR_HOOK
); 
5182             if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
5183                 event
.m_altDown 
= true; 
5185             event
.m_eventObject 
= NULL
; 
5186             event
.m_keyCode 
= id
; 
5187             event
.m_shiftDown 
= wxIsShiftDown(); 
5188             event
.m_controlDown 
= wxIsCtrlDown(); 
5190             event
.SetTimestamp(::GetMessageTime()); 
5192             wxWindow 
*win 
= wxGetActiveWindow(); 
5193             wxEvtHandler 
*handler
; 
5196                 handler 
= win
->GetEventHandler(); 
5197                 event
.SetId(win
->GetId()); 
5205             if ( handler 
&& handler
->ProcessEvent(event
) ) 
5213     return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
); 
5216 #endif // !__WXMICROWIN__ 
5219 const char *wxGetMessageName(int message
) 
5223         case 0x0000: return "WM_NULL"; 
5224         case 0x0001: return "WM_CREATE"; 
5225         case 0x0002: return "WM_DESTROY"; 
5226         case 0x0003: return "WM_MOVE"; 
5227         case 0x0005: return "WM_SIZE"; 
5228         case 0x0006: return "WM_ACTIVATE"; 
5229         case 0x0007: return "WM_SETFOCUS"; 
5230         case 0x0008: return "WM_KILLFOCUS"; 
5231         case 0x000A: return "WM_ENABLE"; 
5232         case 0x000B: return "WM_SETREDRAW"; 
5233         case 0x000C: return "WM_SETTEXT"; 
5234         case 0x000D: return "WM_GETTEXT"; 
5235         case 0x000E: return "WM_GETTEXTLENGTH"; 
5236         case 0x000F: return "WM_PAINT"; 
5237         case 0x0010: return "WM_CLOSE"; 
5238         case 0x0011: return "WM_QUERYENDSESSION"; 
5239         case 0x0012: return "WM_QUIT"; 
5240         case 0x0013: return "WM_QUERYOPEN"; 
5241         case 0x0014: return "WM_ERASEBKGND"; 
5242         case 0x0015: return "WM_SYSCOLORCHANGE"; 
5243         case 0x0016: return "WM_ENDSESSION"; 
5244         case 0x0017: return "WM_SYSTEMERROR"; 
5245         case 0x0018: return "WM_SHOWWINDOW"; 
5246         case 0x0019: return "WM_CTLCOLOR"; 
5247         case 0x001A: return "WM_WININICHANGE"; 
5248         case 0x001B: return "WM_DEVMODECHANGE"; 
5249         case 0x001C: return "WM_ACTIVATEAPP"; 
5250         case 0x001D: return "WM_FONTCHANGE"; 
5251         case 0x001E: return "WM_TIMECHANGE"; 
5252         case 0x001F: return "WM_CANCELMODE"; 
5253         case 0x0020: return "WM_SETCURSOR"; 
5254         case 0x0021: return "WM_MOUSEACTIVATE"; 
5255         case 0x0022: return "WM_CHILDACTIVATE"; 
5256         case 0x0023: return "WM_QUEUESYNC"; 
5257         case 0x0024: return "WM_GETMINMAXINFO"; 
5258         case 0x0026: return "WM_PAINTICON"; 
5259         case 0x0027: return "WM_ICONERASEBKGND"; 
5260         case 0x0028: return "WM_NEXTDLGCTL"; 
5261         case 0x002A: return "WM_SPOOLERSTATUS"; 
5262         case 0x002B: return "WM_DRAWITEM"; 
5263         case 0x002C: return "WM_MEASUREITEM"; 
5264         case 0x002D: return "WM_DELETEITEM"; 
5265         case 0x002E: return "WM_VKEYTOITEM"; 
5266         case 0x002F: return "WM_CHARTOITEM"; 
5267         case 0x0030: return "WM_SETFONT"; 
5268         case 0x0031: return "WM_GETFONT"; 
5269         case 0x0037: return "WM_QUERYDRAGICON"; 
5270         case 0x0039: return "WM_COMPAREITEM"; 
5271         case 0x0041: return "WM_COMPACTING"; 
5272         case 0x0044: return "WM_COMMNOTIFY"; 
5273         case 0x0046: return "WM_WINDOWPOSCHANGING"; 
5274         case 0x0047: return "WM_WINDOWPOSCHANGED"; 
5275         case 0x0048: return "WM_POWER"; 
5277         case 0x004A: return "WM_COPYDATA"; 
5278         case 0x004B: return "WM_CANCELJOURNAL"; 
5279         case 0x004E: return "WM_NOTIFY"; 
5280         case 0x0050: return "WM_INPUTLANGCHANGEREQUEST"; 
5281         case 0x0051: return "WM_INPUTLANGCHANGE"; 
5282         case 0x0052: return "WM_TCARD"; 
5283         case 0x0053: return "WM_HELP"; 
5284         case 0x0054: return "WM_USERCHANGED"; 
5285         case 0x0055: return "WM_NOTIFYFORMAT"; 
5286         case 0x007B: return "WM_CONTEXTMENU"; 
5287         case 0x007C: return "WM_STYLECHANGING"; 
5288         case 0x007D: return "WM_STYLECHANGED"; 
5289         case 0x007E: return "WM_DISPLAYCHANGE"; 
5290         case 0x007F: return "WM_GETICON"; 
5291         case 0x0080: return "WM_SETICON"; 
5293         case 0x0081: return "WM_NCCREATE"; 
5294         case 0x0082: return "WM_NCDESTROY"; 
5295         case 0x0083: return "WM_NCCALCSIZE"; 
5296         case 0x0084: return "WM_NCHITTEST"; 
5297         case 0x0085: return "WM_NCPAINT"; 
5298         case 0x0086: return "WM_NCACTIVATE"; 
5299         case 0x0087: return "WM_GETDLGCODE"; 
5300         case 0x00A0: return "WM_NCMOUSEMOVE"; 
5301         case 0x00A1: return "WM_NCLBUTTONDOWN"; 
5302         case 0x00A2: return "WM_NCLBUTTONUP"; 
5303         case 0x00A3: return "WM_NCLBUTTONDBLCLK"; 
5304         case 0x00A4: return "WM_NCRBUTTONDOWN"; 
5305         case 0x00A5: return "WM_NCRBUTTONUP"; 
5306         case 0x00A6: return "WM_NCRBUTTONDBLCLK"; 
5307         case 0x00A7: return "WM_NCMBUTTONDOWN"; 
5308         case 0x00A8: return "WM_NCMBUTTONUP"; 
5309         case 0x00A9: return "WM_NCMBUTTONDBLCLK"; 
5310         case 0x0100: return "WM_KEYDOWN"; 
5311         case 0x0101: return "WM_KEYUP"; 
5312         case 0x0102: return "WM_CHAR"; 
5313         case 0x0103: return "WM_DEADCHAR"; 
5314         case 0x0104: return "WM_SYSKEYDOWN"; 
5315         case 0x0105: return "WM_SYSKEYUP"; 
5316         case 0x0106: return "WM_SYSCHAR"; 
5317         case 0x0107: return "WM_SYSDEADCHAR"; 
5318         case 0x0108: return "WM_KEYLAST"; 
5320         case 0x010D: return "WM_IME_STARTCOMPOSITION"; 
5321         case 0x010E: return "WM_IME_ENDCOMPOSITION"; 
5322         case 0x010F: return "WM_IME_COMPOSITION"; 
5324         case 0x0110: return "WM_INITDIALOG"; 
5325         case 0x0111: return "WM_COMMAND"; 
5326         case 0x0112: return "WM_SYSCOMMAND"; 
5327         case 0x0113: return "WM_TIMER"; 
5328         case 0x0114: return "WM_HSCROLL"; 
5329         case 0x0115: return "WM_VSCROLL"; 
5330         case 0x0116: return "WM_INITMENU"; 
5331         case 0x0117: return "WM_INITMENUPOPUP"; 
5332         case 0x011F: return "WM_MENUSELECT"; 
5333         case 0x0120: return "WM_MENUCHAR"; 
5334         case 0x0121: return "WM_ENTERIDLE"; 
5335         case 0x0200: return "WM_MOUSEMOVE"; 
5336         case 0x0201: return "WM_LBUTTONDOWN"; 
5337         case 0x0202: return "WM_LBUTTONUP"; 
5338         case 0x0203: return "WM_LBUTTONDBLCLK"; 
5339         case 0x0204: return "WM_RBUTTONDOWN"; 
5340         case 0x0205: return "WM_RBUTTONUP"; 
5341         case 0x0206: return "WM_RBUTTONDBLCLK"; 
5342         case 0x0207: return "WM_MBUTTONDOWN"; 
5343         case 0x0208: return "WM_MBUTTONUP"; 
5344         case 0x0209: return "WM_MBUTTONDBLCLK"; 
5345         case 0x020A: return "WM_MOUSEWHEEL"; 
5346         case 0x0210: return "WM_PARENTNOTIFY"; 
5347         case 0x0211: return "WM_ENTERMENULOOP"; 
5348         case 0x0212: return "WM_EXITMENULOOP"; 
5350         case 0x0213: return "WM_NEXTMENU"; 
5351         case 0x0214: return "WM_SIZING"; 
5352         case 0x0215: return "WM_CAPTURECHANGED"; 
5353         case 0x0216: return "WM_MOVING"; 
5354         case 0x0218: return "WM_POWERBROADCAST"; 
5355         case 0x0219: return "WM_DEVICECHANGE"; 
5357         case 0x0220: return "WM_MDICREATE"; 
5358         case 0x0221: return "WM_MDIDESTROY"; 
5359         case 0x0222: return "WM_MDIACTIVATE"; 
5360         case 0x0223: return "WM_MDIRESTORE"; 
5361         case 0x0224: return "WM_MDINEXT"; 
5362         case 0x0225: return "WM_MDIMAXIMIZE"; 
5363         case 0x0226: return "WM_MDITILE"; 
5364         case 0x0227: return "WM_MDICASCADE"; 
5365         case 0x0228: return "WM_MDIICONARRANGE"; 
5366         case 0x0229: return "WM_MDIGETACTIVE"; 
5367         case 0x0230: return "WM_MDISETMENU"; 
5368         case 0x0233: return "WM_DROPFILES"; 
5370         case 0x0281: return "WM_IME_SETCONTEXT"; 
5371         case 0x0282: return "WM_IME_NOTIFY"; 
5372         case 0x0283: return "WM_IME_CONTROL"; 
5373         case 0x0284: return "WM_IME_COMPOSITIONFULL"; 
5374         case 0x0285: return "WM_IME_SELECT"; 
5375         case 0x0286: return "WM_IME_CHAR"; 
5376         case 0x0290: return "WM_IME_KEYDOWN"; 
5377         case 0x0291: return "WM_IME_KEYUP"; 
5379         case 0x0300: return "WM_CUT"; 
5380         case 0x0301: return "WM_COPY"; 
5381         case 0x0302: return "WM_PASTE"; 
5382         case 0x0303: return "WM_CLEAR"; 
5383         case 0x0304: return "WM_UNDO"; 
5384         case 0x0305: return "WM_RENDERFORMAT"; 
5385         case 0x0306: return "WM_RENDERALLFORMATS"; 
5386         case 0x0307: return "WM_DESTROYCLIPBOARD"; 
5387         case 0x0308: return "WM_DRAWCLIPBOARD"; 
5388         case 0x0309: return "WM_PAINTCLIPBOARD"; 
5389         case 0x030A: return "WM_VSCROLLCLIPBOARD"; 
5390         case 0x030B: return "WM_SIZECLIPBOARD"; 
5391         case 0x030C: return "WM_ASKCBFORMATNAME"; 
5392         case 0x030D: return "WM_CHANGECBCHAIN"; 
5393         case 0x030E: return "WM_HSCROLLCLIPBOARD"; 
5394         case 0x030F: return "WM_QUERYNEWPALETTE"; 
5395         case 0x0310: return "WM_PALETTEISCHANGING"; 
5396         case 0x0311: return "WM_PALETTECHANGED"; 
5398         case 0x0312: return "WM_HOTKEY"; 
5401         // common controls messages - although they're not strictly speaking 
5402         // standard, it's nice to decode them nevertheless 
5405         case 0x1000 + 0: return "LVM_GETBKCOLOR"; 
5406         case 0x1000 + 1: return "LVM_SETBKCOLOR"; 
5407         case 0x1000 + 2: return "LVM_GETIMAGELIST"; 
5408         case 0x1000 + 3: return "LVM_SETIMAGELIST"; 
5409         case 0x1000 + 4: return "LVM_GETITEMCOUNT"; 
5410         case 0x1000 + 5: return "LVM_GETITEMA"; 
5411         case 0x1000 + 75: return "LVM_GETITEMW"; 
5412         case 0x1000 + 6: return "LVM_SETITEMA"; 
5413         case 0x1000 + 76: return "LVM_SETITEMW"; 
5414         case 0x1000 + 7: return "LVM_INSERTITEMA"; 
5415         case 0x1000 + 77: return "LVM_INSERTITEMW"; 
5416         case 0x1000 + 8: return "LVM_DELETEITEM"; 
5417         case 0x1000 + 9: return "LVM_DELETEALLITEMS"; 
5418         case 0x1000 + 10: return "LVM_GETCALLBACKMASK"; 
5419         case 0x1000 + 11: return "LVM_SETCALLBACKMASK"; 
5420         case 0x1000 + 12: return "LVM_GETNEXTITEM"; 
5421         case 0x1000 + 13: return "LVM_FINDITEMA"; 
5422         case 0x1000 + 83: return "LVM_FINDITEMW"; 
5423         case 0x1000 + 14: return "LVM_GETITEMRECT"; 
5424         case 0x1000 + 15: return "LVM_SETITEMPOSITION"; 
5425         case 0x1000 + 16: return "LVM_GETITEMPOSITION"; 
5426         case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA"; 
5427         case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW"; 
5428         case 0x1000 + 18: return "LVM_HITTEST"; 
5429         case 0x1000 + 19: return "LVM_ENSUREVISIBLE"; 
5430         case 0x1000 + 20: return "LVM_SCROLL"; 
5431         case 0x1000 + 21: return "LVM_REDRAWITEMS"; 
5432         case 0x1000 + 22: return "LVM_ARRANGE"; 
5433         case 0x1000 + 23: return "LVM_EDITLABELA"; 
5434         case 0x1000 + 118: return "LVM_EDITLABELW"; 
5435         case 0x1000 + 24: return "LVM_GETEDITCONTROL"; 
5436         case 0x1000 + 25: return "LVM_GETCOLUMNA"; 
5437         case 0x1000 + 95: return "LVM_GETCOLUMNW"; 
5438         case 0x1000 + 26: return "LVM_SETCOLUMNA"; 
5439         case 0x1000 + 96: return "LVM_SETCOLUMNW"; 
5440         case 0x1000 + 27: return "LVM_INSERTCOLUMNA"; 
5441         case 0x1000 + 97: return "LVM_INSERTCOLUMNW"; 
5442         case 0x1000 + 28: return "LVM_DELETECOLUMN"; 
5443         case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH"; 
5444         case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH"; 
5445         case 0x1000 + 31: return "LVM_GETHEADER"; 
5446         case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE"; 
5447         case 0x1000 + 34: return "LVM_GETVIEWRECT"; 
5448         case 0x1000 + 35: return "LVM_GETTEXTCOLOR"; 
5449         case 0x1000 + 36: return "LVM_SETTEXTCOLOR"; 
5450         case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR"; 
5451         case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR"; 
5452         case 0x1000 + 39: return "LVM_GETTOPINDEX"; 
5453         case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE"; 
5454         case 0x1000 + 41: return "LVM_GETORIGIN"; 
5455         case 0x1000 + 42: return "LVM_UPDATE"; 
5456         case 0x1000 + 43: return "LVM_SETITEMSTATE"; 
5457         case 0x1000 + 44: return "LVM_GETITEMSTATE"; 
5458         case 0x1000 + 45: return "LVM_GETITEMTEXTA"; 
5459         case 0x1000 + 115: return "LVM_GETITEMTEXTW"; 
5460         case 0x1000 + 46: return "LVM_SETITEMTEXTA"; 
5461         case 0x1000 + 116: return "LVM_SETITEMTEXTW"; 
5462         case 0x1000 + 47: return "LVM_SETITEMCOUNT"; 
5463         case 0x1000 + 48: return "LVM_SORTITEMS"; 
5464         case 0x1000 + 49: return "LVM_SETITEMPOSITION32"; 
5465         case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT"; 
5466         case 0x1000 + 51: return "LVM_GETITEMSPACING"; 
5467         case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA"; 
5468         case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW"; 
5469         case 0x1000 + 53: return "LVM_SETICONSPACING"; 
5470         case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE"; 
5471         case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE"; 
5472         case 0x1000 + 56: return "LVM_GETSUBITEMRECT"; 
5473         case 0x1000 + 57: return "LVM_SUBITEMHITTEST"; 
5474         case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY"; 
5475         case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY"; 
5476         case 0x1000 + 60: return "LVM_SETHOTITEM"; 
5477         case 0x1000 + 61: return "LVM_GETHOTITEM"; 
5478         case 0x1000 + 62: return "LVM_SETHOTCURSOR"; 
5479         case 0x1000 + 63: return "LVM_GETHOTCURSOR"; 
5480         case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT"; 
5481         case 0x1000 + 65: return "LVM_SETWORKAREA"; 
5484         case 0x1100 + 0: return "TVM_INSERTITEMA"; 
5485         case 0x1100 + 50: return "TVM_INSERTITEMW"; 
5486         case 0x1100 + 1: return "TVM_DELETEITEM"; 
5487         case 0x1100 + 2: return "TVM_EXPAND"; 
5488         case 0x1100 + 4: return "TVM_GETITEMRECT"; 
5489         case 0x1100 + 5: return "TVM_GETCOUNT"; 
5490         case 0x1100 + 6: return "TVM_GETINDENT"; 
5491         case 0x1100 + 7: return "TVM_SETINDENT"; 
5492         case 0x1100 + 8: return "TVM_GETIMAGELIST"; 
5493         case 0x1100 + 9: return "TVM_SETIMAGELIST"; 
5494         case 0x1100 + 10: return "TVM_GETNEXTITEM"; 
5495         case 0x1100 + 11: return "TVM_SELECTITEM"; 
5496         case 0x1100 + 12: return "TVM_GETITEMA"; 
5497         case 0x1100 + 62: return "TVM_GETITEMW"; 
5498         case 0x1100 + 13: return "TVM_SETITEMA"; 
5499         case 0x1100 + 63: return "TVM_SETITEMW"; 
5500         case 0x1100 + 14: return "TVM_EDITLABELA"; 
5501         case 0x1100 + 65: return "TVM_EDITLABELW"; 
5502         case 0x1100 + 15: return "TVM_GETEDITCONTROL"; 
5503         case 0x1100 + 16: return "TVM_GETVISIBLECOUNT"; 
5504         case 0x1100 + 17: return "TVM_HITTEST"; 
5505         case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE"; 
5506         case 0x1100 + 19: return "TVM_SORTCHILDREN"; 
5507         case 0x1100 + 20: return "TVM_ENSUREVISIBLE"; 
5508         case 0x1100 + 21: return "TVM_SORTCHILDRENCB"; 
5509         case 0x1100 + 22: return "TVM_ENDEDITLABELNOW"; 
5510         case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA"; 
5511         case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW"; 
5512         case 0x1100 + 24: return "TVM_SETTOOLTIPS"; 
5513         case 0x1100 + 25: return "TVM_GETTOOLTIPS"; 
5516         case 0x1200 + 0: return "HDM_GETITEMCOUNT"; 
5517         case 0x1200 + 1: return "HDM_INSERTITEMA"; 
5518         case 0x1200 + 10: return "HDM_INSERTITEMW"; 
5519         case 0x1200 + 2: return "HDM_DELETEITEM"; 
5520         case 0x1200 + 3: return "HDM_GETITEMA"; 
5521         case 0x1200 + 11: return "HDM_GETITEMW"; 
5522         case 0x1200 + 4: return "HDM_SETITEMA"; 
5523         case 0x1200 + 12: return "HDM_SETITEMW"; 
5524         case 0x1200 + 5: return "HDM_LAYOUT"; 
5525         case 0x1200 + 6: return "HDM_HITTEST"; 
5526         case 0x1200 + 7: return "HDM_GETITEMRECT"; 
5527         case 0x1200 + 8: return "HDM_SETIMAGELIST"; 
5528         case 0x1200 + 9: return "HDM_GETIMAGELIST"; 
5529         case 0x1200 + 15: return "HDM_ORDERTOINDEX"; 
5530         case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE"; 
5531         case 0x1200 + 17: return "HDM_GETORDERARRAY"; 
5532         case 0x1200 + 18: return "HDM_SETORDERARRAY"; 
5533         case 0x1200 + 19: return "HDM_SETHOTDIVIDER"; 
5536         case 0x1300 + 2: return "TCM_GETIMAGELIST"; 
5537         case 0x1300 + 3: return "TCM_SETIMAGELIST"; 
5538         case 0x1300 + 4: return "TCM_GETITEMCOUNT"; 
5539         case 0x1300 + 5: return "TCM_GETITEMA"; 
5540         case 0x1300 + 60: return "TCM_GETITEMW"; 
5541         case 0x1300 + 6: return "TCM_SETITEMA"; 
5542         case 0x1300 + 61: return "TCM_SETITEMW"; 
5543         case 0x1300 + 7: return "TCM_INSERTITEMA"; 
5544         case 0x1300 + 62: return "TCM_INSERTITEMW"; 
5545         case 0x1300 + 8: return "TCM_DELETEITEM"; 
5546         case 0x1300 + 9: return "TCM_DELETEALLITEMS"; 
5547         case 0x1300 + 10: return "TCM_GETITEMRECT"; 
5548         case 0x1300 + 11: return "TCM_GETCURSEL"; 
5549         case 0x1300 + 12: return "TCM_SETCURSEL"; 
5550         case 0x1300 + 13: return "TCM_HITTEST"; 
5551         case 0x1300 + 14: return "TCM_SETITEMEXTRA"; 
5552         case 0x1300 + 40: return "TCM_ADJUSTRECT"; 
5553         case 0x1300 + 41: return "TCM_SETITEMSIZE"; 
5554         case 0x1300 + 42: return "TCM_REMOVEIMAGE"; 
5555         case 0x1300 + 43: return "TCM_SETPADDING"; 
5556         case 0x1300 + 44: return "TCM_GETROWCOUNT"; 
5557         case 0x1300 + 45: return "TCM_GETTOOLTIPS"; 
5558         case 0x1300 + 46: return "TCM_SETTOOLTIPS"; 
5559         case 0x1300 + 47: return "TCM_GETCURFOCUS"; 
5560         case 0x1300 + 48: return "TCM_SETCURFOCUS"; 
5561         case 0x1300 + 49: return "TCM_SETMINTABWIDTH"; 
5562         case 0x1300 + 50: return "TCM_DESELECTALL"; 
5565         case WM_USER
+1: return "TB_ENABLEBUTTON"; 
5566         case WM_USER
+2: return "TB_CHECKBUTTON"; 
5567         case WM_USER
+3: return "TB_PRESSBUTTON"; 
5568         case WM_USER
+4: return "TB_HIDEBUTTON"; 
5569         case WM_USER
+5: return "TB_INDETERMINATE"; 
5570         case WM_USER
+9: return "TB_ISBUTTONENABLED"; 
5571         case WM_USER
+10: return "TB_ISBUTTONCHECKED"; 
5572         case WM_USER
+11: return "TB_ISBUTTONPRESSED"; 
5573         case WM_USER
+12: return "TB_ISBUTTONHIDDEN"; 
5574         case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE"; 
5575         case WM_USER
+17: return "TB_SETSTATE"; 
5576         case WM_USER
+18: return "TB_GETSTATE"; 
5577         case WM_USER
+19: return "TB_ADDBITMAP"; 
5578         case WM_USER
+20: return "TB_ADDBUTTONS"; 
5579         case WM_USER
+21: return "TB_INSERTBUTTON"; 
5580         case WM_USER
+22: return "TB_DELETEBUTTON"; 
5581         case WM_USER
+23: return "TB_GETBUTTON"; 
5582         case WM_USER
+24: return "TB_BUTTONCOUNT"; 
5583         case WM_USER
+25: return "TB_COMMANDTOINDEX"; 
5584         case WM_USER
+26: return "TB_SAVERESTOREA"; 
5585         case WM_USER
+76: return "TB_SAVERESTOREW"; 
5586         case WM_USER
+27: return "TB_CUSTOMIZE"; 
5587         case WM_USER
+28: return "TB_ADDSTRINGA"; 
5588         case WM_USER
+77: return "TB_ADDSTRINGW"; 
5589         case WM_USER
+29: return "TB_GETITEMRECT"; 
5590         case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE"; 
5591         case WM_USER
+31: return "TB_SETBUTTONSIZE"; 
5592         case WM_USER
+32: return "TB_SETBITMAPSIZE"; 
5593         case WM_USER
+33: return "TB_AUTOSIZE"; 
5594         case WM_USER
+35: return "TB_GETTOOLTIPS"; 
5595         case WM_USER
+36: return "TB_SETTOOLTIPS"; 
5596         case WM_USER
+37: return "TB_SETPARENT"; 
5597         case WM_USER
+39: return "TB_SETROWS"; 
5598         case WM_USER
+40: return "TB_GETROWS"; 
5599         case WM_USER
+42: return "TB_SETCMDID"; 
5600         case WM_USER
+43: return "TB_CHANGEBITMAP"; 
5601         case WM_USER
+44: return "TB_GETBITMAP"; 
5602         case WM_USER
+45: return "TB_GETBUTTONTEXTA"; 
5603         case WM_USER
+75: return "TB_GETBUTTONTEXTW"; 
5604         case WM_USER
+46: return "TB_REPLACEBITMAP"; 
5605         case WM_USER
+47: return "TB_SETINDENT"; 
5606         case WM_USER
+48: return "TB_SETIMAGELIST"; 
5607         case WM_USER
+49: return "TB_GETIMAGELIST"; 
5608         case WM_USER
+50: return "TB_LOADIMAGES"; 
5609         case WM_USER
+51: return "TB_GETRECT"; 
5610         case WM_USER
+52: return "TB_SETHOTIMAGELIST"; 
5611         case WM_USER
+53: return "TB_GETHOTIMAGELIST"; 
5612         case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST"; 
5613         case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST"; 
5614         case WM_USER
+56: return "TB_SETSTYLE"; 
5615         case WM_USER
+57: return "TB_GETSTYLE"; 
5616         case WM_USER
+58: return "TB_GETBUTTONSIZE"; 
5617         case WM_USER
+59: return "TB_SETBUTTONWIDTH"; 
5618         case WM_USER
+60: return "TB_SETMAXTEXTROWS"; 
5619         case WM_USER
+61: return "TB_GETTEXTROWS"; 
5620         case WM_USER
+41: return "TB_GETBITMAPFLAGS"; 
5623             static char s_szBuf
[128]; 
5624             sprintf(s_szBuf
, "<unknown message = %d>", message
); 
5628 #endif //__WXDEBUG__ 
5630 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
5631                                      int *x
, int *y
, WPARAM 
*flags
) 
5633     // construct the key mask 
5634     WPARAM
& fwKeys 
= *flags
; 
5636     fwKeys 
= MK_RBUTTON
; 
5637     if ( wxIsCtrlDown() ) 
5638         fwKeys 
|= MK_CONTROL
; 
5639     if ( wxIsShiftDown() ) 
5642     // simulate right mouse button click 
5643     DWORD dwPos 
= ::GetMessagePos(); 
5644     *x 
= GET_X_LPARAM(dwPos
); 
5645     *y 
= GET_Y_LPARAM(dwPos
); 
5647     win
->ScreenToClient(x
, y
); 
5650 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
) 
5654     HWND hwnd 
= GetHwndOf(win
); 
5655     HDC hdc 
= ::GetDC(hwnd
); 
5657 #if !wxDIALOG_UNIT_COMPATIBILITY 
5658     // and select the current font into it 
5659     HFONT hfont 
= GetHfontOf(win
->GetFont()); 
5662         hfont 
= (HFONT
)::SelectObject(hdc
, hfont
); 
5666     // finally retrieve the text metrics from it 
5667     GetTextMetrics(hdc
, &tm
); 
5669 #if !wxDIALOG_UNIT_COMPATIBILITY 
5673         (void)::SelectObject(hdc
, hfont
); 
5677     ::ReleaseDC(hwnd
, hdc
); 
5682 // Find the wxWindow at the current mouse position, returning the mouse 
5684 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
5686     pt 
= wxGetMousePosition(); 
5687     return wxFindWindowAtPoint(pt
); 
5690 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
5695     HWND hWndHit 
= ::WindowFromPoint(pt2
); 
5697     wxWindow
* win 
= wxFindWinFromHandle((WXHWND
) hWndHit
) ; 
5698     HWND hWnd 
= hWndHit
; 
5700     // Try to find a window with a wxWindow associated with it 
5701     while (!win 
&& (hWnd 
!= 0)) 
5703         hWnd 
= ::GetParent(hWnd
); 
5704         win 
= wxFindWinFromHandle((WXHWND
) hWnd
) ; 
5709 // Get the current mouse position. 
5710 wxPoint 
wxGetMousePosition() 
5713     GetCursorPos( & pt 
); 
5715     return wxPoint(pt
.x
, pt
.y
); 
5720 bool wxWindowMSW::RegisterHotKey(int hotkeyId
, int modifiers
, int keycode
) 
5722     UINT win_modifiers
=0; 
5723     if ( modifiers 
& wxMOD_ALT 
) 
5724         win_modifiers 
|= MOD_ALT
; 
5725     if ( modifiers 
& wxMOD_SHIFT 
) 
5726         win_modifiers 
|= MOD_SHIFT
; 
5727     if ( modifiers 
& wxMOD_CONTROL 
) 
5728         win_modifiers 
|= MOD_CONTROL
; 
5729     if ( modifiers 
& wxMOD_WIN 
) 
5730         win_modifiers 
|= MOD_WIN
; 
5732     if ( !::RegisterHotKey(GetHwnd(), hotkeyId
, win_modifiers
, keycode
) ) 
5734         wxLogLastError(_T("RegisterHotKey")); 
5742 bool wxWindowMSW::UnregisterHotKey(int hotkeyId
) 
5744     if ( !::UnregisterHotKey(GetHwnd(), hotkeyId
) ) 
5746         wxLogLastError(_T("UnregisterHotKey")); 
5754 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam
, WXLPARAM lParam
) 
5756     int hotkeyId 
= wParam
; 
5757     int virtualKey 
= HIWORD(lParam
); 
5758     int win_modifiers 
= LOWORD(lParam
); 
5760     wxKeyEvent 
event(CreateKeyEvent(wxEVT_HOTKEY
, virtualKey
, wParam
, lParam
)); 
5761     event
.SetId(hotkeyId
); 
5762     event
.m_shiftDown 
= (win_modifiers 
& MOD_SHIFT
) != 0; 
5763     event
.m_controlDown 
= (win_modifiers 
& MOD_CONTROL
) != 0; 
5764     event
.m_altDown 
= (win_modifiers 
& MOD_ALT
) != 0; 
5765     event
.m_metaDown 
= (win_modifiers 
& MOD_WIN
) != 0; 
5767     return GetEventHandler()->ProcessEvent(event
); 
5770 #endif // wxUSE_HOTKEY 
5772 // Not tested under WinCE 
5775 // this class installs a message hook which really wakes up our idle processing 
5776 // each time a WM_NULL is received (wxWakeUpIdle does this), even if we're 
5777 // sitting inside a local modal loop (e.g. a menu is opened or scrollbar is 
5778 // being dragged or even inside ::MessageBox()) and so don't control message 
5779 // dispatching otherwise 
5780 class wxIdleWakeUpModule 
: public wxModule
 
5783         virtual bool OnInit() 
5785                 ms_hMsgHookProc 
= ::SetWindowsHookEx
 
5788                              &wxIdleWakeUpModule::MsgHookProc
, 
5790                              GetCurrentThreadId() 
5793         if ( !ms_hMsgHookProc 
) 
5795             wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)")); 
5803         virtual void OnExit() 
5805                 ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc
); 
5808         static LRESULT CALLBACK 
MsgHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
) 
5810                 MSG 
*msg 
= (MSG
*)lParam
; 
5811                 if ( msg
->message 
== WM_NULL 
) 
5813             wxTheApp
->ProcessPendingEvents(); 
5816                 return CallNextHookEx(ms_hMsgHookProc
, nCode
, wParam
, lParam
); 
5820         static HHOOK ms_hMsgHookProc
; 
5822     DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule
) 
5825 HHOOK 
wxIdleWakeUpModule::ms_hMsgHookProc 
= 0; 
5827 IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule
, wxModule
) 
5829 #endif // __WXWINCE__