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 and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // =========================================================================== 
  14 // =========================================================================== 
  16 // --------------------------------------------------------------------------- 
  18 // --------------------------------------------------------------------------- 
  21     #pragma implementation "window.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  33     #include "wx/msw/winundef.h" 
  34     #include "wx/window.h" 
  39     #include "wx/dcclient.h" 
  40     #include "wx/dcmemory.h" 
  43     #include "wx/layout.h" 
  44     #include "wx/dialog.h" 
  46     #include "wx/listbox.h" 
  47     #include "wx/button.h" 
  48     #include "wx/msgdlg.h" 
  49     #include "wx/settings.h" 
  50     #include "wx/statbox.h" 
  54     #include "wx/ownerdrw.h" 
  57 #if wxUSE_DRAG_AND_DROP 
  61 #include "wx/menuitem.h" 
  64 #include "wx/msw/private.h" 
  67     #include "wx/tooltip.h" 
  75     #include "wx/spinctrl.h" 
  76 #endif // wxUSE_SPINCTRL 
  81 #include "wx/textctrl.h" 
  82 #include "wx/notebook.h" 
  86 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) 
  95 #if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) 
  99 #elif !defined(__WXMICROWIN__) // broken compiler 
 101         #include "wx/msw/gnuwin32/extra.h" 
 105 // ---------------------------------------------------------------------------- 
 106 // standard constants not available with all compilers/headers 
 107 // ---------------------------------------------------------------------------- 
 109 // This didn't appear in mingw until 2.95.2 
 111 #define SIF_TRACKPOS 16 
 115     #ifndef WM_MOUSEWHEEL 
 116         #define WM_MOUSEWHEEL           0x020A 
 119         #define WHEEL_DELTA             120 
 121     #ifndef SPI_GETWHEELSCROLLLINES 
 122         #define SPI_GETWHEELSCROLLLINES 104 
 124 #endif // wxUSE_MOUSEWHEEL 
 127     #define VK_OEM_1        0xBA 
 128     #define VK_OEM_PLUS     0xBB 
 129     #define VK_OEM_COMMA    0xBC 
 130     #define VK_OEM_MINUS    0xBD 
 131     #define VK_OEM_PERIOD   0xBE 
 132     #define VK_OEM_2        0xBF 
 133     #define VK_OEM_3        0xC0 
 134     #define VK_OEM_4        0xDB 
 135     #define VK_OEM_5        0xDC 
 136     #define VK_OEM_6        0xDD 
 137     #define VK_OEM_7        0xDE 
 140 // --------------------------------------------------------------------------- 
 142 // --------------------------------------------------------------------------- 
 144 // the last Windows message we got (FIXME-MT) 
 145 extern MSG s_currentMsg
; 
 147 #if wxUSE_MENUS_NATIVE 
 148 wxMenu 
*wxCurrentPopupMenu 
= NULL
; 
 149 #endif // wxUSE_MENUS_NATIVE 
 151 extern const wxChar 
*wxCanvasClassName
; 
 153 // true if we had already created the std colour map, used by 
 154 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT) 
 155 static bool gs_hasStdCmap 
= FALSE
; 
 157 // --------------------------------------------------------------------------- 
 159 // --------------------------------------------------------------------------- 
 161 // the window proc for all our windows 
 162 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
 163                                    WPARAM wParam
, LPARAM lParam
); 
 166     const char *wxGetMessageName(int message
); 
 169 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 170 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 171 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
); 
 173 // this magical function is used to translate VK_APPS key presses to right 
 175 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
 176                                      int *x
, int *y
, WPARAM 
*flags
); 
 178 // get the text metrics for the current font 
 179 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
); 
 181 // wrapper around BringWindowToTop() API 
 182 static inline void wxBringWindowToTop(HWND hwnd
) 
 184 #ifdef __WXMICROWIN__ 
 185     // It seems that MicroWindows brings the _parent_ of the window to the top, 
 186     // which can be the wrong one. 
 188     // activate (set focus to) specified window 
 191     // raise top level parent to top of z order 
 192     ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE 
| SWP_NOSIZE
); 
 193 #else // !__WXMICROWIN__ 
 194     if ( !::BringWindowToTop(hwnd
) ) 
 196         wxLogLastError(_T("BringWindowToTop")); 
 198 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
 201 // --------------------------------------------------------------------------- 
 203 // --------------------------------------------------------------------------- 
 205 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
 207 #ifdef __WXUNIVERSAL__ 
 208     IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
) 
 210     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
 211 #endif // __WXUNIVERSAL__/__WXMSW__ 
 213 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
) 
 214     EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
) 
 215     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
) 
 216     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
) 
 217     EVT_IDLE(wxWindowMSW::OnIdle
) 
 220 // =========================================================================== 
 222 // =========================================================================== 
 224 // --------------------------------------------------------------------------- 
 225 // wxWindow utility functions 
 226 // --------------------------------------------------------------------------- 
 228 // Find an item given the MS Windows id 
 229 wxWindow 
*wxWindowMSW::FindItem(long id
) const 
 232     wxControl 
*item 
= wxDynamicCastThis(wxControl
); 
 235         // is it we or one of our "internal" children? 
 236         if ( item
->GetId() == id
 
 237 #ifndef __WXUNIVERSAL__ 
 238                 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
) 
 239 #endif // __WXUNIVERSAL__ 
 245 #endif // wxUSE_CONTROLS 
 247     wxWindowList::Node 
*current 
= GetChildren().GetFirst(); 
 250         wxWindow 
*childWin 
= current
->GetData(); 
 252         wxWindow 
*wnd 
= childWin
->FindItem(id
); 
 256         current 
= current
->GetNext(); 
 262 // Find an item given the MS Windows handle 
 263 wxWindow 
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const 
 265     wxWindowList::Node 
*current 
= GetChildren().GetFirst(); 
 268         wxWindow 
*parent 
= current
->GetData(); 
 270         // Do a recursive search. 
 271         wxWindow 
*wnd 
= parent
->FindItemByHWND(hWnd
); 
 277                 || parent
->IsKindOf(CLASSINFO(wxControl
)) 
 278 #endif // wxUSE_CONTROLS 
 281             wxWindow 
*item 
= current
->GetData(); 
 282             if ( item
->GetHWND() == hWnd 
) 
 286                 if ( item
->ContainsHWND(hWnd
) ) 
 291         current 
= current
->GetNext(); 
 296 // Default command handler 
 297 bool wxWindowMSW::MSWCommand(WXUINT 
WXUNUSED(param
), WXWORD 
WXUNUSED(id
)) 
 302 // ---------------------------------------------------------------------------- 
 303 // constructors and such 
 304 // ---------------------------------------------------------------------------- 
 306 void wxWindowMSW::Init() 
 312     m_doubleClickAllowed 
= 0; 
 314     m_isBeingDeleted 
= FALSE
; 
 317     m_mouseInWindow 
= FALSE
; 
 318     m_lastKeydownProcessed 
= FALSE
; 
 327     m_backgroundTransparent 
= FALSE
; 
 329     // as all windows are created with WS_VISIBLE style... 
 332 #if wxUSE_MOUSEEVENT_HACK 
 335     m_lastMouseEvent 
= -1; 
 336 #endif // wxUSE_MOUSEEVENT_HACK 
 340 wxWindowMSW::~wxWindowMSW() 
 342     m_isBeingDeleted 
= TRUE
; 
 344 #ifndef __WXUNIVERSAL__ 
 345     // VS: make sure there's no wxFrame with last focus set to us: 
 346     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
 348         wxFrame 
*frame 
= wxDynamicCast(win
, wxFrame
); 
 351             if ( frame
->GetLastFocus() == this ) 
 353                 frame
->SetLastFocus((wxWindow
*)NULL
); 
 358 #endif // __WXUNIVERSAL__ 
 360     // VS: destroy children first and _then_ detach *this from its parent. 
 361     //     If we'd do it the other way around, children wouldn't be able 
 362     //     find their parent frame (see above). 
 366         m_parent
->RemoveChild(this); 
 370         // VZ: test temp removed to understand what really happens here 
 371         //if (::IsWindow(GetHwnd())) 
 373             if ( !::DestroyWindow(GetHwnd()) ) 
 374                 wxLogLastError(wxT("DestroyWindow")); 
 377         // remove hWnd <-> wxWindow association 
 378         wxRemoveHandleAssociation(this); 
 382 // real construction (Init() must have been called before!) 
 383 bool wxWindowMSW::Create(wxWindow 
*parent
, 
 388                          const wxString
& name
) 
 390     wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") ); 
 393     // wxGTK doesn't allow to create controls with static box as the parent so 
 394     // this will result in a crash when the program is ported to wxGTK - warn 
 397     // the correct solution is to create the controls as siblings of the 
 399     wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
), 
 400                   _T("wxStaticBox can't be used as a window parent!") ); 
 401 #endif // wxUSE_STATBOX 
 403     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 406     parent
->AddChild(this); 
 408     // note that all windows are created visible by default 
 410     DWORD msflags 
= WS_VISIBLE 
| MSWGetCreateWindowFlags(&exstyle
); 
 412 #ifdef __WXUNIVERSAL__ 
 413     // no borders, we draw them ourselves 
 415     msflags 
&= ~WS_BORDER
; 
 416 #endif // wxUniversal 
 418     if ( style 
& wxPOPUP_WINDOW 
) 
 420         // a popup window floats on top of everything 
 421         exstyle 
|= WS_EX_TOPMOST 
| WS_EX_TOOLWINDOW
; 
 423         // it is also created hidden as other top level windows 
 424         msflags 
&= ~WS_VISIBLE
; 
 428     return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
); 
 431 // --------------------------------------------------------------------------- 
 433 // --------------------------------------------------------------------------- 
 435 void wxWindowMSW::SetFocus() 
 437     HWND hWnd 
= GetHwnd(); 
 438     wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") ); 
 440 #ifndef __WXMICROWIN__ 
 444     if ( !::SetFocus(hWnd
) ) 
 446 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__) 
 447         // was there really an error? 
 448         DWORD dwRes 
= ::GetLastError(); 
 451             HWND hwndFocus 
= ::GetFocus(); 
 452             if ( hwndFocus 
!= hWnd 
) 
 454                 wxLogApiError(_T("SetFocus"), dwRes
); 
 461 // Get the window with the focus 
 462 wxWindow 
*wxWindowBase::FindFocus() 
 464     HWND hWnd 
= ::GetFocus(); 
 467         return wxGetWindowFromHWND((WXHWND
)hWnd
); 
 473 bool wxWindowMSW::Enable(bool enable
) 
 475     if ( !wxWindowBase::Enable(enable
) ) 
 478     HWND hWnd 
= GetHwnd(); 
 480         ::EnableWindow(hWnd
, (BOOL
)enable
); 
 482     // VZ: no, this is a bad idea: imagine that you have a dialog with some 
 483     //     disabled controls and disable it - you really wouldn't like the 
 484     //     disabled controls be reenabled too when you reenable the dialog! 
 486     wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
 489         wxWindow 
*child 
= node
->GetData(); 
 490         child
->Enable(enable
); 
 492         node 
= node
->GetNext(); 
 499 bool wxWindowMSW::Show(bool show
) 
 501     if ( !wxWindowBase::Show(show
) ) 
 504     HWND hWnd 
= GetHwnd(); 
 505     int cshow 
= show 
? SW_SHOW 
: SW_HIDE
; 
 506     ::ShowWindow(hWnd
, cshow
); 
 510         wxBringWindowToTop(hWnd
); 
 516 // Raise the window to the top of the Z order 
 517 void wxWindowMSW::Raise() 
 519     wxBringWindowToTop(GetHwnd()); 
 522 // Lower the window to the bottom of the Z order 
 523 void wxWindowMSW::Lower() 
 525     ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0, 
 526                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
 529 void wxWindowMSW::SetTitle( const wxString
& title
) 
 531     SetWindowText(GetHwnd(), title
.c_str()); 
 534 wxString 
wxWindowMSW::GetTitle() const 
 536     return wxGetWindowText(GetHWND()); 
 539 void wxWindowMSW::DoCaptureMouse() 
 541     HWND hWnd 
= GetHwnd(); 
 548 void wxWindowMSW::DoReleaseMouse() 
 550     if ( !::ReleaseCapture() ) 
 552         wxLogLastError(_T("ReleaseCapture")); 
 556 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 558     HWND hwnd 
= ::GetCapture(); 
 559     return hwnd 
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow 
*)NULL
; 
 562 bool wxWindowMSW::SetFont(const wxFont
& font
) 
 564     if ( !wxWindowBase::SetFont(font
) ) 
 570     HWND hWnd 
= GetHwnd(); 
 573         WXHANDLE hFont 
= m_font
.GetResourceHandle(); 
 575         wxASSERT_MSG( hFont
, wxT("should have valid font") ); 
 577         ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0)); 
 582 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
) 
 584     if ( !wxWindowBase::SetCursor(cursor
) ) 
 592         HWND hWnd 
= GetHwnd(); 
 594         // Change the cursor NOW if we're within the correct window 
 596         ::GetCursorPos(&point
); 
 598         RECT rect 
= wxGetWindowRect(hWnd
); 
 600         if ( ::PtInRect(&rect
, point
) && !wxIsBusy() ) 
 601             ::SetCursor(GetHcursorOf(m_cursor
)); 
 607 void wxWindowMSW::WarpPointer (int x
, int y
) 
 609     ClientToScreen(&x
, &y
); 
 611     if ( !::SetCursorPos(x
, y
) ) 
 613         wxLogLastError(_T("SetCursorPos")); 
 617 #if WXWIN_COMPATIBILITY 
 618 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const 
 621 #endif // WXWIN_COMPATIBILITY 
 623 // --------------------------------------------------------------------------- 
 625 // --------------------------------------------------------------------------- 
 627 #if WXWIN_COMPATIBILITY 
 628 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
) 
 630 #if defined(__WIN95__) 
 634     // Try to adjust the range to cope with page size > 1 
 635     // - a Windows API quirk 
 636     int pageSize 
= GetScrollPage(orient
); 
 637     if ( pageSize 
> 1 && range 
> 0) 
 639         range1 
+= (pageSize 
- 1); 
 645     if ( orient 
== wxHORIZONTAL 
) { 
 651     info
.cbSize 
= sizeof(SCROLLINFO
); 
 652     info
.nPage 
= pageSize
; // Have to set this, or scrollbar goes awry 
 656     info
.fMask 
= SIF_RANGE 
| SIF_PAGE
; 
 658     HWND hWnd 
= GetHwnd(); 
 660         ::SetScrollInfo(hWnd
, dir
, &info
, refresh
); 
 663     if ( orient 
== wxHORIZONTAL 
) 
 668     HWND hWnd 
= GetHwnd(); 
 670         ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
); 
 674 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
) 
 676 #if defined(__WIN95__) 
 680     if ( orient 
== wxHORIZONTAL 
) { 
 688     info
.cbSize 
= sizeof(SCROLLINFO
); 
 691     info
.fMask 
= SIF_PAGE
; 
 693     HWND hWnd 
= GetHwnd(); 
 695         ::SetScrollInfo(hWnd
, dir
, &info
, refresh
); 
 697     if ( orient 
== wxHORIZONTAL 
) 
 704 int wxWindowMSW::OldGetScrollRange(int orient
) const 
 707     if ( orient 
== wxHORIZONTAL 
) 
 712 #if __WATCOMC__ && defined(__WINDOWS_386__) 
 713     short minPos
, maxPos
; 
 717     HWND hWnd 
= GetHwnd(); 
 720         ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
); 
 721 #if defined(__WIN95__) 
 722         // Try to adjust the range to cope with page size > 1 
 723         // - a Windows API quirk 
 724         int pageSize 
= GetScrollPage(orient
); 
 727             maxPos 
-= (pageSize 
- 1); 
 736 int wxWindowMSW::GetScrollPage(int orient
) const 
 738     if ( orient 
== wxHORIZONTAL 
) 
 744 #endif // WXWIN_COMPATIBILITY 
 746 inline int GetScrollPosition(HWND hWnd
, int wOrient
) 
 748 #ifdef __WXMICROWIN__ 
 749     return ::GetScrollPosWX(hWnd
, wOrient
); 
 751     return ::GetScrollPos(hWnd
, wOrient
); 
 755 int wxWindowMSW::GetScrollPos(int orient
) const 
 758     if ( orient 
== wxHORIZONTAL 
) 
 763     HWND hWnd 
= GetHwnd(); 
 764     wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") ); 
 766     return GetScrollPosition(hWnd
, wOrient
); 
 769 // This now returns the whole range, not just the number 
 770 // of positions that we can scroll. 
 771 int wxWindowMSW::GetScrollRange(int orient
) const 
 774     if ( orient 
== wxHORIZONTAL 
) 
 779 #if __WATCOMC__ && defined(__WINDOWS_386__) 
 780     short minPos
, maxPos
; 
 784     HWND hWnd 
= GetHwnd(); 
 787         ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
); 
 788 #if defined(__WIN95__) 
 789         // Try to adjust the range to cope with page size > 1 
 790         // - a Windows API quirk 
 791         int pageSize 
= GetScrollThumb(orient
); 
 794             maxPos 
-= (pageSize 
- 1); 
 796         // October 10th: new range concept. 
 806 int wxWindowMSW::GetScrollThumb(int orient
) const 
 808     if ( orient 
== wxHORIZONTAL 
) 
 814 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
) 
 816     HWND hWnd 
= GetHwnd(); 
 817     wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") ); 
 819     int dir 
= orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
; 
 821 #if defined(__WIN95__) 
 823     info
.cbSize 
= sizeof(SCROLLINFO
); 
 827     info
.fMask 
= SIF_POS
; 
 829     ::SetScrollInfo(hWnd
, dir
, &info
, refresh
); 
 831     ::SetScrollPos(hWnd
, dir
, pos
, refresh
); 
 832 #endif // __WIN95__/!__WIN95__ 
 835 // New function that will replace some of the above. 
 836 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
, 
 837                             int range
, bool refresh
) 
 839 #if defined(__WIN95__) 
 840     int oldRange 
= range 
- thumbVisible
; 
 842     int range1 
= oldRange
; 
 844     // Try to adjust the range to cope with page size > 1 
 845     // - a Windows API quirk 
 846     int pageSize 
= thumbVisible
; 
 847     if ( pageSize 
> 1 && range 
> 0) 
 849         range1 
+= (pageSize 
- 1); 
 855     if ( orient 
== wxHORIZONTAL 
) { 
 861     info
.cbSize 
= sizeof(SCROLLINFO
); 
 862     info
.nPage 
= pageSize
; // Have to set this, or scrollbar goes awry 
 866     info
.fMask 
= SIF_RANGE 
| SIF_PAGE 
| SIF_POS
; 
 868     HWND hWnd 
= GetHwnd(); 
 870         ::SetScrollInfo(hWnd
, dir
, &info
, refresh
); 
 873     if ( orient 
== wxHORIZONTAL 
) 
 878     HWND hWnd 
= GetHwnd(); 
 881         ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
); 
 882         ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
); 
 885     if ( orient 
== wxHORIZONTAL 
) { 
 886         m_xThumbSize 
= thumbVisible
; 
 888         m_yThumbSize 
= thumbVisible
; 
 892 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect 
*prect
) 
 898         rect
