1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/windows.cpp 
   4 // Author:      Julian Smart 
   5 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // =========================================================================== 
  14 // =========================================================================== 
  16 // --------------------------------------------------------------------------- 
  18 // --------------------------------------------------------------------------- 
  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 #if wxUSE_ACCESSIBILITY 
  62     #include "wx/access.h" 
  66         #define WM_GETOBJECT 0x003D 
  69         #define OBJID_CLIENT 0xFFFFFFFC 
  73 #include "wx/menuitem.h" 
  76 #include "wx/msw/private.h" 
  79     #include "wx/tooltip.h" 
  87     #include "wx/spinctrl.h" 
  88 #endif // wxUSE_SPINCTRL 
  93 #include "wx/textctrl.h" 
  94 #include "wx/notebook.h" 
  98 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) 
 100     #include <mmsystem.h> 
 104     #include <windowsx.h> 
 107 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) 
 109         #include <commctrl.h> 
 111 #elif !defined(__WXMICROWIN__) // broken compiler 
 112     #include "wx/msw/gnuwin32/extra.h" 
 115 #if defined(__GNUG__) 
 116 #include "wx/msw/missing.h" 
 119 // ---------------------------------------------------------------------------- 
 120 // standard constants not available with all compilers/headers 
 121 // ---------------------------------------------------------------------------- 
 123 // This didn't appear in mingw until 2.95.2 
 125 #define SIF_TRACKPOS 16 
 129     #ifndef WM_MOUSEWHEEL 
 130         #define WM_MOUSEWHEEL           0x020A 
 133         #define WHEEL_DELTA             120 
 135     #ifndef SPI_GETWHEELSCROLLLINES 
 136         #define SPI_GETWHEELSCROLLLINES 104 
 138 #endif // wxUSE_MOUSEWHEEL 
 141     #define VK_OEM_1        0xBA 
 142     #define VK_OEM_2        0xBF 
 143     #define VK_OEM_3        0xC0 
 144     #define VK_OEM_4        0xDB 
 145     #define VK_OEM_5        0xDC 
 146     #define VK_OEM_6        0xDD 
 147     #define VK_OEM_7        0xDE 
 151     #define VK_OEM_PLUS     0xBB 
 152     #define VK_OEM_COMMA    0xBC 
 153     #define VK_OEM_MINUS    0xBD 
 154     #define VK_OEM_PERIOD   0xBE 
 157 // --------------------------------------------------------------------------- 
 159 // --------------------------------------------------------------------------- 
 161 // the last Windows message we got (FIXME-MT) 
 162 extern MSG s_currentMsg
; 
 164 #if wxUSE_MENUS_NATIVE 
 165 wxMenu 
*wxCurrentPopupMenu 
= NULL
; 
 166 #endif // wxUSE_MENUS_NATIVE 
 168 extern const wxChar 
*wxCanvasClassName
; 
 170 // true if we had already created the std colour map, used by 
 171 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT) 
 172 static bool gs_hasStdCmap 
= FALSE
; 
 174 // --------------------------------------------------------------------------- 
 176 // --------------------------------------------------------------------------- 
 178 // the window proc for all our windows 
 179 #ifdef __DIGITALMARS__ 
 180 extern "C" LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
 181                                    WPARAM wParam
, LPARAM lParam
); 
 183 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
 184                                    WPARAM wParam
, LPARAM lParam
); 
 189     const char *wxGetMessageName(int message
); 
 192 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 193 #ifdef __DIGITALMARS__ 
 194 extern "C" void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 196 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 198 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
); 
 200 // this magical function is used to translate VK_APPS key presses to right 
 202 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
 203                                      int *x
, int *y
, WPARAM 
*flags
); 
 205 // get the text metrics for the current font 
 206 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
); 
 208 // find the window for the mouse event at the specified position 
 209 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
); //TW:REQ:Univ 
 211 // wrapper around BringWindowToTop() API 
 212 static inline void wxBringWindowToTop(HWND hwnd
) 
 214 #ifdef __WXMICROWIN__ 
 215     // It seems that MicroWindows brings the _parent_ of the window to the top, 
 216     // which can be the wrong one. 
 218     // activate (set focus to) specified window 
 221     // raise top level parent to top of z order 
 222     ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE 
| SWP_NOSIZE
); 
 223 #else // !__WXMICROWIN__ 
 224     if ( !::BringWindowToTop(hwnd
) ) 
 226         wxLogLastError(_T("BringWindowToTop")); 
 228 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
 231 // --------------------------------------------------------------------------- 
 233 // --------------------------------------------------------------------------- 
 235 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
 237 #ifdef __WXUNIVERSAL__ 
 238     IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
) 
 240     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
 241 #endif // __WXUNIVERSAL__/__WXMSW__ 
 243 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
) 
 244     EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
) 
 245     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
) 
 246     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
) 
 247     EVT_IDLE(wxWindowMSW::OnIdle
) 
 250 // =========================================================================== 
 252 // =========================================================================== 
 254 // --------------------------------------------------------------------------- 
 255 // wxWindow utility functions 
 256 // --------------------------------------------------------------------------- 
 258 // Find an item given the MS Windows id 
 259 wxWindow 
*wxWindowMSW::FindItem(long id
) const 
 262     wxControl 
*item 
= wxDynamicCastThis(wxControl
); 
 265         // is it we or one of our "internal" children? 
 266         if ( item
->GetId() == id
 
 267 #ifndef __WXUNIVERSAL__ 
 268                 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
) 
 269 #endif // __WXUNIVERSAL__ 
 275 #endif // wxUSE_CONTROLS 
 277     wxWindowList::Node 
*current 
= GetChildren().GetFirst(); 
 280         wxWindow 
*childWin 
= current
->GetData(); 
 282         wxWindow 
*wnd 
= childWin
->FindItem(id
); 
 286         current 
= current
->GetNext(); 
 292 // Find an item given the MS Windows handle 
 293 wxWindow 
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const 
 295     wxWindowList::Node 
*current 
= GetChildren().GetFirst(); 
 298         wxWindow 
*parent 
= current
->GetData(); 
 300         // Do a recursive search. 
 301         wxWindow 
*wnd 
= parent
->FindItemByHWND(hWnd
); 
 307                 || parent
->IsKindOf(CLASSINFO(wxControl
)) 
 308 #endif // wxUSE_CONTROLS 
 311             wxWindow 
*item 
= current
->GetData(); 
 312             if ( item
->GetHWND() == hWnd 
) 
 316                 if ( item
->ContainsHWND(hWnd
) ) 
 321         current 
= current
->GetNext(); 
 326 // Default command handler 
 327 bool wxWindowMSW::MSWCommand(WXUINT 
WXUNUSED(param
), WXWORD 
WXUNUSED(id
)) 
 332 // ---------------------------------------------------------------------------- 
 333 // constructors and such 
 334 // ---------------------------------------------------------------------------- 
 336 void wxWindowMSW::Init() 
 342     m_isBeingDeleted 
= FALSE
; 
 345     m_mouseInWindow 
= FALSE
; 
 346     m_lastKeydownProcessed 
= FALSE
; 
 348     m_childrenDisabled 
= NULL
; 
 357     m_backgroundTransparent 
= FALSE
; 
 359     // as all windows are created with WS_VISIBLE style... 
 362 #if wxUSE_MOUSEEVENT_HACK 
 365     m_lastMouseEvent 
= -1; 
 366 #endif // wxUSE_MOUSEEVENT_HACK 
 370 wxWindowMSW::~wxWindowMSW() 
 372     m_isBeingDeleted 
= TRUE
; 
 374 #ifndef __WXUNIVERSAL__ 
 375     // VS: make sure there's no wxFrame with last focus set to us: 
 376     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
 378         wxTopLevelWindow 
*frame 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 381             if ( frame
->GetLastFocus() == this ) 
 383                 frame
->SetLastFocus(NULL
); 
 388 #endif // __WXUNIVERSAL__ 
 390     // VS: destroy children first and _then_ detach *this from its parent. 
 391     //     If we'd do it the other way around, children wouldn't be able 
 392     //     find their parent frame (see above). 
 396         m_parent
->RemoveChild(this); 
 400         // VZ: test temp removed to understand what really happens here 
 401         //if (::IsWindow(GetHwnd())) 
 403             if ( !::DestroyWindow(GetHwnd()) ) 
 404                 wxLogLastError(wxT("DestroyWindow")); 
 407         // remove hWnd <-> wxWindow association 
 408         wxRemoveHandleAssociation(this); 
 411     delete m_childrenDisabled
; 
 414 // real construction (Init() must have been called before!) 
 415 bool wxWindowMSW::Create(wxWindow 
*parent
, 
 420                          const wxString
& name
) 
 422     wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") ); 
 424     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 427     parent
->AddChild(this); 
 430     DWORD msflags 
= MSWGetCreateWindowFlags(&exstyle
); 
 432 #ifdef __WXUNIVERSAL__ 
 433     // no borders, we draw them ourselves 
 434     exstyle 
&= ~(WS_EX_DLGMODALFRAME 
| 
 438     msflags 
&= ~WS_BORDER
; 
 439 #endif // wxUniversal 
 441     // all windows are created visible by default except popup ones (which are 
 442     // like the wxTopLevelWindows in this aspect) 
 443     if ( style 
& wxPOPUP_WINDOW 
) 
 445         msflags 
&= ~WS_VISIBLE
; 
 450         msflags 
|= WS_VISIBLE
; 
 453     return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
); 
 456 // --------------------------------------------------------------------------- 
 458 // --------------------------------------------------------------------------- 
 460 void wxWindowMSW::SetFocus() 
 462     HWND hWnd 
= GetHwnd(); 
 463     wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") ); 
 465 #ifndef __WXMICROWIN__ 
 469     if ( !::SetFocus(hWnd
) ) 
 471 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__) 
 472         // was there really an error? 
 473         DWORD dwRes 
= ::GetLastError(); 
 476             HWND hwndFocus 
= ::GetFocus(); 
 477             if ( hwndFocus 
!= hWnd 
) 
 479                 wxLogApiError(_T("SetFocus"), dwRes
); 
 486 void wxWindowMSW::SetFocusFromKbd() 
 488     wxWindowBase::SetFocusFromKbd(); 
 490     // when the focus is given to the control with DLGC_HASSETSEL style from 
 491     // keyboard its contents should be entirely selected: this is what 
 492     // ::IsDialogMessage() does and so we should do it as well to provide the 
 493     // same LNF as the native programs 
 494     if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL 
) 
 496         ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1); 
 500 // Get the window with the focus 
 501 wxWindow 
*wxWindowBase::FindFocus() 
 503     HWND hWnd 
= ::GetFocus(); 
 506         return wxGetWindowFromHWND((WXHWND
)hWnd
); 
 512 bool wxWindowMSW::Enable(bool enable
) 
 514     if ( !wxWindowBase::Enable(enable
) ) 
 517     HWND hWnd 
= GetHwnd(); 
 519         ::EnableWindow(hWnd
, (BOOL
)enable
); 
 521     // the logic below doesn't apply to the top level windows -- otherwise 
 522     // showing a modal dialog would result in total greying out (and ungreying 
 523     // out later) of everything which would be really ugly 
 527     // when the parent is disabled, all of its children should be disabled as 
 528     // well but when it is enabled back, only those of the children which 
 529     // hadn't been already disabled in the beginning should be enabled again, 
 530     // so we have to keep the list of those children 
 531     for ( wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
 533           node 
= node
->GetNext() ) 
 535         wxWindow 
*child 
= node
->GetData(); 
 536         if ( child
->IsTopLevel() ) 
 538             // the logic below doesn't apply to top level children 
 544             // enable the child back unless it had been disabled before us 
 545             if ( !m_childrenDisabled 
|| !m_childrenDisabled
->Find(child
) ) 
 548         else // we're being disabled 
 550             if ( child
->IsEnabled() ) 
 552                 // disable it as children shouldn't stay enabled while the 
 556             else // child already disabled, remember it 
 558                 // have we created the list of disabled children already? 
 559                 if ( !m_childrenDisabled 
) 
 560                     m_childrenDisabled 
= new wxWindowList
; 
 562                 m_childrenDisabled
->Append(child
); 
 567     if ( enable 
&& m_childrenDisabled 
) 
 569         // we don't need this list any more, don't keep unused memory 
 570         delete m_childrenDisabled
; 
 571         m_childrenDisabled 
= NULL
; 
 577 bool wxWindowMSW::Show(bool show
) 
 579     if ( !wxWindowBase::Show(show
) ) 
 582     HWND hWnd 
= GetHwnd(); 
 583     int cshow 
= show 
? SW_SHOW 
: SW_HIDE
; 
 584     ::ShowWindow(hWnd
, cshow
); 
 588         wxBringWindowToTop(hWnd
); 
 594 // Raise the window to the top of the Z order 
 595 void wxWindowMSW::Raise() 
 597     wxBringWindowToTop(GetHwnd()); 
 600 // Lower the window to the bottom of the Z order 
 601 void wxWindowMSW::Lower() 
 603     ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0, 
 604                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
 607 void wxWindowMSW::SetTitle( const wxString
& title
) 
 609     SetWindowText(GetHwnd(), title
.c_str()); 
 612 wxString 
wxWindowMSW::GetTitle() const 
 614     return wxGetWindowText(GetHWND()); 
 617 void wxWindowMSW::DoCaptureMouse() 
 619     HWND hWnd 
= GetHwnd(); 
 626 void wxWindowMSW::DoReleaseMouse() 
 628     if ( !::ReleaseCapture() ) 
 630         wxLogLastError(_T("ReleaseCapture")); 
 634 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 636     HWND hwnd 
= ::GetCapture(); 
 637     return hwnd 
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow 
*)NULL
; 
 640 bool wxWindowMSW::SetFont(const wxFont
& font
) 
 642     if ( !wxWindowBase::SetFont(font
) ) 
 648     HWND hWnd 
= GetHwnd(); 
 651         WXHANDLE hFont 
= m_font
.GetResourceHandle(); 
 653         wxASSERT_MSG( hFont
, wxT("should have valid font") ); 
 655         ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0)); 
 660 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
) 
 662     if ( !wxWindowBase::SetCursor(cursor
) ) 
 670         HWND hWnd 
= GetHwnd(); 
 672         // Change the cursor NOW if we're within the correct window 
 674         ::GetCursorPos(&point
); 
 676         RECT rect 
= wxGetWindowRect(hWnd
); 
 678         if ( ::PtInRect(&rect
, point
) && !wxIsBusy() ) 
 679             ::SetCursor(GetHcursorOf(m_cursor
)); 
 685 void wxWindowMSW::WarpPointer (int x
, int y
) 
 687     ClientToScreen(&x
, &y
); 
 689     if ( !::SetCursorPos(x
, y
) ) 
 691         wxLogLastError(_T("SetCursorPos")); 
 695 #if WXWIN_COMPATIBILITY 
 696 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const 
 699 #endif // WXWIN_COMPATIBILITY 
 701 // --------------------------------------------------------------------------- 
 703 // --------------------------------------------------------------------------- 
 705 // convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT 
 706 static inline int wxDirToWinStyle(int orient
) 
 708     return orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
; 
 711 #if WXWIN_COMPATIBILITY 
 712 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
) 
 716     // Try to adjust the range to cope with page size > 1 
 717     // - a Windows API quirk 
 718     int pageSize 
= GetScrollPage(orient
); 
 719     if ( pageSize 
> 1 && range 
> 0) 
 721         range1 
+= (pageSize 
- 1); 
 724     WinStruct
<SCROLLINFO
> info
; 
 725     info
.nPage 
= pageSize
; // Have to set this, or scrollbar goes awry 
 728     info
.fMask 
= SIF_RANGE 
| SIF_PAGE
; 
 730     HWND hWnd 
= GetHwnd(); 
 732         ::SetScrollInfo(hWnd
, wxDirToWinStyle(orient
), &info
, refresh
); 
 735 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
) 
 737     WinStruct
<SCROLLINFO
> info
; 
 739     info
.fMask 
= SIF_PAGE
; 
 741     HWND hWnd 
= GetHwnd(); 
 743         ::SetScrollInfo(hWnd
, wxDirToWinStyle(orient
), &info
, refresh
); 
 746 int wxWindowMSW::GetScrollPage(int orient
) const 
 748     return orient 
== wxHORIZONTAL 
? m_xThumbSize 
: m_yThumbSize
; 
 751 #endif // WXWIN_COMPATIBILITY 
 753 inline int GetScrollPosition(HWND hWnd
, int wOrient
) 
 755 #ifdef __WXMICROWIN__ 
 756     return ::GetScrollPosWX(hWnd
, wOrient
); 
 758     return ::GetScrollPos(hWnd
, wOrient
); 
 762 int wxWindowMSW::GetScrollPos(int orient
) const 
 764     HWND hWnd 
= GetHwnd(); 
 765     wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") ); 
 767     return GetScrollPosition(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
); 
 770 // This now returns the whole range, not just the number 
 771 // of positions that we can scroll. 
 772 int wxWindowMSW::GetScrollRange(int orient
) const 
 775     HWND hWnd 
= GetHwnd(); 
 779     ::GetScrollRange(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 782     // undo "range - 1" done in SetScrollbar() 
 786 int wxWindowMSW::GetScrollThumb(int orient
) const 
 788     return orient 
== wxHORIZONTAL 
? m_xThumbSize 
: m_yThumbSize
; 
 791 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
) 
 793     HWND hWnd 
= GetHwnd(); 
 794     wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") ); 
 796     WinStruct
<SCROLLINFO
> info
; 
 800     info
.fMask 
= SIF_POS
; 
 802     ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 806 // New function that will replace some of the above. 
 807 void wxWindowMSW::SetScrollbar(int orient
, 
 813     WinStruct
<SCROLLINFO
> info
; 
 814     info
.nPage 
= pageSize
; 
 815     info
.nMin 
= 0;              // range is nMax - nMin + 1 
 816     info
.nMax 
= range 
- 1;      //  as both nMax and nMax are inclusive 
 818     info
.fMask 
= SIF_RANGE 
| SIF_PAGE 
| SIF_POS
; 
 820     HWND hWnd 
= GetHwnd(); 
 823         ::SetScrollInfo(hWnd
, orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
, 
 827     *(orient 
== wxHORIZONTAL 
? &m_xThumbSize 
: &m_yThumbSize
) = pageSize
; 
 830 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect 
*prect
) 
 836         rect
.left 
= prect
->x
; 
 838         rect
.right 
= prect
->x 
+ prect
->width
; 
 839         rect
.bottom 
= prect
->y 
+ prect
->height
; 
 847     ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
); 
 850 static bool ScrollVertically(HWND hwnd
, int kind
, int count
) 
 852     int posStart 
= GetScrollPosition(hwnd
, SB_VERT
); 
 855     for ( int n 
= 0; n 
< count
; n
++ ) 
 857         ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0); 
 859         int posNew 
= GetScrollPosition(hwnd
, SB_VERT
); 
 862             // don't bother to continue, we're already at top/bottom 
 869     return pos 
!= posStart
; 
 872 bool wxWindowMSW::ScrollLines(int lines
) 
 874     bool down 
= lines 
> 0; 
 876     return ScrollVertically(GetHwnd(), 
 877                             down 
? SB_LINEDOWN 
: SB_LINEUP
, 
 878                             down 
? lines 
: -lines
); 
 881 bool wxWindowMSW::ScrollPages(int pages
) 
 883     bool down 
= pages 
> 0; 
 885     return ScrollVertically(GetHwnd(), 
 886                             down 
? SB_PAGEDOWN 
: SB_PAGEUP
, 
 887                             down 
? pages 
: -pages
); 
 890 // --------------------------------------------------------------------------- 
 892 // --------------------------------------------------------------------------- 
 894 void wxWindowMSW::SubclassWin(WXHWND hWnd
) 
 896     wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") ); 
 898     HWND hwnd 