.left 
= prect
->x
; 
 900         rect
.right 
= prect
->x 
+ prect
->width
; 
 901         rect
.bottom 
= prect
->y 
+ prect
->height
; 
 909     ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
); 
 912 static bool ScrollVertically(HWND hwnd
, int kind
, int count
) 
 914     int posStart 
= GetScrollPosition(hwnd
, SB_VERT
); 
 917     for ( int n 
= 0; n 
< count
; n
++ ) 
 919         ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0); 
 921         int posNew 
= GetScrollPosition(hwnd
, SB_VERT
); 
 924             // don't bother to continue, we're already at top/bottom 
 931     return pos 
!= posStart
; 
 934 bool wxWindowMSW::ScrollLines(int lines
) 
 936     bool down 
= lines 
> 0; 
 938     return ScrollVertically(GetHwnd(), 
 939                             down 
? SB_LINEDOWN 
: SB_LINEUP
, 
 940                             down 
? lines 
: -lines
); 
 943 bool wxWindowMSW::ScrollPages(int pages
) 
 945     bool down 
= pages 
> 0; 
 947     return ScrollVertically(GetHwnd(), 
 948                             down 
? SB_PAGEDOWN 
: SB_PAGEUP
, 
 949                             down 
? pages 
: -pages
); 
 952 // --------------------------------------------------------------------------- 
 954 // --------------------------------------------------------------------------- 
 956 void wxWindowMSW::SubclassWin(WXHWND hWnd
) 
 958     wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") ); 
 960     HWND hwnd 
= (HWND
)hWnd
; 
 961     wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") ); 
 963     wxAssociateWinWithHandle(hwnd
, this); 
 965     m_oldWndProc 
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
); 
 967     // we don't need to subclass the window of our own class (in the Windows 
 968     // sense of the word) 
 969     if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) ) 
 971         ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
); 
 975         // don't bother restoring it neither 
 980 void wxWindowMSW::UnsubclassWin() 
 982     wxRemoveHandleAssociation(this); 
 984     // Restore old Window proc 
 985     HWND hwnd 
= GetHwnd(); 
 990         wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") ); 
 994             if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) ) 
 996                 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
); 
1004 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
) 
1006 #if wxUSE_UNICODE_MSLU 
1007     // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll 
1008     //     because it doesn't return pointer to the real wnd proc but rather a handle 
1009     //     of a fake proc that does Unicode<->ANSI translation. 
1011     //     The hack bellow works, because WNDCLASS contains original window handler 
1012     //     rather that the unicows fake one. This may not be on purpose, though; if 
1013     //     it stops working with future versions of unicows.dll, we can override 
1014     //     unicows hooks by setting Unicows_{Set,Get}WindowLong and 
1015     //     Unicows_RegisterClass to our own versions that keep track of 
1016     //     fake<->real wnd proc mapping. 
1018     //     FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set 
1019     //            with RegisterClass!! 
1021     if ( wxUsingUnicowsDll() ) 
1023         static wxChar buffer
[512]; 
1026         ::GetClassName((HWND
)hWnd
, buffer
, 512); 
1027         ::GetClassInfo(wxGetInstance(), buffer
, &cls
); 
1028         return wndProc 
== (WXFARPROC
)cls
.lpfnWndProc
; 
1033         return wndProc 
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
); 
1037 // ---------------------------------------------------------------------------- 
1039 // ---------------------------------------------------------------------------- 
1041 void wxWindowMSW::SetWindowStyleFlag(long flags
) 
1043     long flagsOld 
= GetWindowStyleFlag(); 
1044     if ( flags 
== flagsOld 
) 
1047     // update the internal variable 
1048     wxWindowBase::SetWindowStyleFlag(flags
); 
1050     // now update the Windows style as well if needed - and if the window had 
1051     // been already created 
1055     WXDWORD exstyle
, exstyleOld
; 
1056     long style 
= MSWGetStyle(flags
, &exstyle
), 
1057          styleOld 
= MSWGetStyle(flagsOld
, &exstyleOld
); 
1059     if ( style 
!= styleOld 
) 
1061         // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by 
1062         // this function so instead of simply setting the style to the new 
1063         // value we clear the bits which were set in styleOld but are set in 
1064         // the new one and set the ones which were not set before 
1065         long styleReal 
= ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
1066         styleReal 
&= ~styleOld
; 
1069         ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
); 
1072     // and the extended style 
1073     if ( exstyle 
!= exstyleOld 
) 
1075         long exstyleReal 
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1076         exstyleReal 
&= ~exstyleOld
; 
1077         exstyleReal 
|= exstyle
; 
1079         ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
); 
1081         // we must call SetWindowPos() to flash the cached extended style and 
1082         // also to make the change to wxSTAY_ON_TOP style take effect: just 
1083         // setting the style simply doesn't work 
1084         if ( !::SetWindowPos(GetHwnd(), 
1085                              exstyleReal 
& WS_EX_TOPMOST 
? HWND_TOPMOST
 
1088                              SWP_NOMOVE 
| SWP_NOSIZE
) ) 
1090             wxLogLastError(_T("SetWindowPos")); 
1095 WXDWORD 
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD 
*exstyle
) const 
1097     // translate the style 
1098     WXDWORD style 
= WS_CHILD
; 
1100     if ( flags 
& wxCLIP_CHILDREN 
) 
1101         style 
|= WS_CLIPCHILDREN
; 
1103     if ( flags 
& wxCLIP_SIBLINGS 
) 
1104         style 
|= WS_CLIPSIBLINGS
; 
1106     wxBorder border 
= (wxBorder
)(flags 
& wxBORDER_MASK
); 
1107     if ( border 
!= wxBORDER_NONE 
&& border 
!= wxBORDER_DEFAULT 
) 
1110     // now deal with ext style if the caller wants it 
1115         if ( flags 
& wxTRANSPARENT_WINDOW 
) 
1116             *exstyle 
|= WS_EX_TRANSPARENT
; 
1118         switch ( flags 
& wxBORDER_MASK 
) 
1121                 wxFAIL_MSG( _T("unknown border style") ); 
1125             case wxBORDER_SIMPLE
: 
1126             case wxBORDER_DEFAULT
: 
1129             case wxBORDER_STATIC
: 
1130                 *exstyle 
|= WS_EX_STATICEDGE
; 
1133             case wxBORDER_RAISED
: 
1134                 *exstyle 
|= WS_EX_WINDOWEDGE
; 
1137             case wxBORDER_SUNKEN
: 
1138                 *exstyle 
|= WS_EX_CLIENTEDGE
; 
1141             case wxBORDER_DOUBLE
: 
1142                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1150 // Make a Windows extended style from the given wxWindows window style 
1151 WXDWORD 
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
) 
1153     WXDWORD exStyle 
= 0; 
1154     if ( style 
& wxTRANSPARENT_WINDOW 
) 
1155         exStyle 
|= WS_EX_TRANSPARENT
; 
1157     if ( !eliminateBorders 
) 
1159         if ( style 
& wxSUNKEN_BORDER 
) 
1160             exStyle 
|= WS_EX_CLIENTEDGE
; 
1161         if ( style 
& wxDOUBLE_BORDER 
) 
1162             exStyle 
|= WS_EX_DLGMODALFRAME
; 
1163 #if defined(__WIN95__) 
1164         if ( style 
& wxRAISED_BORDER 
) 
1165             // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does 
1166             exStyle 
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */; 
1167         if ( style 
& wxSTATIC_BORDER 
) 
1168             exStyle 
|= WS_EX_STATICEDGE
; 
1175 // Determines whether native 3D effects or CTL3D should be used, 
1176 // applying a default border style if required, and returning an extended 
1177 // style to pass to CreateWindowEx. 
1178 WXDWORD 
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
, 
1181     // If matches certain criteria, then assume no 3D effects 
1182     // unless specifically requested (dealt with in MakeExtendedStyle) 
1185             || !IsKindOf(CLASSINFO(wxControl
)) 
1186 #endif // wxUSE_CONTROLS 
1187             || (m_windowStyle 
& wxNO_BORDER
) ) 
1190         return MakeExtendedStyle(m_windowStyle
); 
1193     // Determine whether we should be using 3D effects or not. 
1194     bool nativeBorder 
= FALSE
; // by default, we don't want a Win95 effect 
1196     // 1) App can specify global 3D effects 
1197     *want3D 
= wxTheApp
->GetAuto3D(); 
1199     // 2) If the parent is being drawn with user colours, or simple border specified, 
1200     // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D 
1201     if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle 
& wxSIMPLE_BORDER
) ) 
1204     // 3) Control can override this global setting by defining 
1205     // a border style, e.g. wxSUNKEN_BORDER 
1206     if ( m_windowStyle 
& wxSUNKEN_BORDER  
) 
1209     // 4) If it's a special border, CTL3D can't cope so we want a native border 
1210     if ( (m_windowStyle 
& wxDOUBLE_BORDER
) || (m_windowStyle 
& wxRAISED_BORDER
) || 
1211         (m_windowStyle 
& wxSTATIC_BORDER
) ) 
1214         nativeBorder 
= TRUE
; 
1217     // 5) If this isn't a Win95 app, and we are using CTL3D, remove border 
1218     // effects from extended style 
1221         nativeBorder 
= FALSE
; 
1224     DWORD exStyle 
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
); 
1226     // If we want 3D, but haven't specified a border here, 
1227     // apply the default border style specified. 
1228     // TODO what about non-Win95 WIN32? Does it have borders? 
1229 #if defined(__WIN95__) && !wxUSE_CTL3D 
1230     if ( defaultBorderStyle 
&& (*want3D
) && ! ((m_windowStyle 
& wxDOUBLE_BORDER
) || (m_windowStyle 
& wxRAISED_BORDER 
) || 
1231         (m_windowStyle 
& wxSTATIC_BORDER
) || (m_windowStyle 
& wxSIMPLE_BORDER
) )) 
1232         exStyle 
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE; 
1238 #if WXWIN_COMPATIBILITY 
1239 // If nothing defined for this, try the parent. 
1240 // E.g. we may be a button loaded from a resource, with no callback function 
1242 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
) 
1244     if ( GetEventHandler()->ProcessEvent(event
)  ) 
1247         m_parent
->GetEventHandler()->OnCommand(win
, event
); 
1249 #endif // WXWIN_COMPATIBILITY_2 
1251 #if WXWIN_COMPATIBILITY 
1252 wxObject
* wxWindowMSW::GetChild(int number
) const 
1254     // Return a pointer to the Nth object in the Panel 
1255     wxNode 
*node 
= GetChildren().First(); 
1258         node 
= node
->Next(); 
1261         wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
1267 #endif // WXWIN_COMPATIBILITY 
1269 // Setup background and foreground colours correctly 
1270 void wxWindowMSW::SetupColours() 
1273         SetBackgroundColour(GetParent()->GetBackgroundColour()); 
1276 bool wxWindowMSW::IsMouseInWindow() const 
1278     // get the mouse position 
1280     ::GetCursorPos(&pt
); 
1282     // find the window which currently has the cursor and go up the window 
1283     // chain until we find this window - or exhaust it 
1284     HWND hwnd 
= ::WindowFromPoint(pt
); 
1285     while ( hwnd 
&& (hwnd 
!= GetHwnd()) ) 
1286         hwnd 
= ::GetParent(hwnd
); 
1288     return hwnd 
!= NULL
; 
1291 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
)) 
1293     // Check if we need to send a LEAVE event 
1294     if ( m_mouseInWindow 
) 
1296         // note that we should generate the leave event whether the window has 
1297         // or doesn't have mouse capture 
1298         if ( !IsMouseInWindow() ) 
1300             // Generate a LEAVE event 
1301             m_mouseInWindow 
= FALSE
; 
1303             // Unfortunately the mouse button and keyboard state may have 
1304             // changed by the time the OnIdle function is called, so 'state' 
1305             // may be meaningless. 
1307             if ( wxIsShiftDown() ) 
1309             if ( wxIsCtrlDown() ) 
1310                 state 
|= MK_CONTROL
; 
1311             if ( GetKeyState( VK_LBUTTON 
) ) 
1312                 state 
|= MK_LBUTTON
; 
1313             if ( GetKeyState( VK_MBUTTON 
) ) 
1314                 state 
|= MK_MBUTTON
; 
1315             if ( GetKeyState( VK_RBUTTON 
) ) 
1316                 state 
|= MK_RBUTTON
; 
1319             if ( !::GetCursorPos(&pt
) ) 
1321                 wxLogLastError(_T("GetCursorPos")); 
1324             // we need to have client coordinates here for symmetry with 
1325             // wxEVT_ENTER_WINDOW 
1326             RECT rect 
= wxGetWindowRect(GetHwnd()); 
1330             wxMouseEvent 
event2(wxEVT_LEAVE_WINDOW
); 
1331             InitMouseEvent(event2
, pt
.x
, pt
.y
, state
); 
1333             (void)GetEventHandler()->ProcessEvent(event2
); 
1340 // Set this window to be the child of 'parent'. 
1341 bool wxWindowMSW::Reparent(wxWindowBase 
*parent
) 
1343     if ( !wxWindowBase::Reparent(parent
) ) 
1346     HWND hWndChild 
= GetHwnd(); 
1347     HWND hWndParent 
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0; 
1349     ::SetParent(hWndChild
, hWndParent
); 
1354 void wxWindowMSW::Clear() 
1356     wxClientDC 
dc((wxWindow 
*)this); 
1357     wxBrush 
brush(GetBackgroundColour(), wxSOLID
); 
1358     dc
.SetBackground(brush
); 
1362 static inline void SendSetRedraw(HWND hwnd
, bool on
) 
1364 #ifndef __WXMICROWIN__ 
1365     ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0); 
1369 void wxWindowMSW::Freeze() 
1371     SendSetRedraw(GetHwnd(), FALSE
); 
1374 void wxWindowMSW::Thaw() 
1376     SendSetRedraw(GetHwnd(), TRUE
); 
1378     // we need to refresh everything or otherwise he invalidated area is not 
1383 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1385     HWND hWnd 
= GetHwnd(); 
1391             mswRect
.left 
= rect
->x
; 
1392             mswRect
.top 
= rect
->y
; 
1393             mswRect
.right 
= rect
->x 
+ rect
->width
; 
1394             mswRect
.bottom 
= rect
->y 
+ rect
->height
; 
1396             ::InvalidateRect(hWnd
, &mswRect
, eraseBack
); 
1399             ::InvalidateRect(hWnd
, NULL
, eraseBack
); 
1403 void wxWindowMSW::Update() 
1405     if ( !::UpdateWindow(GetHwnd()) ) 
1407         wxLogLastError(_T("UpdateWindow")); 
1410 #if defined(__WIN32__) && !defined(__WXMICROWIN__) 
1411     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT 
1412     // handler needs to be really drawn right now 
1417 // --------------------------------------------------------------------------- 
1419 // --------------------------------------------------------------------------- 
1421 #if wxUSE_DRAG_AND_DROP 
1423 void wxWindowMSW::SetDropTarget(wxDropTarget 
*pDropTarget
) 
1425     if ( m_dropTarget 
!= 0 ) { 
1426         m_dropTarget
->Revoke(m_hWnd
); 
1427         delete m_dropTarget
; 
1430     m_dropTarget 
= pDropTarget
; 
1431     if ( m_dropTarget 
!= 0 ) 
1432         m_dropTarget
->Register(m_hWnd
); 
1435 #endif // wxUSE_DRAG_AND_DROP 
1437 // old style file-manager drag&drop support: we retain the old-style 
1438 // DragAcceptFiles in parallel with SetDropTarget. 
1439 void wxWindowMSW::DragAcceptFiles(bool accept
) 
1441     HWND hWnd 
= GetHwnd(); 
1443         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
1446 // ---------------------------------------------------------------------------- 
1448 // ---------------------------------------------------------------------------- 
1452 void wxWindowMSW::DoSetToolTip(wxToolTip 
*tooltip
) 
1454     wxWindowBase::DoSetToolTip(tooltip
); 
1457         m_tooltip
->SetWindow(this); 
1460 #endif // wxUSE_TOOLTIPS 
1462 // --------------------------------------------------------------------------- 
1463 // moving and resizing 
1464 // --------------------------------------------------------------------------- 
1467 void wxWindowMSW::DoGetSize(int *x
, int *y
) const 
1469     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1472         *x 
= rect
.right 
- rect
.left
; 
1474         *y 
= rect
.bottom 
- rect
.top
; 
1477 // Get size *available for subwindows* i.e. excluding menu bar etc. 
1478 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const 
1480     RECT rect 
= wxGetClientRect(GetHwnd()); 
1488 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const 
1490     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1493     point
.x 
= rect
.left
; 
1496     // we do the adjustments with respect to the parent only for the "real" 
1497     // children, not for the dialogs/frames 
1498     if ( !IsTopLevel() ) 
1500         HWND hParentWnd 
= 0; 
1501         wxWindow 
*parent 
= GetParent(); 
1503             hParentWnd 
= GetWinHwnd(parent
); 
1505         // Since we now have the absolute screen coords, if there's a parent we 
1506         // must subtract its top left corner 
1509             ::ScreenToClient(hParentWnd
, &point
); 
1514             // We may be faking the client origin. So a window that's really at (0, 
1515             // 30) may appear (to wxWin apps) to be at (0, 0). 
1516             wxPoint 
pt(parent
->GetClientAreaOrigin()); 
1528 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const 
1536     ::ScreenToClient(GetHwnd(), &pt
); 
1544 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const 
1552     ::ClientToScreen(GetHwnd(), &pt
); 
1560 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
) 
1562     // TODO: is this consistent with other platforms? 
1563     // Still, negative width or height shouldn't be allowed 
1568     if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) ) 
1570         wxLogLastError(wxT("MoveWindow")); 
1574 // set the size of the window: if the dimensions are positive, just use them, 
1575 // but if any of them is equal to -1, it means that we must find the value for 
1576 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
1577 // which case -1 is a valid value for x and y) 
1579 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
1580 // the width/height to best suit our contents, otherwise we reuse the current 
1582 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
1584     // get the current size and position... 
1585     int currentX
, currentY
; 
1586     GetPosition(¤tX
, ¤tY
); 
1587     int currentW
,currentH
; 
1588     GetSize(¤tW
, ¤tH
); 
1590     // ... and don't do anything (avoiding flicker) if it's already ok 
1591     if ( x 
== currentX 
&& y 
== currentY 
&& 
1592          width 
== currentW 
&& height 
== currentH 
) 
1597     if ( x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1599     if ( y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1602     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
1604     wxSize 
size(-1, -1); 
1607         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
1609             size 
= DoGetBestSize(); 
1614             // just take the current one 
1621         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
1625                 size 
= DoGetBestSize(); 
1627             //else: already called DoGetBestSize() above 
1633             // just take the current one 
1638     DoMoveWindow(x
, y
, width
, height
); 
1641 void wxWindowMSW::DoSetClientSize(int width
, int height
) 
1643     // setting the client size is less obvious than it it could have been 
1644     // because in the result of changing the total size the window scrollbar 
1645     // may [dis]appear and/or its menubar may [un]wrap and so the client size 
1646     // will not be correct as the difference between the total and client size 
1647     // changes - so we keep changing it until we get it right 
1649     // normally this loop shouldn't take more than 3 iterations (usually 1 but 
1650     // if scrollbars [dis]appear as the result of the first call, then 2 and it 
1651     // may become 3 if the window had 0 size originally and so we didn't 
1652     // calculate the scrollbar correction correctly during the first iteration) 
1653     // but just to be on the safe side we check for it instead of making it an 
1654     // "infinite" loop (i.e. leaving break inside as the only way to get out) 
1655     for ( int i 
= 0; i 
< 4; i
++ ) 
1658         ::GetClientRect(GetHwnd(), &rectClient
); 
1660         // if the size is already ok, stop here (rectClient.left = top = 0) 
1661         if ( (rectClient
.right 
== width 
|| width 
== -1) && 
1662              (rectClient
.bottom 
== height 
|| height 
== -1) ) 
1667         int widthClient 
= width
, 
1668             heightClient 
= height
; 
1670         // Find the difference between the entire window (title bar and all) 
1671         // and the client area; add this to the new client size to move the 
1674         ::GetWindowRect(GetHwnd(), &rectWin
); 
1676         widthClient 
+= rectWin
.right 
- rectWin
.left 
- rectClient
.right
; 
1677         heightClient 
+= rectWin
.bottom 
- rectWin
.top 
- rectClient
.bottom
; 
1680         point
.x 
= rectWin
.left
; 
1681         point
.y 
= rectWin
.top
; 
1683         // MoveWindow positions the child windows relative to the parent, so 
1684         // adjust if necessary 
1685         if ( !IsTopLevel() ) 
1687             wxWindow 
*parent 
= GetParent(); 
1690                 ::ScreenToClient(GetHwndOf(parent
), &point
); 
1694         DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
); 
1698 // For implementation purposes - sometimes decorations make the client area 
1700 wxPoint 
wxWindowMSW::GetClientAreaOrigin() const 
1702     return wxPoint(0, 0); 
1705 // --------------------------------------------------------------------------- 
1707 // --------------------------------------------------------------------------- 
1709 int wxWindowMSW::GetCharHeight() const 
1711     return wxGetTextMetrics(this).tmHeight
; 
1714 int wxWindowMSW::GetCharWidth() const 
1716     // +1 is needed because Windows apparently adds it when calculating the 
1717     // dialog units size in pixels 
1718 #if wxDIALOG_UNIT_COMPATIBILITY 
1719     return wxGetTextMetrics(this).tmAveCharWidth
; 
1721     return wxGetTextMetrics(this).tmAveCharWidth 
+ 1; 
1725 void wxWindowMSW::GetTextExtent(const wxString
& string
, 
1727                              int *descent
, int *externalLeading
, 
1728                              const wxFont 
*theFont
) const 
1730     const wxFont 
*fontToUse 
= theFont
; 
1732         fontToUse 
= &m_font
; 
1734     HWND hWnd 
= GetHwnd(); 
1735     HDC dc 
= ::GetDC(hWnd
); 
1739     if ( fontToUse 
&& fontToUse
->Ok() ) 
1741         fnt 
= (HFONT
)((wxFont 
*)fontToUse
)->GetResourceHandle(); // const_cast 
1743             hfontOld 
= (HFONT
)SelectObject(dc
,fnt
); 
1748     GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
); 
1749     GetTextMetrics(dc
, &tm
); 
1751     if ( fontToUse 
&& fnt 
&& hfontOld 
) 
1752         SelectObject(dc
, hfontOld
); 
1754     ReleaseDC(hWnd
, dc
); 
1761         *descent 
= tm
.tmDescent
; 
1762     if ( externalLeading 
) 
1763         *externalLeading 
= tm
.tmExternalLeading
; 
1766 #if wxUSE_CARET && WXWIN_COMPATIBILITY 
1767 // --------------------------------------------------------------------------- 
1768 // Caret manipulation 
1769 // --------------------------------------------------------------------------- 
1771 void wxWindowMSW::CreateCaret(int w
, int h
) 
1773     SetCaret(new wxCaret(this, w
, h
)); 
1776 void wxWindowMSW::CreateCaret(const wxBitmap 
*WXUNUSED(bitmap
)) 
1778     wxFAIL_MSG("not implemented"); 
1781 void wxWindowMSW::ShowCaret(bool show
) 
1783     wxCHECK_RET( m_caret
, "no caret to show" ); 
1785     m_caret
->Show(show
); 
1788 void wxWindowMSW::DestroyCaret() 
1793 void wxWindowMSW::SetCaretPos(int x
, int y
) 
1795     wxCHECK_RET( m_caret
, "no caret to move" ); 
1797     m_caret
->Move(x
, y
); 
1800 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const 
1802     wxCHECK_RET( m_caret
, "no caret to get position of" ); 
1804     m_caret
->GetPosition(x
, y
); 
1806 #endif // wxUSE_CARET 
1808 // --------------------------------------------------------------------------- 
1810 // --------------------------------------------------------------------------- 
1812 #if wxUSE_MENUS_NATIVE 
1814 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue 
1815 // immediately, without waiting for the next event loop iteration 
1817 // NB: this function should probably be made public later as it can almost 
1818 //     surely replace wxYield() elsewhere as well 
1819 static void wxYieldForCommandsOnly() 
1821     // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't 
1822     // want to process it here) 
1824     while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) 
1825                 && msg
.message 
!= WM_QUIT 
) 
1827         wxTheApp
->DoMessage((WXMSG 
*)&msg
); 
1831 bool wxWindowMSW::DoPopupMenu(wxMenu 
*menu
, int x
, int y
) 
1833     menu
->SetInvokingWindow(this); 
1836     HWND hWnd 
= GetHwnd(); 
1837     HMENU hMenu 
= GetHmenuOf(menu
); 
1841     ::ClientToScreen(hWnd
, &point
); 
1842     wxCurrentPopupMenu 
= menu
; 
1843     ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
); 
1845     // we need to do it righ now as otherwise the events are never going to be 
1846     // sent to wxCurrentPopupMenu from HandleCommand() 
1848     // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't 
1849     // help and we'd still need wxYieldForCommandsOnly() as the menu may be 
1850     // destroyed as soon as we return (it can be a local variable in the caller 
1851     // for example) and so we do need to process the event immediately 
1852     wxYieldForCommandsOnly(); 
1854     wxCurrentPopupMenu 
= NULL
; 
1856     menu
->SetInvokingWindow(NULL
); 
1861 #endif // wxUSE_MENUS_NATIVE 
1863 // =========================================================================== 
1864 // pre/post message processing 
1865 // =========================================================================== 
1867 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
1870         return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
1872         return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
); 
1875 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
) 
1877     // wxUniversal implements tab traversal itself 
1878 #ifndef __WXUNIVERSAL__ 
1879     if ( m_hWnd 
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) ) 
1881         // intercept dialog navigation keys 
1882         MSG 
*msg 
= (MSG 
*)pMsg
; 
1884         // here we try to do all the job which ::IsDialogMessage() usually does 
1887         bool bProcess 
= TRUE
; 
1888         if ( msg
->message 
!= WM_KEYDOWN 
) 
1891         if ( bProcess 
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
1896             bool bCtrlDown 
= wxIsCtrlDown(); 
1897             bool bShiftDown 
= wxIsShiftDown(); 
1899             // WM_GETDLGCODE: ask the control if it wants the key for itself, 
1900             // don't process it if it's the case (except for Ctrl-Tab/Enter 
1901             // combinations which are always processed) 
1905                 lDlgCode 
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0); 
1908             bool bForward 
= TRUE
, 
1909                  bWindowChange 
= FALSE
; 
1911             switch ( msg
->wParam 
) 
1914                     // assume that nobody wants Shift-TAB for himself - if we 
1915                     // don't do it there is no easy way for a control to grab 
1916                     // TABs but still let Shift-TAB work as navugation key 
1917                     if ( (lDlgCode 
& DLGC_WANTTAB
) && !bShiftDown 
) { 
1921                         // Ctrl-Tab cycles thru notebook pages 
1922                         bWindowChange 
= bCtrlDown
; 
1923                         bForward 
= !bShiftDown
; 
1929                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1937                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1943                         if ( (lDlgCode 
& DLGC_WANTMESSAGE
) && !bCtrlDown 
) 
1945                             // control wants to process Enter itself, don't 
1946                             // call IsDialogMessage() which would interpret 
1950                         else if ( lDlgCode 
& DLGC_BUTTON 
) 
1952                             // let IsDialogMessage() handle this for all 
1953                             // buttons except the owner-drawn ones which it 
1954                             // just seems to ignore 
1955                             long style 
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
); 
1956                             if ( (style 
& BS_OWNERDRAW
) == BS_OWNERDRAW 
) 
1958                                 // emulate the button click 
1959                                 wxWindow 
*btn 
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
); 
1961                                     btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1966                         // FIXME: this should be handled by 
1967                         //        wxNavigationKeyEvent handler and not here!! 
1971                             wxButton 
*btn 
= wxDynamicCast(GetDefaultItem(), 
1973                             if ( btn 
&& btn
->IsEnabled() ) 
1975                                 // if we do have a default button, do press it 
1976                                 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1980                             else // no default button 
1981 #endif // wxUSE_BUTTON 
1983                                 // no special function for enter and don't even 
1984                                 // let IsDialogMessage() have it: it seems to 
1985                                 // do something really strange with it 
1998                 wxNavigationKeyEvent event
; 
1999                 event
.SetDirection(bForward
); 
2000                 event
.SetWindowChange(bWindowChange
); 
2001                 event
.SetEventObject(this); 
2003                 if ( GetEventHandler()->ProcessEvent(event
) ) 
2010         // let ::IsDialogMessage() do almost everything and handle just the 
2011         // things it doesn't here: Ctrl-TAB for switching notebook pages 
2012         if ( msg
->message 
== WM_KEYDOWN 
) 
2014             // don't process system keys here 
2015             if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) ) 
2017                 if ( (msg
->wParam 
== VK_TAB
) && wxIsCtrlDown() ) 
2019                     // find the first notebook parent and change its page 
2020                     wxWindow 
*win 
= this; 
2021                     wxNotebook 
*nbook 
= NULL
; 
2022                     while ( win 
&& !nbook 
) 
2024                         nbook 
= wxDynamicCast(win
, wxNotebook
); 
2025                         win 
= win
->GetParent(); 
2030                         bool forward 
= !wxIsShiftDown(); 
2032                         nbook
->AdvanceSelection(forward
); 
2039         if ( ::IsDialogMessage(GetHwnd(), msg
) ) 
2041             // IsDialogMessage() did something... 
2045 #endif // __WXUNIVERSAL__ 
2050         // relay mouse move events to the tooltip control 
2051         MSG 
*msg 
= (MSG 
*)pMsg
; 
2052         if ( msg
->message 
== WM_MOUSEMOVE 
) 
2053             m_tooltip
->RelayEvent(pMsg
); 
2055 #endif // wxUSE_TOOLTIPS 
2060 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
) 
2062 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__) 
2063     return m_acceleratorTable
.Translate(this, pMsg
); 
2067 #endif // wxUSE_ACCEL 
2070 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
)) 
2072     // preprocess all messages by default 
2076 // --------------------------------------------------------------------------- 
2077 // message params unpackers (different for Win16 and Win32) 
2078 // --------------------------------------------------------------------------- 
2082 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2083                              WORD 
*id
, WXHWND 
*hwnd
, WORD 
*cmd
) 
2085     *id 
= LOWORD(wParam
); 
2086     *hwnd 
= (WXHWND
)lParam
; 
2087     *cmd 
= HIWORD(wParam
); 
2090 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2091                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2093     *state 
= LOWORD(wParam
); 
2094     *minimized 
= HIWORD(wParam
); 
2095     *hwnd 
= (WXHWND
)lParam
; 
2098 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2099                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2101     *code 
= LOWORD(wParam
); 
2102     *pos 
= HIWORD(wParam
); 
2103     *hwnd 
= (WXHWND
)lParam
; 
2106 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2107                               WXWORD 
*nCtlColor
, WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2109 #ifndef __WXMICROWIN__ 
2110     *nCtlColor 
= CTLCOLOR_BTN
; 
2111     *hwnd 
= (WXHWND
)lParam
; 
2112     *hdc 
= (WXHDC
)wParam
; 
2116 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2117                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2119     *item 
= (WXWORD
)wParam
; 
2120     *flags 
= HIWORD(wParam
); 
2121     *hmenu 
= (WXHMENU
)lParam
; 
2126 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2127                              WXWORD 
*id
, WXHWND 
*hwnd
, WXWORD 
*cmd
) 
2129     *id 
= (WXWORD
)wParam
; 
2130     *hwnd 
= (WXHWND
)LOWORD(lParam
); 
2131     *cmd 
= HIWORD(lParam
); 
2134 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2135                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2137     *state 
= (WXWORD
)wParam
; 
2138     *minimized 
= LOWORD(lParam
); 
2139     *hwnd 
= (WXHWND
)HIWORD(lParam
); 
2142 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2143                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2145     *code 
= (WXWORD
)wParam
; 
2146     *pos 
= LOWORD(lParam
); 
2147     *hwnd 
= (WXHWND
)HIWORD(lParam
); 
2150 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2151                               WXWORD 
*nCtlColor
, WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2153     *hwnd 
= (WXHWND
)LOWORD(lParam
); 
2154     *nCtlColor 
= (int)HIWORD(lParam
); 
2155     *hdc 
= (WXHDC
)wParam
; 
2158 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2159                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2161     *item 
= (WXWORD
)wParam
; 
2162     *flags 
= LOWORD(lParam
); 
2163     *hmenu 
= (WXHMENU
)HIWORD(lParam
); 
2168 // --------------------------------------------------------------------------- 
2169 // Main wxWindows window proc and the window proc for wxWindow 
2170 // --------------------------------------------------------------------------- 
2172 // Hook for new window just as it's being created, when the window isn't yet 
2173 // associated with the handle 
2174 static wxWindowMSW 
*gs_winBeingCreated 
= NULL
; 
2176 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the 
2177 // window being created and insures that it's always unset back later 
2178 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW 
*winBeingCreated
) 
2180     gs_winBeingCreated 
= winBeingCreated
; 
2183 wxWindowCreationHook::~wxWindowCreationHook() 
2185     gs_winBeingCreated 
= NULL
; 
2189 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) 
2191     // trace all messages - useful for the debugging 
2193     wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"), 
2194                wxGetMessageName(message
), wParam
, lParam
); 
2195 #endif // __WXDEBUG__ 
2197     wxWindowMSW 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2199     // when we get the first message for the HWND we just created, we associate 
2200     // it with wxWindow stored in gs_winBeingCreated 
2201     if ( !wnd 
&& gs_winBeingCreated 
) 
2203         wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
); 
2204         wnd 
= gs_winBeingCreated
; 
2205         gs_winBeingCreated 
= NULL
; 
2206         wnd
->SetHWND((WXHWND
)hWnd
); 
2212         rc 
= wnd
->MSWWindowProc(message
, wParam
, lParam
); 
2214         rc 
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
); 
2219 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
2221     // did we process the message? 
2222     bool processed 
= FALSE
; 
2233     // for most messages we should return 0 when we do process the message 
2241                 processed 
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
); 
2244                     // return 0 to allow window creation 
2245                     rc
.result 
= mayCreate 
? 0 : -1; 
2251             // never set processed to TRUE and *always* pass WM_DESTROY to 
2252             // DefWindowProc() as Windows may do some internal cleanup when 
2253             // processing it and failing to pass the message along may cause 
2254             // memory and resource leaks! 
2255             (void)HandleDestroy(); 
2259             processed 
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2267                     // we're not interested in these messages at all 
2270                 case SIZE_MINIMIZED
: 
2271                     // we shouldn't send sizev events for these messages as the 
2272                     // client size may be negative which breaks existing code 
2274                     // OTOH we might send another (wxMinimizedEvent?) one or 
2275                     // add an additional parameter to wxSizeEvent if this is 
2276                     // useful to anybody 
2280                     wxFAIL_MSG( _T("unexpected WM_SIZE parameter") ); 
2281                     // fall through nevertheless 
2283                 case SIZE_MAXIMIZED
: 
2285                     processed 
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), 
2290 #ifndef __WXMICROWIN__ 
2291         case WM_ACTIVATEAPP
: 
2292             wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
2298                 WXWORD state
, minimized
; 
2300                 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
); 
2302                 processed 
= HandleActivate(state
, minimized 
!= 0, (WXHWND
)hwnd
); 
2307             processed 
= HandleSetFocus((WXHWND
)(HWND
)wParam
); 
2311             processed 
= HandleKillFocus((WXHWND
)(HWND
)wParam
); 
2315             processed 
= HandlePaint(); 
2319             // don't let the DefWindowProc() destroy our window - we'll do it 
2320             // ourselves in ~wxWindow 
2326             processed 
= HandleShow(wParam 
!= 0, (int)lParam
); 
2330             processed 
= HandleMouseMove(GET_X_LPARAM(lParam
), 
2331                                         GET_Y_LPARAM(lParam
), 
2335 #if wxUSE_MOUSEWHEEL 
2337             processed 
= HandleMouseWheel(wParam
, lParam
); 
2341         case WM_LBUTTONDOWN
: 
2343         case WM_LBUTTONDBLCLK
: 
2344         case WM_RBUTTONDOWN
: 
2346         case WM_RBUTTONDBLCLK
: 
2347         case WM_MBUTTONDOWN
: 
2349         case WM_MBUTTONDBLCLK
: 
2352 #ifdef __WXMICROWIN__ 
2353                 // MicroWindows seems to ignore the fact that a window is 
2354                 // disabled. So catch mouse events and throw them away if 
2356                 wxWindowMSW
* win 
= this; 
2359                     if (!win
->IsEnabled()) 
2364                     win 
= win
->GetParent(); 
2365                     if (win 
&& win
->IsTopLevel()) 
2368 #endif // __WXMICROWIN__ 
2371                     if (message 
== WM_LBUTTONDOWN 
&& AcceptsFocus()) 
2373                      processed 
= HandleMouseEvent(message
, 
2374                                          GET_X_LPARAM(lParam
), 
2375                                          GET_Y_LPARAM(lParam
), 
2381 #ifdef __WXMICROWIN__ 
2382         case WM_NCLBUTTONDOWN
: 
2383         case WM_NCLBUTTONUP
: 
2384         case WM_NCLBUTTONDBLCLK
: 
2385         case WM_NCRBUTTONDOWN
: 
2386         case WM_NCRBUTTONUP
: 
2387         case WM_NCRBUTTONDBLCLK
: 
2389         case WM_NCMBUTTONDOWN
: 
2390         case WM_NCMBUTTONUP
: 
2391         case WM_NCMBUTTONDBLCLK
: 
2394                 // MicroWindows seems to ignore the fact that a window 
2395                 // is disabled. So catch mouse events and throw them away if necessary. 
2397                 wxWindowMSW
* win 
= this; 
2400                     if (!win
->IsEnabled()) 
2405                     win 
= win
->GetParent(); 
2406                     if (win 
&& win
->IsTopLevel()) 
2411 #endif // __WXMICROWIN__ 
2418         case MM_JOY1BUTTONDOWN
: 
2419         case MM_JOY2BUTTONDOWN
: 
2420         case MM_JOY1BUTTONUP
: 
2421         case MM_JOY2BUTTONUP
: 
2422             processed 
= HandleJoystickEvent(message
, 
2423                                             GET_X_LPARAM(lParam
), 
2424                                             GET_Y_LPARAM(lParam
), 
2427 #endif // __WXMICROWIN__ 
2430             processed 
= HandleSysCommand(wParam
, lParam
); 
2437                 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
); 
2439                 processed 
= HandleCommand(id
, cmd
, hwnd
); 
2445             processed 
= HandleNotify((int)wParam
, lParam
, &rc
.result
); 
2449             // for these messages we must return TRUE if process the message 
2452         case WM_MEASUREITEM
: 
2454                 int idCtrl 
= (UINT
)wParam
; 
2455                 if ( message 
== WM_DRAWITEM 
) 
2457                     processed 
= MSWOnDrawItem(idCtrl
, 
2458                                               (WXDRAWITEMSTRUCT 
*)lParam
); 
2462                     processed 
= MSWOnMeasureItem(idCtrl
, 
2463                                                  (WXMEASUREITEMSTRUCT 
*)lParam
); 
2470 #endif // defined(WM_DRAWITEM) 
2473             if ( GetWindowStyleFlag() & wxWANTS_CHARS 
) 
2475                 // want everything: i.e. all keys and WM_CHAR message 
2476                 rc
.result 
= DLGC_WANTARROWS 
| DLGC_WANTCHARS 
| 
2477                             DLGC_WANTTAB 
| DLGC_WANTMESSAGE
; 
2480             //else: get the dlg code from the DefWindowProc() 
2485             // If this has been processed by an event handler, return 0 now 
2486             // (we've handled it). 
2487             m_lastKeydownProcessed 
= HandleKeyDown((WORD
) wParam
, lParam
); 
2488             if ( m_lastKeydownProcessed 
) 
2496                 // we consider these message "not interesting" to OnChar, so 
2497                 // just don't do anything more with them 
2507                 // avoid duplicate messages to OnChar for these ASCII keys: 
2508                 // they will be translated by TranslateMessage() and received 
2530                     // but set processed to FALSE, not TRUE to still pass them 
2531                     // to the control's default window proc - otherwise 
2532                     // built-in keyboard handling won't work 
2538                 // special case of VK_APPS: treat it the same as right mouse 
2539                 // click because both usually pop up a context menu 
2545                         TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2546                         processed 
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
); 
2552                     if ( m_lastKeydownProcessed 
) 
2554                         // The key was handled in the EVT_KEY_DOWN and handling 
2555                         // a key in an EVT_KEY_DOWN handler is meant, by 
2556                         // design, to prevent EVT_CHARs from happening 
2557                         m_lastKeydownProcessed 
= FALSE
; 
2560                     else // do generate a CHAR event 
2562                         processed 
= HandleChar((WORD
)wParam
, lParam
); 
2571             // special case of VK_APPS: treat it the same as right mouse button 
2572             if ( wParam 
== VK_APPS 
) 
2577                 TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2578                 processed 
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
); 
2583                 processed 
= HandleKeyUp((WORD
) wParam
, lParam
); 
2588         case WM_CHAR
: // Always an ASCII character 
2589             processed 
= HandleChar((WORD
)wParam
, lParam
, TRUE
); 
2597                 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
); 
2599                 processed 
= MSWOnScroll(message 
== WM_HSCROLL 
? wxHORIZONTAL
 
2605         // CTLCOLOR messages are sent by children to query the parent for their 
2606         // colors#ifndef __WXMICROWIN__ 
2607 #ifndef __WXMICROWIN__ 
2609         case WM_CTLCOLORMSGBOX
: 
2610         case WM_CTLCOLOREDIT
: 
2611         case WM_CTLCOLORLISTBOX
: 
2612         case WM_CTLCOLORBTN
: 
2613         case WM_CTLCOLORDLG
: 
2614         case WM_CTLCOLORSCROLLBAR
: 
2615         case WM_CTLCOLORSTATIC
: 
2623                 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
); 
2625                 processed 
= HandleCtlColor(&rc
.hBrush
, 
2634 #endif // !__WXMICROWIN__ 
2636         case WM_SYSCOLORCHANGE
: 
2637             // the return value for this message is ignored 
2638             processed 
= HandleSysColorChange(); 
2641         case WM_DISPLAYCHANGE
: 
2642             processed 
= HandleDisplayChange(); 
2645         case WM_PALETTECHANGED
: 
2646             processed 
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
); 
2649         case WM_QUERYNEWPALETTE
: 
2650             processed 
= HandleQueryNewPalette(); 
2654             processed 
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
2657                 // we processed the message, i.e. erased the background 
2663             processed 
= HandleDropFiles(wParam
); 
2667             processed 
= HandleInitDialog((WXHWND
)(HWND
)wParam
); 
2671                 // we never set focus from here 
2676         case WM_QUERYENDSESSION
: 
2677             processed 
= HandleQueryEndSession(lParam
, &rc
.allow
); 
2681             processed 
= HandleEndSession(wParam 
!= 0, lParam
); 
2684         case WM_GETMINMAXINFO
: 
2685             processed 
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
); 
2689             processed 
= HandleSetCursor((WXHWND
)(HWND
)wParam
, 
2690                                         LOWORD(lParam
),     // hit test 
2691                                         HIWORD(lParam
));    // mouse msg 
2695                 // returning TRUE stops the DefWindowProc() from further 
2696                 // processing this message - exactly what we need because we've 
2697                 // just set the cursor. 
2702 #if defined(__WIN32__) && defined(WM_HELP) 
2705                 HELPINFO
* info 
= (HELPINFO
*) lParam
; 
2706                 // Don't yet process menu help events, just windows 
2707                 if (info
->iContextType 
== HELPINFO_WINDOW
) 
2709                     wxWindowMSW
* subjectOfHelp 
= this; 
2710                     bool eventProcessed 
= FALSE
; 
2711                     while (subjectOfHelp 
&& !eventProcessed
) 
2713                         wxHelpEvent 
helpEvent(wxEVT_HELP
, 
2714                                               subjectOfHelp
->GetId(), 
2715                                               wxPoint(info
->MousePos
.x
, 
2716                                               info
->MousePos
.y
) ); 
2717                         helpEvent
.SetEventObject(this); 
2719                             GetEventHandler()->ProcessEvent(helpEvent
); 
2721                         // Go up the window hierarchy until the event is 
2723                         subjectOfHelp 
= subjectOfHelp
->GetParent(); 
2726                     processed 
= eventProcessed
; 
2728                 else if (info
->iContextType 
== HELPINFO_MENUITEM
) 
2730                     wxHelpEvent 
helpEvent(wxEVT_HELP
, info
->iCtrlId
); 
2731                     helpEvent
.SetEventObject(this); 
2732                     processed 
= GetEventHandler()->ProcessEvent(helpEvent
); 
2735                 //else: processed is already FALSE 
2739         case WM_CONTEXTMENU
: 
2741                 // we don't convert from screen to client coordinates as 
2742                 // the event may be handled by a parent window 
2743                 wxPoint 
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2745                 wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
2746                 processed 
= GetEventHandler()->ProcessEvent(evtCtx
); 
2755         wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."), 
2756                    wxGetMessageName(message
)); 
2757 #endif // __WXDEBUG__ 
2758         rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
2764 // ---------------------------------------------------------------------------- 
2765 // wxWindow <-> HWND map 
2766 // ---------------------------------------------------------------------------- 
2768 wxWinHashTable 
*wxWinHandleHash 
= NULL
; 
2770 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
) 
2772     return wxWinHandleHash
->Get((long)hWnd
); 
2775 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
) 
2777     // adding NULL hWnd is (first) surely a result of an error and 
2778     // (secondly) breaks menu command processing 
2779     wxCHECK_RET( hWnd 
!= (HWND
)NULL
, 
2780                  wxT("attempt to add a NULL hWnd to window list ignored") ); 
2782     wxWindow 
*oldWin 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2784     if ( oldWin 
&& (oldWin 
!= win
) ) 
2786         wxLogDebug(wxT("HWND %X already associated with another window (%s)"), 
2787                    hWnd
, win
->GetClassInfo()->GetClassName()); 
2790 #endif // __WXDEBUG__ 
2793         wxWinHandleHash
->Put((long)hWnd
, (wxWindow 
*)win
); 
2797 void wxRemoveHandleAssociation(wxWindowMSW 
*win
) 
2799     wxWinHandleHash
->Delete((long)win
->GetHWND()); 
2802 // ---------------------------------------------------------------------------- 
2803 // various MSW speciic class dependent functions 
2804 // ---------------------------------------------------------------------------- 
2806 // Default destroyer - override if you destroy it in some other way 
2807 // (e.g. with MDI child windows) 
2808 void wxWindowMSW::MSWDestroyWindow() 
2812 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
, 
2815                                            int& w
, int& h
) const 
2817     bool nonDefault 
= FALSE
; 
2821         // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can 
2822         // just as well set it to CW_USEDEFAULT as well 
2829         y 
= pos
.y 
== -1 ? CW_USEDEFAULT 
: pos
.y
; 
2835       NB: there used to be some code here which set the initial size of the 
2836           window to the client size of the parent if no explicit size was 
2837           specified. This was wrong because wxWindows programs often assume 
2838           that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke 
2839           it. To see why, you should understand that Windows sends WM_SIZE from 
2840           inside ::CreateWindow() anyhow. However, ::CreateWindow() is called 
2841           from some base class ctor and so this WM_SIZE is not processed in the 
2842           real class' OnSize() (because it's not fully constructed yet and the 
2843           event goes to some base class OnSize() instead). So the WM_SIZE we 
2844           rely on is the one sent when the parent frame resizes its children 
2845           but here is the problem: if the child already has just the right 
2846           size, nothing will happen as both wxWindows and Windows check for 
2847           this and ignore any attempts to change the window size to the size it 
2848           already has - so no WM_SIZE would be sent. 
2852         // as abobe, h is not used at all in this case anyhow 
2859         h 
= size
.y 
== -1 ? CW_USEDEFAULT 
: size
.y
; 
2867 bool wxWindowMSW::MSWCreate(const wxChar 
*wclass
, 
2868                             const wxChar 
*title
, 
2872                             WXDWORD extendedStyle
) 
2874     // choose the position/size for the new window 
2876     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
2878     // find the correct parent HWND 
2879     wxWindow 
*parent 
= GetParent(); 
2880     bool isChild 
= (style 
& WS_CHILD
) != 0; 
2882     if ( GetWindowStyleFlag() & wxPOPUP_WINDOW 
) 
2884         // popup windows should have desktop as parent because they shouldn't 
2885         // be limited to the parents client area as child windows usually are 
2886         hParent 
= ::GetDesktopWindow(); 
2890         if ( (isChild 
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent 
) 
2892             // this is either a normal child window or a top level window with 
2893             // wxFRAME_TOOL_WINDOW style (see below) 
2894             hParent 
= GetHwndOf(parent
); 
2898             // this is either a window for which no parent was specified (not 
2899             // much we can do then) or a frame without wxFRAME_TOOL_WINDOW 
2900             // style: we should use NULL parent HWND for it or it would be 
2901             // always on top of its parent which is not what we usually want 
2902             // (in fact, we only want it for frames with the special 
2903             // wxFRAME_TOOL_WINDOW as above) 
2909     // controlId is menu handle for the top level windows, so set it to 0 
2910     // unless we're creating a child window 
2914         controlId 
= GetId(); 
2916         if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS 
) 
2918             style 
|= WS_CLIPSIBLINGS
; 
2926     // for each class "Foo" we have we also have "FooNR" ("no repaint") class 
2927     // which is the same but without CS_[HV]REDRAW class styles so using it 
2928     // ensures that the window is not fully repainted on each resize 
2929     wxString 
className(wclass
); 
2930     if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE 
) 
2932         className 
+= wxT("NR"); 
2935     // do create the window 
2936     wxWindowCreationHook 
hook(this); 
2938     m_hWnd 
= (WXHWND
)::CreateWindowEx
 