= (HWND
)hWnd
; 
 899     wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") ); 
 901     wxAssociateWinWithHandle(hwnd
, this); 
 903     m_oldWndProc 
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
); 
 905     // we don't need to subclass the window of our own class (in the Windows 
 906     // sense of the word) 
 907     if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) ) 
 909         ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
); 
 913         // don't bother restoring it neither: this also makes it easy to 
 914         // implement IsOfStandardClass() method which returns TRUE for the 
 915         // standard controls and FALSE for the wxWindows own windows as it can 
 916         // simply check m_oldWndProc 
 921 void wxWindowMSW::UnsubclassWin() 
 923     wxRemoveHandleAssociation(this); 
 925     // Restore old Window proc 
 926     HWND hwnd 
= GetHwnd(); 
 931         wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") ); 
 935             if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) ) 
 937                 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
); 
 945 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
) 
 947     // Unicows note: the code below works, but only because WNDCLASS contains 
 948     // original window handler rather that the unicows fake one. This may not 
 949     // be on purpose, though; if it stops working with future versions of 
 950     // unicows.dll, we can override unicows hooks by setting 
 951     // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own 
 952     // versions that keep track of fake<->real wnd proc mapping. 
 954     if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd
), &cls
) ) 
 956         wxLogLastError(_T("GetClassInfo")); 
 961     return wndProc 
== (WXFARPROC
)cls
.lpfnWndProc
; 
 964 // ---------------------------------------------------------------------------- 
 966 // ---------------------------------------------------------------------------- 
 968 void wxWindowMSW::SetWindowStyleFlag(long flags
) 
 970     long flagsOld 
= GetWindowStyleFlag(); 
 971     if ( flags 
== flagsOld 
) 
 974     // update the internal variable 
 975     wxWindowBase::SetWindowStyleFlag(flags
); 
 977     // now update the Windows style as well if needed - and if the window had 
 978     // been already created 
 982     WXDWORD exstyle
, exstyleOld
; 
 983     long style 
= MSWGetStyle(flags
, &exstyle
), 
 984          styleOld 
= MSWGetStyle(flagsOld
, &exstyleOld
); 
 986     if ( style 
!= styleOld 
) 
 988         // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by 
 989         // this function so instead of simply setting the style to the new 
 990         // value we clear the bits which were set in styleOld but are set in 
 991         // the new one and set the ones which were not set before 
 992         long styleReal 
= ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
 993         styleReal 
&= ~styleOld
; 
 996         ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
); 
 999     // and the extended style 