2942                 title 
? title 
: wxT(""), 
2948                 NULL                        
// no extra data 
2953         wxLogSysError(_("Can't create window of class %s"), wclass
); 
2958     SubclassWin(m_hWnd
); 
2960     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
2965 // =========================================================================== 
2966 // MSW message handlers 
2967 // =========================================================================== 
2969 // --------------------------------------------------------------------------- 
2971 // --------------------------------------------------------------------------- 
2974 // FIXME: VZ: I'm not sure at all that the order of processing is correct 
2975 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
2977 #ifndef __WXMICROWIN__ 
2978     LPNMHDR hdr 
= (LPNMHDR
)lParam
; 
2979     HWND hWnd 
= hdr
->hwndFrom
; 
2980     wxWindow 
*win 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
2982     // is this one of our windows? 
2985         return win
->MSWOnNotify(idCtrl
, lParam
, result
); 
2988     // try all our children 
2989     wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
2992         wxWindow 
*child 
= node
->GetData(); 
2993         if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) ) 
2998         node 
= node
->GetNext(); 
3001     // finally try this window too (catches toolbar case) 
3002     return MSWOnNotify(idCtrl
, lParam
, result
); 
3003 #else // __WXMICROWIN__ 
3008 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
), 
3010                            WXLPARAM
* WXUNUSED(result
)) 
3013     NMHDR
* hdr 
= (NMHDR 
*)lParam
; 
3014     if ( (int)hdr
->code 
== TTN_NEEDTEXT 
&& m_tooltip 
) 
3016         TOOLTIPTEXT 
*ttt 
= (TOOLTIPTEXT 
*)lParam
; 
3017         ttt
->lpszText 
= (wxChar 
*)m_tooltip
->GetTip().c_str(); 
3022 #endif // wxUSE_TOOLTIPS 
3028 // --------------------------------------------------------------------------- 
3029 // end session messages 
3030 // --------------------------------------------------------------------------- 
3032 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
) 
3034     wxCloseEvent 
event(wxEVT_QUERY_END_SESSION
, -1); 
3035     event
.SetEventObject(wxTheApp
); 
3036     event
.SetCanVeto(TRUE
); 
3037     event
.SetLoggingOff(logOff 
== (long)ENDSESSION_LOGOFF
); 
3039     bool rc 
= wxTheApp
->ProcessEvent(event
); 
3043         // we may end only if the app didn't veto session closing (double 
3045         *mayEnd 
= !event
.GetVeto(); 
3051 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
) 
3053     // do nothing if the session isn't ending 
3058     if ( (this != wxTheApp
->GetTopWindow()) ) 
3061     wxCloseEvent 
event(wxEVT_END_SESSION
, -1); 
3062     event
.SetEventObject(wxTheApp
); 
3063     event
.SetCanVeto(FALSE
); 
3064     event
.SetLoggingOff( (logOff 
== (long)ENDSESSION_LOGOFF
) ); 
3066     return wxTheApp
->ProcessEvent(event
); 
3069 // --------------------------------------------------------------------------- 
3070 // window creation/destruction 
3071 // --------------------------------------------------------------------------- 
3073 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT 
WXUNUSED(cs
), bool *mayCreate
) 
3075     // TODO: should generate this event from WM_NCCREATE 
3076     wxWindowCreateEvent 
event((wxWindow 
*)this); 
3077     (void)GetEventHandler()->ProcessEvent(event
); 
3084 bool wxWindowMSW::HandleDestroy() 
3086     wxWindowDestroyEvent 
event((wxWindow 
*)this); 
3087     (void)GetEventHandler()->ProcessEvent(event
); 
3089     // delete our drop target if we've got one 
3090 #if wxUSE_DRAG_AND_DROP 
3091     if ( m_dropTarget 
!= NULL 
) 
3093         m_dropTarget
->Revoke(m_hWnd
); 
3095         delete m_dropTarget
; 
3096         m_dropTarget 
= NULL
; 
3098 #endif // wxUSE_DRAG_AND_DROP 
3100     // WM_DESTROY handled 
3104 // --------------------------------------------------------------------------- 
3106 // --------------------------------------------------------------------------- 
3108 bool wxWindowMSW::HandleActivate(int state
, 
3109                               bool WXUNUSED(minimized
), 
3110                               WXHWND 
WXUNUSED(activate
)) 
3112     wxActivateEvent 
event(wxEVT_ACTIVATE
, 
3113                           (state 
== WA_ACTIVE
) || (state 
== WA_CLICKACTIVE
), 
3115     event
.SetEventObject(this); 
3117     return GetEventHandler()->ProcessEvent(event
); 
3120 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
) 
3122     // notify the parent keeping track of focus for the kbd navigation 
3123     // purposes that we got it 
3124     wxChildFocusEvent 
eventFocus((wxWindow 
*)this); 
3125     (void)GetEventHandler()->ProcessEvent(eventFocus
); 
3131         m_caret
->OnSetFocus(); 
3133 #endif // wxUSE_CARET 
3136     // If it's a wxTextCtrl don't send the event as it will be done 
3137     // after the control gets to process it from EN_FOCUS handler 
3138     if ( wxDynamicCastThis(wxTextCtrl
) ) 
3142 #endif // wxUSE_TEXTCTRL 
3144     wxFocusEvent 
event(wxEVT_SET_FOCUS
, m_windowId
); 
3145     event
.SetEventObject(this); 
3147     // wxFindWinFromHandle() may return NULL, it is ok 
3148     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3150     return GetEventHandler()->ProcessEvent(event
); 
3153 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
) 
3159         m_caret
->OnKillFocus(); 
3161 #endif // wxUSE_CARET 
3164     // If it's a wxTextCtrl don't send the event as it will be done 
3165     // after the control gets to process it. 
3166     wxTextCtrl 
*ctrl 
= wxDynamicCastThis(wxTextCtrl
); 
3173     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, m_windowId
); 
3174     event
.SetEventObject(this); 
3176     // wxFindWinFromHandle() may return NULL, it is ok 
3177     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3179     return GetEventHandler()->ProcessEvent(event
); 
3182 // --------------------------------------------------------------------------- 
3184 // --------------------------------------------------------------------------- 
3186 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
)) 
3188     wxShowEvent 
event(GetId(), show
); 
3189     event
.m_eventObject 
= this; 
3191     return GetEventHandler()->ProcessEvent(event
); 
3194 bool wxWindowMSW::HandleInitDialog(WXHWND 
WXUNUSED(hWndFocus
)) 
3196     wxInitDialogEvent 
event(GetId()); 
3197     event
.m_eventObject 
= this; 
3199     return GetEventHandler()->ProcessEvent(event
); 
3202 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
) 
3204 #ifndef __WXMICROWIN__ 
3205     HDROP hFilesInfo 
= (HDROP
) wParam
; 
3207     // Get the total number of files dropped 
3208     UINT gwFilesDropped 
= ::DragQueryFile
 
3216     wxString 
*files 
= new wxString
[gwFilesDropped
]; 
3217     for ( UINT wIndex 
= 0; wIndex 
< gwFilesDropped
; wIndex
++ ) 
3219         // first get the needed buffer length (+1 for terminating NUL) 
3220         size_t len 
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1; 
3222         // and now get the file name 
3223         ::DragQueryFile(hFilesInfo
, wIndex
, 
3224                         files
[wIndex
].GetWriteBuf(len
), len
); 
3226         files
[wIndex
].UngetWriteBuf(); 
3228     DragFinish (hFilesInfo
); 
3230     wxDropFilesEvent 
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
); 
3231     event
.m_eventObject 
= this; 
3234     DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
); 
3235     event
.m_pos
.x 
= dropPoint
.x
; 
3236     event
.m_pos
.y 
= dropPoint
.y
; 
3238     return GetEventHandler()->ProcessEvent(event
); 
3239 #else // __WXMICROWIN__ 
3244 bool wxWindowMSW::HandleSetCursor(WXHWND 
WXUNUSED(hWnd
), 
3246                                   int WXUNUSED(mouseMsg
)) 
3248 #ifndef __WXMICROWIN__ 
3249     // the logic is as follows: 
3250     // -1. don't set cursor for non client area, including but not limited to 
3251     //     the title bar, scrollbars, &c 
3252     //  0. allow the user to override default behaviour by using EVT_SET_CURSOR 
3253     //  1. if we have the cursor set it unless wxIsBusy() 
3254     //  2. if we're a top level window, set some cursor anyhow 
3255     //  3. if wxIsBusy(), set the busy cursor, otherwise the global one 
3257     if ( nHitTest 
!= HTCLIENT 
) 
3262     HCURSOR hcursor 
= 0; 
3264     // first ask the user code - it may wish to set the cursor in some very 
3265     // specific way (for example, depending on the current position) 
3268     if ( !::GetCursorPos(&pt
) ) 
3270         wxLogLastError(wxT("GetCursorPos")); 
3273     // In WIN16 it doesn't return a value. 
3274     ::GetCursorPos(&pt
); 
3279     ScreenToClient(&x
, &y
); 
3280     wxSetCursorEvent 
event(x
, y
); 
3282     bool processedEvtSetCursor 
= GetEventHandler()->ProcessEvent(event
); 
3283     if ( processedEvtSetCursor 
&& event
.HasCursor() ) 
3285         hcursor 
= GetHcursorOf(event
.GetCursor()); 
3290         bool isBusy 
= wxIsBusy(); 
3292         // the test for processedEvtSetCursor is here to prevent using m_cursor 
3293         // if the user code caught EVT_SET_CURSOR() and returned nothing from 
3294         // it - this is a way to say that our cursor shouldn't be used for this 
3296         if ( !processedEvtSetCursor 
&& m_cursor
.Ok() ) 
3298             hcursor 
= GetHcursorOf(m_cursor
); 
3305                 hcursor 
= wxGetCurrentBusyCursor(); 
3307             else if ( !hcursor 
) 
3309                 const wxCursor 
*cursor 
= wxGetGlobalCursor(); 
3310                 if ( cursor 
&& cursor
->Ok() ) 
3312                     hcursor 
= GetHcursorOf(*cursor
); 
3320         ::SetCursor(hcursor
); 
3322         // cursor set, stop here 
3325 #endif // __WXMICROWIN__ 
3327     // pass up the window chain 
3331 // --------------------------------------------------------------------------- 
3332 // owner drawn stuff 
3333 // --------------------------------------------------------------------------- 
3335 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT 
*itemStruct
) 
3337 #if wxUSE_OWNER_DRAWN 
3339 #if wxUSE_MENUS_NATIVE 
3340     // is it a menu item? 
3341     DRAWITEMSTRUCT 
*pDrawStruct 
= (DRAWITEMSTRUCT 
*)itemStruct
; 
3342     if ( id 
== 0 && pDrawStruct
->CtlType 
== ODT_MENU 
) 
3344         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pDrawStruct
->itemData
); 
3346         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE 
); 
3348         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent 
3349         // the DC from being released 
3350         wxDCTemp 
dc((WXHDC
)pDrawStruct
->hDC
); 
3351         wxRect 
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
, 
3352                     pDrawStruct
->rcItem
.right 
- pDrawStruct
->rcItem
.left
, 
3353                     pDrawStruct
->rcItem
.bottom 
- pDrawStruct
->rcItem
.top
); 
3355         return pMenuItem
->OnDrawItem
 
3359                 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
, 
3360                 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
 