1000     if ( exstyle 
!= exstyleOld 
) 
1002         long exstyleReal 
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1003         exstyleReal 
&= ~exstyleOld
; 
1004         exstyleReal 
|= exstyle
; 
1006         ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
); 
1008         // we must call SetWindowPos() to flash the cached extended style and 
1009         // also to make the change to wxSTAY_ON_TOP style take effect: just 
1010         // setting the style simply doesn't work 
1011         if ( !::SetWindowPos(GetHwnd(), 
1012                              exstyleReal 
& WS_EX_TOPMOST 
? HWND_TOPMOST
 
1015                              SWP_NOMOVE 
| SWP_NOSIZE
) ) 
1017             wxLogLastError(_T("SetWindowPos")); 
1022 WXDWORD 
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD 
*exstyle
) const 
1024     // translate the style 
1025     WXDWORD style 
= WS_CHILD 
| WS_VISIBLE
; 
1027     if ( flags 
& wxCLIP_CHILDREN 
) 
1028         style 
|= WS_CLIPCHILDREN
; 
1030     if ( flags 
& wxCLIP_SIBLINGS 
) 
1031         style 
|= WS_CLIPSIBLINGS
; 
1033     wxBorder border 
= (wxBorder
)(flags 
& wxBORDER_MASK
); 
1035     // Check if we want to automatically give it a sunken style. 
1036     // Note than because 'sunken' actually maps to WS_EX_CLIENTEDGE, which 
1037     // is a more neutral term, we don't necessarily get a sunken effect in 
1038     // Windows XP. Instead we get the appropriate style for the theme. 
1040     if (border 
== wxBORDER_DEFAULT 
&& wxTheApp
->GetAuto3D() &&  
1041         IsKindOf(CLASSINFO(wxControl
)) && 
1042         GetParent() && (GetParent()->IsKindOf(CLASSINFO(wxPanel
)) || 
1043                         GetParent()->IsKindOf(CLASSINFO(wxDialog
))) && 
1044         ((GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
)) 
1046         border 
= (wxBorder
)((flags 
& wxBORDER_MASK
) | wxBORDER_SUNKEN
); 
1049     // Only give it WS_BORDER for wxBORDER_SIMPLE 
1050     if (border 
& wxBORDER_SIMPLE
) 
1053     // now deal with ext style if the caller wants it 
1058         if ( flags 
& wxTRANSPARENT_WINDOW 
) 
1059             *exstyle 
|= WS_EX_TRANSPARENT
; 
1064                 wxFAIL_MSG( _T("unknown border style") ); 
1068             case wxBORDER_SIMPLE
: 
1069             case wxBORDER_DEFAULT
: 
1072             case wxBORDER_STATIC
: 
1073                 *exstyle 
|= WS_EX_STATICEDGE
; 
1076             case wxBORDER_RAISED
: 
1077                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1080             case wxBORDER_SUNKEN
: 
1081                 *exstyle 
|= WS_EX_CLIENTEDGE
; 
1082                 style 
&= ~WS_BORDER
; 
1085             case wxBORDER_DOUBLE
: 
1086                 *exstyle 
|= WS_EX_DLGMODALFRAME
; 
1090         // wxUniv doesn't use Windows dialog navigation functions at all 
1091 #ifndef __WXUNIVERSAL__ 
1092         // to make the dialog navigation work with the nested panels we must 
1093         // use this style (top level windows such as dialogs don't need it) 
1094         if ( (flags 
& wxTAB_TRAVERSAL
) && !IsTopLevel() ) 
1096             *exstyle 
|= WS_EX_CONTROLPARENT
; 
1098 #endif // __WXUNIVERSAL__ 
1104 #if WXWIN_COMPATIBILITY 
1105 // If nothing defined for this, try the parent. 
1106 // E.g. we may be a button loaded from a resource, with no callback function 
1108 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
) 
1110     if ( GetEventHandler()->ProcessEvent(event
)  ) 
1113         m_parent
->GetEventHandler()->OnCommand(win
, event
); 
1115 #endif // WXWIN_COMPATIBILITY_2 
1117 #if WXWIN_COMPATIBILITY 
1118 wxObject
* wxWindowMSW::GetChild(int number
) const 
1120     // Return a pointer to the Nth object in the Panel 
1121     wxNode 
*node 
= GetChildren().First(); 
1124         node 
= node
->Next(); 
1127         wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
1133 #endif // WXWIN_COMPATIBILITY 
1135 // Setup background and foreground colours correctly 
1136 void wxWindowMSW::SetupColours() 
1139         SetBackgroundColour(GetParent()->GetBackgroundColour()); 
1142 bool wxWindowMSW::IsMouseInWindow() const 
1144     // get the mouse position 
1146     ::GetCursorPos(&pt
); 
1148     // find the window which currently has the cursor and go up the window 
1149     // chain until we find this window - or exhaust it 
1150     HWND hwnd 
= ::WindowFromPoint(pt
); 
1151     while ( hwnd 
&& (hwnd 
!= GetHwnd()) ) 
1152         hwnd 
= ::GetParent(hwnd
); 
1154     return hwnd 
!= NULL
; 
1157 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
)) 
1159     // Check if we need to send a LEAVE event 
1160     if ( m_mouseInWindow 
) 
1162         // note that we should generate the leave event whether the window has 
1163         // or doesn't have mouse capture 
1164         if ( !IsMouseInWindow() ) 
1166             // Generate a LEAVE event 
1167             m_mouseInWindow 
= FALSE
; 
1169             // Unfortunately the mouse button and keyboard state may have 
1170             // changed by the time the OnIdle function is called, so 'state' 
1171             // may be meaningless. 
1173             if ( wxIsShiftDown() ) 
1175             if ( wxIsCtrlDown() ) 
1176                 state 
|= MK_CONTROL
; 
1177             if ( GetKeyState( VK_LBUTTON 
) ) 
1178                 state 
|= MK_LBUTTON
; 
1179             if ( GetKeyState( VK_MBUTTON 
) ) 
1180                 state 
|= MK_MBUTTON
; 
1181             if ( GetKeyState( VK_RBUTTON 
) ) 
1182                 state 
|= MK_RBUTTON
; 
1185             if ( !::GetCursorPos(&pt
) ) 
1187                 wxLogLastError(_T("GetCursorPos")); 
1190             // we need to have client coordinates here for symmetry with 
1191             // wxEVT_ENTER_WINDOW 
1192             RECT rect 
= wxGetWindowRect(GetHwnd()); 
1196             wxMouseEvent 
event2(wxEVT_LEAVE_WINDOW
); 
1197             InitMouseEvent(event2
, pt
.x
, pt
.y
, state
); 
1199             (void)GetEventHandler()->ProcessEvent(event2
); 
1206 // Set this window to be the child of 'parent'. 
1207 bool wxWindowMSW::Reparent(wxWindowBase 
*parent
) 
1209     if ( !wxWindowBase::Reparent(parent
) ) 
1212     HWND hWndChild 
= GetHwnd(); 
1213     HWND hWndParent 
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0; 
1215     ::SetParent(hWndChild
, hWndParent
); 
1220 void wxWindowMSW::Clear() 
1222     wxClientDC 
dc((wxWindow 
*)this); 
1223     wxBrush 
brush(GetBackgroundColour(), wxSOLID
); 
1224     dc
.SetBackground(brush
); 
1228 static inline void SendSetRedraw(HWND hwnd
, bool on
) 
1230 #ifndef __WXMICROWIN__ 
1231     ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0); 
1235 void wxWindowMSW::Freeze() 
1237     SendSetRedraw(GetHwnd(), FALSE
); 
1240 void wxWindowMSW::Thaw() 
1242     SendSetRedraw(GetHwnd(), TRUE
); 
1244     // we need to refresh everything or otherwise he invalidated area is not 
1249 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1251     HWND hWnd 
= GetHwnd(); 
1257             mswRect
.left 
= rect
->x
; 
1258             mswRect
.top 
= rect
->y
; 
1259             mswRect
.right 
= rect
->x 
+ rect
->width
; 
1260             mswRect
.bottom 
= rect
->y 
+ rect
->height
; 
1262             ::InvalidateRect(hWnd
, &mswRect
, eraseBack
); 
1265             ::InvalidateRect(hWnd
, NULL
, eraseBack
); 
1269 void wxWindowMSW::Update() 
1271     if ( !::UpdateWindow(GetHwnd()) ) 
1273         wxLogLastError(_T("UpdateWindow")); 
1276 #if defined(__WIN32__) && !defined(__WXMICROWIN__) 
1277     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT 
1278     // handler needs to be really drawn right now 
1283 // --------------------------------------------------------------------------- 
1285 // --------------------------------------------------------------------------- 
1288 #if wxUSE_DRAG_AND_DROP 
1289 void wxWindowMSW::SetDropTarget(wxDropTarget 
*pDropTarget
) 
1291     if ( m_dropTarget 
!= 0 ) { 
1292         m_dropTarget
->Revoke(m_hWnd
); 
1293         delete m_dropTarget
; 
1296     m_dropTarget 
= pDropTarget
; 
1297     if ( m_dropTarget 
!= 0 ) 
1298         m_dropTarget
->Register(m_hWnd
); 
1300 #endif // wxUSE_DRAG_AND_DROP 
1302 // old style file-manager drag&drop support: we retain the old-style 
1303 // DragAcceptFiles in parallel with SetDropTarget. 
1304 void wxWindowMSW::DragAcceptFiles(bool accept
) 
1306     HWND hWnd 
= GetHwnd(); 
1308         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
1311 // ---------------------------------------------------------------------------- 
1313 // ---------------------------------------------------------------------------- 
1317 void wxWindowMSW::DoSetToolTip(wxToolTip 
*tooltip
) 
1319     wxWindowBase::DoSetToolTip(tooltip
); 
1322         m_tooltip
->SetWindow((wxWindow 
*)this); 
1325 #endif // wxUSE_TOOLTIPS 
1327 // --------------------------------------------------------------------------- 
1328 // moving and resizing 
1329 // --------------------------------------------------------------------------- 
1332 void wxWindowMSW::DoGetSize(int *x
, int *y
) const 
1334     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1337         *x 
= rect
.right 
- rect
.left
; 
1339         *y 
= rect
.bottom 
- rect
.top
; 
1342 // Get size *available for subwindows* i.e. excluding menu bar etc. 
1343 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const 
1345     RECT rect 
= wxGetClientRect(GetHwnd()); 
1353 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const 
1355     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1358     point
.x 
= rect
.left
; 
1361     // we do the adjustments with respect to the parent only for the "real" 
1362     // children, not for the dialogs/frames 
1363     if ( !IsTopLevel() ) 
1365         HWND hParentWnd 
= 0; 
1366         wxWindow 
*parent 
= GetParent(); 
1368             hParentWnd 
= GetWinHwnd(parent
); 
1370         // Since we now have the absolute screen coords, if there's a parent we 
1371         // must subtract its top left corner 
1374             ::ScreenToClient(hParentWnd
, &point
); 
1379             // We may be faking the client origin. So a window that's really at (0, 
1380             // 30) may appear (to wxWin apps) to be at (0, 0). 
1381             wxPoint 
pt(parent
->GetClientAreaOrigin()); 
1393 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const 
1401     ::ScreenToClient(GetHwnd(), &pt
); 
1409 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const 
1417     ::ClientToScreen(GetHwnd(), &pt
); 
1425 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
) 
1427     // TODO: is this consistent with other platforms? 
1428     // Still, negative width or height shouldn't be allowed 
1433     if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) ) 
1435         wxLogLastError(wxT("MoveWindow")); 
1439 // set the size of the window: if the dimensions are positive, just use them, 
1440 // but if any of them is equal to -1, it means that we must find the value for 
1441 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
1442 // which case -1 is a valid value for x and y) 
1444 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
1445 // the width/height to best suit our contents, otherwise we reuse the current 
1447 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
1449     // get the current size and position... 
1450     int currentX
, currentY
; 
1451     GetPosition(¤tX
, ¤tY
); 
1452     int currentW
,currentH
; 
1453     GetSize(¤tW
, ¤tH
); 
1455     // ... and don't do anything (avoiding flicker) if it's already ok 
1456     if ( x 
== currentX 
&& y 
== currentY 
&& 
1457          width 
== currentW 
&& height 
== currentH 
) 
1462     if ( x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1464     if ( y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1467     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
1469     wxSize 
size(-1, -1); 
1472         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
1474             size 
= DoGetBestSize(); 
1479             // just take the current one 
1486         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
1490                 size 
= DoGetBestSize(); 
1492             //else: already called DoGetBestSize() above 
1498             // just take the current one 
1503     DoMoveWindow(x
, y
, width
, height
); 
1506 void wxWindowMSW::DoSetClientSize(int width
, int height
) 
1508     // setting the client size is less obvious than it it could have been 
1509     // because in the result of changing the total size the window scrollbar 
1510     // may [dis]appear and/or its menubar may [un]wrap and so the client size 
1511     // will not be correct as the difference between the total and client size 
1512     // changes - so we keep changing it until we get it right 
1514     // normally this loop shouldn't take more than 3 iterations (usually 1 but 
1515     // if scrollbars [dis]appear as the result of the first call, then 2 and it 
1516     // may become 3 if the window had 0 size originally and so we didn't 
1517     // calculate the scrollbar correction correctly during the first iteration) 
1518     // but just to be on the safe side we check for it instead of making it an 
1519     // "infinite" loop (i.e. leaving break inside as the only way to get out) 
1520     for ( int i 
= 0; i 
< 4; i
++ ) 
1523         ::GetClientRect(GetHwnd(), &rectClient
); 
1525         // if the size is already ok, stop here (rectClient.left = top = 0) 
1526         if ( (rectClient
.right 
== width 
|| width 
== -1) && 
1527              (rectClient
.bottom 
== height 
|| height 
== -1) ) 
1532         int widthClient 
= width
, 
1533             heightClient 
= height
; 
1535         // Find the difference between the entire window (title bar and all) 
1536         // and the client area; add this to the new client size to move the 
1539         ::GetWindowRect(GetHwnd(), &rectWin
); 
1541         widthClient 
+= rectWin
.right 
- rectWin
.left 
- rectClient
.right
; 
1542         heightClient 
+= rectWin
.bottom 
- rectWin
.top 
- rectClient
.bottom
; 
1545         point
.x 
= rectWin
.left
; 
1546         point
.y 
= rectWin
.top
; 
1548         // MoveWindow positions the child windows relative to the parent, so 
1549         // adjust if necessary 
1550         if ( !IsTopLevel() ) 
1552             wxWindow 
*parent 
= GetParent(); 
1555                 ::ScreenToClient(GetHwndOf(parent
), &point
); 
1559         DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
); 
1563 // For implementation purposes - sometimes decorations make the client area 
1565 wxPoint 
wxWindowMSW::GetClientAreaOrigin() const 
1567     return wxPoint(0, 0); 
1570 // --------------------------------------------------------------------------- 
1572 // --------------------------------------------------------------------------- 
1574 int wxWindowMSW::GetCharHeight() const 
1576     return wxGetTextMetrics(this).tmHeight
; 
1579 int wxWindowMSW::GetCharWidth() const 
1581     // +1 is needed because Windows apparently adds it when calculating the 
1582     // dialog units size in pixels 
1583 #if wxDIALOG_UNIT_COMPATIBILITY 
1584     return wxGetTextMetrics(this).tmAveCharWidth
; 
1586     return wxGetTextMetrics(this).tmAveCharWidth 
+ 1; 
1590 void wxWindowMSW::GetTextExtent(const wxString
& string
, 
1592                              int *descent
, int *externalLeading
, 
1593                              const wxFont 
*theFont
) const 
1595     const wxFont 
*fontToUse 
= theFont
; 
1597         fontToUse 
= &m_font
; 
1599     HWND hWnd 
= GetHwnd(); 
1600     HDC dc 
= ::GetDC(hWnd
); 
1604     if ( fontToUse 
&& fontToUse
->Ok() ) 
1606         fnt 
= (HFONT
)((wxFont 
*)fontToUse
)->GetResourceHandle(); // const_cast 
1608             hfontOld 
= (HFONT
)SelectObject(dc
,fnt
); 
1613     GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
); 
1614     GetTextMetrics(dc
, &tm
); 
1616     if ( fontToUse 
&& fnt 
&& hfontOld 
) 
1617         SelectObject(dc
, hfontOld
); 
1619     ReleaseDC(hWnd
, dc
); 
1626         *descent 
= tm
.tmDescent
; 
1627     if ( externalLeading 
) 
1628         *externalLeading 
= tm
.tmExternalLeading
; 
1631 #if wxUSE_CARET && WXWIN_COMPATIBILITY 
1632 // --------------------------------------------------------------------------- 
1633 // Caret manipulation 
1634 // --------------------------------------------------------------------------- 
1636 void wxWindowMSW::CreateCaret(int w
, int h
) 
1638     SetCaret(new wxCaret(this, w
, h
)); 
1641 void wxWindowMSW::CreateCaret(const wxBitmap 
*WXUNUSED(bitmap
)) 
1643     wxFAIL_MSG("not implemented"); 
1646 void wxWindowMSW::ShowCaret(bool show
) 
1648     wxCHECK_RET( m_caret
, "no caret to show" ); 
1650     m_caret
->Show(show
); 
1653 void wxWindowMSW::DestroyCaret() 
1658 void wxWindowMSW::SetCaretPos(int x
, int y
) 
1660     wxCHECK_RET( m_caret
, "no caret to move" ); 
1662     m_caret
->Move(x
, y
); 
1665 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const 
1667     wxCHECK_RET( m_caret
, "no caret to get position of" ); 
1669     m_caret
->GetPosition(x
, y
); 
1671 #endif // wxUSE_CARET 
1673 // --------------------------------------------------------------------------- 
1675 // --------------------------------------------------------------------------- 
1677 #if wxUSE_MENUS_NATIVE 
1679 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue 
1680 // immediately, without waiting for the next event loop iteration 
1682 // NB: this function should probably be made public later as it can almost 
1683 //     surely replace wxYield() elsewhere as well 
1684 static void wxYieldForCommandsOnly() 
1686     // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't 
1687     // want to process it here) 
1689     while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) 
1690                 && msg
.message 
!= WM_QUIT 
) 
1692         wxTheApp
->DoMessage((WXMSG 
*)&msg
); 
1695     // If we retrieved a WM_QUIT, insert back into the message queue. 
1696     if (msg
.message 
== WM_QUIT
) 
1697         ::PostQuitMessage(0); 
1700 bool wxWindowMSW::DoPopupMenu(wxMenu 
*menu
, int x
, int y
) 
1702     menu
->SetInvokingWindow(this); 
1705     HWND hWnd 
= GetHwnd(); 
1706     HMENU hMenu 
= GetHmenuOf(menu
); 
1710     ::ClientToScreen(hWnd
, &point
); 
1711     wxCurrentPopupMenu 
= menu
; 
1712     ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
); 
1714     // we need to do it righ now as otherwise the events are never going to be 
1715     // sent to wxCurrentPopupMenu from HandleCommand() 
1717     // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't 
1718     // help and we'd still need wxYieldForCommandsOnly() as the menu may be 
1719     // destroyed as soon as we return (it can be a local variable in the caller 
1720     // for example) and so we do need to process the event immediately 
1721     wxYieldForCommandsOnly(); 
1723     wxCurrentPopupMenu 
= NULL
; 
1725     menu
->SetInvokingWindow(NULL
); 
1730 #endif // wxUSE_MENUS_NATIVE 
1732 // =========================================================================== 
1733 // pre/post message processing 
1734 // =========================================================================== 
1736 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
1739 #ifdef __DIGITALMARS__ 
1740         return ::CallWindowProc( (FARPROC
) m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
1742         return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
1745         return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
); 
1748 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
) 
1750     // wxUniversal implements tab traversal itself 
1751 #ifndef __WXUNIVERSAL__ 
1752     if ( m_hWnd 
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) ) 
1754         // intercept dialog navigation keys 
1755         MSG 
*msg 
= (MSG 
*)pMsg
; 
1757         // here we try to do all the job which ::IsDialogMessage() usually does 
1760         if ( msg
->message 
== WM_KEYDOWN 
) 
1762             bool bCtrlDown 
= wxIsCtrlDown(); 
1763             bool bShiftDown 
= wxIsShiftDown(); 
1765             // WM_GETDLGCODE: ask the control if it wants the key for itself, 
1766             // don't process it if it's the case (except for Ctrl-Tab/Enter 
1767             // combinations which are always processed) 
1771                 lDlgCode 
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0); 
1773                 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the 
1774                 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, 
1775                 // it, of course, implies them 
1776                 if ( lDlgCode 
& DLGC_WANTALLKEYS 
) 
1778                     lDlgCode 
|= DLGC_WANTTAB 
| DLGC_WANTARROWS
; 
1782             bool bForward 
= TRUE
, 
1783                  bWindowChange 
= FALSE
; 
1785             // should we process this message specially? 
1786             bool bProcess 
= TRUE
; 
1787             switch ( msg
->wParam 
) 
1790                     // assume that nobody wants Shift-TAB for himself - if we 
1791                     // don't do it there is no easy way for a control to grab 
1792                     // TABs but still let Shift-TAB work as navugation key 
1793                     if ( (lDlgCode 
& DLGC_WANTTAB
) && !bShiftDown 
) { 
1797                         // Ctrl-Tab cycles thru notebook pages 
1798                         bWindowChange 
= bCtrlDown
; 
1799                         bForward 
= !bShiftDown
; 
1805                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1813                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1819                         if ( (lDlgCode 
& DLGC_WANTMESSAGE
) && !bCtrlDown 
) 
1821                             // control wants to process Enter itself, don't 
1822                             // call IsDialogMessage() which would interpret 
1826                         else if ( lDlgCode 
& DLGC_BUTTON 
) 
1828                             // let IsDialogMessage() handle this for all 
1829                             // buttons except the owner-drawn ones which it 
1830                             // just seems to ignore 
1831                             long style 
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
); 
1832                             if ( (style 
& BS_OWNERDRAW
) == BS_OWNERDRAW 
) 
1834                                 // emulate the button click 
1835                                 wxWindow 
*btn 
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
); 
1837                                     btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1842                         // FIXME: this should be handled by 
1843                         //        wxNavigationKeyEvent handler and not here!! 
1847                             wxButton 
*btn 
= wxDynamicCast(GetDefaultItem(), 
1849                             if ( btn 
&& btn
->IsEnabled() ) 
1851                                 // if we do have a default button, do press it 
1852                                 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1856                             else // no default button 
1858 #endif // wxUSE_BUTTON 
1859                                 // this is a quick and dirty test for a text 
1861                                 if ( !(lDlgCode 
& DLGC_HASSETSEL
) ) 
1863                                     // don't process Enter, the control might 
1864                                     // need it for itself and don't let 
1865                                     // ::IsDialogMessage() have it as it can 
1866                                     // eat the Enter events sometimes 
1869                                 else if (!IsTopLevel()) 
1871                                     // if not a top level window, let parent 
1875                                 //else: treat Enter as TAB: pass to the next 
1876                                 //      control as this is the best thing to do 
1877                                 //      if the text doesn't handle Enter itself 
1889                 wxNavigationKeyEvent event
; 
1890                 event
.SetDirection(bForward
); 
1891                 event
.SetWindowChange(bWindowChange
); 
1892                 event
.SetEventObject(this); 
1894                 if ( GetEventHandler()->ProcessEvent(event
) ) 
1901         // let ::IsDialogMessage() do almost everything and handle just the 
1902         // things it doesn't here: Ctrl-TAB for switching notebook pages 
1903         if ( msg
->message 
== WM_KEYDOWN 
) 
1905             // don't process system keys here 
1906             if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) ) 
1908                 if ( (msg
->wParam 
== VK_TAB
) && wxIsCtrlDown() ) 
1910                     // find the first notebook parent and change its page 
1911                     wxWindow 
*win 
= this; 
1912                     wxNotebook 
*nbook 
= NULL
; 
1913                     while ( win 
&& !nbook 
) 
1915                         nbook 
= wxDynamicCast(win
, wxNotebook
); 
1916                         win 
= win
->GetParent(); 
1921                         bool forward 
= !wxIsShiftDown(); 
1923                         nbook
->AdvanceSelection(forward
); 
1930         // we handle VK_ESCAPE ourselves in wxDialog::OnCharHook() and we 
1931         // shouldn't let IsDialogMessage() get it as it _always_ eats the 
1932         // message even when there is no cancel button and when the message is 
1933         // needed by the control itself: in particular, it prevents the tree in 
1934         // place edit control from being closed with Escape in a dialog 
1935         if ( msg
->message 
!= WM_KEYDOWN 
|| msg
->wParam 
!= VK_ESCAPE 
) 
1937             // ::IsDialogMessage() can enter in an infinite loop when the 
1938             // currently focused window is disabled or hidden and its parent 
1939             // has WS_EX_CONTROLPARENT style, so don't call it in this case 
1940             bool canSafelyCallIsDlgMsg 
= TRUE
; 
1942             HWND hwndFocus 
= ::GetFocus(); 
1945                 if ( !::IsWindowEnabled(hwndFocus
) || 
1946                         !::IsWindowVisible(hwndFocus
) ) 
1948                     // it would enter an infinite loop if we do this! 
1949                     canSafelyCallIsDlgMsg 
= FALSE
; 
1954                 if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) ) 
1956                     // it's a top level window, don't go further -- e.g. even 
1957                     // if the parent of a dialog is disabled, this doesn't 
1958                     // break navigation inside the dialog 
1962                 hwndFocus 
= ::GetParent(hwndFocus
); 
1965             if ( canSafelyCallIsDlgMsg 
&& ::IsDialogMessage(GetHwnd(), msg
) ) 
1967                 // IsDialogMessage() did something... 
1972 #endif // __WXUNIVERSAL__ 
1977         // relay mouse move events to the tooltip control 
1978         MSG 
*msg 
= (MSG 
*)pMsg
; 
1979         if ( msg
->message 
== WM_MOUSEMOVE 
) 
1980             m_tooltip
->RelayEvent(pMsg
); 
1982 #endif // wxUSE_TOOLTIPS 
1987 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
) 
1989 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__) 
1990     return m_acceleratorTable
.Translate(this, pMsg
); 
1994 #endif // wxUSE_ACCEL 
1997 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
)) 
1999     // preprocess all messages by default 
2003 // --------------------------------------------------------------------------- 
2004 // message params unpackers (different for Win16 and Win32) 
2005 // --------------------------------------------------------------------------- 
2009 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2010                              WORD 
*id
, WXHWND 
*hwnd
, WORD 
*cmd
) 
2012     *id 
= LOWORD(wParam
); 
2013     *hwnd 
= (WXHWND
)lParam
; 
2014     *cmd 
= HIWORD(wParam
); 
2017 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2018                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2020     *state 
= LOWORD(wParam
); 
2021     *minimized 
= HIWORD(wParam
); 
2022     *hwnd 
= (WXHWND
)lParam
; 
2025 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2026                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2028     *code 
= LOWORD(wParam
); 
2029     *pos 
= HIWORD(wParam
); 
2030     *hwnd 
= (WXHWND
)lParam
; 
2033 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2034                               WXWORD 
*nCtlColor
, WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2036 #ifndef __WXMICROWIN__ 
2037     *nCtlColor 
= CTLCOLOR_BTN
; 
2038     *hwnd 
= (WXHWND
)lParam
; 
2039     *hdc 
= (WXHDC
)wParam
; 
2043 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2044                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2046     *item 
= (WXWORD
)wParam
; 
2047     *flags 
= HIWORD(wParam
); 
2048     *hmenu 
= (WXHMENU
)lParam
; 
2053 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2054                              WXWORD 
*id
, WXHWND 
*hwnd
, WXWORD 
*cmd
) 
2056     *id 
= (WXWORD
)wParam
; 
2057     *hwnd 
= (WXHWND
)LOWORD(lParam
); 
2058     *cmd 
= HIWORD(lParam
); 
2061 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2062                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2064     *state 
= (WXWORD
)wParam
; 
2065     *minimized 
= LOWORD(lParam
); 
2066     *hwnd 
= (WXHWND
)HIWORD(lParam
); 
2069 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2070                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2072     *code 
= (WXWORD
)wParam
; 
2073     *pos 
= LOWORD(lParam
); 
2074     *hwnd 
= (WXHWND
)HIWORD(lParam
); 
2077 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2078                               WXWORD 
*nCtlColor
, WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2080     *hwnd 
= (WXHWND
)LOWORD(lParam
); 
2081     *nCtlColor 
= (int)HIWORD(lParam
); 
2082     *hdc 
= (WXHDC
)wParam
; 
2085 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2086                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2088     *item 
= (WXWORD
)wParam
; 
2089     *flags 
= LOWORD(lParam
); 
2090     *hmenu 
= (WXHMENU
)HIWORD(lParam
); 
2095 // --------------------------------------------------------------------------- 
2096 // Main wxWindows window proc and the window proc for wxWindow 
2097 // --------------------------------------------------------------------------- 
2099 // Hook for new window just as it's being created, when the window isn't yet 
2100 // associated with the handle 
2101 static wxWindowMSW 
*gs_winBeingCreated 
= NULL
; 
2103 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the 
2104 // window being created and insures that it's always unset back later 
2105 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW 
*winBeingCreated
) 
2107     gs_winBeingCreated 
= winBeingCreated
; 
2110 wxWindowCreationHook::~wxWindowCreationHook() 
2112     gs_winBeingCreated 
= NULL
; 
2116 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) 
2118     // trace all messages - useful for the debugging 
2121     wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"), 
2122                wxGetMessageName(message
), (long) wParam
, lParam
); 
2124 #endif // __WXDEBUG__ 
2126     wxWindowMSW 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2128     // when we get the first message for the HWND we just created, we associate 
2129     // it with wxWindow stored in gs_winBeingCreated 
2130     if ( !wnd 
&& gs_winBeingCreated 
) 
2132         wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
); 
2133         wnd 
= gs_winBeingCreated
; 
2134         gs_winBeingCreated 
= NULL
; 
2135         wnd
->SetHWND((WXHWND
)hWnd
); 
2141         rc 
= wnd
->MSWWindowProc(message
, wParam
, lParam
); 
2143         rc 
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
); 
2148 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
2150     // did we process the message? 
2151     bool processed 
= FALSE
; 
2162     // for most messages we should return 0 when we do process the message 
2170                 processed 
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
); 
2173                     // return 0 to allow window creation 
2174                     rc
.result 
= mayCreate 
? 0 : -1; 
2180             // never set processed to TRUE and *always* pass WM_DESTROY to 
2181             // DefWindowProc() as Windows may do some internal cleanup when 
2182             // processing it and failing to pass the message along may cause 
2183             // memory and resource leaks! 
2184             (void)HandleDestroy(); 
2188             processed 
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2193                                 LPRECT pRect 
= (LPRECT
)lParam
; 
2195                                 rc
.SetLeft(pRect
->left
); 
2196                                 rc
.SetTop(pRect
->top
); 
2197                                 rc
.SetRight(pRect
->right
); 
2198                                 rc
.SetBottom(pRect
->bottom
); 
2199                                 processed 
= HandleMoving(rc
); 
2201                                         pRect
->left 
= rc
.GetLeft(); 
2202                                         pRect
->top 
= rc
.GetTop(); 
2203                                         pRect
->right 
= rc
.GetRight(); 
2204                                         pRect
->bottom 
= rc
.GetBottom(); 
2214                     // we're not interested in these messages at all 
2217                 case SIZE_MINIMIZED
: 
2218                     // we shouldn't send sizev events for these messages as the 
2219                     // client size may be negative which breaks existing code 
2221                     // OTOH we might send another (wxMinimizedEvent?) one or 
2222                     // add an additional parameter to wxSizeEvent if this is 
2223                     // useful to anybody 
2227                     wxFAIL_MSG( _T("unexpected WM_SIZE parameter") ); 
2228                     // fall through nevertheless 
2230                 case SIZE_MAXIMIZED
: 
2232                     processed 
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), 
2239                 LPRECT pRect 
= (LPRECT
)lParam
; 
2241                 rc
.SetLeft(pRect
->left
); 
2242                 rc
.SetTop(pRect
->top
); 
2243                 rc
.SetRight(pRect
->right
); 
2244                 rc
.SetBottom(pRect
->bottom
); 
2245                 processed 
= HandleSizing(rc
); 
2247                     pRect
->left 
= rc
.GetLeft(); 
2248                     pRect
->top 
= rc
.GetTop(); 
2249                     pRect
->right 
= rc
.GetRight(); 
2250                     pRect
->bottom 
= rc
.GetBottom(); 
2255 #ifndef __WXMICROWIN__ 
2256         case WM_ACTIVATEAPP
: 
2257             wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
2263                 WXWORD state
, minimized
; 
2265                 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
); 
2267                 processed 
= HandleActivate(state
, minimized 
!= 0, (WXHWND
)hwnd
); 
2272             processed 
= HandleSetFocus((WXHWND
)(HWND
)wParam
); 
2276             processed 
= HandleKillFocus((WXHWND
)(HWND
)wParam
); 
2280             processed 
= HandlePaint(); 
2284 #ifdef __WXUNIVERSAL__ 
2285             // Universal uses its own wxFrame/wxDialog, so we don't receive 
2286             // close events unless we have this. 
2291             // don't let the DefWindowProc() destroy our window - we'll do it 
2292             // ourselves in ~wxWindow 
2299             processed 
= HandleShow(wParam 
!= 0, (int)lParam
); 
2303             processed 
= HandleMouseMove(GET_X_LPARAM(lParam
), 
2304                                         GET_Y_LPARAM(lParam
), 
2308 #if wxUSE_MOUSEWHEEL 
2310             processed 
= HandleMouseWheel(wParam
, lParam
); 
2314         case WM_LBUTTONDOWN
: 
2316         case WM_LBUTTONDBLCLK
: 
2317         case WM_RBUTTONDOWN
: 
2319         case WM_RBUTTONDBLCLK
: 
2320         case WM_MBUTTONDOWN
: 
2322         case WM_MBUTTONDBLCLK
: 
2324 #ifdef __WXMICROWIN__ 
2325                 // MicroWindows seems to ignore the fact that a window is 
2326                 // disabled. So catch mouse events and throw them away if 
2328                 wxWindowMSW
* win 
= this; 
2331                     if (!win
->IsEnabled()) 
2337                     win 
= win
->GetParent(); 
2338                     if ( !win 
|| win
->IsTopLevel() ) 
2345 #endif // __WXMICROWIN__ 
2346                 int x 
= GET_X_LPARAM(lParam
), 
2347                     y 
= GET_Y_LPARAM(lParam
); 
2349                 // redirect the event to a static control if necessary by 
2350                 // finding one under mouse 
2352                 if ( GetCapture() == this ) 
2354                     // but don't do it if the mouse is captured by this window 
2355                     // because then it should really get this event itself 
2360                     win 
= FindWindowForMouseEvent(this, &x
, &y
); 
2362                     // this should never happen 
2363                     wxCHECK_MSG( win
, 0, 
2364                                  _T("FindWindowForMouseEvent() returned NULL") ); 
2366                     // for the standard classes their WndProc sets the focus to 
2367                     // them anyhow and doing it from here results in some weird 
2368                     // problems, but for our windows we want them to acquire 
2369                     // focus when clicked 
2370                     if ( !win
->IsOfStandardClass() ) 
2372                         if ( message 
== WM_LBUTTONDOWN 
&& win
->AcceptsFocus() ) 
2377                 processed 
= win
->HandleMouseEvent(message
, x
, y
, wParam
); 
2386         case MM_JOY1BUTTONDOWN
: 
2387         case MM_JOY2BUTTONDOWN
: 
2388         case MM_JOY1BUTTONUP
: 
2389         case MM_JOY2BUTTONUP
: 
2390             processed 
= HandleJoystickEvent(message
, 
2391                                             GET_X_LPARAM(lParam
), 
2392                                             GET_Y_LPARAM(lParam
), 
2395 #endif // __WXMICROWIN__ 
2398             processed 
= HandleSysCommand(wParam
, lParam
); 
2405                 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
); 
2407                 processed 
= HandleCommand(id
, cmd
, hwnd
); 
2413             processed 
= HandleNotify((int)wParam
, lParam
, &rc
.result
); 
2417             // for these messages we must return TRUE if process the message 
2420         case WM_MEASUREITEM
: 
2422                 int idCtrl 
= (UINT
)wParam
; 
2423                 if ( message 
== WM_DRAWITEM 
) 
2425                     processed 
= MSWOnDrawItem(idCtrl
, 
2426                                               (WXDRAWITEMSTRUCT 
*)lParam
); 
2430                     processed 
= MSWOnMeasureItem(idCtrl
, 
2431                                                  (WXMEASUREITEMSTRUCT 
*)lParam
); 
2438 #endif // defined(WM_DRAWITEM) 
2441             if ( !IsOfStandardClass() ) 
2443                 // we always want to get the char events 
2444                 rc
.result 
= DLGC_WANTCHARS
; 
2446                 if ( GetWindowStyleFlag() & wxWANTS_CHARS 
) 
2448                     // in fact, we want everything 
2449                     rc
.result 
|= DLGC_WANTARROWS 
| 
2456             //else: get the dlg code from the DefWindowProc() 
2461             // If this has been processed by an event handler, return 0 now 
2462             // (we've handled it). 
2463             m_lastKeydownProcessed 
= HandleKeyDown((WORD
) wParam
, lParam
); 
2464             if ( m_lastKeydownProcessed 
) 
2473                     // we consider these message "not interesting" to OnChar, so 
2474                     // just don't do anything more with them 
2484                     // avoid duplicate messages to OnChar for these ASCII keys: 
2485                     // they will be translated by TranslateMessage() and received 
2507                         // but set processed to FALSE, not TRUE to still pass them 
2508                         // to the control's default window proc - otherwise 
2509                         // built-in keyboard handling won't work 
2514                     // special case of VK_APPS: treat it the same as right mouse 
2515                     // click because both usually pop up a context menu 
2521                             TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2522                             processed 
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
); 
2528                         // do generate a CHAR event 
2529                         processed 
= HandleChar((WORD
)wParam
, lParam
); 
2532             if (message 
== WM_SYSKEYDOWN
)  // Let Windows still handle the SYSKEYs 
2539             // special case of VK_APPS: treat it the same as right mouse button 
2540             if ( wParam 
== VK_APPS 
) 
2545                 TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2546                 processed 
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
); 
2551                 processed 
= HandleKeyUp((WORD
) wParam
, lParam
); 
2556         case WM_CHAR
: // Always an ASCII character 
2557             if ( m_lastKeydownProcessed 
) 
2559                 // The key was handled in the EVT_KEY_DOWN and handling 
2560                 // a key in an EVT_KEY_DOWN handler is meant, by 
2561                 // design, to prevent EVT_CHARs from happening 
2562                 m_lastKeydownProcessed 
= FALSE
; 
2567                 processed 
= HandleChar((WORD
)wParam
, lParam
, TRUE
); 
2576                 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
); 
2578                 processed 
= MSWOnScroll(message 
== WM_HSCROLL 
? wxHORIZONTAL
 
2584         // CTLCOLOR messages are sent by children to query the parent for their 
2585         // colors#ifndef __WXMICROWIN__ 
2586 #ifndef __WXMICROWIN__ 
2588         case WM_CTLCOLORMSGBOX
: 
2589         case WM_CTLCOLOREDIT
: 
2590         case WM_CTLCOLORLISTBOX
: 
2591         case WM_CTLCOLORBTN
: 
2592         case WM_CTLCOLORDLG
: 
2593         case WM_CTLCOLORSCROLLBAR
: 
2594         case WM_CTLCOLORSTATIC
: 
2602                 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
); 
2604                 processed 
= HandleCtlColor(&rc
.hBrush
, 
2613 #endif // !__WXMICROWIN__ 
2615         case WM_SYSCOLORCHANGE
: 
2616             // the return value for this message is ignored 
2617             processed 
= HandleSysColorChange(); 
2620         case WM_DISPLAYCHANGE
: 
2621             processed 
= HandleDisplayChange(); 
2624         case WM_PALETTECHANGED
: 
2625             processed 
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
); 
2628         case WM_CAPTURECHANGED
: 
2629             processed 
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
); 
2632         case WM_QUERYNEWPALETTE
: 
2633             processed 
= HandleQueryNewPalette(); 
2637             processed 
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
2640                 // we processed the message, i.e. erased the background 
2646             processed 
= HandleDropFiles(wParam
); 
2650             processed 
= HandleInitDialog((WXHWND
)(HWND
)wParam
); 
2654                 // we never set focus from here 
2659         case WM_QUERYENDSESSION
: 
2660             processed 
= HandleQueryEndSession(lParam
, &rc
.allow
); 
2664             processed 
= HandleEndSession(wParam 
!= 0, lParam
); 
2667         case WM_GETMINMAXINFO
: 
2668             processed 
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
); 
2672             processed 
= HandleSetCursor((WXHWND
)(HWND
)wParam
, 
2673                                         LOWORD(lParam
),     // hit test 
2674                                         HIWORD(lParam
));    // mouse msg 
2678                 // returning TRUE stops the DefWindowProc() from further 
2679                 // processing this message - exactly what we need because we've 
2680                 // just set the cursor. 
2685 #if wxUSE_ACCESSIBILITY 
2688                 //WPARAM dwFlags = (WPARAM) (DWORD) wParam; 
2689                 LPARAM dwObjId 
= (LPARAM
) (DWORD
) lParam
; 
2691                 if (dwObjId 
== OBJID_CLIENT 
&& GetOrCreateAccessible()) 
2693                     return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible()); 
2699 #if defined(__WIN32__) && defined(WM_HELP) 
2702                 HELPINFO
* info 
= (HELPINFO
*) lParam
; 
2703                 // Don't yet process menu help events, just windows 
2704                 if (info
->iContextType 
== HELPINFO_WINDOW
) 
2706                     wxWindowMSW
* subjectOfHelp 
= this; 
2707                     bool eventProcessed 
= FALSE
; 
2708                     while (subjectOfHelp 
&& !eventProcessed
) 
2710                         wxHelpEvent 
helpEvent(wxEVT_HELP
, 
2711                                               subjectOfHelp
->GetId(), 
2712                                               wxPoint(info
->MousePos
.x
, 
2713                                               info
->MousePos
.y
) ); 
2714                         helpEvent
.SetEventObject(this); 
2716                             GetEventHandler()->ProcessEvent(helpEvent
); 
2718                         // Go up the window hierarchy until the event is 
2720                         subjectOfHelp 
= subjectOfHelp
->GetParent(); 
2723                     processed 
= eventProcessed
; 
2725                 else if (info
->iContextType 
== HELPINFO_MENUITEM
) 
2727                     wxHelpEvent 
helpEvent(wxEVT_HELP
, info
->iCtrlId
); 
2728                     helpEvent
.SetEventObject(this); 
2729                     processed 
= GetEventHandler()->ProcessEvent(helpEvent
); 
2732                 //else: processed is already FALSE 
2736         case WM_CONTEXTMENU
: 
2738                 // we don't convert from screen to client coordinates as 
2739                 // the event may be handled by a parent window 
2740                 wxPoint 
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2742                 wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
2743                 processed 
= GetEventHandler()->ProcessEvent(evtCtx
); 
2748             // we're only interested in our own menus, not MF_SYSMENU 
2749             if ( HIWORD(wParam
) == MF_POPUP 
) 
2751                 // handle menu chars for ownerdrawn menu items 
2752                 int i 
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
); 
2753                 if ( i 
!= wxNOT_FOUND 
) 
2755                     rc
.result 
= MAKELRESULT(i
, MNC_EXECUTE
); 
2767         wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."), 
2768                    wxGetMessageName(message
)); 
2770 #endif // __WXDEBUG__ 
2771         rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
2777 // ---------------------------------------------------------------------------- 
2778 // wxWindow <-> HWND map 
2779 // ---------------------------------------------------------------------------- 
2781 wxWinHashTable 
*wxWinHandleHash 
= NULL
; 
2783 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
) 
2785     return wxWinHandleHash
->Get((long)hWnd
); 
2788 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
) 
2790     // adding NULL hWnd is (first) surely a result of an error and 
2791     // (secondly) breaks menu command processing 
2792     wxCHECK_RET( hWnd 
!= (HWND
)NULL
, 
2793                  wxT("attempt to add a NULL hWnd to window list ignored") ); 
2795     wxWindow 
*oldWin 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2797     if ( oldWin 
&& (oldWin 
!= win
) ) 
2799         wxLogDebug(wxT("HWND %X already associated with another window (%s)"), 
2800                    (int) hWnd
, win
->GetClassInfo()->GetClassName()); 
2803 #endif // __WXDEBUG__ 
2806         wxWinHandleHash
->Put((long)hWnd
, (wxWindow 
*)win
); 
2810 void wxRemoveHandleAssociation(wxWindowMSW 
*win
) 
2812     wxWinHandleHash
->Delete((long)win
->GetHWND()); 
2815 // ---------------------------------------------------------------------------- 
2816 // various MSW speciic class dependent functions 
2817 // ---------------------------------------------------------------------------- 
2819 // Default destroyer - override if you destroy it in some other way 
2820 // (e.g. with MDI child windows) 
2821 void wxWindowMSW::MSWDestroyWindow() 
2825 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
, 
2828                                            int& w
, int& h
) const 
2830     static const int DEFAULT_Y 
= 200; 
2831     static const int DEFAULT_H 
= 250; 
2833     bool nonDefault 
= FALSE
; 
2837         // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can 
2838         // just as well set it to CW_USEDEFAULT as well 
2844         // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it 
2845         // neither because it is not handled as a special value by Windows then 
2846         // and so we have to choose some default value for it 
2848         y 
= pos
.y 
== -1 ? DEFAULT_Y 
: pos
.y
; 
2854       NB: there used to be some code here which set the initial size of the 
2855           window to the client size of the parent if no explicit size was 
2856           specified. This was wrong because wxWindows programs often assume 
2857           that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke 
2858           it. To see why, you should understand that Windows sends WM_SIZE from 
2859           inside ::CreateWindow() anyhow. However, ::CreateWindow() is called 
2860           from some base class ctor and so this WM_SIZE is not processed in the 
2861           real class' OnSize() (because it's not fully constructed yet and the 
2862           event goes to some base class OnSize() instead). So the WM_SIZE we 
2863           rely on is the one sent when the parent frame resizes its children 
2864           but here is the problem: if the child already has just the right 
2865           size, nothing will happen as both wxWindows and Windows check for 
2866           this and ignore any attempts to change the window size to the size it 
2867           already has - so no WM_SIZE would be sent. 
2871         // as above, h is not used at all in this case anyhow 
2877         // and, again as above, we can't set the height to CW_USEDEFAULT here 
2879         h 
= size
.y 
== -1 ? DEFAULT_H  
: size
.y
; 
2887 WXHWND 
wxWindowMSW::MSWGetParent() const 
2889     return m_parent 
? m_parent
->GetHWND() : WXHWND(NULL
); 
2892 bool wxWindowMSW::MSWCreate(const wxChar 
*wclass
, 
2893                             const wxChar 
*title
, 
2897                             WXDWORD extendedStyle
) 
2899     // choose the position/size for the new window 
2901     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
2903     // controlId is menu handle for the top level windows, so set it to 0 
2904     // unless we're creating a child window 
2905     int controlId 
= style 
& WS_CHILD 
? GetId() : 0; 
2907     // for each class "Foo" we have we also have "FooNR" ("no repaint") class 
2908     // which is the same but without CS_[HV]REDRAW class styles so using it 
2909     // ensures that the window is not fully repainted on each resize 
2910     wxString 
className(wclass
); 
2911     if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE 
) 
2913         className 
+= wxT("NR"); 
2916     // do create the window 
2917     wxWindowCreationHook 
hook(this); 
2919     m_hWnd 
= (WXHWND
)::CreateWindowEx
 