3363 #endif // wxUSE_MENUS_NATIVE 
3366     wxWindow 
*item 
= FindItem(id
); 
3367     if ( item 
&& item
->IsKindOf(CLASSINFO(wxControl
)) ) 
3369         return ((wxControl 
*)item
)->MSWOnDraw(itemStruct
); 
3371 #endif // wxUSE_CONTROLS 
3373 #endif // USE_OWNER_DRAWN 
3378 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT 
*itemStruct
) 
3380 #if wxUSE_OWNER_DRAWN 
3381     // is it a menu item? 
3382     MEASUREITEMSTRUCT 
*pMeasureStruct 
= (MEASUREITEMSTRUCT 
*)itemStruct
; 
3383     if ( id 
== 0 && pMeasureStruct
->CtlType 
== ODT_MENU 
) 
3385         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pMeasureStruct
->itemData
); 
3387         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE 
); 
3389         return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
, 
3390                                         &pMeasureStruct
->itemHeight
); 
3393     wxWindow 
*item 
= FindItem(id
); 
3394     if ( item 
&& item
->IsKindOf(CLASSINFO(wxControl
)) ) 
3396         return ((wxControl 
*)item
)->MSWOnMeasure(itemStruct
); 
3398 #endif  // owner-drawn menus 
3402 // --------------------------------------------------------------------------- 
3403 // colours and palettes 
3404 // --------------------------------------------------------------------------- 
3406 bool wxWindowMSW::HandleSysColorChange() 
3408     wxSysColourChangedEvent event
; 
3409     event
.SetEventObject(this); 
3411     (void)GetEventHandler()->ProcessEvent(event
); 
3413     // always let the system carry on the default processing to allow the 
3414     // native controls to react to the colours update 
3418 bool wxWindowMSW::HandleDisplayChange() 
3420     wxDisplayChangedEvent event
; 
3421     event
.SetEventObject(this); 
3423     return GetEventHandler()->ProcessEvent(event
); 
3426 bool wxWindowMSW::HandleCtlColor(WXHBRUSH 
*brush
, 
3434 #ifndef __WXMICROWIN__ 
3435     WXHBRUSH hBrush 
= 0; 
3437     if ( nCtlColor 
== CTLCOLOR_DLG 
) 
3439         hBrush 
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3444         wxControl 
*item 
= (wxControl 
*)FindItemByHWND(pWnd
, TRUE
); 
3446             hBrush 
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3448 #endif // wxUSE_CONTROLS 
3454 #else // __WXMICROWIN__ 
3459 // Define for each class of dialog and control 
3460 WXHBRUSH 
wxWindowMSW::OnCtlColor(WXHDC 
WXUNUSED(hDC
), 
3461                                  WXHWND 
WXUNUSED(hWnd
), 
3462                                  WXUINT 
WXUNUSED(nCtlColor
), 
3463                                  WXUINT 
WXUNUSED(message
), 
3464                                  WXWPARAM 
WXUNUSED(wParam
), 
3465                                  WXLPARAM 
WXUNUSED(lParam
)) 
3470 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
) 
3473     // same as below except we don't respond to our own messages 
3474     if ( hWndPalChange 
!= GetHWND() ) 
3476         // check to see if we our our parents have a custom palette 
3477         wxWindow 
*win 
= this; 
3478         while ( win 
&& !win
->HasCustomPalette() ) 
3480             win 
= win
->GetParent(); 
3483         if ( win 
&& win
->HasCustomPalette() ) 
3485             // realize the palette to see whether redrawing is needed 
3486             HDC hdc 
= ::GetDC((HWND
) hWndPalChange
); 
3487             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3488                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3490             int result 
= ::RealizePalette(hdc
); 
3492             // restore the palette (before releasing the DC) 
3493             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3494                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3495             ::RealizePalette(hdc
); 
3496             ::ReleaseDC((HWND
) hWndPalChange
, hdc
); 
3498             // now check for the need to redraw 
3500                 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
); 
3504 #endif // wxUSE_PALETTE 
3506     wxPaletteChangedEvent 
event(GetId()); 
3507     event
.SetEventObject(this); 
3508     event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
)); 
3510     return GetEventHandler()->ProcessEvent(event
); 
3513 bool wxWindowMSW::HandleQueryNewPalette() 
3517     // check to see if we our our parents have a custom palette 
3518     wxWindow 
*win 
= this; 
3519     while (!win
->HasCustomPalette() && win
->GetParent()) win 
= win
->GetParent(); 
3520     if (win
->HasCustomPalette()) { 
3521         /* realize the palette to see whether redrawing is needed */ 
3522         HDC hdc 
= GetDC((HWND
) GetHWND()); 
3523         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3524              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) ); 
3526         int result 
= ::RealizePalette(hdc
); 
3527         /* restore the palette (before releasing the DC) */ 
3528         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3529              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) ); 
3530         ::RealizePalette(hdc
); 
3531         ::ReleaseDC((HWND
) GetHWND(), hdc
); 
3532         /* now check for the need to redraw */ 
3534             ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
); 
3536 #endif // wxUSE_PALETTE 
3538     wxQueryNewPaletteEvent 
event(GetId()); 
3539     event
.SetEventObject(this); 
3541     return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized(); 
3544 // Responds to colour changes: passes event on to children. 
3545 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
3547     // the top level window also reset the standard colour map as it might have 
3548     // changed (there is no need to do it for the non top level windows as we 
3549     // only have to do it once) 
3553         gs_hasStdCmap 
= FALSE
; 
3555     wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
3558         // Only propagate to non-top-level windows because Windows already 
3559         // sends this event to all top-level ones 
3560         wxWindow 
*win 
= node
->GetData(); 
3561         if ( !win
->IsTopLevel() ) 
3563             // we need to send the real WM_SYSCOLORCHANGE and not just trigger 
3564             // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for 
3565             // the standard controls 
3566             ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0); 
3569         node 
= node
->GetNext(); 
3572     // update the colours we use if they were not set explicitly by the user: 
3573     // this must be done or OnCtlColor() would continue to use the old colours 
3576         m_foregroundColour 
= wxSystemSettings:: 
3577                                 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
); 
3582         m_backgroundColour 
= wxSystemSettings:: 
3583                                 GetSystemColour(wxSYS_COLOUR_BTNFACE
); 
3587 extern wxCOLORMAP 
*wxGetStdColourMap() 
3589     static COLORREF s_stdColours
[wxSTD_COL_MAX
]; 
3590     static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
]; 
3592     if ( !gs_hasStdCmap 
) 
3594         static bool s_coloursInit 
= FALSE
; 
3596         if ( !s_coloursInit 
) 
3598             // When a bitmap is loaded, the RGB values can change (apparently 
3599             // because Windows adjusts them to care for the old programs always 
3600             // using 0xc0c0c0 while the transparent colour for the new Windows 
3601             // versions is different). But we do this adjustment ourselves so 
3602             // we want to avoid Windows' "help" and for this we need to have a 
3603             // reference bitmap which can tell us what the RGB values change 
3605             wxBitmap 
stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); 
3606             if ( stdColourBitmap
.Ok() ) 
3608                 // the pixels in the bitmap must correspond to wxSTD_COL_XXX! 
3609                 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
, 
3610                               _T("forgot to update wxBITMAP_STD_COLOURS!") ); 
3613                 memDC
.SelectObject(stdColourBitmap
); 
3616                 for ( size_t i 
= 0; i 
< WXSIZEOF(s_stdColours
); i
++ ) 
3618                     memDC
.GetPixel(i
, 0, &colour
); 
3619                     s_stdColours
[i
] = wxColourToRGB(colour
); 
3622             else // wxBITMAP_STD_COLOURS couldn't be loaded 
3624                 s_stdColours
[0] = RGB(000,000,000);     // black 
3625                 s_stdColours
[1] = RGB(128,128,128);     // dark grey 
3626                 s_stdColours
[2] = RGB(192,192,192);     // light grey 
3627                 s_stdColours
[3] = RGB(255,255,255);     // white 
3628                 //s_stdColours[4] = RGB(000,000,255);     // blue 
3629                 //s_stdColours[5] = RGB(255,000,255);     // magenta 
3632             s_coloursInit 
= TRUE
; 
3635         gs_hasStdCmap 
= TRUE
; 
3637         // create the colour map 
3638 #define INIT_CMAP_ENTRY(col) \ 
3639             s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \ 
3640             s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col) 
3642         INIT_CMAP_ENTRY(BTNTEXT
); 
3643         INIT_CMAP_ENTRY(BTNSHADOW
); 
3644         INIT_CMAP_ENTRY(BTNFACE
); 
3645         INIT_CMAP_ENTRY(BTNHIGHLIGHT
); 
3647 #undef INIT_CMAP_ENTRY 
3653 // --------------------------------------------------------------------------- 
3655 // --------------------------------------------------------------------------- 
3657 bool wxWindowMSW::HandlePaint() 
3660     HRGN hRegion 
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle 
3662         wxLogLastError(wxT("CreateRectRgn")); 
3663     if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR 
) 
3664         wxLogLastError(wxT("GetUpdateRgn")); 
3666     m_updateRegion 
= wxRegion((WXHRGN
) hRegion
); 
3669     ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
); 
3671     m_updateRegion 
= wxRegion(updateRect
.left
, updateRect
.top
, 
3672                               updateRect
.right 
- updateRect
.left
, 
3673                               updateRect
.bottom 
- updateRect
.top
); 
3676     wxPaintEvent 
event(m_windowId
); 
3677     event
.SetEventObject(this); 
3679     bool processed 
= GetEventHandler()->ProcessEvent(event
); 
3681     // note that we must generate NC event after the normal one as otherwise 
3682     // BeginPaint() will happily overwrite our decorations with the background 
3684     wxNcPaintEvent 
eventNc(m_windowId
); 
3685     eventNc
.SetEventObject(this); 
3686     GetEventHandler()->ProcessEvent(eventNc
); 
3691 // Can be called from an application's OnPaint handler 
3692 void wxWindowMSW::OnPaint(wxPaintEvent
& event
) 
3694 #ifdef __WXUNIVERSAL__ 
3697     HDC hDC 
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject()); 
3700         MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0); 
3705 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
) 
3707     // Prevents flicker when dragging 
3708     if ( ::IsIconic(GetHwnd()) ) 
3714     dc
.SetWindow((wxWindow 
*)this); 
3717     wxEraseEvent 
event(m_windowId
, &dc
); 
3718     event
.SetEventObject(this); 
3719     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
3723     // must be called manually as ~wxDC doesn't do anything for wxDCTemp 
3724     dc
.SelectOldObjects(hdc
); 
3729 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
) 
3732     ::GetClientRect(GetHwnd(), &rect
); 
3734     COLORREF ref 
= PALETTERGB(m_backgroundColour
.Red(), 
3735                               m_backgroundColour
.Green(), 
3736                               m_backgroundColour
.Blue()); 
3737     HBRUSH hBrush 
= ::CreateSolidBrush(ref
); 
3739         wxLogLastError(wxT("CreateSolidBrush")); 
3741     HDC hdc 
= (HDC
)event
.GetDC()->GetHDC(); 
3743     int mode 
= ::SetMapMode(hdc
, MM_TEXT
); 
3745     ::FillRect(hdc
, &rect
, hBrush
); 
3746     ::DeleteObject(hBrush
); 
3747     ::SetMapMode(hdc
, mode
); 
3750 // --------------------------------------------------------------------------- 
3751 // moving and resizing 
3752 // --------------------------------------------------------------------------- 
3754 bool wxWindowMSW::HandleMinimize() 
3756     wxIconizeEvent 
event(m_windowId
); 
3757     event
.SetEventObject(this); 
3759     return GetEventHandler()->ProcessEvent(event
); 
3762 bool wxWindowMSW::HandleMaximize() 
3764     wxMaximizeEvent 
event(m_windowId
); 
3765     event
.SetEventObject(this); 
3767     return GetEventHandler()->ProcessEvent(event
); 
3770 bool wxWindowMSW::HandleMove(int x
, int y
) 
3772     wxMoveEvent 
event(wxPoint(x
, y
), m_windowId
); 
3773     event
.SetEventObject(this); 
3775     return GetEventHandler()->ProcessEvent(event
); 
3778 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), 
3779                              WXUINT 
WXUNUSED(flag
)) 
3781     // don't use w and h parameters as they specify the client size while 
3782     // according to the docs EVT_SIZE handler is supposed to receive the total 
3784     wxSizeEvent 
event(GetSize(), m_windowId
); 
3785     event
.SetEventObject(this); 
3787     return GetEventHandler()->ProcessEvent(event
); 
3790 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
) 
3792     MINMAXINFO 
*info 
= (MINMAXINFO 
*)mmInfo
; 
3796     int minWidth 
= GetMinWidth(), 
3797         minHeight 
= GetMinHeight(), 
3798         maxWidth 
= GetMaxWidth(), 
3799         maxHeight 
= GetMaxHeight(); 
3801     if ( minWidth 
!= -1 ) 
3803         info
->ptMinTrackSize
.x 
= minWidth
; 
3807     if ( minHeight 
!= -1 ) 
3809         info
->ptMinTrackSize
.y 
= minHeight
; 
3813     if ( maxWidth 
!= -1 ) 
3815         info
->ptMaxTrackSize
.x 
= maxWidth
; 
3819     if ( maxHeight 
!= -1 ) 
3821         info
->ptMaxTrackSize
.y 
= maxHeight
; 
3828 // --------------------------------------------------------------------------- 
3830 // --------------------------------------------------------------------------- 
3832 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
) 
3834 #if wxUSE_MENUS_NATIVE 
3835     if ( !cmd 
&& wxCurrentPopupMenu 
) 
3837         wxMenu 
*popupMenu 
= wxCurrentPopupMenu
; 
3838         wxCurrentPopupMenu 
= NULL
; 
3840         return popupMenu
->MSWCommand(cmd
, id
); 
3842 #endif // wxUSE_MENUS_NATIVE 
3844     wxWindow 
*win 
= NULL
; 
3846     // first try to find it from HWND - this works even with the broken 
3847     // programs using the same ids for different controls 
3850         win 
= wxFindWinFromHandle(control
); 
3856         // must cast to a signed type before comparing with other ids! 
3857         win 
= FindItem((signed short)id
); 
3862         return win
->MSWCommand(cmd
, id
); 
3865     // the messages sent from the in-place edit control used by the treectrl 
3866     // for label editing have id == 0, but they should _not_ be treated as menu 
3867     // messages (they are EN_XXX ones, in fact) so don't translate anything 
3868     // coming from a control to wxEVT_COMMAND_MENU_SELECTED 
3871         // If no child window, it may be an accelerator, e.g. for a popup menu 
3874         wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
); 
3875         event
.SetEventObject(this); 
3879         return GetEventHandler()->ProcessEvent(event
); 
3881 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
3884         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND 
3885         // notifications to its parent which we want to reflect back to 
3887         wxSpinCtrl 
*spin 
= wxSpinCtrl::GetSpinForTextCtrl(control
); 
3888         if ( spin 
&& spin
->ProcessTextCommand(cmd
, id
) ) 
3891 #endif // wxUSE_SPINCTRL 
3896 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM 
WXUNUSED(lParam
)) 
3898     // 4 bits are reserved 
3899     switch ( wParam 
& 0xFFFFFFF0 ) 
3902             return HandleMaximize(); 
3905             return HandleMinimize(); 
3911 // --------------------------------------------------------------------------- 
3913 // --------------------------------------------------------------------------- 
3915 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
, 
3919     // our client coords are not quite the same as Windows ones 
3920     wxPoint pt 
= GetClientAreaOrigin(); 
3921     event
.m_x 
= x 
- pt
.x
; 
3922     event
.m_y 
= y 
- pt
.y
; 
3924     event
.m_shiftDown 
= (flags 
& MK_SHIFT
) != 0; 
3925     event
.m_controlDown 
= (flags 
& MK_CONTROL
) != 0; 
3926     event
.m_leftDown 
= (flags 
& MK_LBUTTON
) != 0; 
3927     event
.m_middleDown 
= (flags 
& MK_MBUTTON
) != 0; 
3928     event
.m_rightDown 
= (flags 
& MK_RBUTTON
) != 0; 
3929     event
.m_altDown 
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0; 
3931     event
.SetTimestamp(s_currentMsg
.time
); 
3932     event
.m_eventObject 
= this; 
3934 #if wxUSE_MOUSEEVENT_HACK 
3937     m_lastMouseEvent 
= event
.GetEventType(); 
3938 #endif // wxUSE_MOUSEEVENT_HACK 
3941 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
3943     // the mouse events take consecutive IDs from WM_MOUSEFIRST to 
3944     // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST 
3945     // from the message id and take the value in the table to get wxWin event 
3947     static const wxEventType eventsMouse
[] = 
3961     wxMouseEvent 
event(eventsMouse
[msg 
- WM_MOUSEMOVE
]); 
3962     InitMouseEvent(event
, x
, y
, flags
); 
3964     return GetEventHandler()->ProcessEvent(event
); 
3967 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
) 
3969     if ( !m_mouseInWindow 
) 
3971         // it would be wrong to assume that just because we get a mouse move 
3972         // event that the mouse is inside the window: although this is usually 
3973         // true, it is not if we had captured the mouse, so we need to check 
3974         // the mouse coordinates here 
3975         if ( !HasCapture() || IsMouseInWindow() ) 
3977             // Generate an ENTER event 
3978             m_mouseInWindow 
= TRUE
; 
3980             wxMouseEvent 
event(wxEVT_ENTER_WINDOW
); 
3981             InitMouseEvent(event
, x
, y
, flags
); 
3983             (void)GetEventHandler()->ProcessEvent(event
); 
3987 #if wxUSE_MOUSEEVENT_HACK 
3988     // Window gets a click down message followed by a mouse move message even 
3989     // if position isn't changed!  We want to discard the trailing move event 
3990     // if x and y are the same. 
3991     if ( (m_lastMouseEvent 
== wxEVT_RIGHT_DOWN 
|| 
3992           m_lastMouseEvent 
== wxEVT_LEFT_DOWN 
|| 
3993           m_lastMouseEvent 
== wxEVT_MIDDLE_DOWN
) && 
3994          (m_lastMouseX 
== x 
&& m_lastMouseY 
== y
) ) 
3996         m_lastMouseEvent 
= wxEVT_MOTION
; 
4000 #endif // wxUSE_MOUSEEVENT_HACK 
4002     return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
); 
4006 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
) 
4008 #if wxUSE_MOUSEWHEEL 
4009     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
4010     InitMouseEvent(event
, 
4011                    GET_X_LPARAM(lParam
), 
4012                    GET_Y_LPARAM(lParam
), 
4014     event
.m_wheelRotation 
= (short)HIWORD(wParam
); 
4015     event
.m_wheelDelta 
= WHEEL_DELTA
; 
4018     static int s_linesPerRotation 
= -1; 
4019     if ( s_linesPerRotation 
== -1 ) 
4021         if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, 
4022                                      &s_linesPerRotation
, 0)) 
4024             // this is not supposed to happen 
4025             wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)")); 
4027             // the default is 3, so use it if SystemParametersInfo() failed 
4028             s_linesPerRotation 
= 3; 
4032     // no SystemParametersInfo() under Win16 
4033     static const int s_linesPerRotation 
= 3; 
4036     event
.m_linesPerAction 
= s_linesPerRotation
; 
4037     return GetEventHandler()->ProcessEvent(event
); 
4048 // --------------------------------------------------------------------------- 
4049 // keyboard handling 
4050 // --------------------------------------------------------------------------- 
4052 // create the key event of the given type for the given key - used by 
4053 // HandleChar and HandleKeyDown/Up 
4054 wxKeyEvent 
wxWindowMSW::CreateKeyEvent(wxEventType evType
, 
4057                                        WXWPARAM wParam
) const 
4059     wxKeyEvent 
event(evType
); 
4060     event
.SetId(GetId()); 
4061     event
.m_shiftDown 
= wxIsShiftDown(); 
4062     event
.m_controlDown 
= wxIsCtrlDown(); 
4063     event
.m_altDown 
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
; 
4065     event
.m_eventObject 
= (wxWindow 
*)this; // const_cast 
4066     event
.m_keyCode 
= id
; 
4067     event
.m_rawCode 
= (wxUint32
) wParam
; 
4068     event
.m_rawFlags 
= (wxUint32
) lParam
; 
4069     event
.SetTimestamp(s_currentMsg
.time
); 
4071     // translate the position to client coords 
4075     GetWindowRect(GetHwnd(),&rect
); 
4085 // isASCII is TRUE only when we're called from WM_CHAR handler and not from 
4087 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
) 
4089     bool ctrlDown 
= FALSE
; 
4094         // If 1 -> 26, translate to CTRL plus a letter. 
4096         if ( (id 
> 0) && (id 
< 27) ) 
4118     else // we're called from WM_KEYDOWN 
4120         id 
= wxCharCodeMSWToWX(wParam
); 
4123             // it's ASCII and will be processed here only when called from 
4124             // WM_CHAR (i.e. when isASCII = TRUE), don't process it now 
4129     wxKeyEvent 
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
)); 
4132         event
.m_controlDown 
= TRUE
; 
4135     return GetEventHandler()->ProcessEvent(event
); 
4138 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
) 
4140     int id 
= wxCharCodeMSWToWX(wParam
); 
4144         // normal ASCII char 
4148     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4150         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
)); 
4151         if ( GetEventHandler()->ProcessEvent(event
) ) 
4160 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
) 
4162     int id 
= wxCharCodeMSWToWX(wParam
); 
4166         // normal ASCII char 
4170     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4172         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
)); 
4173         if ( GetEventHandler()->ProcessEvent(event
) ) 
4180 // --------------------------------------------------------------------------- 
4182 // --------------------------------------------------------------------------- 
4184 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4188     if ( flags 
& JOY_BUTTON1CHG 
) 
4189         change 
= wxJOY_BUTTON1
; 
4190     if ( flags 
& JOY_BUTTON2CHG 
) 
4191         change 
= wxJOY_BUTTON2
; 
4192     if ( flags 
& JOY_BUTTON3CHG 
) 
4193         change 
= wxJOY_BUTTON3
; 
4194     if ( flags 
& JOY_BUTTON4CHG 
) 
4195         change 
= wxJOY_BUTTON4
; 
4198     if ( flags 
& JOY_BUTTON1 
) 
4199         buttons 
|= wxJOY_BUTTON1
; 
4200     if ( flags 
& JOY_BUTTON2 
) 
4201         buttons 
|= wxJOY_BUTTON2
; 
4202     if ( flags 
& JOY_BUTTON3 
) 
4203         buttons 
|= wxJOY_BUTTON3
; 
4204     if ( flags 
& JOY_BUTTON4 
) 
4205         buttons 
|= wxJOY_BUTTON4
; 
4207     // the event ids aren't consecutive so we can't use table based lookup 
4209     wxEventType eventType
; 
4214             eventType 
= wxEVT_JOY_MOVE
; 
4219             eventType 
= wxEVT_JOY_MOVE
; 
4224             eventType 
= wxEVT_JOY_ZMOVE
; 
4229             eventType 
= wxEVT_JOY_ZMOVE
; 
4232         case MM_JOY1BUTTONDOWN
: 
4234             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4237         case MM_JOY2BUTTONDOWN
: 
4239             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4242         case MM_JOY1BUTTONUP
: 
4244             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4247         case MM_JOY2BUTTONUP
: 
4249             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4253             wxFAIL_MSG(wxT("no such joystick event")); 
4258     wxJoystickEvent 
event(eventType
, buttons
, joystick
, change
); 
4259     event
.SetPosition(wxPoint(x
, y
)); 
4260     event
.SetEventObject(this); 
4262     return GetEventHandler()->ProcessEvent(event
); 
4268 // --------------------------------------------------------------------------- 
4270 // --------------------------------------------------------------------------- 
4272 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
, 
4273                            WXWORD pos
, WXHWND control
) 
4277         wxWindow 
*child 
= wxFindWinFromHandle(control
); 
4279             return child
->MSWOnScroll(orientation
, wParam
, pos
, control
); 
4282     wxScrollWinEvent event
; 
4283     event
.SetPosition(pos
); 
4284     event
.SetOrientation(orientation
); 
4285     event
.m_eventObject 
= this; 
4290         event
.m_eventType 
= wxEVT_SCROLLWIN_TOP
; 
4294         event
.m_eventType 
= wxEVT_SCROLLWIN_BOTTOM
; 
4298         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEUP
; 
4302         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEDOWN
; 
4306         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEUP
; 
4310         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEDOWN
; 
4313     case SB_THUMBPOSITION
: 
4316         // under Win32, the scrollbar range and position are 32 bit integers, 
4317         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must 
4318         // explicitly query the scrollbar for the correct position (this must 
4319         // be done only for these two SB_ events as they are the only one 
4320         // carrying the scrollbar position) 
4322             SCROLLINFO scrollInfo
; 
4323             wxZeroMemory(scrollInfo
); 
4324             scrollInfo
.cbSize 
= sizeof(SCROLLINFO
); 
4325             scrollInfo
.fMask 
= SIF_TRACKPOS
; 
4327             if ( !::GetScrollInfo(GetHwnd(), 
4328                                   orientation 
== wxHORIZONTAL 
? SB_HORZ
 
4332                 wxLogLastError(_T("GetScrollInfo")); 
4335             event
.SetPosition(scrollInfo
.nTrackPos
); 
4339         event
.m_eventType 
= wParam 
== SB_THUMBPOSITION
 
4340                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
 
4341                                 : wxEVT_SCROLLWIN_THUMBTRACK
; 
4348     return GetEventHandler()->ProcessEvent(event
); 
4351 // =========================================================================== 
4353 // =========================================================================== 
4355 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont 
*the_font
) 
4358     HDC dc 
= ::GetDC((HWND
) wnd
); 
4363         //    the_font->UseResource(); 
4364         //    the_font->RealizeResource(); 
4365         fnt 
= (HFONT
)((wxFont 
*)the_font
)->GetResourceHandle(); // const_cast 
4367             was 
= (HFONT
) SelectObject(dc
,fnt
); 
4369     GetTextMetrics(dc
, &tm
); 
4370     if ( the_font 
&& fnt 
&& was 
) 
4372         SelectObject(dc
,was
); 
4374     ReleaseDC((HWND
)wnd
, dc
); 
4377         *x 
= tm
.tmAveCharWidth
; 
4379         *y 
= tm
.tmHeight 
+ tm
.tmExternalLeading
; 
4382     //    the_font->ReleaseResource(); 
4385 // Returns 0 if was a normal ASCII value, not a special key. This indicates that 
4386 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. 
4387 int wxCharCodeMSWToWX(int keySym
) 
4392         case VK_CANCEL
:     id 
= WXK_CANCEL
; break; 
4393         case VK_BACK
:       id 
= WXK_BACK
; break; 
4394         case VK_TAB
:        id 
= WXK_TAB
; break; 
4395         case VK_CLEAR
:      id 
= WXK_CLEAR
; break; 
4396         case VK_RETURN
:     id 
= WXK_RETURN
; break; 
4397         case VK_SHIFT
:      id 
= WXK_SHIFT
; break; 
4398         case VK_CONTROL
:    id 
= WXK_CONTROL
; break; 
4399         case VK_MENU 
:      id 
= WXK_MENU
; break; 
4400         case VK_PAUSE
:      id 
= WXK_PAUSE
; break; 
4401         case VK_CAPITAL
:    id 
= WXK_CAPITAL
; break; 
4402         case VK_SPACE
:      id 
= WXK_SPACE
; break; 
4403         case VK_ESCAPE
:     id 
= WXK_ESCAPE
; break; 
4404         case VK_PRIOR
:      id 
= WXK_PRIOR
; break; 
4405         case VK_NEXT 
:      id 
= WXK_NEXT
; break; 
4406         case VK_END
:        id 
= WXK_END
; break; 
4407         case VK_HOME 
:      id 
= WXK_HOME
; break; 
4408         case VK_LEFT 
:      id 
= WXK_LEFT
; break; 
4409         case VK_UP
:         id 
= WXK_UP
; break; 
4410         case VK_RIGHT
:      id 
= WXK_RIGHT
; break; 
4411         case VK_DOWN 
:      id 
= WXK_DOWN
; break; 
4412         case VK_SELECT
:     id 
= WXK_SELECT
; break; 
4413         case VK_PRINT
:      id 
= WXK_PRINT
; break; 
4414         case VK_EXECUTE
:    id 
= WXK_EXECUTE
; break; 
4415         case VK_INSERT
:     id 
= WXK_INSERT
; break; 
4416         case VK_DELETE
:     id 
= WXK_DELETE
; break; 
4417         case VK_HELP 
:      id 
= WXK_HELP
; break; 
4418         case VK_NUMPAD0
:    id 
= WXK_NUMPAD0
; break; 
4419         case VK_NUMPAD1
:    id 
= WXK_NUMPAD1
; break; 
4420         case VK_NUMPAD2
:    id 
= WXK_NUMPAD2
; break; 
4421         case VK_NUMPAD3
:    id 
= WXK_NUMPAD3
; break; 
4422         case VK_NUMPAD4
:    id 
= WXK_NUMPAD4
; break; 
4423         case VK_NUMPAD5
:    id 
= WXK_NUMPAD5
; break; 
4424         case VK_NUMPAD6
:    id 
= WXK_NUMPAD6
; break; 
4425         case VK_NUMPAD7
:    id 
= WXK_NUMPAD7
; break; 
4426         case VK_NUMPAD8
:    id 
= WXK_NUMPAD8
; break; 
4427         case VK_NUMPAD9
:    id 
= WXK_NUMPAD9
; break; 
4428         case VK_MULTIPLY
:   id 
= WXK_NUMPAD_MULTIPLY
; break; 
4429         case VK_ADD
:        id 
= WXK_NUMPAD_ADD
; break; 
4430         case VK_SUBTRACT
:   id 
= WXK_NUMPAD_SUBTRACT
; break; 
4431         case VK_DECIMAL
:    id 
= WXK_NUMPAD_DECIMAL
; break; 
4432         case VK_DIVIDE
:     id 
= WXK_NUMPAD_DIVIDE
; break; 
4433         case VK_F1
:         id 
= WXK_F1
; break; 
4434         case VK_F2
:         id 
= WXK_F2
; break; 
4435         case VK_F3
:         id 
= WXK_F3
; break; 
4436         case VK_F4
:         id 
= WXK_F4
; break; 
4437         case VK_F5
:         id 
= WXK_F5
; break; 
4438         case VK_F6
:         id 
= WXK_F6
; break; 
4439         case VK_F7
:         id 
= WXK_F7
; break; 
4440         case VK_F8
:         id 
= WXK_F8
; break; 
4441         case VK_F9
:         id 
= WXK_F9
; break; 
4442         case VK_F10
:        id 
= WXK_F10
; break; 
4443         case VK_F11
:        id 
= WXK_F11
; break; 
4444         case VK_F12
:        id 
= WXK_F12
; break; 
4445         case VK_F13
:        id 
= WXK_F13
; break; 
4446         case VK_F14
:        id 
= WXK_F14
; break; 
4447         case VK_F15
:        id 
= WXK_F15
; break; 
4448         case VK_F16
:        id 
= WXK_F16
; break; 
4449         case VK_F17
:        id 
= WXK_F17
; break; 
4450         case VK_F18
:        id 
= WXK_F18
; break; 
4451         case VK_F19
:        id 
= WXK_F19
; break; 
4452         case VK_F20
:        id 
= WXK_F20
; break; 
4453         case VK_F21
:        id 
= WXK_F21
; break; 
4454         case VK_F22
:        id 
= WXK_F22
; break; 
4455         case VK_F23
:        id 
= WXK_F23
; break; 
4456         case VK_F24
:        id 
= WXK_F24
; break; 
4457         case VK_NUMLOCK
:    id 
= WXK_NUMLOCK
; break; 
4458         case VK_SCROLL
:     id 
= WXK_SCROLL
; break; 
4460         case VK_OEM_1
:      id 
= ';'; break; 
4461         case VK_OEM_PLUS
:   id 
= '+'; break; 
4462         case VK_OEM_COMMA
:  id 
= ','; break; 
4463         case VK_OEM_MINUS
:  id 
= '-'; break; 
4464         case VK_OEM_PERIOD
: id 
= '.'; break; 
4465         case VK_OEM_2
:      id 
= '/'; break; 
4466         case VK_OEM_3
:      id 
= '~'; break; 
4467         case VK_OEM_4
:      id 
= '['; break; 
4468         case VK_OEM_5
:      id 
= '\\'; break; 
4469         case VK_OEM_6
:      id 
= ']'; break; 
4470         case VK_OEM_7
:      id 
= '\''; break; 
4479 int wxCharCodeWXToMSW(int id
, bool *isVirtual
) 
4485     case WXK_CANCEL
:    keySym 
= VK_CANCEL
; break; 
4486     case WXK_CLEAR
:     keySym 
= VK_CLEAR
; break; 
4487     case WXK_SHIFT
:     keySym 
= VK_SHIFT
; break; 
4488     case WXK_CONTROL
:   keySym 
= VK_CONTROL
; break; 
4489     case WXK_MENU 
:     keySym 
= VK_MENU
; break; 
4490     case WXK_PAUSE
:     keySym 
= VK_PAUSE
; break; 
4491     case WXK_PRIOR
:     keySym 
= VK_PRIOR
; break; 
4492     case WXK_NEXT 
:     keySym 
= VK_NEXT
; break; 
4493     case WXK_END
:       keySym 
= VK_END
; break; 
4494     case WXK_HOME 
:     keySym 
= VK_HOME
; break; 
4495     case WXK_LEFT 
:     keySym 
= VK_LEFT
; break; 
4496     case WXK_UP
:        keySym 
= VK_UP
; break; 
4497     case WXK_RIGHT
:     keySym 
= VK_RIGHT
; break; 
4498     case WXK_DOWN 
:     keySym 
= VK_DOWN
; break; 
4499     case WXK_SELECT
:    keySym 
= VK_SELECT
; break; 
4500     case WXK_PRINT
:     keySym 
= VK_PRINT
; break; 
4501     case WXK_EXECUTE
:   keySym 
= VK_EXECUTE
; break; 
4502     case WXK_INSERT
:    keySym 
= VK_INSERT
; break; 
4503     case WXK_DELETE
:    keySym 
= VK_DELETE
; break; 
4504     case WXK_HELP 
:     keySym 
= VK_HELP
; break; 
4505     case WXK_NUMPAD0
:   keySym 
= VK_NUMPAD0
; break; 
4506     case WXK_NUMPAD1
:   keySym 
= VK_NUMPAD1
; break; 
4507     case WXK_NUMPAD2
:   keySym 
= VK_NUMPAD2
; break; 
4508     case WXK_NUMPAD3
:   keySym 
= VK_NUMPAD3
; break; 
4509     case WXK_NUMPAD4
:   keySym 
= VK_NUMPAD4
; break; 
4510     case WXK_NUMPAD5
:   keySym 
= VK_NUMPAD5
; break; 
4511     case WXK_NUMPAD6
:   keySym 
= VK_NUMPAD6
; break; 
4512     case WXK_NUMPAD7
:   keySym 
= VK_NUMPAD7
; break; 
4513     case WXK_NUMPAD8
:   keySym 
= VK_NUMPAD8
; break; 
4514     case WXK_NUMPAD9
:   keySym 
= VK_NUMPAD9
; break; 
4515     case WXK_NUMPAD_MULTIPLY
:  keySym 
= VK_MULTIPLY
; break; 
4516     case WXK_NUMPAD_ADD
:       keySym 
= VK_ADD
; break; 
4517     case WXK_NUMPAD_SUBTRACT
:  keySym 
= VK_SUBTRACT
; break; 
4518     case WXK_NUMPAD_DECIMAL
:   keySym 
= VK_DECIMAL
; break; 
4519     case WXK_NUMPAD_DIVIDE
:    keySym 
= VK_DIVIDE
; break; 
4520     case WXK_F1
:        keySym 
= VK_F1
; break; 
4521     case WXK_F2
:        keySym 
= VK_F2
; break; 
4522     case WXK_F3
:        keySym 
= VK_F3
; break; 
4523     case WXK_F4
:        keySym 
= VK_F4
; break; 
4524     case WXK_F5
:        keySym 
= VK_F5
; break; 
4525     case WXK_F6
:        keySym 
= VK_F6
; break; 
4526     case WXK_F7
:        keySym 
= VK_F7
; break; 
4527     case WXK_F8
:        keySym 
= VK_F8
; break; 
4528     case WXK_F9
:        keySym 
= VK_F9
; break; 
4529     case WXK_F10
:       keySym 
= VK_F10
; break; 
4530     case WXK_F11
:       keySym 
= VK_F11
; break; 
4531     case WXK_F12
:       keySym 
= VK_F12
; break; 
4532     case WXK_F13
:       keySym 
= VK_F13
; break; 
4533     case WXK_F14
:       keySym 
= VK_F14
; break; 
4534     case WXK_F15
:       keySym 
= VK_F15
; break; 
4535     case WXK_F16
:       keySym 
= VK_F16
; break; 
4536     case WXK_F17
:       keySym 
= VK_F17
; break; 
4537     case WXK_F18
:       keySym 
= VK_F18
; break; 
4538     case WXK_F19
:       keySym 
= VK_F19
; break; 
4539     case WXK_F20
:       keySym 
= VK_F20
; break; 
4540     case WXK_F21
:       keySym 
= VK_F21
; break; 
4541     case WXK_F22
:       keySym 
= VK_F22
; break; 
4542     case WXK_F23
:       keySym 
= VK_F23
; break; 
4543     case WXK_F24
:       keySym 
= VK_F24
; break; 
4544     case WXK_NUMLOCK
:   keySym 
= VK_NUMLOCK
; break; 
4545     case WXK_SCROLL
:    keySym 
= VK_SCROLL
; break; 
4556 wxWindow 
*wxGetActiveWindow() 
4558     HWND hWnd 
= GetActiveWindow(); 
4561         return wxFindWinFromHandle((WXHWND
) hWnd
); 
4566 extern wxWindow 
*wxGetWindowFromHWND(WXHWND hWnd
) 
4568     HWND hwnd 
= (HWND
)hWnd
; 
4570     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set 
4571     // by code in msw/radiobox.cpp), for all the others we just search up the 
4573     wxWindow 
*win 
= (wxWindow 
*)NULL
; 
4576         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
4579             // all these hacks only work under Win32 anyhow 
4583             // native radiobuttons return DLGC_RADIOBUTTON here and for any 
4584             // wxWindow class which overrides WM_GETDLGCODE processing to 
4585             // do it as well, win would be already non NULL 
4586             if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON 
) 
4588                 win 
= (wxWindow 
*)::GetWindowLong(hwnd
, GWL_USERDATA
); 
4590             //else: it's a wxRadioButton, not a radiobutton from wxRadioBox 
4591 #endif // wxUSE_RADIOBOX 
4593             // spin control text buddy window should be mapped to spin ctrl 
4594             // itself so try it too 
4595 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
4598                 win 
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
); 
4600 #endif // wxUSE_SPINCTRL 
4606     while ( hwnd 
&& !win 
) 
4608         // this is a really ugly hack needed to avoid mistakenly returning the 
4609         // parent frame wxWindow for the find/replace modeless dialog HWND - 
4610         // this, in turn, is needed to call IsDialogMessage() from 
4611         // wxApp::ProcessMessage() as for this we must return NULL from here 
4613         // FIXME: this is clearly not the best way to do it but I think we'll 
4614         //        need to change HWND <-> wxWindow code more heavily than I can 
4615         //        do it now to fix it 
4616 #ifndef __WXMICROWIN__ 
4617         if ( ::GetWindow(hwnd
, GW_OWNER
) ) 
4619             // it's a dialog box, don't go upwards 
4624         hwnd 
= ::GetParent(hwnd
); 
4625         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
4631 #ifndef __WXMICROWIN__ 
4633 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE 
4634 // in active frames and dialogs, regardless of where the focus is. 
4635 static HHOOK wxTheKeyboardHook 
= 0; 
4636 static FARPROC wxTheKeyboardHookProc 
= 0; 
4637 int APIENTRY _EXPORT
 
4638 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
); 
4640 void wxSetKeyboardHook(bool doIt
) 
4644         wxTheKeyboardHookProc 
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance()); 
4645         wxTheKeyboardHook 
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(), 
4647 #if defined(__WIN32__) && !defined(__TWIN32__) 
4648             GetCurrentThreadId() 
4649         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? 
4657         UnhookWindowsHookEx(wxTheKeyboardHook
); 
4659         // avoids warning about statement with no effect (FreeProcInstance 
4660         // doesn't do anything under Win32) 
4661 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__) 
4662         FreeProcInstance(wxTheKeyboardHookProc
); 
4667 int APIENTRY _EXPORT
 
4668 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
) 
4670     DWORD hiWord 
= HIWORD(lParam
); 
4671     if ( nCode 
!= HC_NOREMOVE 
&& ((hiWord 
& KF_UP
) == 0) ) 
4673         int id 
= wxCharCodeMSWToWX(wParam
); 
4676             wxKeyEvent 
event(wxEVT_CHAR_HOOK
); 
4677             if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
4678                 event
.m_altDown 
= TRUE
; 
4680             event
.m_eventObject 
= NULL
; 
4681             event
.m_keyCode 
= id
; 
4682             event
.m_shiftDown 
= wxIsShiftDown(); 
4683             event
.m_controlDown 
= wxIsCtrlDown(); 
4684             event
.SetTimestamp(s_currentMsg
.time
); 
4686             wxWindow 
*win 
= wxGetActiveWindow(); 
4687             wxEvtHandler 
*handler
; 
4690                 handler 
= win
->GetEventHandler(); 
4691                 event
.SetId(win
->GetId()); 
4699             if ( handler 
&& handler
->ProcessEvent(event
) ) 
4707     return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
); 
4710 #endif // !__WXMICROWIN__ 
4713 const char *wxGetMessageName(int message
) 
4717         case 0x0000: return "WM_NULL"; 
4718         case 0x0001: return "WM_CREATE"; 
4719         case 0x0002: return "WM_DESTROY"; 
4720         case 0x0003: return "WM_MOVE"; 
4721         case 0x0005: return "WM_SIZE"; 
4722         case 0x0006: return "WM_ACTIVATE"; 
4723         case 0x0007: return "WM_SETFOCUS"; 
4724         case 0x0008: return "WM_KILLFOCUS"; 
4725         case 0x000A: return "WM_ENABLE"; 
4726         case 0x000B: return "WM_SETREDRAW"; 
4727         case 0x000C: return "WM_SETTEXT"; 
4728         case 0x000D: return "WM_GETTEXT"; 
4729         case 0x000E: return "WM_GETTEXTLENGTH"; 
4730         case 0x000F: return "WM_PAINT"; 
4731         case 0x0010: return "WM_CLOSE"; 
4732         case 0x0011: return "WM_QUERYENDSESSION"; 
4733         case 0x0012: return "WM_QUIT"; 
4734         case 0x0013: return "WM_QUERYOPEN"; 
4735         case 0x0014: return "WM_ERASEBKGND"; 
4736         case 0x0015: return "WM_SYSCOLORCHANGE"; 
4737         case 0x0016: return "WM_ENDSESSION"; 
4738         case 0x0017: return "WM_SYSTEMERROR"; 
4739         case 0x0018: return "WM_SHOWWINDOW"; 
4740         case 0x0019: return "WM_CTLCOLOR"; 
4741         case 0x001A: return "WM_WININICHANGE"; 
4742         case 0x001B: return "WM_DEVMODECHANGE"; 
4743         case 0x001C: return "WM_ACTIVATEAPP"; 
4744         case 0x001D: return "WM_FONTCHANGE"; 
4745         case 0x001E: return "WM_TIMECHANGE"; 
4746         case 0x001F: return "WM_CANCELMODE"; 
4747         case 0x0020: return "WM_SETCURSOR"; 
4748         case 0x0021: return "WM_MOUSEACTIVATE"; 
4749         case 0x0022: return "WM_CHILDACTIVATE"; 
4750         case 0x0023: return "WM_QUEUESYNC"; 
4751         case 0x0024: return "WM_GETMINMAXINFO"; 
4752         case 0x0026: return "WM_PAINTICON"; 
4753         case 0x0027: return "WM_ICONERASEBKGND"; 
4754         case 0x0028: return "WM_NEXTDLGCTL"; 
4755         case 0x002A: return "WM_SPOOLERSTATUS"; 
4756         case 0x002B: return "WM_DRAWITEM"; 
4757         case 0x002C: return "WM_MEASUREITEM"; 
4758         case 0x002D: return "WM_DELETEITEM"; 
4759         case 0x002E: return "WM_VKEYTOITEM"; 
4760         case 0x002F: return "WM_CHARTOITEM"; 
4761         case 0x0030: return "WM_SETFONT"; 
4762         case 0x0031: return "WM_GETFONT"; 
4763         case 0x0037: return "WM_QUERYDRAGICON"; 
4764         case 0x0039: return "WM_COMPAREITEM"; 
4765         case 0x0041: return "WM_COMPACTING"; 
4766         case 0x0044: return "WM_COMMNOTIFY"; 
4767         case 0x0046: return "WM_WINDOWPOSCHANGING"; 
4768         case 0x0047: return "WM_WINDOWPOSCHANGED"; 
4769         case 0x0048: return "WM_POWER"; 
4772         case 0x004A: return "WM_COPYDATA"; 
4773         case 0x004B: return "WM_CANCELJOURNAL"; 
4774         case 0x004E: return "WM_NOTIFY"; 
4775         case 0x0050: return "WM_INPUTLANGCHANGEREQUEST"; 
4776         case 0x0051: return "WM_INPUTLANGCHANGE"; 
4777         case 0x0052: return "WM_TCARD"; 
4778         case 0x0053: return "WM_HELP"; 
4779         case 0x0054: return "WM_USERCHANGED"; 
4780         case 0x0055: return "WM_NOTIFYFORMAT"; 
4781         case 0x007B: return "WM_CONTEXTMENU"; 
4782         case 0x007C: return "WM_STYLECHANGING"; 
4783         case 0x007D: return "WM_STYLECHANGED"; 
4784         case 0x007E: return "WM_DISPLAYCHANGE"; 
4785         case 0x007F: return "WM_GETICON"; 
4786         case 0x0080: return "WM_SETICON"; 
4789         case 0x0081: return "WM_NCCREATE"; 
4790         case 0x0082: return "WM_NCDESTROY"; 
4791         case 0x0083: return "WM_NCCALCSIZE"; 
4792         case 0x0084: return "WM_NCHITTEST"; 
4793         case 0x0085: return "WM_NCPAINT"; 
4794         case 0x0086: return "WM_NCACTIVATE"; 
4795         case 0x0087: return "WM_GETDLGCODE"; 
4796         case 0x00A0: return "WM_NCMOUSEMOVE"; 
4797         case 0x00A1: return "WM_NCLBUTTONDOWN"; 
4798         case 0x00A2: return "WM_NCLBUTTONUP"; 
4799         case 0x00A3: return "WM_NCLBUTTONDBLCLK"; 
4800         case 0x00A4: return "WM_NCRBUTTONDOWN"; 
4801         case 0x00A5: return "WM_NCRBUTTONUP"; 
4802         case 0x00A6: return "WM_NCRBUTTONDBLCLK"; 
4803         case 0x00A7: return "WM_NCMBUTTONDOWN"; 
4804         case 0x00A8: return "WM_NCMBUTTONUP"; 
4805         case 0x00A9: return "WM_NCMBUTTONDBLCLK"; 
4806         case 0x0100: return "WM_KEYDOWN"; 
4807         case 0x0101: return "WM_KEYUP"; 
4808         case 0x0102: return "WM_CHAR"; 
4809         case 0x0103: return "WM_DEADCHAR"; 
4810         case 0x0104: return "WM_SYSKEYDOWN"; 
4811         case 0x0105: return "WM_SYSKEYUP"; 
4812         case 0x0106: return "WM_SYSCHAR"; 
4813         case 0x0107: return "WM_SYSDEADCHAR"; 
4814         case 0x0108: return "WM_KEYLAST"; 
4817         case 0x010D: return "WM_IME_STARTCOMPOSITION"; 
4818         case 0x010E: return "WM_IME_ENDCOMPOSITION"; 
4819         case 0x010F: return "WM_IME_COMPOSITION"; 
4822         case 0x0110: return "WM_INITDIALOG"; 
4823         case 0x0111: return "WM_COMMAND"; 
4824         case 0x0112: return "WM_SYSCOMMAND"; 
4825         case 0x0113: return "WM_TIMER"; 
4826         case 0x0114: return "WM_HSCROLL"; 
4827         case 0x0115: return "WM_VSCROLL"; 
4828         case 0x0116: return "WM_INITMENU"; 
4829         case 0x0117: return "WM_INITMENUPOPUP"; 
4830         case 0x011F: return "WM_MENUSELECT"; 
4831         case 0x0120: return "WM_MENUCHAR"; 
4832         case 0x0121: return "WM_ENTERIDLE"; 
4833         case 0x0200: return "WM_MOUSEMOVE"; 
4834         case 0x0201: return "WM_LBUTTONDOWN"; 
4835         case 0x0202: return "WM_LBUTTONUP"; 
4836         case 0x0203: return "WM_LBUTTONDBLCLK"; 
4837         case 0x0204: return "WM_RBUTTONDOWN"; 
4838         case 0x0205: return "WM_RBUTTONUP"; 
4839         case 0x0206: return "WM_RBUTTONDBLCLK"; 
4840         case 0x0207: return "WM_MBUTTONDOWN"; 
4841         case 0x0208: return "WM_MBUTTONUP"; 
4842         case 0x0209: return "WM_MBUTTONDBLCLK"; 
4843         case 0x020A: return "WM_MOUSEWHEEL"; 
4844         case 0x0210: return "WM_PARENTNOTIFY"; 
4845         case 0x0211: return "WM_ENTERMENULOOP"; 
4846         case 0x0212: return "WM_EXITMENULOOP"; 
4849         case 0x0213: return "WM_NEXTMENU"; 
4850         case 0x0214: return "WM_SIZING"; 
4851         case 0x0215: return "WM_CAPTURECHANGED"; 
4852         case 0x0216: return "WM_MOVING"; 
4853         case 0x0218: return "WM_POWERBROADCAST"; 
4854         case 0x0219: return "WM_DEVICECHANGE"; 
4857         case 0x0220: return "WM_MDICREATE"; 
4858         case 0x0221: return "WM_MDIDESTROY"; 
4859         case 0x0222: return "WM_MDIACTIVATE"; 
4860         case 0x0223: return "WM_MDIRESTORE"; 
4861         case 0x0224: return "WM_MDINEXT"; 
4862         case 0x0225: return "WM_MDIMAXIMIZE"; 
4863         case 0x0226: return "WM_MDITILE"; 
4864         case 0x0227: return "WM_MDICASCADE"; 
4865         case 0x0228: return "WM_MDIICONARRANGE"; 
4866         case 0x0229: return "WM_MDIGETACTIVE"; 
4867         case 0x0230: return "WM_MDISETMENU"; 
4868         case 0x0233: return "WM_DROPFILES"; 
4871         case 0x0281: return "WM_IME_SETCONTEXT"; 
4872         case 0x0282: return "WM_IME_NOTIFY"; 
4873         case 0x0283: return "WM_IME_CONTROL"; 
4874         case 0x0284: return "WM_IME_COMPOSITIONFULL"; 
4875         case 0x0285: return "WM_IME_SELECT"; 
4876         case 0x0286: return "WM_IME_CHAR"; 
4877         case 0x0290: return "WM_IME_KEYDOWN"; 
4878         case 0x0291: return "WM_IME_KEYUP"; 
4881         case 0x0300: return "WM_CUT"; 
4882         case 0x0301: return "WM_COPY"; 
4883         case 0x0302: return "WM_PASTE"; 
4884         case 0x0303: return "WM_CLEAR"; 
4885         case 0x0304: return "WM_UNDO"; 
4886         case 0x0305: return "WM_RENDERFORMAT"; 
4887         case 0x0306: return "WM_RENDERALLFORMATS"; 
4888         case 0x0307: return "WM_DESTROYCLIPBOARD"; 
4889         case 0x0308: return "WM_DRAWCLIPBOARD"; 
4890         case 0x0309: return "WM_PAINTCLIPBOARD"; 
4891         case 0x030A: return "WM_VSCROLLCLIPBOARD"; 
4892         case 0x030B: return "WM_SIZECLIPBOARD"; 
4893         case 0x030C: return "WM_ASKCBFORMATNAME"; 
4894         case 0x030D: return "WM_CHANGECBCHAIN"; 
4895         case 0x030E: return "WM_HSCROLLCLIPBOARD"; 
4896         case 0x030F: return "WM_QUERYNEWPALETTE"; 
4897         case 0x0310: return "WM_PALETTEISCHANGING"; 
4898         case 0x0311: return "WM_PALETTECHANGED"; 
4901         // common controls messages - although they're not strictly speaking 
4902         // standard, it's nice to decode them nevertheless 
4905         case 0x1000 + 0: return "LVM_GETBKCOLOR"; 
4906         case 0x1000 + 1: return "LVM_SETBKCOLOR"; 
4907         case 0x1000 + 2: return "LVM_GETIMAGELIST"; 
4908         case 0x1000 + 3: return "LVM_SETIMAGELIST"; 
4909         case 0x1000 + 4: return "LVM_GETITEMCOUNT"; 
4910         case 0x1000 + 5: return "LVM_GETITEMA"; 
4911         case 0x1000 + 75: return "LVM_GETITEMW"; 
4912         case 0x1000 + 6: return "LVM_SETITEMA"; 
4913         case 0x1000 + 76: return "LVM_SETITEMW"; 
4914         case 0x1000 + 7: return "LVM_INSERTITEMA"; 
4915         case 0x1000 + 77: return "LVM_INSERTITEMW"; 
4916         case 0x1000 + 8: return "LVM_DELETEITEM"; 
4917         case 0x1000 + 9: return "LVM_DELETEALLITEMS"; 
4918         case 0x1000 + 10: return "LVM_GETCALLBACKMASK"; 
4919         case 0x1000 + 11: return "LVM_SETCALLBACKMASK"; 
4920         case 0x1000 + 12: return "LVM_GETNEXTITEM"; 
4921         case 0x1000 + 13: return "LVM_FINDITEMA"; 
4922         case 0x1000 + 83: return "LVM_FINDITEMW"; 
4923         case 0x1000 + 14: return "LVM_GETITEMRECT"; 
4924         case 0x1000 + 15: return "LVM_SETITEMPOSITION"; 
4925         case 0x1000 + 16: return "LVM_GETITEMPOSITION"; 
4926         case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA"; 
4927         case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW"; 
4928         case 0x1000 + 18: return "LVM_HITTEST"; 
4929         case 0x1000 + 19: return "LVM_ENSUREVISIBLE"; 
4930         case 0x1000 + 20: return "LVM_SCROLL"; 
4931         case 0x1000 + 21: return "LVM_REDRAWITEMS"; 
4932         case 0x1000 + 22: return "LVM_ARRANGE"; 
4933         case 0x1000 + 23: return "LVM_EDITLABELA"; 
4934         case 0x1000 + 118: return "LVM_EDITLABELW"; 
4935         case 0x1000 + 24: return "LVM_GETEDITCONTROL"; 
4936         case 0x1000 + 25: return "LVM_GETCOLUMNA"; 
4937         case 0x1000 + 95: return "LVM_GETCOLUMNW"; 
4938         case 0x1000 + 26: return "LVM_SETCOLUMNA"; 
4939         case 0x1000 + 96: return "LVM_SETCOLUMNW"; 
4940         case 0x1000 + 27: return "LVM_INSERTCOLUMNA"; 
4941         case 0x1000 + 97: return "LVM_INSERTCOLUMNW"; 
4942         case 0x1000 + 28: return "LVM_DELETECOLUMN"; 
4943         case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH"; 
4944         case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH"; 
4945         case 0x1000 + 31: return "LVM_GETHEADER"; 
4946         case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE"; 
4947         case 0x1000 + 34: return "LVM_GETVIEWRECT"; 
4948         case 0x1000 + 35: return "LVM_GETTEXTCOLOR"; 
4949         case 0x1000 + 36: return "LVM_SETTEXTCOLOR"; 
4950         case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR"; 
4951         case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR"; 
4952         case 0x1000 + 39: return "LVM_GETTOPINDEX"; 
4953         case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE"; 
4954         case 0x1000 + 41: return "LVM_GETORIGIN"; 
4955         case 0x1000 + 42: return "LVM_UPDATE"; 
4956         case 0x1000 + 43: return "LVM_SETITEMSTATE"; 
4957         case 0x1000 + 44: return "LVM_GETITEMSTATE"; 
4958         case 0x1000 + 45: return "LVM_GETITEMTEXTA"; 
4959         case 0x1000 + 115: return "LVM_GETITEMTEXTW"; 
4960         case 0x1000 + 46: return "LVM_SETITEMTEXTA"; 
4961         case 0x1000 + 116: return "LVM_SETITEMTEXTW"; 
4962         case 0x1000 + 47: return "LVM_SETITEMCOUNT"; 
4963         case 0x1000 + 48: return "LVM_SORTITEMS"; 
4964         case 0x1000 + 49: return "LVM_SETITEMPOSITION32"; 
4965         case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT"; 
4966         case 0x1000 + 51: return "LVM_GETITEMSPACING"; 
4967         case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA"; 
4968         case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW"; 
4969         case 0x1000 + 53: return "LVM_SETICONSPACING"; 
4970         case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE"; 
4971         case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE"; 
4972         case 0x1000 + 56: return "LVM_GETSUBITEMRECT"; 
4973         case 0x1000 + 57: return "LVM_SUBITEMHITTEST"; 
4974         case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY"; 
4975         case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY"; 
4976         case 0x1000 + 60: return "LVM_SETHOTITEM"; 
4977         case 0x1000 + 61: return "LVM_GETHOTITEM"; 
4978         case 0x1000 + 62: return "LVM_SETHOTCURSOR"; 
4979         case 0x1000 + 63: return "LVM_GETHOTCURSOR"; 
4980         case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT"; 
4981         case 0x1000 + 65: return "LVM_SETWORKAREA"; 
4984         case 0x1100 + 0: return "TVM_INSERTITEMA"; 
4985         case 0x1100 + 50: return "TVM_INSERTITEMW"; 
4986         case 0x1100 + 1: return "TVM_DELETEITEM"; 
4987         case 0x1100 + 2: return "TVM_EXPAND"; 
4988         case 0x1100 + 4: return "TVM_GETITEMRECT"; 
4989         case 0x1100 + 5: return "TVM_GETCOUNT"; 
4990         case 0x1100 + 6: return "TVM_GETINDENT"; 
4991         case 0x1100 + 7: return "TVM_SETINDENT"; 
4992         case 0x1100 + 8: return "TVM_GETIMAGELIST"; 
4993         case 0x1100 + 9: return "TVM_SETIMAGELIST"; 
4994         case 0x1100 + 10: return "TVM_GETNEXTITEM"; 
4995         case 0x1100 + 11: return "TVM_SELECTITEM"; 
4996         case 0x1100 + 12: return "TVM_GETITEMA"; 
4997         case 0x1100 + 62: return "TVM_GETITEMW"; 
4998         case 0x1100 + 13: return "TVM_SETITEMA"; 
4999         case 0x1100 + 63: return "TVM_SETITEMW"; 
5000         case 0x1100 + 14: return "TVM_EDITLABELA"; 
5001         case 0x1100 + 65: return "TVM_EDITLABELW"; 
5002         case 0x1100 + 15: return "TVM_GETEDITCONTROL"; 
5003         case 0x1100 + 16: return "TVM_GETVISIBLECOUNT"; 
5004         case 0x1100 + 17: return "TVM_HITTEST"; 
5005         case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE"; 
5006         case 0x1100 + 19: return "TVM_SORTCHILDREN"; 
5007         case 0x1100 + 20: return "TVM_ENSUREVISIBLE"; 
5008         case 0x1100 + 21: return "TVM_SORTCHILDRENCB"; 
5009         case 0x1100 + 22: return "TVM_ENDEDITLABELNOW"; 
5010         case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA"; 
5011         case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW"; 
5012         case 0x1100 + 24: return "TVM_SETTOOLTIPS"; 
5013         case 0x1100 + 25: return "TVM_GETTOOLTIPS"; 
5016         case 0x1200 + 0: return "HDM_GETITEMCOUNT"; 
5017         case 0x1200 + 1: return "HDM_INSERTITEMA"; 
5018         case 0x1200 + 10: return "HDM_INSERTITEMW"; 
5019         case 0x1200 + 2: return "HDM_DELETEITEM"; 
5020         case 0x1200 + 3: return "HDM_GETITEMA"; 
5021         case 0x1200 + 11: return "HDM_GETITEMW"; 
5022         case 0x1200 + 4: return "HDM_SETITEMA"; 
5023         case 0x1200 + 12: return "HDM_SETITEMW"; 
5024         case 0x1200 + 5: return "HDM_LAYOUT"; 
5025         case 0x1200 + 6: return "HDM_HITTEST"; 
5026         case 0x1200 + 7: return "HDM_GETITEMRECT"; 
5027         case 0x1200 + 8: return "HDM_SETIMAGELIST"; 
5028         case 0x1200 + 9: return "HDM_GETIMAGELIST"; 
5029         case 0x1200 + 15: return "HDM_ORDERTOINDEX"; 
5030         case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE"; 
5031         case 0x1200 + 17: return "HDM_GETORDERARRAY"; 
5032         case 0x1200 + 18: return "HDM_SETORDERARRAY"; 
5033         case 0x1200 + 19: return "HDM_SETHOTDIVIDER"; 
5036         case 0x1300 + 2: return "TCM_GETIMAGELIST"; 
5037         case 0x1300 + 3: return "TCM_SETIMAGELIST"; 
5038         case 0x1300 + 4: return "TCM_GETITEMCOUNT"; 
5039         case 0x1300 + 5: return "TCM_GETITEMA"; 
5040         case 0x1300 + 60: return "TCM_GETITEMW"; 
5041         case 0x1300 + 6: return "TCM_SETITEMA"; 
5042         case 0x1300 + 61: return "TCM_SETITEMW"; 
5043         case 0x1300 + 7: return "TCM_INSERTITEMA"; 
5044         case 0x1300 + 62: return "TCM_INSERTITEMW"; 
5045         case 0x1300 + 8: return "TCM_DELETEITEM"; 
5046         case 0x1300 + 9: return "TCM_DELETEALLITEMS"; 
5047         case 0x1300 + 10: return "TCM_GETITEMRECT"; 
5048         case 0x1300 + 11: return "TCM_GETCURSEL"; 
5049         case 0x1300 + 12: return "TCM_SETCURSEL"; 
5050         case 0x1300 + 13: return "TCM_HITTEST"; 
5051         case 0x1300 + 14: return "TCM_SETITEMEXTRA"; 
5052         case 0x1300 + 40: return "TCM_ADJUSTRECT"; 
5053         case 0x1300 + 41: return "TCM_SETITEMSIZE"; 
5054         case 0x1300 + 42: return "TCM_REMOVEIMAGE"; 
5055         case 0x1300 + 43: return "TCM_SETPADDING"; 
5056         case 0x1300 + 44: return "TCM_GETROWCOUNT"; 
5057         case 0x1300 + 45: return "TCM_GETTOOLTIPS"; 
5058         case 0x1300 + 46: return "TCM_SETTOOLTIPS"; 
5059         case 0x1300 + 47: return "TCM_GETCURFOCUS"; 
5060         case 0x1300 + 48: return "TCM_SETCURFOCUS"; 
5061         case 0x1300 + 49: return "TCM_SETMINTABWIDTH"; 
5062         case 0x1300 + 50: return "TCM_DESELECTALL"; 
5065         case WM_USER
+1: return "TB_ENABLEBUTTON"; 
5066         case WM_USER
+2: return "TB_CHECKBUTTON"; 
5067         case WM_USER
+3: return "TB_PRESSBUTTON"; 
5068         case WM_USER
+4: return "TB_HIDEBUTTON"; 
5069         case WM_USER
+5: return "TB_INDETERMINATE"; 
5070         case WM_USER
+9: return "TB_ISBUTTONENABLED"; 
5071         case WM_USER
+10: return "TB_ISBUTTONCHECKED"; 
5072         case WM_USER
+11: return "TB_ISBUTTONPRESSED"; 
5073         case WM_USER
+12: return "TB_ISBUTTONHIDDEN"; 
5074         case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE"; 
5075         case WM_USER
+17: return "TB_SETSTATE"; 
5076         case WM_USER
+18: return "TB_GETSTATE"; 
5077         case WM_USER
+19: return "TB_ADDBITMAP"; 
5078         case WM_USER
+20: return "TB_ADDBUTTONS"; 
5079         case WM_USER
+21: return "TB_INSERTBUTTON"; 
5080         case WM_USER
+22: return "TB_DELETEBUTTON"; 
5081         case WM_USER
+23: return "TB_GETBUTTON"; 
5082         case WM_USER
+24: return "TB_BUTTONCOUNT"; 
5083         case WM_USER
+25: return "TB_COMMANDTOINDEX"; 
5084         case WM_USER
+26: return "TB_SAVERESTOREA"; 
5085         case WM_USER
+76: return "TB_SAVERESTOREW"; 
5086         case WM_USER
+27: return "TB_CUSTOMIZE"; 
5087         case WM_USER
+28: return "TB_ADDSTRINGA"; 
5088         case WM_USER
+77: return "TB_ADDSTRINGW"; 
5089         case WM_USER
+29: return "TB_GETITEMRECT"; 
5090         case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE"; 
5091         case WM_USER
+31: return "TB_SETBUTTONSIZE"; 
5092         case WM_USER
+32: return "TB_SETBITMAPSIZE"; 
5093         case WM_USER
+33: return "TB_AUTOSIZE"; 
5094         case WM_USER
+35: return "TB_GETTOOLTIPS"; 
5095         case WM_USER
+36: return "TB_SETTOOLTIPS"; 
5096         case WM_USER
+37: return "TB_SETPARENT"; 
5097         case WM_USER
+39: return "TB_SETROWS"; 
5098         case WM_USER
+40: return "TB_GETROWS"; 
5099         case WM_USER
+42: return "TB_SETCMDID"; 
5100         case WM_USER
+43: return "TB_CHANGEBITMAP"; 
5101         case WM_USER
+44: return "TB_GETBITMAP"; 
5102         case WM_USER
+45: return "TB_GETBUTTONTEXTA"; 
5103         case WM_USER
+75: return "TB_GETBUTTONTEXTW"; 
5104         case WM_USER
+46: return "TB_REPLACEBITMAP"; 
5105         case WM_USER
+47: return "TB_SETINDENT"; 
5106         case WM_USER
+48: return "TB_SETIMAGELIST"; 
5107         case WM_USER
+49: return "TB_GETIMAGELIST"; 
5108         case WM_USER
+50: return "TB_LOADIMAGES"; 
5109         case WM_USER
+51: return "TB_GETRECT"; 
5110         case WM_USER
+52: return "TB_SETHOTIMAGELIST"; 
5111         case WM_USER
+53: return "TB_GETHOTIMAGELIST"; 
5112         case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST"; 
5113         case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST"; 
5114         case WM_USER
+56: return "TB_SETSTYLE"; 
5115         case WM_USER
+57: return "TB_GETSTYLE"; 
5116         case WM_USER
+58: return "TB_GETBUTTONSIZE"; 
5117         case WM_USER
+59: return "TB_SETBUTTONWIDTH"; 
5118         case WM_USER
+60: return "TB_SETMAXTEXTROWS"; 
5119         case WM_USER
+61: return "TB_GETTEXTROWS"; 
5120         case WM_USER
+41: return "TB_GETBITMAPFLAGS"; 
5125             static char s_szBuf
[128]; 
5126             sprintf(s_szBuf
, "<unknown message = %d>", message
); 
5130 #endif //__WXDEBUG__ 
5132 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
5133                                      int *x
, int *y
, WPARAM 
*flags
) 
5135     // construct the key mask 
5136     WPARAM
& fwKeys 
= *flags
; 
5138     fwKeys 
= MK_RBUTTON
; 
5139     if ( wxIsCtrlDown() ) 
5140         fwKeys 
|= MK_CONTROL
; 
5141     if ( wxIsShiftDown() ) 
5144     // simulate right mouse button click 
5145     DWORD dwPos 
= ::GetMessagePos(); 
5146     *x 
= GET_X_LPARAM(dwPos
); 
5147     *y 
= GET_Y_LPARAM(dwPos
); 
5149     win
->ScreenToClient(x
, y
); 
5152 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
) 
5156     HWND hwnd 
= GetHwndOf(win
); 
5157     HDC hdc 
= ::GetDC(hwnd
); 
5159 #if !wxDIALOG_UNIT_COMPATIBILITY 
5160     // and select the current font into it 
5161     HFONT hfont 
= GetHfontOf(win
->GetFont()); 
5164         hfont 
= (HFONT
)::SelectObject(hdc
, hfont
); 
5168     // finally retrieve the text metrics from it 
5169     GetTextMetrics(hdc
, &tm
); 
5171 #if !wxDIALOG_UNIT_COMPATIBILITY 
5175         (void)::SelectObject(hdc
, hfont
); 
5179     ::ReleaseDC(hwnd
, hdc
); 
5184 // Find the wxWindow at the current mouse position, returning the mouse 
5186 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
)) 
5188     return wxFindWindowAtPoint(wxGetMousePosition()); 
5191 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
5196     HWND hWndHit 
= ::WindowFromPoint(pt2
); 
5198     wxWindow
* win 
= wxFindWinFromHandle((WXHWND
) hWndHit
) ; 
5199     HWND hWnd 
= hWndHit
; 
5201     // Try to find a window with a wxWindow associated with it 
5202     while (!win 
&& (hWnd 
!= 0)) 
5204         hWnd 
= ::GetParent(hWnd
); 
5205         win 
= wxFindWinFromHandle((WXHWND
) hWnd
) ; 
5210 // Get the current mouse position. 
5211 wxPoint 
wxGetMousePosition() 
5214     GetCursorPos( & pt 
); 
5216     return wxPoint(pt
.x
, pt
.y
);