2923                             title 
? title 
: wxT(""), 
2926                             (HWND
)MSWGetParent(), 
2929                             NULL                        
// no extra data 
2934         wxLogSysError(_("Can't create window of class %s"), wclass
); 
2939     SubclassWin(m_hWnd
); 
2941     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
2946 // =========================================================================== 
2947 // MSW message handlers 
2948 // =========================================================================== 
2950 // --------------------------------------------------------------------------- 
2952 // --------------------------------------------------------------------------- 
2956 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
2958 #ifndef __WXMICROWIN__ 
2959     LPNMHDR hdr 
= (LPNMHDR
)lParam
; 
2960     HWND hWnd 
= hdr
->hwndFrom
; 
2961     wxWindow 
*win 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
2963     // if the control is one of our windows, let it handle the message itself 
2966         return win
->MSWOnNotify(idCtrl
, lParam
, result
); 
2969     // VZ: why did we do it? normally this is unnecessary and, besides, it 
2970     //     breaks the message processing for the toolbars because the tooltip 
2971     //     notifications were being forwarded to the toolbar child controls 
2972     //     (if it had any) before being passed to the toolbar itself, so in my 
2973     //     example the tooltip for the combobox was always shown instead of the 
2974     //     correct button tooltips 
2976     // try all our children 
2977     wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
2980         wxWindow 
*child 
= node
->GetData(); 
2981         if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) ) 
2986         node 
= node
->GetNext(); 
2990     // by default, handle it ourselves 
2991     return MSWOnNotify(idCtrl
, lParam
, result
); 
2992 #else // __WXMICROWIN__ 
2999 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
, 
3001                                       const wxString
& ttip
) 
3003     // I don't know why it happens, but the versions of comctl32.dll starting 
3004     // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally, 
3005     // this message is supposed to be sent to Unicode programs only) -- hence 
3006     // we need to handle it as well, otherwise no tooltips will be shown in 
3009     if ( !(code 
== (WXUINT
) TTN_NEEDTEXTA 
|| code 
== (WXUINT
) TTN_NEEDTEXTW
) || ttip
.empty() ) 
3011         // not a tooltip message or no tooltip to show anyhow 
3015     LPTOOLTIPTEXT ttText 
= (LPTOOLTIPTEXT
)lParam
; 
3018     if ( code 
== (WXUINT
) TTN_NEEDTEXTA 
) 
3020         // we pass just the pointer as we store the string internally anyhow 
3021         ttText
->lpszText 
= (char *)ttip
.c_str(); 
3023     else // TTN_NEEDTEXTW 
3027         // in Unicode mode this is just what we need 
3028         ttText
->lpszText 
= (wxChar 
*)ttip
.c_str(); 
3030         MultiByteToWideChar(CP_ACP
, 0, ttip
, ttip
.length()+1, 
3031                             (wchar_t *)ttText
->szText
, 
3032                             sizeof(ttText
->szText
) / sizeof(wchar_t)); 
3033 #endif // Unicode/!Unicode 
3039 #endif // wxUSE_TOOLTIPS 
3041 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
), 
3043                               WXLPARAM
* WXUNUSED(result
)) 
3048         NMHDR
* hdr 
= (NMHDR 
*)lParam
; 
3049         if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip())) 
3055 #endif // wxUSE_TOOLTIPS 
3062 // --------------------------------------------------------------------------- 
3063 // end session messages 
3064 // --------------------------------------------------------------------------- 
3066 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
) 
3068     wxCloseEvent 
event(wxEVT_QUERY_END_SESSION
, -1); 
3069     event
.SetEventObject(wxTheApp
); 
3070     event
.SetCanVeto(TRUE
); 
3071     event
.SetLoggingOff(logOff 
== (long)ENDSESSION_LOGOFF
); 
3073     bool rc 
= wxTheApp
->ProcessEvent(event
); 
3077         // we may end only if the app didn't veto session closing (double 
3079         *mayEnd 
= !event
.GetVeto(); 
3085 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
) 
3087     // do nothing if the session isn't ending 
3092     if ( (this != wxTheApp
->GetTopWindow()) ) 
3095     wxCloseEvent 
event(wxEVT_END_SESSION
, -1); 
3096     event
.SetEventObject(wxTheApp
); 
3097     event
.SetCanVeto(FALSE
); 
3098     event
.SetLoggingOff( (logOff 
== (long)ENDSESSION_LOGOFF
) ); 
3100     return wxTheApp
->ProcessEvent(event
); 
3103 // --------------------------------------------------------------------------- 
3104 // window creation/destruction 
3105 // --------------------------------------------------------------------------- 
3107 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs
, bool *mayCreate
) 
3109     // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our 
3110     // parent as well as otherwise several Win32 functions using 
3111     // GetNextDlgTabItem() to iterate over all controls such as 
3112     // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, 
3113     // all of them iterate over all the controls starting from the focus and 
3114     // stop iterating when they get back to the focus but unless all parents 
3115     // have WS_EX_CONTROLPARENT bit set, they would never get back to focus 
3116     if ( ((CREATESTRUCT 
*)cs
)->dwExStyle 
& WS_EX_CONTROLPARENT 
) 
3118         // there is no need to do anything for the top level windows 
3119         const wxWindow 
*parent 
= GetParent(); 
3120         while ( parent 
&& !parent
->IsTopLevel() ) 
3122             LONG exStyle 
= ::GetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
); 
3123             if ( !(exStyle 
& WS_EX_CONTROLPARENT
) ) 
3125                 // force the parent to have this style 
3126                 ::SetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
, 
3127                                 exStyle 
| WS_EX_CONTROLPARENT
); 
3130             parent 
= parent
->GetParent(); 
3134     // TODO: should generate this event from WM_NCCREATE 
3135     wxWindowCreateEvent 
event((wxWindow 
*)this); 
3136     (void)GetEventHandler()->ProcessEvent(event
); 
3143 bool wxWindowMSW::HandleDestroy() 
3147     // delete our drop target if we've got one 
3148 #if wxUSE_DRAG_AND_DROP 
3149     if ( m_dropTarget 
!= NULL 
) 
3151         m_dropTarget
->Revoke(m_hWnd
); 
3153         delete m_dropTarget
; 
3154         m_dropTarget 
= NULL
; 
3156 #endif // wxUSE_DRAG_AND_DROP 
3158     // WM_DESTROY handled 
3162 // --------------------------------------------------------------------------- 
3164 // --------------------------------------------------------------------------- 
3166 bool wxWindowMSW::HandleActivate(int state
, 
3167                               bool WXUNUSED(minimized
), 
3168                               WXHWND 
WXUNUSED(activate
)) 
3170     wxActivateEvent 
event(wxEVT_ACTIVATE
, 
3171                           (state 
== WA_ACTIVE
) || (state 
== WA_CLICKACTIVE
), 
3173     event
.SetEventObject(this); 
3175     return GetEventHandler()->ProcessEvent(event
); 
3178 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
) 
3180     // notify the parent keeping track of focus for the kbd navigation 
3181     // purposes that we got it 
3182     wxChildFocusEvent 
eventFocus((wxWindow 
*)this); 
3183     (void)GetEventHandler()->ProcessEvent(eventFocus
); 
3189         m_caret
->OnSetFocus(); 
3191 #endif // wxUSE_CARET 
3194     // If it's a wxTextCtrl don't send the event as it will be done 
3195     // after the control gets to process it from EN_FOCUS handler 
3196     if ( wxDynamicCastThis(wxTextCtrl
) ) 
3200 #endif // wxUSE_TEXTCTRL 
3202     wxFocusEvent 
event(wxEVT_SET_FOCUS
, m_windowId
); 
3203     event
.SetEventObject(this); 
3205     // wxFindWinFromHandle() may return NULL, it is ok 
3206     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3208     return GetEventHandler()->ProcessEvent(event
); 
3211 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
) 
3217         m_caret
->OnKillFocus(); 
3219 #endif // wxUSE_CARET 
3222     // If it's a wxTextCtrl don't send the event as it will be done 
3223     // after the control gets to process it. 
3224     wxTextCtrl 
*ctrl 
= wxDynamicCastThis(wxTextCtrl
); 
3231     // Don't send the event when in the process of being deleted.  This can 
3232     // only cause problems if the event handler tries to access the object. 
3233     if ( m_isBeingDeleted 
) 
3238     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, m_windowId
); 
3239     event
.SetEventObject(this); 
3241     // wxFindWinFromHandle() may return NULL, it is ok 
3242     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3244     return GetEventHandler()->ProcessEvent(event
); 
3247 // --------------------------------------------------------------------------- 
3249 // --------------------------------------------------------------------------- 
3251 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
)) 
3253     wxShowEvent 
event(GetId(), show
); 
3254     event
.m_eventObject 
= this; 
3256     return GetEventHandler()->ProcessEvent(event
); 
3259 bool wxWindowMSW::HandleInitDialog(WXHWND 
WXUNUSED(hWndFocus
)) 
3261     wxInitDialogEvent 
event(GetId()); 
3262     event
.m_eventObject 
= this; 
3264     return GetEventHandler()->ProcessEvent(event
); 
3267 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
) 
3269 #if defined (__WXMICROWIN__)  
3271 #else // __WXMICROWIN__ 
3272     HDROP hFilesInfo 
= (HDROP
) wParam
; 
3274     // Get the total number of files dropped 
3275     UINT gwFilesDropped 
= ::DragQueryFile
 
3283     wxString 
*files 
= new wxString
[gwFilesDropped
]; 
3284     for ( UINT wIndex 
= 0; wIndex 
< gwFilesDropped
; wIndex
++ ) 
3286         // first get the needed buffer length (+1 for terminating NUL) 
3287         size_t len 
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1; 
3289         // and now get the file name 
3290         ::DragQueryFile(hFilesInfo
, wIndex
, 
3291                         files
[wIndex
].GetWriteBuf(len
), len
); 
3293         files
[wIndex
].UngetWriteBuf(); 
3295     DragFinish (hFilesInfo
); 
3297     wxDropFilesEvent 
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
); 
3298     event
.m_eventObject 
= this; 
3301     DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
); 
3302     event
.m_pos
.x 
= dropPoint
.x
; 
3303     event
.m_pos
.y 
= dropPoint
.y
; 
3305     return GetEventHandler()->ProcessEvent(event
); 
3309 #ifdef __DIGITALMARS__ 
3310 extern "C" HCURSOR 
wxGetCurrentBusyCursor(); 
3313 bool wxWindowMSW::HandleSetCursor(WXHWND 
WXUNUSED(hWnd
), 
3315                                   int WXUNUSED(mouseMsg
)) 
3317 #ifndef __WXMICROWIN__ 
3318     // the logic is as follows: 
3319     // -1. don't set cursor for non client area, including but not limited to 
3320     //     the title bar, scrollbars, &c 
3321     //  0. allow the user to override default behaviour by using EVT_SET_CURSOR 
3322     //  1. if we have the cursor set it unless wxIsBusy() 
3323     //  2. if we're a top level window, set some cursor anyhow 
3324     //  3. if wxIsBusy(), set the busy cursor, otherwise the global one 
3326     if ( nHitTest 
!= HTCLIENT 
) 
3331     HCURSOR hcursor 
= 0; 
3333     // first ask the user code - it may wish to set the cursor in some very 
3334     // specific way (for example, depending on the current position) 
3337     if ( !::GetCursorPos(&pt
) ) 
3339         wxLogLastError(wxT("GetCursorPos")); 
3342     // In WIN16 it doesn't return a value. 
3343     ::GetCursorPos(&pt
); 
3348     ScreenToClient(&x
, &y
); 
3349     wxSetCursorEvent 
event(x
, y
); 
3351     bool processedEvtSetCursor 
= GetEventHandler()->ProcessEvent(event
); 
3352     if ( processedEvtSetCursor 
&& event
.HasCursor() ) 
3354         hcursor 
= GetHcursorOf(event
.GetCursor()); 
3359         bool isBusy 
= wxIsBusy(); 
3361         // the test for processedEvtSetCursor is here to prevent using m_cursor 
3362         // if the user code caught EVT_SET_CURSOR() and returned nothing from 
3363         // it - this is a way to say that our cursor shouldn't be used for this 
3365         if ( !processedEvtSetCursor 
&& m_cursor
.Ok() ) 
3367             hcursor 
= GetHcursorOf(m_cursor
); 
3374                 hcursor 
= wxGetCurrentBusyCursor(); 
3376             else if ( !hcursor 
) 
3378                 const wxCursor 
*cursor 
= wxGetGlobalCursor(); 
3379                 if ( cursor 
&& cursor
->Ok() ) 
3381                     hcursor 
= GetHcursorOf(*cursor
); 
3389 //        wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor); 
3391         ::SetCursor(hcursor
); 
3393         // cursor set, stop here 
3396 #endif // __WXMICROWIN__ 
3398     // pass up the window chain 
3402 // --------------------------------------------------------------------------- 
3403 // owner drawn stuff 
3404 // --------------------------------------------------------------------------- 
3406 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT 
*itemStruct
) 
3408 #if wxUSE_OWNER_DRAWN 
3410 #if wxUSE_MENUS_NATIVE 
3411     // is it a menu item? 
3412     DRAWITEMSTRUCT 
*pDrawStruct 
= (DRAWITEMSTRUCT 
*)itemStruct
; 
3413     if ( id 
== 0 && pDrawStruct
->CtlType 
== ODT_MENU 
) 
3415         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pDrawStruct
->itemData
); 
3417         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE 
); 
3419         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent 
3420         // the DC from being released 
3421         wxDCTemp 
dc((WXHDC
)pDrawStruct
->hDC
); 
3422         wxRect 
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
, 
3423                     pDrawStruct
->rcItem
.right 
- pDrawStruct
->rcItem
.left
, 
3424                     pDrawStruct
->rcItem
.bottom 
- pDrawStruct
->rcItem
.top
); 
3426         return pMenuItem
->OnDrawItem
 
3430                 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
, 
3431                 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
 
3434 #endif // wxUSE_MENUS_NATIVE 
3437     wxWindow 
*item 
= FindItem(id
); 
3438     if ( item 
&& item
->IsKindOf(CLASSINFO(wxControl
)) ) 
3440         return ((wxControl 
*)item
)->MSWOnDraw(itemStruct
); 
3442 #endif // wxUSE_CONTROLS 
3444 #endif // USE_OWNER_DRAWN 
3449 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT 
*itemStruct
) 
3451 #if wxUSE_OWNER_DRAWN 
3452     // is it a menu item? 
3453     MEASUREITEMSTRUCT 
*pMeasureStruct 
= (MEASUREITEMSTRUCT 
*)itemStruct
; 
3454     if ( id 
== 0 && pMeasureStruct
->CtlType 
== ODT_MENU 
) 
3456         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pMeasureStruct
->itemData
); 
3458         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE 
); 
3460         return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
, 
3461                                         &pMeasureStruct
->itemHeight
); 
3464     wxWindow 
*item 
= FindItem(id
); 
3465     if ( item 
&& item
->IsKindOf(CLASSINFO(wxControl
)) ) 
3467         return ((wxControl 
*)item
)->MSWOnMeasure(itemStruct
); 
3469 #endif  // owner-drawn menus 
3473 // --------------------------------------------------------------------------- 
3474 // colours and palettes 
3475 // --------------------------------------------------------------------------- 
3477 bool wxWindowMSW::HandleSysColorChange() 
3479     wxSysColourChangedEvent event
; 
3480     event
.SetEventObject(this); 
3482     (void)GetEventHandler()->ProcessEvent(event
); 
3484     // always let the system carry on the default processing to allow the 
3485     // native controls to react to the colours update 
3489 bool wxWindowMSW::HandleDisplayChange() 
3491     wxDisplayChangedEvent event
; 
3492     event
.SetEventObject(this); 
3494     return GetEventHandler()->ProcessEvent(event
); 
3497 bool wxWindowMSW::HandleCtlColor(WXHBRUSH 
*brush
, 
3505 #ifndef __WXMICROWIN__ 
3506     WXHBRUSH hBrush 
= 0; 
3508     if ( nCtlColor 
== CTLCOLOR_DLG 
) 
3510         hBrush 
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3515         wxControl 
*item 
= (wxControl 
*)FindItemByHWND(pWnd
, TRUE
); 
3517             hBrush 
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3519 #endif // wxUSE_CONTROLS 
3525 #else // __WXMICROWIN__ 
3530 // Define for each class of dialog and control 
3531 WXHBRUSH 
wxWindowMSW::OnCtlColor(WXHDC 
WXUNUSED(hDC
), 
3532                                  WXHWND 
WXUNUSED(hWnd
), 
3533                                  WXUINT 
WXUNUSED(nCtlColor
), 
3534                                  WXUINT 
WXUNUSED(message
), 
3535                                  WXWPARAM 
WXUNUSED(wParam
), 
3536                                  WXLPARAM 
WXUNUSED(lParam
)) 
3541 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
) 
3544     // same as below except we don't respond to our own messages 
3545     if ( hWndPalChange 
!= GetHWND() ) 
3547         // check to see if we our our parents have a custom palette 
3548         wxWindowMSW 
*win 
= this; 
3549         while ( win 
&& !win
->HasCustomPalette() ) 
3551             win 
= win
->GetParent(); 
3554         if ( win 
&& win
->HasCustomPalette() ) 
3556             // realize the palette to see whether redrawing is needed 
3557             HDC hdc 
= ::GetDC((HWND
) hWndPalChange
); 
3558             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3559                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3561             int result 
= ::RealizePalette(hdc
); 
3563             // restore the palette (before releasing the DC) 
3564             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3565                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3566             ::RealizePalette(hdc
); 
3567             ::ReleaseDC((HWND
) hWndPalChange
, hdc
); 
3569             // now check for the need to redraw 
3571                 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
); 
3575 #endif // wxUSE_PALETTE 
3577     wxPaletteChangedEvent 
event(GetId()); 
3578     event
.SetEventObject(this); 
3579     event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
)); 
3581     return GetEventHandler()->ProcessEvent(event
); 
3584 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
) 
3586     wxMouseCaptureChangedEvent 
event(GetId(), wxFindWinFromHandle(hWndGainedCapture
)); 
3587     event
.SetEventObject(this); 
3589     return GetEventHandler()->ProcessEvent(event
); 
3592 bool wxWindowMSW::HandleQueryNewPalette() 
3596     // check to see if we our our parents have a custom palette 
3597     wxWindowMSW 
*win 
= this; 
3598     while (!win
->HasCustomPalette() && win
->GetParent()) win 
= win
->GetParent(); 
3599     if (win
->HasCustomPalette()) { 
3600         /* realize the palette to see whether redrawing is needed */ 
3601         HDC hdc 
= GetDC((HWND
) GetHWND()); 
3602         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3603              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) ); 
3605         int result 
= ::RealizePalette(hdc
); 
3606         /* restore the palette (before releasing the DC) */ 
3607         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3608              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) ); 
3609         ::RealizePalette(hdc
); 
3610         ::ReleaseDC((HWND
) GetHWND(), hdc
); 
3611         /* now check for the need to redraw */ 
3613             ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
); 
3615 #endif // wxUSE_PALETTE 
3617     wxQueryNewPaletteEvent 
event(GetId()); 
3618     event
.SetEventObject(this); 
3620     return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized(); 
3623 // Responds to colour changes: passes event on to children. 
3624 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
3626     // the top level window also reset the standard colour map as it might have 
3627     // changed (there is no need to do it for the non top level windows as we 
3628     // only have to do it once) 
3632         gs_hasStdCmap 
= FALSE
; 
3634     wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
3637         // Only propagate to non-top-level windows because Windows already 
3638         // sends this event to all top-level ones 
3639         wxWindow 
*win 
= node
->GetData(); 
3640         if ( !win
->IsTopLevel() ) 
3642             // we need to send the real WM_SYSCOLORCHANGE and not just trigger 
3643             // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for 
3644             // the standard controls 
3645             ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0); 
3648         node 
= node
->GetNext(); 
3651     // update the colours we use if they were not set explicitly by the user: 
3652     // this must be done or OnCtlColor() would continue to use the old colours 
3655         m_foregroundColour 
= wxSystemSettings:: 
3656                                 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
); 
3661         m_backgroundColour 
= wxSystemSettings:: 
3662                                 GetSystemColour(wxSYS_COLOUR_BTNFACE
); 
3666 extern wxCOLORMAP 
*wxGetStdColourMap() 
3668     static COLORREF s_stdColours
[wxSTD_COL_MAX
]; 
3669     static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
]; 
3671     if ( !gs_hasStdCmap 
) 
3673         static bool s_coloursInit 
= FALSE
; 
3675         if ( !s_coloursInit 
) 
3677             // When a bitmap is loaded, the RGB values can change (apparently 
3678             // because Windows adjusts them to care for the old programs always 
3679             // using 0xc0c0c0 while the transparent colour for the new Windows 
3680             // versions is different). But we do this adjustment ourselves so 
3681             // we want to avoid Windows' "help" and for this we need to have a 
3682             // reference bitmap which can tell us what the RGB values change 
3684             wxBitmap 
stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); 
3685             if ( stdColourBitmap
.Ok() ) 
3687                 // the pixels in the bitmap must correspond to wxSTD_COL_XXX! 
3688                 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
, 
3689                               _T("forgot to update wxBITMAP_STD_COLOURS!") ); 
3692                 memDC
.SelectObject(stdColourBitmap
); 
3695                 for ( size_t i 
= 0; i 
< WXSIZEOF(s_stdColours
); i
++ ) 
3697                     memDC
.GetPixel(i
, 0, &colour
); 
3698                     s_stdColours
[i
] = wxColourToRGB(colour
); 
3701             else // wxBITMAP_STD_COLOURS couldn't be loaded 
3703                 s_stdColours
[0] = RGB(000,000,000);     // black 
3704                 s_stdColours
[1] = RGB(128,128,128);     // dark grey 
3705                 s_stdColours
[2] = RGB(192,192,192);     // light grey 
3706                 s_stdColours
[3] = RGB(255,255,255);     // white 
3707                 //s_stdColours[4] = RGB(000,000,255);     // blue 
3708                 //s_stdColours[5] = RGB(255,000,255);     // magenta 
3711             s_coloursInit 
= TRUE
; 
3714         gs_hasStdCmap 
= TRUE
; 
3716         // create the colour map 
3717 #define INIT_CMAP_ENTRY(col) \ 
3718             s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \ 
3719             s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col) 
3721         INIT_CMAP_ENTRY(BTNTEXT
); 
3722         INIT_CMAP_ENTRY(BTNSHADOW
); 
3723         INIT_CMAP_ENTRY(BTNFACE
); 
3724         INIT_CMAP_ENTRY(BTNHIGHLIGHT
); 
3726 #undef INIT_CMAP_ENTRY 
3732 // --------------------------------------------------------------------------- 
3734 // --------------------------------------------------------------------------- 
3736 bool wxWindowMSW::HandlePaint() 
3739     HRGN hRegion 
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle 
3741         wxLogLastError(wxT("CreateRectRgn")); 
3742     if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR 
) 
3743         wxLogLastError(wxT("GetUpdateRgn")); 
3745     m_updateRegion 
= wxRegion((WXHRGN
) hRegion
); 
3748     ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
); 
3750     m_updateRegion 
= wxRegion(updateRect
.left
, updateRect
.top
, 
3751                               updateRect
.right 
- updateRect
.left
, 
3752                               updateRect
.bottom 
- updateRect
.top
); 
3755     wxPaintEvent 
event(m_windowId
); 
3756     event
.SetEventObject(this); 
3758     bool processed 
= GetEventHandler()->ProcessEvent(event
); 
3760     // note that we must generate NC event after the normal one as otherwise 
3761     // BeginPaint() will happily overwrite our decorations with the background 
3763     wxNcPaintEvent 
eventNc(m_windowId
); 
3764     eventNc
.SetEventObject(this); 
3765     GetEventHandler()->ProcessEvent(eventNc
); 
3770 // Can be called from an application's OnPaint handler 
3771 void wxWindowMSW::OnPaint(wxPaintEvent
& event
) 
3773 #ifdef __WXUNIVERSAL__ 
3776     HDC hDC 
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject()); 
3779         MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0); 
3784 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
) 
3786     // Prevents flicker when dragging 
3787     if ( ::IsIconic(GetHwnd()) ) 
3793     dc
.SetWindow((wxWindow 
*)this); 
3796     wxEraseEvent 
event(m_windowId
, &dc
); 
3797     event
.SetEventObject(this); 
3798     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
3802     // must be called manually as ~wxDC doesn't do anything for wxDCTemp 
3803     dc
.SelectOldObjects(hdc
); 
3808 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
) 
3811     ::GetClientRect(GetHwnd(), &rect
); 
3813     COLORREF ref 
= PALETTERGB(m_backgroundColour
.Red(), 
3814                               m_backgroundColour
.Green(), 
3815                               m_backgroundColour
.Blue()); 
3816     HBRUSH hBrush 
= ::CreateSolidBrush(ref
); 
3818         wxLogLastError(wxT("CreateSolidBrush")); 
3820     HDC hdc 
= (HDC
)event
.GetDC()->GetHDC(); 
3822     int mode 
= ::SetMapMode(hdc
, MM_TEXT
); 
3824     ::FillRect(hdc
, &rect
, hBrush
); 
3825     ::DeleteObject(hBrush
); 
3826     ::SetMapMode(hdc
, mode
); 
3829 // --------------------------------------------------------------------------- 
3830 // moving and resizing 
3831 // --------------------------------------------------------------------------- 
3833 bool wxWindowMSW::HandleMinimize() 
3835     wxIconizeEvent 
event(m_windowId
); 
3836     event
.SetEventObject(this); 
3838     return GetEventHandler()->ProcessEvent(event
); 
3841 bool wxWindowMSW::HandleMaximize() 
3843     wxMaximizeEvent 
event(m_windowId
); 
3844     event
.SetEventObject(this); 
3846     return GetEventHandler()->ProcessEvent(event
); 
3849 bool wxWindowMSW::HandleMove(int x
, int y
) 
3851     wxMoveEvent 
event(wxPoint(x
, y
), m_windowId
); 
3852     event
.SetEventObject(this); 
3854     return GetEventHandler()->ProcessEvent(event
); 
3857 bool wxWindowMSW::HandleMoving(wxRect
& rect
) 
3859     wxMoveEvent 
event(rect
, m_windowId
); 
3860     event
.SetEventObject(this); 
3862     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
3864         rect 
= event
.GetRect(); 
3868 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), 
3869                              WXUINT 
WXUNUSED(flag
)) 
3871     // don't use w and h parameters as they specify the client size while 
3872     // according to the docs EVT_SIZE handler is supposed to receive the total 
3874     wxSizeEvent 
event(GetSize(), m_windowId
); 
3875     event
.SetEventObject(this); 
3877     return GetEventHandler()->ProcessEvent(event
); 
3880 bool wxWindowMSW::HandleSizing(wxRect
& rect
) 
3882     wxSizeEvent 
event(rect
, m_windowId
); 
3883     event
.SetEventObject(this); 
3885     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
3887         rect 
= event
.GetRect(); 
3891 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
) 
3893     MINMAXINFO 
*info 
= (MINMAXINFO 
*)mmInfo
; 
3897     int minWidth 
= GetMinWidth(), 
3898         minHeight 
= GetMinHeight(), 
3899         maxWidth 
= GetMaxWidth(), 
3900         maxHeight 
= GetMaxHeight(); 
3902     if ( minWidth 
!= -1 ) 
3904         info
->ptMinTrackSize
.x 
= minWidth
; 
3908     if ( minHeight 
!= -1 ) 
3910         info
->ptMinTrackSize
.y 
= minHeight
; 
3914     if ( maxWidth 
!= -1 ) 
3916         info
->ptMaxTrackSize
.x 
= maxWidth
; 
3920     if ( maxHeight 
!= -1 ) 
3922         info
->ptMaxTrackSize
.y 
= maxHeight
; 
3929 // --------------------------------------------------------------------------- 
3931 // --------------------------------------------------------------------------- 
3933 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
) 
3935 #if wxUSE_MENUS_NATIVE 
3936     if ( !cmd 
&& wxCurrentPopupMenu 
) 
3938         wxMenu 
*popupMenu 
= wxCurrentPopupMenu
; 
3939         wxCurrentPopupMenu 
= NULL
; 
3941         return popupMenu
->MSWCommand(cmd
, id
); 
3943 #endif // wxUSE_MENUS_NATIVE 
3945     wxWindow 
*win 
= NULL
; 
3947     // first try to find it from HWND - this works even with the broken 
3948     // programs using the same ids for different controls 
3951         win 
= wxFindWinFromHandle(control
); 
3957         // must cast to a signed type before comparing with other ids! 
3958         win 
= FindItem((signed short)id
); 
3963         return win
->MSWCommand(cmd
, id
); 
3966     // the messages sent from the in-place edit control used by the treectrl 
3967     // for label editing have id == 0, but they should _not_ be treated as menu 
3968     // messages (they are EN_XXX ones, in fact) so don't translate anything 
3969     // coming from a control to wxEVT_COMMAND_MENU_SELECTED 
3972         // If no child window, it may be an accelerator, e.g. for a popup menu 
3975         wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
); 
3976         event
.SetEventObject(this); 
3980         return GetEventHandler()->ProcessEvent(event
); 
3982 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
3985         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND 
3986         // notifications to its parent which we want to reflect back to 
3988         wxSpinCtrl 
*spin 
= wxSpinCtrl::GetSpinForTextCtrl(control
); 
3989         if ( spin 
&& spin
->ProcessTextCommand(cmd
, id
) ) 
3992 #endif // wxUSE_SPINCTRL 
3997 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM 
WXUNUSED(lParam
)) 
3999     // 4 bits are reserved 
4000     switch ( wParam 
& 0xFFFFFFF0 ) 
4003             return HandleMaximize(); 
4006             return HandleMinimize(); 
4012 // --------------------------------------------------------------------------- 
4014 // --------------------------------------------------------------------------- 
4016 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
, 
4020     // our client coords are not quite the same as Windows ones 
4021     wxPoint pt 
= GetClientAreaOrigin(); 
4022     event
.m_x 
= x 
- pt
.x
; 
4023     event
.m_y 
= y 
- pt
.y
; 
4025     event
.m_shiftDown 
= (flags 
& MK_SHIFT
) != 0; 
4026     event
.m_controlDown 
= (flags 
& MK_CONTROL
) != 0; 
4027     event
.m_leftDown 
= (flags 
& MK_LBUTTON
) != 0; 
4028     event
.m_middleDown 
= (flags 
& MK_MBUTTON
) != 0; 
4029     event
.m_rightDown 
= (flags 
& MK_RBUTTON
) != 0; 
4030  //   event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; 
4031     // Returns different negative values on WinME and WinNT, 
4032     // so simply test for negative value. 
4033     event
.m_altDown 
= ::GetKeyState(VK_MENU
) < 0; 
4035     event
.SetTimestamp(s_currentMsg
.time
); 
4036     event
.m_eventObject 
= this; 
4037     event
.SetId(GetId()); 
4039 #if wxUSE_MOUSEEVENT_HACK 
4042     m_lastMouseEvent 
= event
.GetEventType(); 
4043 #endif // wxUSE_MOUSEEVENT_HACK 
4046 // Windows doesn't send the mouse events to the static controls (which are 
4047 // transparent in the sense that their WM_NCHITTEST handler returns 
4048 // HTTRANSPARENT) at all but we want all controls to receive the mouse events 
4049 // and so we manually check if we don't have a child window under mouse and if 
4050 // we do, send the event to it instead of the window Windows had sent WM_XXX 
4053 // Notice that this is not done for the mouse move events because this could 
4054 // (would?) be too slow, but only for clicks which means that the static texts 
4055 // still don't get move, enter nor leave events. 
4056 static wxWindowMSW 
*FindWindowForMouseEvent(wxWindowMSW 
*win
, int *x
, int *y
) //TW:REQ:Univ 
4058     wxCHECK_MSG( x 
&& y
, win
, _T("NULL pointer in FindWindowForMouseEvent") ); 
4060     // first try to find a non transparent child: this allows us to send events 
4061     // to a static text which is inside a static box, for example 
4062     POINT pt 
= { *x
, *y 
}; 
4063     HWND hwnd 
= GetHwndOf(win
), 
4067     hwndUnderMouse 
= ::ChildWindowFromPointEx
 
4076     if ( !hwndUnderMouse 
|| hwndUnderMouse 
== hwnd 
) 
4079         // now try any child window at all 
4080         hwndUnderMouse 
= ::ChildWindowFromPoint(hwnd
, pt
); 
4083     // check that we have a child window which is susceptible to receive mouse 
4084     // events: for this it must be shown and enabled 
4085     if ( hwndUnderMouse 
&& 
4086             hwndUnderMouse 
!= hwnd 
&& 
4087                 ::IsWindowVisible(hwndUnderMouse
) && 
4088                     ::IsWindowEnabled(hwndUnderMouse
) ) 
4090         wxWindow 
*winUnderMouse 
= wxFindWinFromHandle((WXHWND
)hwndUnderMouse
); 
4091         if ( winUnderMouse 
) 
4093             // translate the mouse coords to the other window coords 
4094             win
->ClientToScreen(x
, y
); 
4095             winUnderMouse
->ScreenToClient(x
, y
); 
4097             win 
= winUnderMouse
; 
4104 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4106     // the mouse events take consecutive IDs from WM_MOUSEFIRST to 
4107     // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST 
4108     // from the message id and take the value in the table to get wxWin event 
4110     static const wxEventType eventsMouse
[] = 
4124     wxMouseEvent 
event(eventsMouse
[msg 
- WM_MOUSEMOVE
]); 
4125     InitMouseEvent(event
, x
, y
, flags
); 
4127     return GetEventHandler()->ProcessEvent(event
); 
4130 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
) 
4132     if ( !m_mouseInWindow 
) 
4134         // it would be wrong to assume that just because we get a mouse move 
4135         // event that the mouse is inside the window: although this is usually 
4136         // true, it is not if we had captured the mouse, so we need to check 
4137         // the mouse coordinates here 
4138         if ( !HasCapture() || IsMouseInWindow() ) 
4140             // Generate an ENTER event 
4141             m_mouseInWindow 
= TRUE
; 
4143             wxMouseEvent 
event(wxEVT_ENTER_WINDOW
); 
4144             InitMouseEvent(event
, x
, y
, flags
); 
4146             (void)GetEventHandler()->ProcessEvent(event
); 
4150 #if wxUSE_MOUSEEVENT_HACK 
4151     // Window gets a click down message followed by a mouse move message even 
4152     // if position isn't changed!  We want to discard the trailing move event 
4153     // if x and y are the same. 
4154     if ( (m_lastMouseEvent 
== wxEVT_RIGHT_DOWN 
|| 
4155           m_lastMouseEvent 
== wxEVT_LEFT_DOWN 
|| 
4156           m_lastMouseEvent 
== wxEVT_MIDDLE_DOWN
) && 
4157          (m_lastMouseX 
== x 
&& m_lastMouseY 
== y
) ) 
4159         m_lastMouseEvent 
= wxEVT_MOTION
; 
4163 #endif // wxUSE_MOUSEEVENT_HACK 
4165     return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
); 
4169 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
) 
4171 #if wxUSE_MOUSEWHEEL 
4172     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
4173     InitMouseEvent(event
, 
4174                    GET_X_LPARAM(lParam
), 
4175                    GET_Y_LPARAM(lParam
), 
4177     event
.m_wheelRotation 
= (short)HIWORD(wParam
); 
4178     event
.m_wheelDelta 
= WHEEL_DELTA
; 
4181     static int s_linesPerRotation 
= -1; 
4182     if ( s_linesPerRotation 
== -1 ) 
4184         if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, 
4185                                      &s_linesPerRotation
, 0)) 
4187             // this is not supposed to happen 
4188             wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)")); 
4190             // the default is 3, so use it if SystemParametersInfo() failed 
4191             s_linesPerRotation 
= 3; 
4195     // no SystemParametersInfo() under Win16 
4196     static const int s_linesPerRotation 
= 3; 
4199     event
.m_linesPerAction 
= s_linesPerRotation
; 
4200     return GetEventHandler()->ProcessEvent(event
); 
4211 // --------------------------------------------------------------------------- 
4212 // keyboard handling 
4213 // --------------------------------------------------------------------------- 
4215 // create the key event of the given type for the given key - used by 
4216 // HandleChar and HandleKeyDown/Up 
4217 wxKeyEvent 
wxWindowMSW::CreateKeyEvent(wxEventType evType
, 
4220                                        WXWPARAM wParam
) const 
4222     wxKeyEvent 
event(evType
); 
4223     event
.SetId(GetId()); 
4224     event
.m_shiftDown 
= wxIsShiftDown(); 
4225     event
.m_controlDown 
= wxIsCtrlDown(); 
4226     event
.m_altDown 
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
; 
4228     event
.m_eventObject 
= (wxWindow 
*)this; // const_cast 
4229     event
.m_keyCode 
= id
; 
4230     event
.m_rawCode 
= (wxUint32
) wParam
; 
4231     event
.m_rawFlags 
= (wxUint32
) lParam
; 
4232     event
.SetTimestamp(s_currentMsg
.time
); 
4234     // translate the position to client coords 
4238     GetWindowRect(GetHwnd(),&rect
); 
4248 // isASCII is TRUE only when we're called from WM_CHAR handler and not from 
4250 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
) 
4252     bool ctrlDown 
= FALSE
; 
4257         // If 1 -> 26, translate to either special keycode or just set 
4258         // ctrlDown.  IOW, Ctrl-C should result in keycode == 3 and 
4259         // ControlDown() == TRUE. 
4261         if ( (id 
> 0) && (id 
< 27) ) 
4283     else // we're called from WM_KEYDOWN 
4285         id 
= wxCharCodeMSWToWX(wParam
); 
4288             // it's ASCII and will be processed here only when called from 
4289             // WM_CHAR (i.e. when isASCII = TRUE), don't process it now 
4294     wxKeyEvent 
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
)); 
4296     // the alphanumeric keys produced by pressing AltGr+something on European 
4297     // keyboards have both Ctrl and Alt modifiers which may confuse the user 
4298     // code as, normally, keys with Ctrl and/or Alt don't result in anything 
4299     // alphanumeric, so pretend that there are no modifiers at all (the 
4300     // KEY_DOWN event would still have the correct modifiers if they're really 
4302     if ( event
.m_controlDown 
&& event
.m_altDown 
&& 
4303             (id 
>= 32 && id 
< 256) ) 
4305         event
.m_controlDown 
= 
4306         event
.m_altDown 
= FALSE
; 
4309     return GetEventHandler()->ProcessEvent(event
); 
4312 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
) 
4314     int id 
= wxCharCodeMSWToWX(wParam
); 
4318         // normal ASCII char 
4322     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4324         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
)); 
4325         if ( GetEventHandler()->ProcessEvent(event
) ) 
4334 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
) 
4336     int id 
= wxCharCodeMSWToWX(wParam
); 
4340         // normal ASCII char 
4344     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4346         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
)); 
4347         if ( GetEventHandler()->ProcessEvent(event
) ) 
4356 int wxWindowMSW::HandleMenuChar(int chAccel
, WXLPARAM lParam
) 
4358     const HMENU hmenu 
= (HMENU
)lParam
; 
4362     mii
.cbSize 
= sizeof(MENUITEMINFO
); 
4363     mii
.fMask 
= MIIM_TYPE 
| MIIM_DATA
; 
4365     // find if we have this letter in any owner drawn item 
4366     const int count 
= ::GetMenuItemCount(hmenu
); 
4367     for ( int i 
= 0; i 
< count
; i
++ ) 
4369         if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) ) 
4371             if ( mii
.fType 
== MFT_OWNERDRAW 
) 
4373                 //  dwItemData member of the MENUITEMINFO is a 
4374                 //  pointer to the associated wxMenuItem -- see the 
4375                 //  menu creation code 
4376                 wxMenuItem 
*item 
= (wxMenuItem
*)mii
.dwItemData
; 
4378                 const wxChar 
*p 
= wxStrchr(item
->GetText(), _T('&')); 
4381                     if ( *p 
== _T('&') ) 
4383                         // this is not the accel char, find the real one 
4384                         p 
= wxStrchr(p 
+ 1, _T('&')); 
4386                     else // got the accel char 
4388                         // FIXME-UNICODE: this comparison doesn't risk to work 
4389                         // for non ASCII accelerator characters I'm afraid, but 
4391                         if ( wxToupper(*p
) == chAccel 
) 
4397                             // this one doesn't match 
4404         else // failed ot get the menu text? 
4406             // it's not fatal, so don't show error, but still log 
4408             wxLogLastError(_T("GetMenuItemInfo")); 
4417 // --------------------------------------------------------------------------- 
4419 // --------------------------------------------------------------------------- 
4421 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4425     if ( flags 
& JOY_BUTTON1CHG 
) 
4426         change 
= wxJOY_BUTTON1
; 
4427     if ( flags 
& JOY_BUTTON2CHG 
) 
4428         change 
= wxJOY_BUTTON2
; 
4429     if ( flags 
& JOY_BUTTON3CHG 
) 
4430         change 
= wxJOY_BUTTON3
; 
4431     if ( flags 
& JOY_BUTTON4CHG 
) 
4432         change 
= wxJOY_BUTTON4
; 
4435     if ( flags 
& JOY_BUTTON1 
) 
4436         buttons 
|= wxJOY_BUTTON1
; 
4437     if ( flags 
& JOY_BUTTON2 
) 
4438         buttons 
|= wxJOY_BUTTON2
; 
4439     if ( flags 
& JOY_BUTTON3 
) 
4440         buttons 
|= wxJOY_BUTTON3
; 
4441     if ( flags 
& JOY_BUTTON4 
) 
4442         buttons 
|= wxJOY_BUTTON4
; 
4444     // the event ids aren't consecutive so we can't use table based lookup 
4446     wxEventType eventType
; 
4451             eventType 
= wxEVT_JOY_MOVE
; 
4456             eventType 
= wxEVT_JOY_MOVE
; 
4461             eventType 
= wxEVT_JOY_ZMOVE
; 
4466             eventType 
= wxEVT_JOY_ZMOVE
; 
4469         case MM_JOY1BUTTONDOWN
: 
4471             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4474         case MM_JOY2BUTTONDOWN
: 
4476             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4479         case MM_JOY1BUTTONUP
: 
4481             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4484         case MM_JOY2BUTTONUP
: 
4486             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4490             wxFAIL_MSG(wxT("no such joystick event")); 
4495     wxJoystickEvent 
event(eventType
, buttons
, joystick
, change
); 
4496     event
.SetPosition(wxPoint(x
, y
)); 
4497     event
.SetEventObject(this); 
4499     return GetEventHandler()->ProcessEvent(event
); 
4505 // --------------------------------------------------------------------------- 
4507 // --------------------------------------------------------------------------- 
4509 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
, 
4510                               WXWORD pos
, WXHWND control
) 
4514         wxWindow 
*child 
= wxFindWinFromHandle(control
); 
4516             return child
->MSWOnScroll(orientation
, wParam
, pos
, control
); 
4519     wxScrollWinEvent event
; 
4520     event
.SetPosition(pos
); 
4521     event
.SetOrientation(orientation
); 
4522     event
.m_eventObject 
= this; 
4527         event
.m_eventType 
= wxEVT_SCROLLWIN_TOP
; 
4531         event
.m_eventType 
= wxEVT_SCROLLWIN_BOTTOM
; 
4535         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEUP
; 
4539         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEDOWN
; 
4543         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEUP
; 
4547         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEDOWN
; 
4550     case SB_THUMBPOSITION
: 
4553         // under Win32, the scrollbar range and position are 32 bit integers, 
4554         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must 
4555         // explicitly query the scrollbar for the correct position (this must 
4556         // be done only for these two SB_ events as they are the only one 
4557         // carrying the scrollbar position) 
4559             WinStruct
<SCROLLINFO
> scrollInfo
; 
4560             scrollInfo
.fMask 
= SIF_TRACKPOS
; 
4562             if ( !::GetScrollInfo(GetHwnd(), 
4563                                   orientation 
== wxHORIZONTAL 
? SB_HORZ
 
4567                 wxLogLastError(_T("GetScrollInfo")); 
4570             event
.SetPosition(scrollInfo
.nTrackPos
); 
4574         event
.m_eventType 
= wParam 
== SB_THUMBPOSITION
 
4575                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
 
4576                                 : wxEVT_SCROLLWIN_THUMBTRACK
; 
4583     return GetEventHandler()->ProcessEvent(event
); 
4586 // =========================================================================== 
4588 // =========================================================================== 
4590 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont 
*the_font
) 
4593     HDC dc 
= ::GetDC((HWND
) wnd
); 
4598         //    the_font->UseResource(); 
4599         //    the_font->RealizeResource(); 
4600         fnt 
= (HFONT
)((wxFont 
*)the_font
)->GetResourceHandle(); // const_cast 
4602             was 
= (HFONT
) SelectObject(dc
,fnt
); 
4604     GetTextMetrics(dc
, &tm
); 
4605     if ( the_font 
&& fnt 
&& was 
) 
4607         SelectObject(dc
,was
); 
4609     ReleaseDC((HWND
)wnd
, dc
); 
4612         *x 
= tm
.tmAveCharWidth
; 
4614         *y 
= tm
.tmHeight 
+ tm
.tmExternalLeading
; 
4617     //    the_font->ReleaseResource(); 
4620 // Returns 0 if was a normal ASCII value, not a special key. This indicates that 
4621 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. 
4622 int wxCharCodeMSWToWX(int keySym
) 
4627         case VK_CANCEL
:     id 
= WXK_CANCEL
; break; 
4628         case VK_BACK
:       id 
= WXK_BACK
; break; 
4629         case VK_TAB
:        id 
= WXK_TAB
; break; 
4630         case VK_CLEAR
:      id 
= WXK_CLEAR
; break; 
4631         case VK_RETURN
:     id 
= WXK_RETURN
; break; 
4632         case VK_SHIFT
:      id 
= WXK_SHIFT
; break; 
4633         case VK_CONTROL
:    id 
= WXK_CONTROL
; break; 
4634         case VK_MENU 
:      id 
= WXK_MENU
; break; 
4635         case VK_PAUSE
:      id 
= WXK_PAUSE
; break; 
4636         case VK_CAPITAL
:    id 
= WXK_CAPITAL
; break; 
4637         case VK_SPACE
:      id 
= WXK_SPACE
; break; 
4638         case VK_ESCAPE
:     id 
= WXK_ESCAPE
; break; 
4639         case VK_PRIOR
:      id 
= WXK_PRIOR
; break; 
4640         case VK_NEXT 
:      id 
= WXK_NEXT
; break; 
4641         case VK_END
:        id 
= WXK_END
; break; 
4642         case VK_HOME 
:      id 
= WXK_HOME
; break; 
4643         case VK_LEFT 
:      id 
= WXK_LEFT
; break; 
4644         case VK_UP
:         id 
= WXK_UP
; break; 
4645         case VK_RIGHT
:      id 
= WXK_RIGHT
; break; 
4646         case VK_DOWN 
:      id 
= WXK_DOWN
; break; 
4647         case VK_SELECT
:     id 
= WXK_SELECT
; break; 
4648         case VK_PRINT
:      id 
= WXK_PRINT
; break; 
4649         case VK_EXECUTE
:    id 
= WXK_EXECUTE
; break; 
4650         case VK_INSERT
:     id 
= WXK_INSERT
; break; 
4651         case VK_DELETE
:     id 
= WXK_DELETE
; break; 
4652         case VK_HELP 
:      id 
= WXK_HELP
; break; 
4653         case VK_NUMPAD0
:    id 
= WXK_NUMPAD0
; break; 
4654         case VK_NUMPAD1
:    id 
= WXK_NUMPAD1
; break; 
4655         case VK_NUMPAD2
:    id 
= WXK_NUMPAD2
; break; 
4656         case VK_NUMPAD3
:    id 
= WXK_NUMPAD3
; break; 
4657         case VK_NUMPAD4
:    id 
= WXK_NUMPAD4
; break; 
4658         case VK_NUMPAD5
:    id 
= WXK_NUMPAD5
; break; 
4659         case VK_NUMPAD6
:    id 
= WXK_NUMPAD6
; break; 
4660         case VK_NUMPAD7
:    id 
= WXK_NUMPAD7
; break; 
4661         case VK_NUMPAD8
:    id 
= WXK_NUMPAD8
; break; 
4662         case VK_NUMPAD9
:    id 
= WXK_NUMPAD9
; break; 
4663         case VK_MULTIPLY
:   id 
= WXK_NUMPAD_MULTIPLY
; break; 
4664         case VK_ADD
:        id 
= WXK_NUMPAD_ADD
; break; 
4665         case VK_SUBTRACT
:   id 
= WXK_NUMPAD_SUBTRACT
; break; 
4666         case VK_DECIMAL
:    id 
= WXK_NUMPAD_DECIMAL
; break; 
4667         case VK_DIVIDE
:     id 
= WXK_NUMPAD_DIVIDE
; break; 
4668         case VK_F1
:         id 
= WXK_F1
; break; 
4669         case VK_F2
:         id 
= WXK_F2
; break; 
4670         case VK_F3
:         id 
= WXK_F3
; break; 
4671         case VK_F4
:         id 
= WXK_F4
; break; 
4672         case VK_F5
:         id 
= WXK_F5
; break; 
4673         case VK_F6
:         id 
= WXK_F6
; break; 
4674         case VK_F7
:         id 
= WXK_F7
; break; 
4675         case VK_F8
:         id 
= WXK_F8
; break; 
4676         case VK_F9
:         id 
= WXK_F9
; break; 
4677         case VK_F10
:        id 
= WXK_F10
; break; 
4678         case VK_F11
:        id 
= WXK_F11
; break; 
4679         case VK_F12
:        id 
= WXK_F12
; break; 
4680         case VK_F13
:        id 
= WXK_F13
; break; 
4681         case VK_F14
:        id 
= WXK_F14
; break; 
4682         case VK_F15
:        id 
= WXK_F15
; break; 
4683         case VK_F16
:        id 
= WXK_F16
; break; 
4684         case VK_F17
:        id 
= WXK_F17
; break; 
4685         case VK_F18
:        id 
= WXK_F18
; break; 
4686         case VK_F19
:        id 
= WXK_F19
; break; 
4687         case VK_F20
:        id 
= WXK_F20
; break; 
4688         case VK_F21
:        id 
= WXK_F21
; break; 
4689         case VK_F22
:        id 
= WXK_F22
; break; 
4690         case VK_F23
:        id 
= WXK_F23
; break; 
4691         case VK_F24
:        id 
= WXK_F24
; break; 
4692         case VK_NUMLOCK
:    id 
= WXK_NUMLOCK
; break; 
4693         case VK_SCROLL
:     id 
= WXK_SCROLL
; break; 
4695         case VK_OEM_1
:      id 
= ';'; break; 
4696         case VK_OEM_PLUS
:   id 
= '+'; break; 
4697         case VK_OEM_COMMA
:  id 
= ','; break; 
4698         case VK_OEM_MINUS
:  id 
= '-'; break; 
4699         case VK_OEM_PERIOD
: id 
= '.'; break; 
4700         case VK_OEM_2
:      id 
= '/'; break; 
4701         case VK_OEM_3
:      id 
= '~'; break; 
4702         case VK_OEM_4
:      id 
= '['; break; 
4703         case VK_OEM_5
:      id 
= '\\'; break; 
4704         case VK_OEM_6
:      id 
= ']'; break; 
4705         case VK_OEM_7
:      id 
= '\''; break; 
4708         case VK_LWIN
:       id 
= WXK_WINDOWS_LEFT
; break; 
4709         case VK_RWIN
:       id 
= WXK_WINDOWS_RIGHT
; break; 
4710         case VK_APPS
:       id 
= WXK_WINDOWS_MENU
; break; 
4711 #endif // VK_APPS defined 
4720 int wxCharCodeWXToMSW(int id
, bool *isVirtual
) 
4726     case WXK_CANCEL
:    keySym 
= VK_CANCEL
; break; 
4727     case WXK_CLEAR
:     keySym 
= VK_CLEAR
; break; 
4728     case WXK_SHIFT
:     keySym 
= VK_SHIFT
; break; 
4729     case WXK_CONTROL
:   keySym 
= VK_CONTROL
; break; 
4730     case WXK_MENU 
:     keySym 
= VK_MENU
; break; 
4731     case WXK_PAUSE
:     keySym 
= VK_PAUSE
; break; 
4732     case WXK_PRIOR
:     keySym 
= VK_PRIOR
; break; 
4733     case WXK_NEXT 
:     keySym 
= VK_NEXT
; break; 
4734     case WXK_END
:       keySym 
= VK_END
; break; 
4735     case WXK_HOME 
:     keySym 
= VK_HOME
; break; 
4736     case WXK_LEFT 
:     keySym 
= VK_LEFT
; break; 
4737     case WXK_UP
:        keySym 
= VK_UP
; break; 
4738     case WXK_RIGHT
:     keySym 
= VK_RIGHT
; break; 
4739     case WXK_DOWN 
:     keySym 
= VK_DOWN
; break; 
4740     case WXK_SELECT
:    keySym 
= VK_SELECT
; break; 
4741     case WXK_PRINT
:     keySym 
= VK_PRINT
; break; 
4742     case WXK_EXECUTE
:   keySym 
= VK_EXECUTE
; break; 
4743     case WXK_INSERT
:    keySym 
= VK_INSERT
; break; 
4744     case WXK_DELETE
:    keySym 
= VK_DELETE
; break; 
4745     case WXK_HELP 
:     keySym 
= VK_HELP
; break; 
4746     case WXK_NUMPAD0
:   keySym 
= VK_NUMPAD0
; break; 
4747     case WXK_NUMPAD1
:   keySym 
= VK_NUMPAD1
; break; 
4748     case WXK_NUMPAD2
:   keySym 
= VK_NUMPAD2
; break; 
4749     case WXK_NUMPAD3
:   keySym 
= VK_NUMPAD3
; break; 
4750     case WXK_NUMPAD4
:   keySym 
= VK_NUMPAD4
; break; 
4751     case WXK_NUMPAD5
:   keySym 
= VK_NUMPAD5
; break; 
4752     case WXK_NUMPAD6
:   keySym 
= VK_NUMPAD6
; break; 
4753     case WXK_NUMPAD7
:   keySym 
= VK_NUMPAD7
; break; 
4754     case WXK_NUMPAD8
:   keySym 
= VK_NUMPAD8
; break; 
4755     case WXK_NUMPAD9
:   keySym 
= VK_NUMPAD9
; break; 
4756     case WXK_NUMPAD_MULTIPLY
:  keySym 
= VK_MULTIPLY
; break; 
4757     case WXK_NUMPAD_ADD
:       keySym 
= VK_ADD
; break; 
4758     case WXK_NUMPAD_SUBTRACT
:  keySym 
= VK_SUBTRACT
; break; 
4759     case WXK_NUMPAD_DECIMAL
:   keySym 
= VK_DECIMAL
; break; 
4760     case WXK_NUMPAD_DIVIDE
:    keySym 
= VK_DIVIDE
; break; 
4761     case WXK_F1
:        keySym 
= VK_F1
; break; 
4762     case WXK_F2
:        keySym 
= VK_F2
; break; 
4763     case WXK_F3
:        keySym 
= VK_F3
; break; 
4764     case WXK_F4
:        keySym 
= VK_F4
; break; 
4765     case WXK_F5
:        keySym 
= VK_F5
; break; 
4766     case WXK_F6
:        keySym 
= VK_F6
; break; 
4767     case WXK_F7
:        keySym 
= VK_F7
; break; 
4768     case WXK_F8
:        keySym 
= VK_F8
; break; 
4769     case WXK_F9
:        keySym 
= VK_F9
; break; 
4770     case WXK_F10
:       keySym 
= VK_F10
; break; 
4771     case WXK_F11
:       keySym 
= VK_F11
; break; 
4772     case WXK_F12
:       keySym 
= VK_F12
; break; 
4773     case WXK_F13
:       keySym 
= VK_F13
; break; 
4774     case WXK_F14
:       keySym 
= VK_F14
; break; 
4775     case WXK_F15
:       keySym 
= VK_F15
; break; 
4776     case WXK_F16
:       keySym 
= VK_F16
; break; 
4777     case WXK_F17
:       keySym 
= VK_F17
; break; 
4778     case WXK_F18
:       keySym 
= VK_F18
; break; 
4779     case WXK_F19
:       keySym 
= VK_F19
; break; 
4780     case WXK_F20
:       keySym 
= VK_F20
; break; 
4781     case WXK_F21
:       keySym 
= VK_F21
; break; 
4782     case WXK_F22
:       keySym 
= VK_F22
; break; 
4783     case WXK_F23
:       keySym 
= VK_F23
; break; 
4784     case WXK_F24
:       keySym 
= VK_F24
; break; 
4785     case WXK_NUMLOCK
:   keySym 
= VK_NUMLOCK
; break; 
4786     case WXK_SCROLL
:    keySym 
= VK_SCROLL
; break; 
4797 wxWindow 
*wxGetActiveWindow() 
4799     HWND hWnd 
= GetActiveWindow(); 
4802         return wxFindWinFromHandle((WXHWND
) hWnd
); 
4807 extern wxWindow 
*wxGetWindowFromHWND(WXHWND hWnd
) 
4809     HWND hwnd 
= (HWND
)hWnd
; 
4811     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set 
4812     // by code in msw/radiobox.cpp), for all the others we just search up the 
4814     wxWindow 
*win 
= (wxWindow 
*)NULL
; 
4817         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
4820             // all these hacks only work under Win32 anyhow 
4824             // native radiobuttons return DLGC_RADIOBUTTON here and for any 
4825             // wxWindow class which overrides WM_GETDLGCODE processing to 
4826             // do it as well, win would be already non NULL 
4827             if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON 
) 
4829                 win 
= (wxWindow 
*)::GetWindowLong(hwnd
, GWL_USERDATA
); 
4831             //else: it's a wxRadioButton, not a radiobutton from wxRadioBox 
4832 #endif // wxUSE_RADIOBOX 
4834             // spin control text buddy window should be mapped to spin ctrl 
4835             // itself so try it too 
4836 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
4839                 win 
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
); 
4841 #endif // wxUSE_SPINCTRL 
4847     while ( hwnd 
&& !win 
) 
4849         // this is a really ugly hack needed to avoid mistakenly returning the 
4850         // parent frame wxWindow for the find/replace modeless dialog HWND - 
4851         // this, in turn, is needed to call IsDialogMessage() from 
4852         // wxApp::ProcessMessage() as for this we must return NULL from here 
4854         // FIXME: this is clearly not the best way to do it but I think we'll 
4855         //        need to change HWND <-> wxWindow code more heavily than I can 
4856         //        do it now to fix it 
4857 #ifndef __WXMICROWIN__ 
4858         if ( ::GetWindow(hwnd
, GW_OWNER
) ) 
4860             // it's a dialog box, don't go upwards 
4865         hwnd 
= ::GetParent(hwnd
); 
4866         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
4872 #ifndef __WXMICROWIN__ 
4874 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE 
4875 // in active frames and dialogs, regardless of where the focus is. 
4876 static HHOOK wxTheKeyboardHook 
= 0; 
4877 static FARPROC wxTheKeyboardHookProc 
= 0; 
4878 int APIENTRY _EXPORT
 
4879 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
); 
4881 void wxSetKeyboardHook(bool doIt
) 
4885         wxTheKeyboardHookProc 
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance()); 
4886         wxTheKeyboardHook 
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(), 
4888 #if defined(__WIN32__) 
4889             GetCurrentThreadId() 
4890         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? 
4898         UnhookWindowsHookEx(wxTheKeyboardHook
); 
4900         // avoids warning about statement with no effect (FreeProcInstance 
4901         // doesn't do anything under Win32) 
4902 #if !defined(__WIN32__) && !defined(__NT__) 
4903         FreeProcInstance(wxTheKeyboardHookProc
); 
4908 int APIENTRY _EXPORT
 
4909 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
) 
4911     DWORD hiWord 
= HIWORD(lParam
); 
4912     if ( nCode 
!= HC_NOREMOVE 
&& ((hiWord 
& KF_UP
) == 0) ) 
4914         int id 
= wxCharCodeMSWToWX(wParam
); 
4917             wxKeyEvent 
event(wxEVT_CHAR_HOOK
); 
4918             if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
4919                 event
.m_altDown 
= TRUE
; 
4921             event
.m_eventObject 
= NULL
; 
4922             event
.m_keyCode 
= id
; 
4923             event
.m_shiftDown 
= wxIsShiftDown(); 
4924             event
.m_controlDown 
= wxIsCtrlDown(); 
4925             event
.SetTimestamp(s_currentMsg
.time
); 
4927             wxWindow 
*win 
= wxGetActiveWindow(); 
4928             wxEvtHandler 
*handler
; 
4931                 handler 
= win
->GetEventHandler(); 
4932                 event
.SetId(win
->GetId()); 
4940             if ( handler 
&& handler
->ProcessEvent(event
) ) 
4948     return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
); 
4951 #endif // !__WXMICROWIN__ 
4954 const char *wxGetMessageName(int message
) 
4958         case 0x0000: return "WM_NULL"; 
4959         case 0x0001: return "WM_CREATE"; 
4960         case 0x0002: return "WM_DESTROY"; 
4961         case 0x0003: return "WM_MOVE"; 
4962         case 0x0005: return "WM_SIZE"; 
4963         case 0x0006: return "WM_ACTIVATE"; 
4964         case 0x0007: return "WM_SETFOCUS"; 
4965         case 0x0008: return "WM_KILLFOCUS"; 
4966         case 0x000A: return "WM_ENABLE"; 
4967         case 0x000B: return "WM_SETREDRAW"; 
4968         case 0x000C: return "WM_SETTEXT"; 
4969         case 0x000D: return "WM_GETTEXT"; 
4970         case 0x000E: return "WM_GETTEXTLENGTH"; 
4971         case 0x000F: return "WM_PAINT"; 
4972         case 0x0010: return "WM_CLOSE"; 
4973         case 0x0011: return "WM_QUERYENDSESSION"; 
4974         case 0x0012: return "WM_QUIT"; 
4975         case 0x0013: return "WM_QUERYOPEN"; 
4976         case 0x0014: return "WM_ERASEBKGND"; 
4977         case 0x0015: return "WM_SYSCOLORCHANGE"; 
4978         case 0x0016: return "WM_ENDSESSION"; 
4979         case 0x0017: return "WM_SYSTEMERROR"; 
4980         case 0x0018: return "WM_SHOWWINDOW"; 
4981         case 0x0019: return "WM_CTLCOLOR"; 
4982         case 0x001A: return "WM_WININICHANGE"; 
4983         case 0x001B: return "WM_DEVMODECHANGE"; 
4984         case 0x001C: return "WM_ACTIVATEAPP"; 
4985         case 0x001D: return "WM_FONTCHANGE"; 
4986         case 0x001E: return "WM_TIMECHANGE"; 
4987         case 0x001F: return "WM_CANCELMODE"; 
4988         case 0x0020: return "WM_SETCURSOR"; 
4989         case 0x0021: return "WM_MOUSEACTIVATE"; 
4990         case 0x0022: return "WM_CHILDACTIVATE"; 
4991         case 0x0023: return "WM_QUEUESYNC"; 
4992         case 0x0024: return "WM_GETMINMAXINFO"; 
4993         case 0x0026: return "WM_PAINTICON"; 
4994         case 0x0027: return "WM_ICONERASEBKGND"; 
4995         case 0x0028: return "WM_NEXTDLGCTL"; 
4996         case 0x002A: return "WM_SPOOLERSTATUS"; 
4997         case 0x002B: return "WM_DRAWITEM"; 
4998         case 0x002C: return "WM_MEASUREITEM"; 
4999         case 0x002D: return "WM_DELETEITEM"; 
5000         case 0x002E: return "WM_VKEYTOITEM"; 
5001         case 0x002F: return "WM_CHARTOITEM"; 
5002         case 0x0030: return "WM_SETFONT"; 
5003         case 0x0031: return "WM_GETFONT"; 
5004         case 0x0037: return "WM_QUERYDRAGICON"; 
5005         case 0x0039: return "WM_COMPAREITEM"; 
5006         case 0x0041: return "WM_COMPACTING"; 
5007         case 0x0044: return "WM_COMMNOTIFY"; 
5008         case 0x0046: return "WM_WINDOWPOSCHANGING"; 
5009         case 0x0047: return "WM_WINDOWPOSCHANGED"; 
5010         case 0x0048: return "WM_POWER"; 
5013         case 0x004A: return "WM_COPYDATA"; 
5014         case 0x004B: return "WM_CANCELJOURNAL"; 
5015         case 0x004E: return "WM_NOTIFY"; 
5016         case 0x0050: return "WM_INPUTLANGCHANGEREQUEST"; 
5017         case 0x0051: return "WM_INPUTLANGCHANGE"; 
5018         case 0x0052: return "WM_TCARD"; 
5019         case 0x0053: return "WM_HELP"; 
5020         case 0x0054: return "WM_USERCHANGED"; 
5021         case 0x0055: return "WM_NOTIFYFORMAT"; 
5022         case 0x007B: return "WM_CONTEXTMENU"; 
5023         case 0x007C: return "WM_STYLECHANGING"; 
5024         case 0x007D: return "WM_STYLECHANGED"; 
5025         case 0x007E: return "WM_DISPLAYCHANGE"; 
5026         case 0x007F: return "WM_GETICON"; 
5027         case 0x0080: return "WM_SETICON"; 
5030         case 0x0081: return "WM_NCCREATE"; 
5031         case 0x0082: return "WM_NCDESTROY"; 
5032         case 0x0083: return "WM_NCCALCSIZE"; 
5033         case 0x0084: return "WM_NCHITTEST"; 
5034         case 0x0085: return "WM_NCPAINT"; 
5035         case 0x0086: return "WM_NCACTIVATE"; 
5036         case 0x0087: return "WM_GETDLGCODE"; 
5037         case 0x00A0: return "WM_NCMOUSEMOVE"; 
5038         case 0x00A1: return "WM_NCLBUTTONDOWN"; 
5039         case 0x00A2: return "WM_NCLBUTTONUP"; 
5040         case 0x00A3: return "WM_NCLBUTTONDBLCLK"; 
5041         case 0x00A4: return "WM_NCRBUTTONDOWN"; 
5042         case 0x00A5: return "WM_NCRBUTTONUP"; 
5043         case 0x00A6: return "WM_NCRBUTTONDBLCLK"; 
5044         case 0x00A7: return "WM_NCMBUTTONDOWN"; 
5045         case 0x00A8: return "WM_NCMBUTTONUP"; 
5046         case 0x00A9: return "WM_NCMBUTTONDBLCLK"; 
5047         case 0x0100: return "WM_KEYDOWN"; 
5048         case 0x0101: return "WM_KEYUP"; 
5049         case 0x0102: return "WM_CHAR"; 
5050         case 0x0103: return "WM_DEADCHAR"; 
5051         case 0x0104: return "WM_SYSKEYDOWN"; 
5052         case 0x0105: return "WM_SYSKEYUP"; 
5053         case 0x0106: return "WM_SYSCHAR"; 
5054         case 0x0107: return "WM_SYSDEADCHAR"; 
5055         case 0x0108: return "WM_KEYLAST"; 
5058         case 0x010D: return "WM_IME_STARTCOMPOSITION"; 
5059         case 0x010E: return "WM_IME_ENDCOMPOSITION"; 
5060         case 0x010F: return "WM_IME_COMPOSITION"; 
5063         case 0x0110: return "WM_INITDIALOG"; 
5064         case 0x0111: return "WM_COMMAND"; 
5065         case 0x0112: return "WM_SYSCOMMAND"; 
5066         case 0x0113: return "WM_TIMER"; 
5067         case 0x0114: return "WM_HSCROLL"; 
5068         case 0x0115: return "WM_VSCROLL"; 
5069         case 0x0116: return "WM_INITMENU"; 
5070         case 0x0117: return "WM_INITMENUPOPUP"; 
5071         case 0x011F: return "WM_MENUSELECT"; 
5072         case 0x0120: return "WM_MENUCHAR"; 
5073         case 0x0121: return "WM_ENTERIDLE"; 
5074         case 0x0200: return "WM_MOUSEMOVE"; 
5075         case 0x0201: return "WM_LBUTTONDOWN"; 
5076         case 0x0202: return "WM_LBUTTONUP"; 
5077         case 0x0203: return "WM_LBUTTONDBLCLK"; 
5078         case 0x0204: return "WM_RBUTTONDOWN"; 
5079         case 0x0205: return "WM_RBUTTONUP"; 
5080         case 0x0206: return "WM_RBUTTONDBLCLK"; 
5081         case 0x0207: return "WM_MBUTTONDOWN"; 
5082         case 0x0208: return "WM_MBUTTONUP"; 
5083         case 0x0209: return "WM_MBUTTONDBLCLK"; 
5084         case 0x020A: return "WM_MOUSEWHEEL"; 
5085         case 0x0210: return "WM_PARENTNOTIFY"; 
5086         case 0x0211: return "WM_ENTERMENULOOP"; 
5087         case 0x0212: return "WM_EXITMENULOOP"; 
5090         case 0x0213: return "WM_NEXTMENU"; 
5091         case 0x0214: return "WM_SIZING"; 
5092         case 0x0215: return "WM_CAPTURECHANGED"; 
5093         case 0x0216: return "WM_MOVING"; 
5094         case 0x0218: return "WM_POWERBROADCAST"; 
5095         case 0x0219: return "WM_DEVICECHANGE"; 
5098         case 0x0220: return "WM_MDICREATE"; 
5099         case 0x0221: return "WM_MDIDESTROY"; 
5100         case 0x0222: return "WM_MDIACTIVATE"; 
5101         case 0x0223: return "WM_MDIRESTORE"; 
5102         case 0x0224: return "WM_MDINEXT"; 
5103         case 0x0225: return "WM_MDIMAXIMIZE"; 
5104         case 0x0226: return "WM_MDITILE"; 
5105         case 0x0227: return "WM_MDICASCADE"; 
5106         case 0x0228: return "WM_MDIICONARRANGE"; 
5107         case 0x0229: return "WM_MDIGETACTIVE"; 
5108         case 0x0230: return "WM_MDISETMENU"; 
5109         case 0x0233: return "WM_DROPFILES"; 
5112         case 0x0281: return "WM_IME_SETCONTEXT"; 
5113         case 0x0282: return "WM_IME_NOTIFY"; 
5114         case 0x0283: return "WM_IME_CONTROL"; 
5115         case 0x0284: return "WM_IME_COMPOSITIONFULL"; 
5116         case 0x0285: return "WM_IME_SELECT"; 
5117         case 0x0286: return "WM_IME_CHAR"; 
5118         case 0x0290: return "WM_IME_KEYDOWN"; 
5119         case 0x0291: return "WM_IME_KEYUP"; 
5122         case 0x0300: return "WM_CUT"; 
5123         case 0x0301: return "WM_COPY"; 
5124         case 0x0302: return "WM_PASTE"; 
5125         case 0x0303: return "WM_CLEAR"; 
5126         case 0x0304: return "WM_UNDO"; 
5127         case 0x0305: return "WM_RENDERFORMAT"; 
5128         case 0x0306: return "WM_RENDERALLFORMATS"; 
5129         case 0x0307: return "WM_DESTROYCLIPBOARD"; 
5130         case 0x0308: return "WM_DRAWCLIPBOARD"; 
5131         case 0x0309: return "WM_PAINTCLIPBOARD"; 
5132         case 0x030A: return "WM_VSCROLLCLIPBOARD"; 
5133         case 0x030B: return "WM_SIZECLIPBOARD"; 
5134         case 0x030C: return "WM_ASKCBFORMATNAME"; 
5135         case 0x030D: return "WM_CHANGECBCHAIN"; 
5136         case 0x030E: return "WM_HSCROLLCLIPBOARD"; 
5137         case 0x030F: return "WM_QUERYNEWPALETTE"; 
5138         case 0x0310: return "WM_PALETTEISCHANGING"; 
5139         case 0x0311: return "WM_PALETTECHANGED"; 
5142         // common controls messages - although they're not strictly speaking 
5143         // standard, it's nice to decode them nevertheless 
5146         case 0x1000 + 0: return "LVM_GETBKCOLOR"; 
5147         case 0x1000 + 1: return "LVM_SETBKCOLOR"; 
5148         case 0x1000 + 2: return "LVM_GETIMAGELIST"; 
5149         case 0x1000 + 3: return "LVM_SETIMAGELIST"; 
5150         case 0x1000 + 4: return "LVM_GETITEMCOUNT"; 
5151         case 0x1000 + 5: return "LVM_GETITEMA"; 
5152         case 0x1000 + 75: return "LVM_GETITEMW"; 
5153         case 0x1000 + 6: return "LVM_SETITEMA"; 
5154         case 0x1000 + 76: return "LVM_SETITEMW"; 
5155         case 0x1000 + 7: return "LVM_INSERTITEMA"; 
5156         case 0x1000 + 77: return "LVM_INSERTITEMW"; 
5157         case 0x1000 + 8: return "LVM_DELETEITEM"; 
5158         case 0x1000 + 9: return "LVM_DELETEALLITEMS"; 
5159         case 0x1000 + 10: return "LVM_GETCALLBACKMASK"; 
5160         case 0x1000 + 11: return "LVM_SETCALLBACKMASK"; 
5161         case 0x1000 + 12: return "LVM_GETNEXTITEM"; 
5162         case 0x1000 + 13: return "LVM_FINDITEMA"; 
5163         case 0x1000 + 83: return "LVM_FINDITEMW"; 
5164         case 0x1000 + 14: return "LVM_GETITEMRECT"; 
5165         case 0x1000 + 15: return "LVM_SETITEMPOSITION"; 
5166         case 0x1000 + 16: return "LVM_GETITEMPOSITION"; 
5167         case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA"; 
5168         case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW"; 
5169         case 0x1000 + 18: return "LVM_HITTEST"; 
5170         case 0x1000 + 19: return "LVM_ENSUREVISIBLE"; 
5171         case 0x1000 + 20: return "LVM_SCROLL"; 
5172         case 0x1000 + 21: return "LVM_REDRAWITEMS"; 
5173         case 0x1000 + 22: return "LVM_ARRANGE"; 
5174         case 0x1000 + 23: return "LVM_EDITLABELA"; 
5175         case 0x1000 + 118: return "LVM_EDITLABELW"; 
5176         case 0x1000 + 24: return "LVM_GETEDITCONTROL"; 
5177         case 0x1000 + 25: return "LVM_GETCOLUMNA"; 
5178         case 0x1000 + 95: return "LVM_GETCOLUMNW"; 
5179         case 0x1000 + 26: return "LVM_SETCOLUMNA"; 
5180         case 0x1000 + 96: return "LVM_SETCOLUMNW"; 
5181         case 0x1000 + 27: return "LVM_INSERTCOLUMNA"; 
5182         case 0x1000 + 97: return "LVM_INSERTCOLUMNW"; 
5183         case 0x1000 + 28: return "LVM_DELETECOLUMN"; 
5184         case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH"; 
5185         case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH"; 
5186         case 0x1000 + 31: return "LVM_GETHEADER"; 
5187         case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE"; 
5188         case 0x1000 + 34: return "LVM_GETVIEWRECT"; 
5189         case 0x1000 + 35: return "LVM_GETTEXTCOLOR"; 
5190         case 0x1000 + 36: return "LVM_SETTEXTCOLOR"; 
5191         case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR"; 
5192         case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR"; 
5193         case 0x1000 + 39: return "LVM_GETTOPINDEX"; 
5194         case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE"; 
5195         case 0x1000 + 41: return "LVM_GETORIGIN"; 
5196         case 0x1000 + 42: return "LVM_UPDATE"; 
5197         case 0x1000 + 43: return "LVM_SETITEMSTATE"; 
5198         case 0x1000 + 44: return "LVM_GETITEMSTATE"; 
5199         case 0x1000 + 45: return "LVM_GETITEMTEXTA"; 
5200         case 0x1000 + 115: return "LVM_GETITEMTEXTW"; 
5201         case 0x1000 + 46: return "LVM_SETITEMTEXTA"; 
5202         case 0x1000 + 116: return "LVM_SETITEMTEXTW"; 
5203         case 0x1000 + 47: return "LVM_SETITEMCOUNT"; 
5204         case 0x1000 + 48: return "LVM_SORTITEMS"; 
5205         case 0x1000 + 49: return "LVM_SETITEMPOSITION32"; 
5206         case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT"; 
5207         case 0x1000 + 51: return "LVM_GETITEMSPACING"; 
5208         case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA"; 
5209         case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW"; 
5210         case 0x1000 + 53: return "LVM_SETICONSPACING"; 
5211         case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE"; 
5212         case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE"; 
5213         case 0x1000 + 56: return "LVM_GETSUBITEMRECT"; 
5214         case 0x1000 + 57: return "LVM_SUBITEMHITTEST"; 
5215         case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY"; 
5216         case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY"; 
5217         case 0x1000 + 60: return "LVM_SETHOTITEM"; 
5218         case 0x1000 + 61: return "LVM_GETHOTITEM"; 
5219         case 0x1000 + 62: return "LVM_SETHOTCURSOR"; 
5220         case 0x1000 + 63: return "LVM_GETHOTCURSOR"; 
5221         case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT"; 
5222         case 0x1000 + 65: return "LVM_SETWORKAREA"; 
5225         case 0x1100 + 0: return "TVM_INSERTITEMA"; 
5226         case 0x1100 + 50: return "TVM_INSERTITEMW"; 
5227         case 0x1100 + 1: return "TVM_DELETEITEM"; 
5228         case 0x1100 + 2: return "TVM_EXPAND"; 
5229         case 0x1100 + 4: return "TVM_GETITEMRECT"; 
5230         case 0x1100 + 5: return "TVM_GETCOUNT"; 
5231         case 0x1100 + 6: return "TVM_GETINDENT"; 
5232         case 0x1100 + 7: return "TVM_SETINDENT"; 
5233         case 0x1100 + 8: return "TVM_GETIMAGELIST"; 
5234         case 0x1100 + 9: return "TVM_SETIMAGELIST"; 
5235         case 0x1100 + 10: return "TVM_GETNEXTITEM"; 
5236         case 0x1100 + 11: return "TVM_SELECTITEM"; 
5237         case 0x1100 + 12: return "TVM_GETITEMA"; 
5238         case 0x1100 + 62: return "TVM_GETITEMW"; 
5239         case 0x1100 + 13: return "TVM_SETITEMA"; 
5240         case 0x1100 + 63: return "TVM_SETITEMW"; 
5241         case 0x1100 + 14: return "TVM_EDITLABELA"; 
5242         case 0x1100 + 65: return "TVM_EDITLABELW"; 
5243         case 0x1100 + 15: return "TVM_GETEDITCONTROL"; 
5244         case 0x1100 + 16: return "TVM_GETVISIBLECOUNT"; 
5245         case 0x1100 + 17: return "TVM_HITTEST"; 
5246         case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE"; 
5247         case 0x1100 + 19: return "TVM_SORTCHILDREN"; 
5248         case 0x1100 + 20: return "TVM_ENSUREVISIBLE"; 
5249         case 0x1100 + 21: return "TVM_SORTCHILDRENCB"; 
5250         case 0x1100 + 22: return "TVM_ENDEDITLABELNOW"; 
5251         case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA"; 
5252         case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW"; 
5253         case 0x1100 + 24: return "TVM_SETTOOLTIPS"; 
5254         case 0x1100 + 25: return "TVM_GETTOOLTIPS"; 
5257         case 0x1200 + 0: return "HDM_GETITEMCOUNT"; 
5258         case 0x1200 + 1: return "HDM_INSERTITEMA"; 
5259         case 0x1200 + 10: return "HDM_INSERTITEMW"; 
5260         case 0x1200 + 2: return "HDM_DELETEITEM"; 
5261         case 0x1200 + 3: return "HDM_GETITEMA"; 
5262         case 0x1200 + 11: return "HDM_GETITEMW"; 
5263         case 0x1200 + 4: return "HDM_SETITEMA"; 
5264         case 0x1200 + 12: return "HDM_SETITEMW"; 
5265         case 0x1200 + 5: return "HDM_LAYOUT"; 
5266         case 0x1200 + 6: return "HDM_HITTEST"; 
5267         case 0x1200 + 7: return "HDM_GETITEMRECT"; 
5268         case 0x1200 + 8: return "HDM_SETIMAGELIST"; 
5269         case 0x1200 + 9: return "HDM_GETIMAGELIST"; 
5270         case 0x1200 + 15: return "HDM_ORDERTOINDEX"; 
5271         case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE"; 
5272         case 0x1200 + 17: return "HDM_GETORDERARRAY"; 
5273         case 0x1200 + 18: return "HDM_SETORDERARRAY"; 
5274         case 0x1200 + 19: return "HDM_SETHOTDIVIDER"; 
5277         case 0x1300 + 2: return "TCM_GETIMAGELIST"; 
5278         case 0x1300 + 3: return "TCM_SETIMAGELIST"; 
5279         case 0x1300 + 4: return "TCM_GETITEMCOUNT"; 
5280         case 0x1300 + 5: return "TCM_GETITEMA"; 
5281         case 0x1300 + 60: return "TCM_GETITEMW"; 
5282         case 0x1300 + 6: return "TCM_SETITEMA"; 
5283         case 0x1300 + 61: return "TCM_SETITEMW"; 
5284         case 0x1300 + 7: return "TCM_INSERTITEMA"; 
5285         case 0x1300 + 62: return "TCM_INSERTITEMW"; 
5286         case 0x1300 + 8: return "TCM_DELETEITEM"; 
5287         case 0x1300 + 9: return "TCM_DELETEALLITEMS"; 
5288         case 0x1300 + 10: return "TCM_GETITEMRECT"; 
5289         case 0x1300 + 11: return "TCM_GETCURSEL"; 
5290         case 0x1300 + 12: return "TCM_SETCURSEL"; 
5291         case 0x1300 + 13: return "TCM_HITTEST"; 
5292         case 0x1300 + 14: return "TCM_SETITEMEXTRA"; 
5293         case 0x1300 + 40: return "TCM_ADJUSTRECT"; 
5294         case 0x1300 + 41: return "TCM_SETITEMSIZE"; 
5295         case 0x1300 + 42: return "TCM_REMOVEIMAGE"; 
5296         case 0x1300 + 43: return "TCM_SETPADDING"; 
5297         case 0x1300 + 44: return "TCM_GETROWCOUNT"; 
5298         case 0x1300 + 45: return "TCM_GETTOOLTIPS"; 
5299         case 0x1300 + 46: return "TCM_SETTOOLTIPS"; 
5300         case 0x1300 + 47: return "TCM_GETCURFOCUS"; 
5301         case 0x1300 + 48: return "TCM_SETCURFOCUS"; 
5302         case 0x1300 + 49: return "TCM_SETMINTABWIDTH"; 
5303         case 0x1300 + 50: return "TCM_DESELECTALL"; 
5306         case WM_USER
+1: return "TB_ENABLEBUTTON"; 
5307         case WM_USER
+2: return "TB_CHECKBUTTON"; 
5308         case WM_USER
+3: return "TB_PRESSBUTTON"; 
5309         case WM_USER
+4: return "TB_HIDEBUTTON"; 
5310         case WM_USER
+5: return "TB_INDETERMINATE"; 
5311         case WM_USER
+9: return "TB_ISBUTTONENABLED"; 
5312         case WM_USER
+10: return "TB_ISBUTTONCHECKED"; 
5313         case WM_USER
+11: return "TB_ISBUTTONPRESSED"; 
5314         case WM_USER
+12: return "TB_ISBUTTONHIDDEN"; 
5315         case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE"; 
5316         case WM_USER
+17: return "TB_SETSTATE"; 
5317         case WM_USER
+18: return "TB_GETSTATE"; 
5318         case WM_USER
+19: return "TB_ADDBITMAP"; 
5319         case WM_USER
+20: return "TB_ADDBUTTONS"; 
5320         case WM_USER
+21: return "TB_INSERTBUTTON"; 
5321         case WM_USER
+22: return "TB_DELETEBUTTON"; 
5322         case WM_USER
+23: return "TB_GETBUTTON"; 
5323         case WM_USER
+24: return "TB_BUTTONCOUNT"; 
5324         case WM_USER
+25: return "TB_COMMANDTOINDEX"; 
5325         case WM_USER
+26: return "TB_SAVERESTOREA"; 
5326         case WM_USER
+76: return "TB_SAVERESTOREW"; 
5327         case WM_USER
+27: return "TB_CUSTOMIZE"; 
5328         case WM_USER
+28: return "TB_ADDSTRINGA"; 
5329         case WM_USER
+77: return "TB_ADDSTRINGW"; 
5330         case WM_USER
+29: return "TB_GETITEMRECT"; 
5331         case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE"; 
5332         case WM_USER
+31: return "TB_SETBUTTONSIZE"; 
5333         case WM_USER
+32: return "TB_SETBITMAPSIZE"; 
5334         case WM_USER
+33: return "TB_AUTOSIZE"; 
5335         case WM_USER
+35: return "TB_GETTOOLTIPS"; 
5336         case WM_USER
+36: return "TB_SETTOOLTIPS"; 
5337         case WM_USER
+37: return "TB_SETPARENT"; 
5338         case WM_USER
+39: return "TB_SETROWS"; 
5339         case WM_USER
+40: return "TB_GETROWS"; 
5340         case WM_USER
+42: return "TB_SETCMDID"; 
5341         case WM_USER
+43: return "TB_CHANGEBITMAP"; 
5342         case WM_USER
+44: return "TB_GETBITMAP"; 
5343         case WM_USER
+45: return "TB_GETBUTTONTEXTA"; 
5344         case WM_USER
+75: return "TB_GETBUTTONTEXTW"; 
5345         case WM_USER
+46: return "TB_REPLACEBITMAP"; 
5346         case WM_USER
+47: return "TB_SETINDENT"; 
5347         case WM_USER
+48: return "TB_SETIMAGELIST"; 
5348         case WM_USER
+49: return "TB_GETIMAGELIST"; 
5349         case WM_USER
+50: return "TB_LOADIMAGES"; 
5350         case WM_USER
+51: return "TB_GETRECT"; 
5351         case WM_USER
+52: return "TB_SETHOTIMAGELIST"; 
5352         case WM_USER
+53: return "TB_GETHOTIMAGELIST"; 
5353         case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST"; 
5354         case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST"; 
5355         case WM_USER
+56: return "TB_SETSTYLE"; 
5356         case WM_USER
+57: return "TB_GETSTYLE"; 
5357         case WM_USER
+58: return "TB_GETBUTTONSIZE"; 
5358         case WM_USER
+59: return "TB_SETBUTTONWIDTH"; 
5359         case WM_USER
+60: return "TB_SETMAXTEXTROWS"; 
5360         case WM_USER
+61: return "TB_GETTEXTROWS"; 
5361         case WM_USER
+41: return "TB_GETBITMAPFLAGS"; 
5366             static char s_szBuf
[128]; 
5367             sprintf(s_szBuf
, "<unknown message = %d>", message
); 
5371 #endif //__WXDEBUG__ 
5373 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
5374                                      int *x
, int *y
, WPARAM 
*flags
) 
5376     // construct the key mask 
5377     WPARAM
& fwKeys 
= *flags
; 
5379     fwKeys 
= MK_RBUTTON
; 
5380     if ( wxIsCtrlDown() ) 
5381         fwKeys 
|= MK_CONTROL
; 
5382     if ( wxIsShiftDown() ) 
5385     // simulate right mouse button click 
5386     DWORD dwPos 
= ::GetMessagePos(); 
5387     *x 
= GET_X_LPARAM(dwPos
); 
5388     *y 
= GET_Y_LPARAM(dwPos
); 
5390     win
->ScreenToClient(x
, y
); 
5393 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
) 
5397     HWND hwnd 
= GetHwndOf(win
); 
5398     HDC hdc 
= ::GetDC(hwnd
); 
5400 #if !wxDIALOG_UNIT_COMPATIBILITY 
5401     // and select the current font into it 
5402     HFONT hfont 
= GetHfontOf(win
->GetFont()); 
5405         hfont 
= (HFONT
)::SelectObject(hdc
, hfont
); 
5409     // finally retrieve the text metrics from it 
5410     GetTextMetrics(hdc
, &tm
); 
5412 #if !wxDIALOG_UNIT_COMPATIBILITY 
5416         (void)::SelectObject(hdc
, hfont
); 
5420     ::ReleaseDC(hwnd
, hdc
); 
5425 // Find the wxWindow at the current mouse position, returning the mouse 
5427 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
) 
5429     pt 
= wxGetMousePosition(); 
5430     return wxFindWindowAtPoint(pt
); 
5433 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
5438     HWND hWndHit 
= ::WindowFromPoint(pt2
); 
5440     wxWindow
* win 
= wxFindWinFromHandle((WXHWND
) hWndHit
) ; 
5441     HWND hWnd 
= hWndHit
; 
5443     // Try to find a window with a wxWindow associated with it 
5444     while (!win 
&& (hWnd 
!= 0)) 
5446         hWnd 
= ::GetParent(hWnd
); 
5447         win 
= wxFindWinFromHandle((WXHWND
) hWnd
) ; 
5452 // Get the current mouse position. 
5453 wxPoint 
wxGetMousePosition() 
5456     GetCursorPos( & pt 
); 
5458     return wxPoint(pt
.x
, pt
.y
);