1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/windows.cpp 
   4 // Author:      Julian Smart 
   5 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // =========================================================================== 
  14 // =========================================================================== 
  16 // --------------------------------------------------------------------------- 
  18 // --------------------------------------------------------------------------- 
  21     #pragma implementation "window.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  33     #include "wx/msw/winundef.h" 
  34     #include "wx/window.h" 
  39     #include "wx/dcclient.h" 
  40     #include "wx/dcmemory.h" 
  43     #include "wx/layout.h" 
  44     #include "wx/dialog.h" 
  46     #include "wx/listbox.h" 
  47     #include "wx/button.h" 
  48     #include "wx/msgdlg.h" 
  49     #include "wx/settings.h" 
  50     #include "wx/statbox.h" 
  54     #include "wx/ownerdrw.h" 
  57 #if wxUSE_DRAG_AND_DROP 
  61 #include "wx/menuitem.h" 
  64 #include "wx/msw/private.h" 
  67     #include "wx/tooltip.h" 
  75     #include "wx/spinctrl.h" 
  76 #endif // wxUSE_SPINCTRL 
  81 #include "wx/textctrl.h" 
  82 #include "wx/notebook.h" 
  86 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) 
  95 #if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) 
  99 #elif !defined(__WXMICROWIN__) // broken compiler 
 101         #include "wx/msw/gnuwin32/extra.h" 
 105 // This didn't appear in mingw until 2.95.2 
 107 #define SIF_TRACKPOS 16 
 111     #ifndef WM_MOUSEWHEEL 
 112         #define WM_MOUSEWHEEL           0x020A 
 115         #define WHEEL_DELTA             120 
 117     #ifndef SPI_GETWHEELSCROLLLINES 
 118         #define SPI_GETWHEELSCROLLLINES 104 
 122 // --------------------------------------------------------------------------- 
 124 // --------------------------------------------------------------------------- 
 126 // the last Windows message we got (FIXME-MT) 
 127 extern MSG s_currentMsg
; 
 129 #if wxUSE_MENUS_NATIVE 
 130 wxMenu 
*wxCurrentPopupMenu 
= NULL
; 
 131 #endif // wxUSE_MENUS_NATIVE 
 133 extern const wxChar 
*wxCanvasClassName
; 
 135 // true if we had already created the std colour map, used by 
 136 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT) 
 137 static bool gs_hasStdCmap 
= FALSE
; 
 139 // --------------------------------------------------------------------------- 
 141 // --------------------------------------------------------------------------- 
 143 // the window proc for all our windows 
 144 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, 
 145                                    WPARAM wParam
, LPARAM lParam
); 
 148     const char *wxGetMessageName(int message
); 
 151 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 152 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 153 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
); 
 155 // this magical function is used to translate VK_APPS key presses to right 
 157 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
 158                                      int *x
, int *y
, WPARAM 
*flags
); 
 160 // get the text metrics for the current font 
 161 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
); 
 163 // wrapper around BringWindowToTop() API 
 164 static inline void wxBringWindowToTop(HWND hwnd
) 
 166 #ifdef __WXMICROWIN__ 
 167     // It seems that MicroWindows brings the _parent_ of the window to the top, 
 168     // which can be the wrong one. 
 170     // activate (set focus to) specified window 
 173     // raise top level parent to top of z order 
 174     ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE 
| SWP_NOSIZE
); 
 175 #else // !__WXMICROWIN__ 
 176     if ( !::BringWindowToTop(hwnd
) ) 
 178         wxLogLastError(_T("BringWindowToTop")); 
 180 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
 183 // --------------------------------------------------------------------------- 
 185 // --------------------------------------------------------------------------- 
 187 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu() 
 189 #ifdef __WXUNIVERSAL__ 
 190     IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
) 
 192     IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
) 
 193 #endif // __WXUNIVERSAL__/__WXMSW__ 
 195 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
) 
 196     EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
) 
 197     EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
) 
 198     EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
) 
 199     EVT_IDLE(wxWindowMSW::OnIdle
) 
 202 // =========================================================================== 
 204 // =========================================================================== 
 206 // --------------------------------------------------------------------------- 
 207 // wxWindow utility functions 
 208 // --------------------------------------------------------------------------- 
 210 // Find an item given the MS Windows id 
 211 wxWindow 
*wxWindowMSW::FindItem(long id
) const 
 214     wxControl 
*item 
= wxDynamicCastThis(wxControl
); 
 217         // is it we or one of our "internal" children? 
 218         if ( item
->GetId() == id
 
 219 #ifndef __WXUNIVERSAL__ 
 220                 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
) 
 221 #endif // __WXUNIVERSAL__ 
 227 #endif // wxUSE_CONTROLS 
 229     wxWindowList::Node 
*current 
= GetChildren().GetFirst(); 
 232         wxWindow 
*childWin 
= current
->GetData(); 
 234         wxWindow 
*wnd 
= childWin
->FindItem(id
); 
 238         current 
= current
->GetNext(); 
 244 // Find an item given the MS Windows handle 
 245 wxWindow 
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const 
 247     wxWindowList::Node 
*current 
= GetChildren().GetFirst(); 
 250         wxWindow 
*parent 
= current
->GetData(); 
 252         // Do a recursive search. 
 253         wxWindow 
*wnd 
= parent
->FindItemByHWND(hWnd
); 
 259                 || parent
->IsKindOf(CLASSINFO(wxControl
)) 
 260 #endif // wxUSE_CONTROLS 
 263             wxWindow 
*item 
= current
->GetData(); 
 264             if ( item
->GetHWND() == hWnd 
) 
 268                 if ( item
->ContainsHWND(hWnd
) ) 
 273         current 
= current
->GetNext(); 
 278 // Default command handler 
 279 bool wxWindowMSW::MSWCommand(WXUINT 
WXUNUSED(param
), WXWORD 
WXUNUSED(id
)) 
 284 // ---------------------------------------------------------------------------- 
 285 // constructors and such 
 286 // ---------------------------------------------------------------------------- 
 288 void wxWindowMSW::Init() 
 294     m_doubleClickAllowed 
= 0; 
 296     m_isBeingDeleted 
= FALSE
; 
 299     m_mouseInWindow 
= FALSE
; 
 308     m_backgroundTransparent 
= FALSE
; 
 310     // as all windows are created with WS_VISIBLE style... 
 313 #if wxUSE_MOUSEEVENT_HACK 
 316     m_lastMouseEvent 
= -1; 
 317 #endif // wxUSE_MOUSEEVENT_HACK 
 321 wxWindowMSW::~wxWindowMSW() 
 323     m_isBeingDeleted 
= TRUE
; 
 325 #ifndef __WXUNIVERSAL__ 
 326     // VS: make sure there's no wxFrame with last focus set to us: 
 327     for ( wxWindow 
*win 
= GetParent(); win
; win 
= win
->GetParent() ) 
 329         wxFrame 
*frame 
= wxDynamicCast(win
, wxFrame
); 
 332             if ( frame
->GetLastFocus() == this ) 
 334                 frame
->SetLastFocus((wxWindow
*)NULL
); 
 339 #endif // __WXUNIVERSAL__ 
 341     // VS: destroy children first and _then_ detach *this from its parent. 
 342     //     If we'd do it the other way around, children wouldn't be able 
 343     //     find their parent frame (see above). 
 347         m_parent
->RemoveChild(this); 
 351         // VZ: test temp removed to understand what really happens here 
 352         //if (::IsWindow(GetHwnd())) 
 354             if ( !::DestroyWindow(GetHwnd()) ) 
 355                 wxLogLastError(wxT("DestroyWindow")); 
 358         // remove hWnd <-> wxWindow association 
 359         wxRemoveHandleAssociation(this); 
 363 // real construction (Init() must have been called before!) 
 364 bool wxWindowMSW::Create(wxWindow 
*parent
, 
 369                          const wxString
& name
) 
 371     wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") ); 
 374     // wxGTK doesn't allow to create controls with static box as the parent so 
 375     // this will result in a crash when the program is ported to wxGTK - warn 
 378     // the correct solution is to create the controls as siblings of the 
 380     wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
), 
 381                   _T("wxStaticBox can't be used as a window parent!") ); 
 382 #endif // wxUSE_STATBOX 
 384     if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 387     parent
->AddChild(this); 
 389     // all windows are created visible 
 390     DWORD msflags 
= WS_CHILD 
| WS_VISIBLE
; 
 392 #ifdef __WXUNIVERSAL__ 
 393     // no 3d effects, we draw them ourselves 
 395 #else // !wxUniversal 
 396     if ( style 
& wxCLIP_CHILDREN 
) 
 397         msflags 
|= WS_CLIPCHILDREN
; 
 398     if ( style 
& wxCLIP_SIBLINGS 
) 
 399         msflags 
|= WS_CLIPSIBLINGS
; 
 402     WXDWORD exStyle 
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
); 
 404     // Even with extended styles, need to combine with WS_BORDER 
 405     // for them to look right. 
 407         (m_windowStyle 
& (wxBORDER 
| 
 413         msflags 
|= WS_BORDER
; 
 415 #endif // wxUniversal/!wxUniversal 
 417     if ( style 
& wxPOPUP_WINDOW 
) 
 419         // a popup window floats on top of everything 
 420         exStyle 
|= WS_EX_TOPMOST 
| WS_EX_TOOLWINDOW
; 
 422         // it is also created hidden as other top level windows 
 423         msflags 
&= ~WS_VISIBLE
; 
 427     return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
); 
 430 // --------------------------------------------------------------------------- 
 432 // --------------------------------------------------------------------------- 
 434 void wxWindowMSW::SetFocus() 
 436     HWND hWnd 
= GetHwnd(); 
 437     wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") ); 
 439 #ifndef __WXMICROWIN__ 
 443     if ( !::SetFocus(hWnd
) ) 
 445 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__) 
 446         // was there really an error? 
 447         DWORD dwRes 
= ::GetLastError(); 
 450             HWND hwndFocus 
= ::GetFocus(); 
 451             if ( hwndFocus 
!= hWnd 
) 
 453                 wxLogApiError(_T("SetFocus"), dwRes
); 
 460 // Get the window with the focus 
 461 wxWindow 
*wxWindowBase::FindFocus() 
 463     HWND hWnd 
= ::GetFocus(); 
 466         return wxGetWindowFromHWND((WXHWND
)hWnd
); 
 472 bool wxWindowMSW::Enable(bool enable
) 
 474     if ( !wxWindowBase::Enable(enable
) ) 
 477     HWND hWnd 
= GetHwnd(); 
 479         ::EnableWindow(hWnd
, (BOOL
)enable
); 
 481     // VZ: no, this is a bad idea: imagine that you have a dialog with some 
 482     //     disabled controls and disable it - you really wouldn't like the 
 483     //     disabled controls be reenabled too when you reenable the dialog! 
 485     wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
 488         wxWindow 
*child 
= node
->GetData(); 
 489         child
->Enable(enable
); 
 491         node 
= node
->GetNext(); 
 498 bool wxWindowMSW::Show(bool show
) 
 500     if ( !wxWindowBase::Show(show
) ) 
 503     HWND hWnd 
= GetHwnd(); 
 504     int cshow 
= show 
? SW_SHOW 
: SW_HIDE
; 
 505     ::ShowWindow(hWnd
, cshow
); 
 509         wxBringWindowToTop(hWnd
); 
 515 // Raise the window to the top of the Z order 
 516 void wxWindowMSW::Raise() 
 518     wxBringWindowToTop(GetHwnd()); 
 521 // Lower the window to the bottom of the Z order 
 522 void wxWindowMSW::Lower() 
 524     ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0, 
 525                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOACTIVATE
); 
 528 void wxWindowMSW::SetTitle( const wxString
& title
) 
 530     SetWindowText(GetHwnd(), title
.c_str()); 
 533 wxString 
wxWindowMSW::GetTitle() const 
 535     return wxGetWindowText(GetHWND()); 
 538 void wxWindowMSW::DoCaptureMouse() 
 540     HWND hWnd 
= GetHwnd(); 
 547 void wxWindowMSW::DoReleaseMouse() 
 549     if ( !::ReleaseCapture() ) 
 551         wxLogLastError(_T("ReleaseCapture")); 
 555 /* static */ wxWindow 
*wxWindowBase::GetCapture() 
 557     HWND hwnd 
= ::GetCapture(); 
 558     return hwnd 
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow 
*)NULL
; 
 561 bool wxWindowMSW::SetFont(const wxFont
& font
) 
 563     if ( !wxWindowBase::SetFont(font
) ) 
 569     HWND hWnd 
= GetHwnd(); 
 572         WXHANDLE hFont 
= m_font
.GetResourceHandle(); 
 574         wxASSERT_MSG( hFont
, wxT("should have valid font") ); 
 576         ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0)); 
 581 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
) 
 583     if ( !wxWindowBase::SetCursor(cursor
) ) 
 591         HWND hWnd 
= GetHwnd(); 
 593         // Change the cursor NOW if we're within the correct window 
 595         ::GetCursorPos(&point
); 
 597         RECT rect 
= wxGetWindowRect(hWnd
); 
 599         if ( ::PtInRect(&rect
, point
) && !wxIsBusy() ) 
 600             ::SetCursor(GetHcursorOf(m_cursor
)); 
 606 void wxWindowMSW::WarpPointer (int x
, int y
) 
 608     ClientToScreen(&x
, &y
); 
 610     if ( !::SetCursorPos(x
, y
) ) 
 612         wxLogLastError(_T("SetCursorPos")); 
 616 #if WXWIN_COMPATIBILITY 
 617 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const 
 620 #endif // WXWIN_COMPATIBILITY 
 622 // --------------------------------------------------------------------------- 
 624 // --------------------------------------------------------------------------- 
 626 #if WXWIN_COMPATIBILITY 
 627 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
) 
 629 #if defined(__WIN95__) 
 633     // Try to adjust the range to cope with page size > 1 
 634     // - a Windows API quirk 
 635     int pageSize 
= GetScrollPage(orient
); 
 636     if ( pageSize 
> 1 && range 
> 0) 
 638         range1 
+= (pageSize 
- 1); 
 644     if ( orient 
== wxHORIZONTAL 
) { 
 650     info
.cbSize 
= sizeof(SCROLLINFO
); 
 651     info
.nPage 
= pageSize
; // Have to set this, or scrollbar goes awry 
 655     info
.fMask 
= SIF_RANGE 
| SIF_PAGE
; 
 657     HWND hWnd 
= GetHwnd(); 
 659         ::SetScrollInfo(hWnd
, dir
, &info
, refresh
); 
 662     if ( orient 
== wxHORIZONTAL 
) 
 667     HWND hWnd 
= GetHwnd(); 
 669         ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
); 
 673 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
) 
 675 #if defined(__WIN95__) 
 679     if ( orient 
== wxHORIZONTAL 
) { 
 687     info
.cbSize 
= sizeof(SCROLLINFO
); 
 690     info
.fMask 
= SIF_PAGE
; 
 692     HWND hWnd 
= GetHwnd(); 
 694         ::SetScrollInfo(hWnd
, dir
, &info
, refresh
); 
 696     if ( orient 
== wxHORIZONTAL 
) 
 703 int wxWindowMSW::OldGetScrollRange(int orient
) const 
 706     if ( orient 
== wxHORIZONTAL 
) 
 711 #if __WATCOMC__ && defined(__WINDOWS_386__) 
 712     short minPos
, maxPos
; 
 716     HWND hWnd 
= GetHwnd(); 
 719         ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
); 
 720 #if defined(__WIN95__) 
 721         // Try to adjust the range to cope with page size > 1 
 722         // - a Windows API quirk 
 723         int pageSize 
= GetScrollPage(orient
); 
 726             maxPos 
-= (pageSize 
- 1); 
 735 int wxWindowMSW::GetScrollPage(int orient
) const 
 737     if ( orient 
== wxHORIZONTAL 
) 
 743 #endif // WXWIN_COMPATIBILITY 
 745 inline int GetScrollPosition(HWND hWnd
, int wOrient
) 
 747 #ifdef __WXMICROWIN__ 
 748     return ::GetScrollPosWX(hWnd
, wOrient
); 
 750     return ::GetScrollPos(hWnd
, wOrient
); 
 754 int wxWindowMSW::GetScrollPos(int orient
) const 
 757     if ( orient 
== wxHORIZONTAL 
) 
 762     HWND hWnd 
= GetHwnd(); 
 763     wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") ); 
 765     return GetScrollPosition(hWnd
, wOrient
); 
 768 // This now returns the whole range, not just the number 
 769 // of positions that we can scroll. 
 770 int wxWindowMSW::GetScrollRange(int orient
) const 
 773     if ( orient 
== wxHORIZONTAL 
) 
 778 #if __WATCOMC__ && defined(__WINDOWS_386__) 
 779     short minPos
, maxPos
; 
 783     HWND hWnd 
= GetHwnd(); 
 786         ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
); 
 787 #if defined(__WIN95__) 
 788         // Try to adjust the range to cope with page size > 1 
 789         // - a Windows API quirk 
 790         int pageSize 
= GetScrollThumb(orient
); 
 793             maxPos 
-= (pageSize 
- 1); 
 795         // October 10th: new range concept. 
 805 int wxWindowMSW::GetScrollThumb(int orient
) const 
 807     if ( orient 
== wxHORIZONTAL 
) 
 813 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
) 
 815     HWND hWnd 
= GetHwnd(); 
 816     wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") ); 
 818     int dir 
= orient 
== wxHORIZONTAL 
? SB_HORZ 
: SB_VERT
; 
 820 #if defined(__WIN95__) 
 822     info
.cbSize 
= sizeof(SCROLLINFO
); 
 826     info
.fMask 
= SIF_POS
; 
 828     ::SetScrollInfo(hWnd
, dir
, &info
, refresh
); 
 830     ::SetScrollPos(hWnd
, dir
, pos
, refresh
); 
 831 #endif // __WIN95__/!__WIN95__ 
 834 // New function that will replace some of the above. 
 835 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
, 
 836                             int range
, bool refresh
) 
 838 #if defined(__WIN95__) 
 839     int oldRange 
= range 
- thumbVisible
; 
 841     int range1 
= oldRange
; 
 843     // Try to adjust the range to cope with page size > 1 
 844     // - a Windows API quirk 
 845     int pageSize 
= thumbVisible
; 
 846     if ( pageSize 
> 1 && range 
> 0) 
 848         range1 
+= (pageSize 
- 1); 
 854     if ( orient 
== wxHORIZONTAL 
) { 
 860     info
.cbSize 
= sizeof(SCROLLINFO
); 
 861     info
.nPage 
= pageSize
; // Have to set this, or scrollbar goes awry 
 865     info
.fMask 
= SIF_RANGE 
| SIF_PAGE 
| SIF_POS
; 
 867     HWND hWnd 
= GetHwnd(); 
 869         ::SetScrollInfo(hWnd
, dir
, &info
, refresh
); 
 872     if ( orient 
== wxHORIZONTAL 
) 
 877     HWND hWnd 
= GetHwnd(); 
 880         ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
); 
 881         ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
); 
 884     if ( orient 
== wxHORIZONTAL 
) { 
 885         m_xThumbSize 
= thumbVisible
; 
 887         m_yThumbSize 
= thumbVisible
; 
 891 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect 
*prect
) 
 897         rect
.left 
= prect
->x
; 
 899         rect
.right 
= prect
->x 
+ prect
->width
; 
 900         rect
.bottom 
= prect
->y 
+ prect
->height
; 
 908     ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
); 
 911 static bool ScrollVertically(HWND hwnd
, int kind
, int count
) 
 913     int posStart 
= GetScrollPosition(hwnd
, SB_VERT
); 
 916     for ( int n 
= 0; n 
< count
; n
++ ) 
 918         ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0); 
 920         int posNew 
= GetScrollPosition(hwnd
, SB_VERT
); 
 923             // don't bother to continue, we're already at top/bottom 
 930     return pos 
!= posStart
; 
 933 bool wxWindowMSW::ScrollLines(int lines
) 
 935     bool down 
= lines 
> 0; 
 937     return ScrollVertically(GetHwnd(), 
 938                             down 
? SB_LINEDOWN 
: SB_LINEUP
, 
 939                             down 
? lines 
: -lines
); 
 942 bool wxWindowMSW::ScrollPages(int pages
) 
 944     bool down 
= pages 
> 0; 
 946     return ScrollVertically(GetHwnd(), 
 947                             down 
? SB_PAGEDOWN 
: SB_PAGEUP
, 
 948                             down 
? pages 
: -pages
); 
 951 // --------------------------------------------------------------------------- 
 953 // --------------------------------------------------------------------------- 
 955 void wxWindowMSW::SubclassWin(WXHWND hWnd
) 
 957     wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") ); 
 959     HWND hwnd 
= (HWND
)hWnd
; 
 960     wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") ); 
 962     wxAssociateWinWithHandle(hwnd
, this); 
 964     m_oldWndProc 
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
); 
 966     // we don't need to subclass the window of our own class (in the Windows 
 967     // sense of the word) 
 968     if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) ) 
 970         ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
); 
 974         // don't bother restoring it neither 
 979 void wxWindowMSW::UnsubclassWin() 
 981     wxRemoveHandleAssociation(this); 
 983     // Restore old Window proc 
 984     HWND hwnd 
= GetHwnd(); 
 989         wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") ); 
 993             if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) ) 
 995                 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
); 
1003 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
) 
1005 #if wxUSE_UNICODE_MSLU 
1006     // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll 
1007     //     because it doesn't return pointer to the real wnd proc but rather a handle 
1008     //     of a fake proc that does Unicode<->ANSI translation. 
1010     //     The hack bellow works, because WNDCLASS contains original window handler 
1011     //     rather that the unicows fake one. This may not be on purpose, though; if 
1012     //     it stops working with future versions of unicows.dll, we can override 
1013     //     unicows hooks by setting Unicows_{Set,Get}WindowLong and 
1014     //     Unicows_RegisterClass to our own versions that keep track of 
1015     //     fake<->real wnd proc mapping. 
1017     //     FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set 
1018     //            with RegisterClass!! 
1020     static wxChar buffer
[512]; 
1023     ::GetClassName((HWND
)hWnd
, buffer
, 512); 
1024     ::GetClassInfo(wxGetInstance(), buffer
, &cls
); 
1025     return wndProc 
== (WXFARPROC
)cls
.lpfnWndProc
; 
1027     return wndProc 
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
); 
1032 // Make a Windows extended style from the given wxWindows window style 
1033 WXDWORD 
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
) 
1035     WXDWORD exStyle 
= 0; 
1036     if ( style 
& wxTRANSPARENT_WINDOW 
) 
1037         exStyle 
|= WS_EX_TRANSPARENT
; 
1039     if ( !eliminateBorders 
) 
1041         if ( style 
& wxSUNKEN_BORDER 
) 
1042             exStyle 
|= WS_EX_CLIENTEDGE
; 
1043         if ( style 
& wxDOUBLE_BORDER 
) 
1044             exStyle 
|= WS_EX_DLGMODALFRAME
; 
1045 #if defined(__WIN95__) 
1046         if ( style 
& wxRAISED_BORDER 
) 
1047             // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does 
1048             exStyle 
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */; 
1049         if ( style 
& wxSTATIC_BORDER 
) 
1050             exStyle 
|= WS_EX_STATICEDGE
; 
1057 // Determines whether native 3D effects or CTL3D should be used, 
1058 // applying a default border style if required, and returning an extended 
1059 // style to pass to CreateWindowEx. 
1060 WXDWORD 
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
, 
1063     // If matches certain criteria, then assume no 3D effects 
1064     // unless specifically requested (dealt with in MakeExtendedStyle) 
1067             || !IsKindOf(CLASSINFO(wxControl
)) 
1068 #endif // wxUSE_CONTROLS 
1069             || (m_windowStyle 
& wxNO_BORDER
) ) 
1072         return MakeExtendedStyle(m_windowStyle
); 
1075     // Determine whether we should be using 3D effects or not. 
1076     bool nativeBorder 
= FALSE
; // by default, we don't want a Win95 effect 
1078     // 1) App can specify global 3D effects 
1079     *want3D 
= wxTheApp
->GetAuto3D(); 
1081     // 2) If the parent is being drawn with user colours, or simple border specified, 
1082     // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D 
1083     if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle 
& wxSIMPLE_BORDER
) ) 
1086     // 3) Control can override this global setting by defining 
1087     // a border style, e.g. wxSUNKEN_BORDER 
1088     if ( m_windowStyle 
& wxSUNKEN_BORDER  
) 
1091     // 4) If it's a special border, CTL3D can't cope so we want a native border 
1092     if ( (m_windowStyle 
& wxDOUBLE_BORDER
) || (m_windowStyle 
& wxRAISED_BORDER
) || 
1093         (m_windowStyle 
& wxSTATIC_BORDER
) ) 
1096         nativeBorder 
= TRUE
; 
1099     // 5) If this isn't a Win95 app, and we are using CTL3D, remove border 
1100     // effects from extended style 
1103         nativeBorder 
= FALSE
; 
1106     DWORD exStyle 
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
); 
1108     // If we want 3D, but haven't specified a border here, 
1109     // apply the default border style specified. 
1110     // TODO what about non-Win95 WIN32? Does it have borders? 
1111 #if defined(__WIN95__) && !wxUSE_CTL3D 
1112     if ( defaultBorderStyle 
&& (*want3D
) && ! ((m_windowStyle 
& wxDOUBLE_BORDER
) || (m_windowStyle 
& wxRAISED_BORDER 
) || 
1113         (m_windowStyle 
& wxSTATIC_BORDER
) || (m_windowStyle 
& wxSIMPLE_BORDER
) )) 
1114         exStyle 
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE; 
1120 #if WXWIN_COMPATIBILITY 
1121 // If nothing defined for this, try the parent. 
1122 // E.g. we may be a button loaded from a resource, with no callback function 
1124 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
) 
1126     if ( GetEventHandler()->ProcessEvent(event
)  ) 
1129         m_parent
->GetEventHandler()->OnCommand(win
, event
); 
1131 #endif // WXWIN_COMPATIBILITY_2 
1133 #if WXWIN_COMPATIBILITY 
1134 wxObject
* wxWindowMSW::GetChild(int number
) const 
1136     // Return a pointer to the Nth object in the Panel 
1137     wxNode 
*node 
= GetChildren().First(); 
1140         node 
= node
->Next(); 
1143         wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
1149 #endif // WXWIN_COMPATIBILITY 
1151 // Setup background and foreground colours correctly 
1152 void wxWindowMSW::SetupColours() 
1155         SetBackgroundColour(GetParent()->GetBackgroundColour()); 
1158 bool wxWindowMSW::IsMouseInWindow() const 
1160     // get the mouse position 
1162     ::GetCursorPos(&pt
); 
1164     // find the window which currently has the cursor and go up the window 
1165     // chain until we find this window - or exhaust it 
1166     HWND hwnd 
= ::WindowFromPoint(pt
); 
1167     while ( hwnd 
&& (hwnd 
!= GetHwnd()) ) 
1168         hwnd 
= ::GetParent(hwnd
); 
1170     return hwnd 
!= NULL
; 
1173 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
)) 
1175     // Check if we need to send a LEAVE event 
1176     if ( m_mouseInWindow 
) 
1178         if ( !IsMouseInWindow() && !HasCapture()) 
1180             // Generate a LEAVE event 
1181             m_mouseInWindow 
= FALSE
; 
1183             // Unfortunately the mouse button and keyboard state may have 
1184             // changed by the time the OnIdle function is called, so 'state' 
1185             // may be meaningless. 
1187             if ( wxIsShiftDown() ) 
1189             if ( wxIsCtrlDown() ) 
1190                 state 
|= MK_CONTROL
; 
1191             if ( GetKeyState( VK_LBUTTON 
) ) 
1192                 state 
|= MK_LBUTTON
; 
1193             if ( GetKeyState( VK_MBUTTON 
) ) 
1194                 state 
|= MK_MBUTTON
; 
1195             if ( GetKeyState( VK_RBUTTON 
) ) 
1196                 state 
|= MK_RBUTTON
; 
1199             if ( !::GetCursorPos(&pt
) ) 
1201                 wxLogLastError(_T("GetCursorPos")); 
1204             // we need to have client coordinates here for symmetry with 
1205             // wxEVT_ENTER_WINDOW 
1206             RECT rect 
= wxGetWindowRect(GetHwnd()); 
1210             wxMouseEvent 
event2(wxEVT_LEAVE_WINDOW
); 
1211             InitMouseEvent(event2
, pt
.x
, pt
.y
, state
); 
1213             (void)GetEventHandler()->ProcessEvent(event2
); 
1220 // Set this window to be the child of 'parent'. 
1221 bool wxWindowMSW::Reparent(wxWindowBase 
*parent
) 
1223     if ( !wxWindowBase::Reparent(parent
) ) 
1226     HWND hWndChild 
= GetHwnd(); 
1227     HWND hWndParent 
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0; 
1229     ::SetParent(hWndChild
, hWndParent
); 
1234 void wxWindowMSW::Clear() 
1236     wxClientDC 
dc((wxWindow 
*)this); 
1237     wxBrush 
brush(GetBackgroundColour(), wxSOLID
); 
1238     dc
.SetBackground(brush
); 
1242 static inline void SendSetRedraw(HWND hwnd
, bool on
) 
1244 #ifndef __WXMICROWIN__ 
1245     ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0); 
1249 void wxWindowMSW::Freeze() 
1251     SendSetRedraw(GetHwnd(), FALSE
); 
1254 void wxWindowMSW::Thaw() 
1256     SendSetRedraw(GetHwnd(), TRUE
); 
1258     // we need to refresh everything or otherwise he invalidated area is not 
1263 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect 
*rect
) 
1265     HWND hWnd 
= GetHwnd(); 
1271             mswRect
.left 
= rect
->x
; 
1272             mswRect
.top 
= rect
->y
; 
1273             mswRect
.right 
= rect
->x 
+ rect
->width
; 
1274             mswRect
.bottom 
= rect
->y 
+ rect
->height
; 
1276             ::InvalidateRect(hWnd
, &mswRect
, eraseBack
); 
1279             ::InvalidateRect(hWnd
, NULL
, eraseBack
); 
1283 void wxWindowMSW::Update() 
1285     if ( !::UpdateWindow(GetHwnd()) ) 
1287         wxLogLastError(_T("UpdateWindow")); 
1290 #if defined(__WIN32__) && !defined(__WXMICROWIN__) 
1291     // just calling UpdateWindow() is not enough, what we did in our WM_PAINT 
1292     // handler needs to be really drawn right now 
1297 // --------------------------------------------------------------------------- 
1299 // --------------------------------------------------------------------------- 
1301 #if wxUSE_DRAG_AND_DROP 
1303 void wxWindowMSW::SetDropTarget(wxDropTarget 
*pDropTarget
) 
1305     if ( m_dropTarget 
!= 0 ) { 
1306         m_dropTarget
->Revoke(m_hWnd
); 
1307         delete m_dropTarget
; 
1310     m_dropTarget 
= pDropTarget
; 
1311     if ( m_dropTarget 
!= 0 ) 
1312         m_dropTarget
->Register(m_hWnd
); 
1315 #endif // wxUSE_DRAG_AND_DROP 
1317 // old style file-manager drag&drop support: we retain the old-style 
1318 // DragAcceptFiles in parallel with SetDropTarget. 
1319 void wxWindowMSW::DragAcceptFiles(bool accept
) 
1321     HWND hWnd 
= GetHwnd(); 
1323         ::DragAcceptFiles(hWnd
, (BOOL
)accept
); 
1326 // ---------------------------------------------------------------------------- 
1328 // ---------------------------------------------------------------------------- 
1332 void wxWindowMSW::DoSetToolTip(wxToolTip 
*tooltip
) 
1334     wxWindowBase::DoSetToolTip(tooltip
); 
1337         m_tooltip
->SetWindow(this); 
1340 #endif // wxUSE_TOOLTIPS 
1342 // --------------------------------------------------------------------------- 
1343 // moving and resizing 
1344 // --------------------------------------------------------------------------- 
1347 void wxWindowMSW::DoGetSize(int *x
, int *y
) const 
1349     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1352         *x 
= rect
.right 
- rect
.left
; 
1354         *y 
= rect
.bottom 
- rect
.top
; 
1357 // Get size *available for subwindows* i.e. excluding menu bar etc. 
1358 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const 
1360     RECT rect 
= wxGetClientRect(GetHwnd()); 
1368 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const 
1370     RECT rect 
= wxGetWindowRect(GetHwnd()); 
1373     point
.x 
= rect
.left
; 
1376     // we do the adjustments with respect to the parent only for the "real" 
1377     // children, not for the dialogs/frames 
1378     if ( !IsTopLevel() ) 
1380         HWND hParentWnd 
= 0; 
1381         wxWindow 
*parent 
= GetParent(); 
1383             hParentWnd 
= GetWinHwnd(parent
); 
1385         // Since we now have the absolute screen coords, if there's a parent we 
1386         // must subtract its top left corner 
1389             ::ScreenToClient(hParentWnd
, &point
); 
1394             // We may be faking the client origin. So a window that's really at (0, 
1395             // 30) may appear (to wxWin apps) to be at (0, 0). 
1396             wxPoint 
pt(parent
->GetClientAreaOrigin()); 
1408 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const 
1416     ::ScreenToClient(GetHwnd(), &pt
); 
1424 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const 
1432     ::ClientToScreen(GetHwnd(), &pt
); 
1440 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
) 
1442     // TODO: is this consistent with other platforms? 
1443     // Still, negative width or height shouldn't be allowed 
1448     if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) ) 
1450         wxLogLastError(wxT("MoveWindow")); 
1454 // set the size of the window: if the dimensions are positive, just use them, 
1455 // but if any of them is equal to -1, it means that we must find the value for 
1456 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 
1457 // which case -1 is a valid value for x and y) 
1459 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 
1460 // the width/height to best suit our contents, otherwise we reuse the current 
1462 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
1464     // get the current size and position... 
1465     int currentX
, currentY
; 
1466     GetPosition(¤tX
, ¤tY
); 
1467     int currentW
,currentH
; 
1468     GetSize(¤tW
, ¤tH
); 
1470     // ... and don't do anything (avoiding flicker) if it's already ok 
1471     if ( x 
== currentX 
&& y 
== currentY 
&& 
1472          width 
== currentW 
&& height 
== currentH 
) 
1477     if ( x 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1479     if ( y 
== -1 && !(sizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
) ) 
1482     AdjustForParentClientOrigin(x
, y
, sizeFlags
); 
1484     wxSize 
size(-1, -1); 
1487         if ( sizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
1489             size 
= DoGetBestSize(); 
1494             // just take the current one 
1501         if ( sizeFlags 
& wxSIZE_AUTO_HEIGHT 
) 
1505                 size 
= DoGetBestSize(); 
1507             //else: already called DoGetBestSize() above 
1513             // just take the current one 
1518     DoMoveWindow(x
, y
, width
, height
); 
1521 void wxWindowMSW::DoSetClientSize(int width
, int height
) 
1523     // setting the client size is less obvious than it it could have been 
1524     // because in the result of changing the total size the window scrollbar 
1525     // may [dis]appear and/or its menubar may [un]wrap and so the client size 
1526     // will not be correct as the difference between the total and client size 
1527     // changes - so we keep changing it until we get it right 
1529     // normally this loop shouldn't take more than 3 iterations (usually 1 but 
1530     // if scrollbars [dis]appear as the result of the first call, then 2 and it 
1531     // may become 3 if the window had 0 size originally and so we didn't 
1532     // calculate the scrollbar correction correctly during the first iteration) 
1533     // but just to be on the safe side we check for it instead of making it an 
1534     // "infinite" loop (i.e. leaving break inside as the only way to get out) 
1535     for ( int i 
= 0; i 
< 4; i
++ ) 
1538         ::GetClientRect(GetHwnd(), &rectClient
); 
1540         // if the size is already ok, stop here (rectClient.left = top = 0) 
1541         if ( (rectClient
.right 
== width 
|| width 
== -1) && 
1542              (rectClient
.bottom 
== height 
|| height 
== -1) ) 
1549             // how did it happen? maybe OnSize() handler does something really 
1550             // strange in this class? 
1551             wxFAIL_MSG( _T("logic error in DoSetClientSize") ); 
1556         int widthClient 
= width
, 
1557             heightClient 
= height
; 
1559         // Find the difference between the entire window (title bar and all) 
1560         // and the client area; add this to the new client size to move the 
1563         ::GetWindowRect(GetHwnd(), &rectWin
); 
1565         widthClient 
+= rectWin
.right 
- rectWin
.left 
- rectClient
.right
; 
1566         heightClient 
+= rectWin
.bottom 
- rectWin
.top 
- rectClient
.bottom
; 
1569         point
.x 
= rectWin
.left
; 
1570         point
.y 
= rectWin
.top
; 
1572         // MoveWindow positions the child windows relative to the parent, so 
1573         // adjust if necessary 
1574         if ( !IsTopLevel() ) 
1576             wxWindow 
*parent 
= GetParent(); 
1579                 ::ScreenToClient(GetHwndOf(parent
), &point
); 
1583         DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
); 
1587 // For implementation purposes - sometimes decorations make the client area 
1589 wxPoint 
wxWindowMSW::GetClientAreaOrigin() const 
1591     return wxPoint(0, 0); 
1594 // --------------------------------------------------------------------------- 
1596 // --------------------------------------------------------------------------- 
1598 int wxWindowMSW::GetCharHeight() const 
1600     return wxGetTextMetrics(this).tmHeight
; 
1603 int wxWindowMSW::GetCharWidth() const 
1605     // +1 is needed because Windows apparently adds it when calculating the 
1606     // dialog units size in pixels 
1607 #if wxDIALOG_UNIT_COMPATIBILITY 
1608     return wxGetTextMetrics(this).tmAveCharWidth
; 
1610     return wxGetTextMetrics(this).tmAveCharWidth 
+ 1; 
1614 void wxWindowMSW::GetTextExtent(const wxString
& string
, 
1616                              int *descent
, int *externalLeading
, 
1617                              const wxFont 
*theFont
) const 
1619     const wxFont 
*fontToUse 
= theFont
; 
1621         fontToUse 
= &m_font
; 
1623     HWND hWnd 
= GetHwnd(); 
1624     HDC dc 
= ::GetDC(hWnd
); 
1628     if ( fontToUse 
&& fontToUse
->Ok() ) 
1630         fnt 
= (HFONT
)((wxFont 
*)fontToUse
)->GetResourceHandle(); // const_cast 
1632             hfontOld 
= (HFONT
)SelectObject(dc
,fnt
); 
1637     GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
); 
1638     GetTextMetrics(dc
, &tm
); 
1640     if ( fontToUse 
&& fnt 
&& hfontOld 
) 
1641         SelectObject(dc
, hfontOld
); 
1643     ReleaseDC(hWnd
, dc
); 
1650         *descent 
= tm
.tmDescent
; 
1651     if ( externalLeading 
) 
1652         *externalLeading 
= tm
.tmExternalLeading
; 
1655 #if wxUSE_CARET && WXWIN_COMPATIBILITY 
1656 // --------------------------------------------------------------------------- 
1657 // Caret manipulation 
1658 // --------------------------------------------------------------------------- 
1660 void wxWindowMSW::CreateCaret(int w
, int h
) 
1662     SetCaret(new wxCaret(this, w
, h
)); 
1665 void wxWindowMSW::CreateCaret(const wxBitmap 
*WXUNUSED(bitmap
)) 
1667     wxFAIL_MSG("not implemented"); 
1670 void wxWindowMSW::ShowCaret(bool show
) 
1672     wxCHECK_RET( m_caret
, "no caret to show" ); 
1674     m_caret
->Show(show
); 
1677 void wxWindowMSW::DestroyCaret() 
1682 void wxWindowMSW::SetCaretPos(int x
, int y
) 
1684     wxCHECK_RET( m_caret
, "no caret to move" ); 
1686     m_caret
->Move(x
, y
); 
1689 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const 
1691     wxCHECK_RET( m_caret
, "no caret to get position of" ); 
1693     m_caret
->GetPosition(x
, y
); 
1695 #endif // wxUSE_CARET 
1697 // --------------------------------------------------------------------------- 
1699 // --------------------------------------------------------------------------- 
1701 #if wxUSE_MENUS_NATIVE 
1703 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue 
1704 // immediately, without waiting for the next event loop iteration 
1706 // NB: this function should probably be made public later as it can almost 
1707 //     surely replace wxYield() elsewhere as well 
1708 static void wxYieldForCommandsOnly() 
1710     // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't 
1711     // want to process it here) 
1713     while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) 
1714                 && msg
.message 
!= WM_QUIT 
) 
1716         wxTheApp
->DoMessage((WXMSG 
*)&msg
); 
1720 bool wxWindowMSW::DoPopupMenu(wxMenu 
*menu
, int x
, int y
) 
1722     menu
->SetInvokingWindow(this); 
1725     HWND hWnd 
= GetHwnd(); 
1726     HMENU hMenu 
= GetHmenuOf(menu
); 
1730     ::ClientToScreen(hWnd
, &point
); 
1731     wxCurrentPopupMenu 
= menu
; 
1732     ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
); 
1734     // we need to do it righ now as otherwise the events are never going to be 
1735     // sent to wxCurrentPopupMenu from HandleCommand() 
1737     // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't 
1738     // help and we'd still need wxYieldForCommandsOnly() as the menu may be 
1739     // destroyed as soon as we return (it can be a local variable in the caller 
1740     // for example) and so we do need to process the event immediately 
1741     wxYieldForCommandsOnly(); 
1743     wxCurrentPopupMenu 
= NULL
; 
1745     menu
->SetInvokingWindow(NULL
); 
1750 #endif // wxUSE_MENUS_NATIVE 
1752 // =========================================================================== 
1753 // pre/post message processing 
1754 // =========================================================================== 
1756 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
1759         return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
); 
1761         return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
); 
1764 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
) 
1766     // wxUniversal implements tab traversal itself 
1767 #ifndef __WXUNIVERSAL__ 
1768     if ( m_hWnd 
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) ) 
1770         // intercept dialog navigation keys 
1771         MSG 
*msg 
= (MSG 
*)pMsg
; 
1773         // here we try to do all the job which ::IsDialogMessage() usually does 
1776         bool bProcess 
= TRUE
; 
1777         if ( msg
->message 
!= WM_KEYDOWN 
) 
1780         if ( bProcess 
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
1785             bool bCtrlDown 
= wxIsCtrlDown(); 
1786             bool bShiftDown 
= wxIsShiftDown(); 
1788             // WM_GETDLGCODE: ask the control if it wants the key for itself, 
1789             // don't process it if it's the case (except for Ctrl-Tab/Enter 
1790             // combinations which are always processed) 
1794                 lDlgCode 
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0); 
1797             bool bForward 
= TRUE
, 
1798                  bWindowChange 
= FALSE
; 
1800             switch ( msg
->wParam 
) 
1803                     // assume that nobody wants Shift-TAB for himself - if we 
1804                     // don't do it there is no easy way for a control to grab 
1805                     // TABs but still let Shift-TAB work as navugation key 
1806                     if ( (lDlgCode 
& DLGC_WANTTAB
) && !bShiftDown 
) { 
1810                         // Ctrl-Tab cycles thru notebook pages 
1811                         bWindowChange 
= bCtrlDown
; 
1812                         bForward 
= !bShiftDown
; 
1818                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1826                     if ( (lDlgCode 
& DLGC_WANTARROWS
) || bCtrlDown 
) 
1832                         if ( (lDlgCode 
& DLGC_WANTMESSAGE
) && !bCtrlDown 
) 
1834                             // control wants to process Enter itself, don't 
1835                             // call IsDialogMessage() which would interpret 
1839                         else if ( lDlgCode 
& DLGC_BUTTON 
) 
1841                             // let IsDialogMessage() handle this for all 
1842                             // buttons except the owner-drawn ones which it 
1843                             // just seems to ignore 
1844                             long style 
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
); 
1845                             if ( (style 
& BS_OWNERDRAW
) == BS_OWNERDRAW 
) 
1847                                 // emulate the button click 
1848                                 wxWindow 
*btn 
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
); 
1850                                     btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1855                         // FIXME: this should be handled by 
1856                         //        wxNavigationKeyEvent handler and not here!! 
1860                             wxButton 
*btn 
= wxDynamicCast(GetDefaultItem(), 
1862                             if ( btn 
&& btn
->IsEnabled() ) 
1864                                 // if we do have a default button, do press it 
1865                                 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */); 
1869                             else // no default button 
1870 #endif // wxUSE_BUTTON 
1872                                 // no special function for enter and don't even 
1873                                 // let IsDialogMessage() have it: it seems to 
1874                                 // do something really strange with it 
1887                 wxNavigationKeyEvent event
; 
1888                 event
.SetDirection(bForward
); 
1889                 event
.SetWindowChange(bWindowChange
); 
1890                 event
.SetEventObject(this); 
1892                 if ( GetEventHandler()->ProcessEvent(event
) ) 
1899         // let ::IsDialogMessage() do almost everything and handle just the 
1900         // things it doesn't here: Ctrl-TAB for switching notebook pages 
1901         if ( msg
->message 
== WM_KEYDOWN 
) 
1903             // don't process system keys here 
1904             if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) ) 
1906                 if ( (msg
->wParam 
== VK_TAB
) && wxIsCtrlDown() ) 
1908                     // find the first notebook parent and change its page 
1909                     wxWindow 
*win 
= this; 
1910                     wxNotebook 
*nbook 
= NULL
; 
1911                     while ( win 
&& !nbook 
) 
1913                         nbook 
= wxDynamicCast(win
, wxNotebook
); 
1914                         win 
= win
->GetParent(); 
1919                         bool forward 
= !wxIsShiftDown(); 
1921                         nbook
->AdvanceSelection(forward
); 
1928         if ( ::IsDialogMessage(GetHwnd(), msg
) ) 
1930             // IsDialogMessage() did something... 
1934 #endif // __WXUNIVERSAL__ 
1939         // relay mouse move events to the tooltip control 
1940         MSG 
*msg 
= (MSG 
*)pMsg
; 
1941         if ( msg
->message 
== WM_MOUSEMOVE 
) 
1942             m_tooltip
->RelayEvent(pMsg
); 
1944 #endif // wxUSE_TOOLTIPS 
1949 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
) 
1951 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__) 
1952     return m_acceleratorTable
.Translate(this, pMsg
); 
1956 #endif // wxUSE_ACCEL 
1959 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
)) 
1961     // preprocess all messages by default 
1965 // --------------------------------------------------------------------------- 
1966 // message params unpackers (different for Win16 and Win32) 
1967 // --------------------------------------------------------------------------- 
1971 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
1972                              WORD 
*id
, WXHWND 
*hwnd
, WORD 
*cmd
) 
1974     *id 
= LOWORD(wParam
); 
1975     *hwnd 
= (WXHWND
)lParam
; 
1976     *cmd 
= HIWORD(wParam
); 
1979 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
1980                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
1982     *state 
= LOWORD(wParam
); 
1983     *minimized 
= HIWORD(wParam
); 
1984     *hwnd 
= (WXHWND
)lParam
; 
1987 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
1988                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
1990     *code 
= LOWORD(wParam
); 
1991     *pos 
= HIWORD(wParam
); 
1992     *hwnd 
= (WXHWND
)lParam
; 
1995 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
1996                               WXWORD 
*nCtlColor
, WXHDC 
*hdc
, WXHWND 
*hwnd
) 
1998 #ifndef __WXMICROWIN__ 
1999     *nCtlColor 
= CTLCOLOR_BTN
; 
2000     *hwnd 
= (WXHWND
)lParam
; 
2001     *hdc 
= (WXHDC
)wParam
; 
2005 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2006                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2008     *item 
= (WXWORD
)wParam
; 
2009     *flags 
= HIWORD(wParam
); 
2010     *hmenu 
= (WXHMENU
)lParam
; 
2015 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
, 
2016                              WXWORD 
*id
, WXHWND 
*hwnd
, WXWORD 
*cmd
) 
2018     *id 
= (WXWORD
)wParam
; 
2019     *hwnd 
= (WXHWND
)LOWORD(lParam
); 
2020     *cmd 
= HIWORD(lParam
); 
2023 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
, 
2024                               WXWORD 
*state
, WXWORD 
*minimized
, WXHWND 
*hwnd
) 
2026     *state 
= (WXWORD
)wParam
; 
2027     *minimized 
= LOWORD(lParam
); 
2028     *hwnd 
= (WXHWND
)HIWORD(lParam
); 
2031 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
, 
2032                             WXWORD 
*code
, WXWORD 
*pos
, WXHWND 
*hwnd
) 
2034     *code 
= (WXWORD
)wParam
; 
2035     *pos 
= LOWORD(lParam
); 
2036     *hwnd 
= (WXHWND
)HIWORD(lParam
); 
2039 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
, 
2040                               WXWORD 
*nCtlColor
, WXHDC 
*hdc
, WXHWND 
*hwnd
) 
2042     *hwnd 
= (WXHWND
)LOWORD(lParam
); 
2043     *nCtlColor 
= (int)HIWORD(lParam
); 
2044     *hdc 
= (WXHDC
)wParam
; 
2047 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
, 
2048                                 WXWORD 
*item
, WXWORD 
*flags
, WXHMENU 
*hmenu
) 
2050     *item 
= (WXWORD
)wParam
; 
2051     *flags 
= LOWORD(lParam
); 
2052     *hmenu 
= (WXHMENU
)HIWORD(lParam
); 
2057 // --------------------------------------------------------------------------- 
2058 // Main wxWindows window proc and the window proc for wxWindow 
2059 // --------------------------------------------------------------------------- 
2061 // Hook for new window just as it's being created, when the window isn't yet 
2062 // associated with the handle 
2063 static wxWindowMSW 
*gs_winBeingCreated 
= NULL
; 
2065 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the 
2066 // window being created and insures that it's always unset back later 
2067 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW 
*winBeingCreated
) 
2069     gs_winBeingCreated 
= winBeingCreated
; 
2072 wxWindowCreationHook::~wxWindowCreationHook() 
2074     gs_winBeingCreated 
= NULL
; 
2078 LRESULT WXDLLEXPORT APIENTRY _EXPORT 
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) 
2080     // trace all messages - useful for the debugging 
2082     wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"), 
2083                wxGetMessageName(message
), wParam
, lParam
); 
2084 #endif // __WXDEBUG__ 
2086     wxWindowMSW 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2088     // when we get the first message for the HWND we just created, we associate 
2089     // it with wxWindow stored in gs_winBeingCreated 
2090     if ( !wnd 
&& gs_winBeingCreated 
) 
2092         wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
); 
2093         wnd 
= gs_winBeingCreated
; 
2094         gs_winBeingCreated 
= NULL
; 
2095         wnd
->SetHWND((WXHWND
)hWnd
); 
2101         rc 
= wnd
->MSWWindowProc(message
, wParam
, lParam
); 
2103         rc 
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
); 
2108 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
2110     // did we process the message? 
2111     bool processed 
= FALSE
; 
2122     // for most messages we should return 0 when we do process the message 
2130                 processed 
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
); 
2133                     // return 0 to allow window creation 
2134                     rc
.result 
= mayCreate 
? 0 : -1; 
2140             // never set processed to TRUE and *always* pass WM_DESTROY to 
2141             // DefWindowProc() as Windows may do some internal cleanup when 
2142             // processing it and failing to pass the message along may cause 
2143             // memory and resource leaks! 
2144             (void)HandleDestroy(); 
2148             processed 
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2156                     // we're not interested in these messages at all 
2159                 case SIZE_MINIMIZED
: 
2160                     // we shouldn't send sizev events for these messages as the 
2161                     // client size may be negative which breaks existing code 
2163                     // OTOH we might send another (wxMinimizedEvent?) one or 
2164                     // add an additional parameter to wxSizeEvent if this is 
2165                     // useful to anybody 
2169                     wxFAIL_MSG( _T("unexpected WM_SIZE parameter") ); 
2170                     // fall through nevertheless 
2172                 case SIZE_MAXIMIZED
: 
2174                     processed 
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), 
2179 #ifndef __WXMICROWIN__ 
2180         case WM_ACTIVATEAPP
: 
2181             wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
2187                 WXWORD state
, minimized
; 
2189                 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
); 
2191                 processed 
= HandleActivate(state
, minimized 
!= 0, (WXHWND
)hwnd
); 
2196             processed 
= HandleSetFocus((WXHWND
)(HWND
)wParam
); 
2200             processed 
= HandleKillFocus((WXHWND
)(HWND
)wParam
); 
2204             processed 
= HandlePaint(); 
2208             // don't let the DefWindowProc() destroy our window - we'll do it 
2209             // ourselves in ~wxWindow 
2215             processed 
= HandleShow(wParam 
!= 0, (int)lParam
); 
2219             processed 
= HandleMouseMove(GET_X_LPARAM(lParam
), 
2220                                         GET_Y_LPARAM(lParam
), 
2224 #if wxUSE_MOUSEWHEEL 
2226             processed 
= HandleMouseWheel(wParam
, lParam
); 
2230         case WM_LBUTTONDOWN
: 
2232         case WM_LBUTTONDBLCLK
: 
2233         case WM_RBUTTONDOWN
: 
2235         case WM_RBUTTONDBLCLK
: 
2236         case WM_MBUTTONDOWN
: 
2238         case WM_MBUTTONDBLCLK
: 
2241 #ifdef __WXMICROWIN__ 
2242                 // MicroWindows seems to ignore the fact that a window is 
2243                 // disabled. So catch mouse events and throw them away if 
2245                 wxWindowMSW
* win 
= this; 
2248                     if (!win
->IsEnabled()) 
2253                     win 
= win
->GetParent(); 
2254                     if (win 
&& win
->IsTopLevel()) 
2257 #endif // __WXMICROWIN__ 
2260                     if (message 
== WM_LBUTTONDOWN 
&& AcceptsFocus()) 
2262                      processed 
= HandleMouseEvent(message
, 
2263                                          GET_X_LPARAM(lParam
), 
2264                                          GET_Y_LPARAM(lParam
), 
2270 #ifdef __WXMICROWIN__ 
2271         case WM_NCLBUTTONDOWN
: 
2272         case WM_NCLBUTTONUP
: 
2273         case WM_NCLBUTTONDBLCLK
: 
2274         case WM_NCRBUTTONDOWN
: 
2275         case WM_NCRBUTTONUP
: 
2276         case WM_NCRBUTTONDBLCLK
: 
2278         case WM_NCMBUTTONDOWN
: 
2279         case WM_NCMBUTTONUP
: 
2280         case WM_NCMBUTTONDBLCLK
: 
2283                 // MicroWindows seems to ignore the fact that a window 
2284                 // is disabled. So catch mouse events and throw them away if necessary. 
2286                 wxWindowMSW
* win 
= this; 
2289                     if (!win
->IsEnabled()) 
2294                     win 
= win
->GetParent(); 
2295                     if (win 
&& win
->IsTopLevel()) 
2300 #endif // __WXMICROWIN__ 
2307         case MM_JOY1BUTTONDOWN
: 
2308         case MM_JOY2BUTTONDOWN
: 
2309         case MM_JOY1BUTTONUP
: 
2310         case MM_JOY2BUTTONUP
: 
2311             processed 
= HandleJoystickEvent(message
, 
2312                                             GET_X_LPARAM(lParam
), 
2313                                             GET_Y_LPARAM(lParam
), 
2316 #endif // __WXMICROWIN__ 
2319             processed 
= HandleSysCommand(wParam
, lParam
); 
2326                 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
); 
2328                 processed 
= HandleCommand(id
, cmd
, hwnd
); 
2334             processed 
= HandleNotify((int)wParam
, lParam
, &rc
.result
); 
2338             // for these messages we must return TRUE if process the message 
2341         case WM_MEASUREITEM
: 
2343                 int idCtrl 
= (UINT
)wParam
; 
2344                 if ( message 
== WM_DRAWITEM 
) 
2346                     processed 
= MSWOnDrawItem(idCtrl
, 
2347                                               (WXDRAWITEMSTRUCT 
*)lParam
); 
2351                     processed 
= MSWOnMeasureItem(idCtrl
, 
2352                                                  (WXMEASUREITEMSTRUCT 
*)lParam
); 
2359 #endif // defined(WM_DRAWITEM) 
2362             if ( GetWindowStyleFlag() & wxWANTS_CHARS 
) 
2364                 // want everything: i.e. all keys and WM_CHAR message 
2365                 rc
.result 
= DLGC_WANTARROWS 
| DLGC_WANTCHARS 
| 
2366                             DLGC_WANTTAB 
| DLGC_WANTMESSAGE
; 
2369             //else: get the dlg code from the DefWindowProc() 
2374             // If this has been processed by an event handler, 
2375             // return 0 now (we've handled it). 
2376             if ( HandleKeyDown((WORD
) wParam
, lParam
) ) 
2383             // we consider these message "not interesting" to OnChar 
2384             if ( wParam 
== VK_SHIFT 
|| wParam 
== VK_CONTROL 
) 
2393                 // avoid duplicate messages to OnChar for these ASCII keys: they 
2394                 // will be translated by TranslateMessage() and received in WM_CHAR 
2402                     // but set processed to FALSE, not TRUE to still pass them to 
2403                     // the control's default window proc - otherwise built-in 
2404                     // keyboard handling won't work 
2410                 // special case of VK_APPS: treat it the same as right mouse 
2411                 // click because both usually pop up a context menu 
2417                         TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2418                         processed 
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
); 
2428                     processed 
= HandleChar((WORD
)wParam
, lParam
); 
2435             // special case of VK_APPS: treat it the same as right mouse button 
2436             if ( wParam 
== VK_APPS 
) 
2441                 TranslateKbdEventToMouse(this, &x
, &y
, &flags
); 
2442                 processed 
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
); 
2447                 processed 
= HandleKeyUp((WORD
) wParam
, lParam
); 
2452         case WM_CHAR
: // Always an ASCII character 
2453             processed 
= HandleChar((WORD
)wParam
, lParam
, TRUE
); 
2461                 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
); 
2463                 processed 
= MSWOnScroll(message 
== WM_HSCROLL 
? wxHORIZONTAL
 
2469         // CTLCOLOR messages are sent by children to query the parent for their 
2470         // colors#ifndef __WXMICROWIN__ 
2471 #ifndef __WXMICROWIN__ 
2473         case WM_CTLCOLORMSGBOX
: 
2474         case WM_CTLCOLOREDIT
: 
2475         case WM_CTLCOLORLISTBOX
: 
2476         case WM_CTLCOLORBTN
: 
2477         case WM_CTLCOLORDLG
: 
2478         case WM_CTLCOLORSCROLLBAR
: 
2479         case WM_CTLCOLORSTATIC
: 
2487                 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
); 
2489                 processed 
= HandleCtlColor(&rc
.hBrush
, 
2498 #endif // !__WXMICROWIN__ 
2500         case WM_SYSCOLORCHANGE
: 
2501             // the return value for this message is ignored 
2502             processed 
= HandleSysColorChange(); 
2505         case WM_DISPLAYCHANGE
: 
2506             processed 
= HandleDisplayChange(); 
2509         case WM_PALETTECHANGED
: 
2510             processed 
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
); 
2513         case WM_QUERYNEWPALETTE
: 
2514             processed 
= HandleQueryNewPalette(); 
2518             processed 
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
); 
2521                 // we processed the message, i.e. erased the background 
2527             processed 
= HandleDropFiles(wParam
); 
2531             processed 
= HandleInitDialog((WXHWND
)(HWND
)wParam
); 
2535                 // we never set focus from here 
2540         case WM_QUERYENDSESSION
: 
2541             processed 
= HandleQueryEndSession(lParam
, &rc
.allow
); 
2545             processed 
= HandleEndSession(wParam 
!= 0, lParam
); 
2548         case WM_GETMINMAXINFO
: 
2549             processed 
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
); 
2553             processed 
= HandleSetCursor((WXHWND
)(HWND
)wParam
, 
2554                                         LOWORD(lParam
),     // hit test 
2555                                         HIWORD(lParam
));    // mouse msg 
2559                 // returning TRUE stops the DefWindowProc() from further 
2560                 // processing this message - exactly what we need because we've 
2561                 // just set the cursor. 
2566 #if defined(__WIN32__) && defined(WM_HELP) 
2569                 HELPINFO
* info 
= (HELPINFO
*) lParam
; 
2570                 // Don't yet process menu help events, just windows 
2571                 if (info
->iContextType 
== HELPINFO_WINDOW
) 
2573                     wxWindowMSW
* subjectOfHelp 
= this; 
2574                     bool eventProcessed 
= FALSE
; 
2575                     while (subjectOfHelp 
&& !eventProcessed
) 
2577                         wxHelpEvent 
helpEvent(wxEVT_HELP
, 
2578                                               subjectOfHelp
->GetId(), 
2579                                               wxPoint(info
->MousePos
.x
, 
2580                                               info
->MousePos
.y
) ); 
2581                         helpEvent
.SetEventObject(this); 
2583                             GetEventHandler()->ProcessEvent(helpEvent
); 
2585                         // Go up the window hierarchy until the event is 
2587                         subjectOfHelp 
= subjectOfHelp
->GetParent(); 
2590                     processed 
= eventProcessed
; 
2592                 else if (info
->iContextType 
== HELPINFO_MENUITEM
) 
2594                     wxHelpEvent 
helpEvent(wxEVT_HELP
, info
->iCtrlId
); 
2595                     helpEvent
.SetEventObject(this); 
2596                     processed 
= GetEventHandler()->ProcessEvent(helpEvent
); 
2599                 //else: processed is already FALSE 
2603         case WM_CONTEXTMENU
: 
2605                 // we don't convert from screen to client coordinates as 
2606                 // the event may be handled by a parent window 
2607                 wxPoint 
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)); 
2609                 wxContextMenuEvent 
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
); 
2610                 processed 
= GetEventHandler()->ProcessEvent(evtCtx
); 
2615             // unfortunately this doesn't really work as then window which 
2616             // doesn't accept focus doesn't get any mouse events neither which 
2617             // means it can't get any input at all 
2618 #if 0 //def __WXUNIVERSAL__ 
2620             // we shouldn't allow the windows which don't want to get focus to 
2622             if ( !AcceptsFocus() ) 
2624                 rc
.result 
= HTTRANSPARENT
; 
2628 #endif // __WXUNIVERSAL__ 
2634         wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."), 
2635                    wxGetMessageName(message
)); 
2636 #endif // __WXDEBUG__ 
2637         rc
.result 
= MSWDefWindowProc(message
, wParam
, lParam
); 
2643 // ---------------------------------------------------------------------------- 
2644 // wxWindow <-> HWND map 
2645 // ---------------------------------------------------------------------------- 
2647 wxWinHashTable 
*wxWinHandleHash 
= NULL
; 
2649 wxWindow 
*wxFindWinFromHandle(WXHWND hWnd
) 
2651     return wxWinHandleHash
->Get((long)hWnd
); 
2654 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
) 
2656     // adding NULL hWnd is (first) surely a result of an error and 
2657     // (secondly) breaks menu command processing 
2658     wxCHECK_RET( hWnd 
!= (HWND
)NULL
, 
2659                  wxT("attempt to add a NULL hWnd to window list ignored") ); 
2661     wxWindow 
*oldWin 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
2663     if ( oldWin 
&& (oldWin 
!= win
) ) 
2665         wxLogDebug(wxT("HWND %X already associated with another window (%s)"), 
2666                    hWnd
, win
->GetClassInfo()->GetClassName()); 
2669 #endif // __WXDEBUG__ 
2672         wxWinHandleHash
->Put((long)hWnd
, (wxWindow 
*)win
); 
2676 void wxRemoveHandleAssociation(wxWindowMSW 
*win
) 
2678     wxWinHandleHash
->Delete((long)win
->GetHWND()); 
2681 // ---------------------------------------------------------------------------- 
2682 // various MSW speciic class dependent functions 
2683 // ---------------------------------------------------------------------------- 
2685 // Default destroyer - override if you destroy it in some other way 
2686 // (e.g. with MDI child windows) 
2687 void wxWindowMSW::MSWDestroyWindow() 
2691 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
, 
2694                                            int& w
, int& h
) const 
2696     bool nonDefault 
= FALSE
; 
2700         // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can 
2701         // just as well set it to CW_USEDEFAULT as well 
2708         y 
= pos
.y 
== -1 ? CW_USEDEFAULT 
: pos
.y
; 
2714       NB: there used to be some code here which set the initial size of the 
2715           window to the client size of the parent if no explicit size was 
2716           specified. This was wrong because wxWindows programs often assume 
2717           that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke 
2718           it. To see why, you should understand that Windows sends WM_SIZE from 
2719           inside ::CreateWindow() anyhow. However, ::CreateWindow() is called 
2720           from some base class ctor and so this WM_SIZE is not processed in the 
2721           real class' OnSize() (because it's not fully constructed yet and the 
2722           event goes to some base class OnSize() instead). So the WM_SIZE we 
2723           rely on is the one sent when the parent frame resizes its children 
2724           but here is the problem: if the child already has just the right 
2725           size, nothing will happen as both wxWindows and Windows check for 
2726           this and ignore any attempts to change the window size to the size it 
2727           already has - so no WM_SIZE would be sent. 
2731         // as abobe, h is not used at all in this case anyhow 
2738         h 
= size
.y 
== -1 ? CW_USEDEFAULT 
: size
.y
; 
2746 bool wxWindowMSW::MSWCreate(const wxChar 
*wclass
, 
2747                             const wxChar 
*title
, 
2751                             WXDWORD extendedStyle
) 
2753     // choose the position/size for the new window 
2755     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
2757     // find the correct parent HWND 
2758     wxWindow 
*parent 
= GetParent(); 
2759     bool isChild 
= (style 
& WS_CHILD
) != 0; 
2761     if ( GetWindowStyleFlag() & wxPOPUP_WINDOW 
) 
2763         // popup windows should have desktop as parent because they shouldn't 
2764         // be limited to the parents client area as child windows usually are 
2765         hParent 
= ::GetDesktopWindow(); 
2769         if ( (isChild 
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent 
) 
2771             // this is either a normal child window or a top level window with 
2772             // wxFRAME_TOOL_WINDOW style (see below) 
2773             hParent 
= GetHwndOf(parent
); 
2777             // this is either a window for which no parent was specified (not 
2778             // much we can do then) or a frame without wxFRAME_TOOL_WINDOW 
2779             // style: we should use NULL parent HWND for it or it would be 
2780             // always on top of its parent which is not what we usually want 
2781             // (in fact, we only want it for frames with the special 
2782             // wxFRAME_TOOL_WINDOW as above) 
2788     // controlId is menu handle for the top level windows, so set it to 0 
2789     // unless we're creating a child window 
2793         controlId 
= GetId(); 
2795         if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS 
) 
2797             style 
|= WS_CLIPSIBLINGS
; 
2805     // for each class "Foo" we have we also have "FooNR" ("no repaint") class 
2806     // which is the same but without CS_[HV]REDRAW class styles so using it 
2807     // ensures that the window is not fully repainted on each resize 
2808     wxString 
className(wclass
); 
2809     if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE 
) 
2811         className 
+= wxT("NR"); 
2814     // do create the window 
2815     wxWindowCreationHook 
hook(this); 
2817     m_hWnd 
= (WXHWND
)::CreateWindowEx
 
2821                 title 
? title 
: wxT(""), 
2827                 NULL                        
// no extra data 
2832         wxLogSysError(_("Can't create window of class %s"), wclass
); 
2837     SubclassWin(m_hWnd
); 
2839     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
2844 // =========================================================================== 
2845 // MSW message handlers 
2846 // =========================================================================== 
2848 // --------------------------------------------------------------------------- 
2850 // --------------------------------------------------------------------------- 
2853 // FIXME: VZ: I'm not sure at all that the order of processing is correct 
2854 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
2856 #ifndef __WXMICROWIN__ 
2857     LPNMHDR hdr 
= (LPNMHDR
)lParam
; 
2858     HWND hWnd 
= hdr
->hwndFrom
; 
2859     wxWindow 
*win 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
2861     // is this one of our windows? 
2864         return win
->MSWOnNotify(idCtrl
, lParam
, result
); 
2867     // try all our children 
2868     wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
2871         wxWindow 
*child 
= node
->GetData(); 
2872         if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) ) 
2877         node 
= node
->GetNext(); 
2880     // finally try this window too (catches toolbar case) 
2881     return MSWOnNotify(idCtrl
, lParam
, result
); 
2882 #else // __WXMICROWIN__ 
2887 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
), 
2889                            WXLPARAM
* WXUNUSED(result
)) 
2892     NMHDR
* hdr 
= (NMHDR 
*)lParam
; 
2893     if ( (int)hdr
->code 
== TTN_NEEDTEXT 
&& m_tooltip 
) 
2895         TOOLTIPTEXT 
*ttt 
= (TOOLTIPTEXT 
*)lParam
; 
2896         ttt
->lpszText 
= (wxChar 
*)m_tooltip
->GetTip().c_str(); 
2901 #endif // wxUSE_TOOLTIPS 
2907 // --------------------------------------------------------------------------- 
2908 // end session messages 
2909 // --------------------------------------------------------------------------- 
2911 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
) 
2913     wxCloseEvent 
event(wxEVT_QUERY_END_SESSION
, -1); 
2914     event
.SetEventObject(wxTheApp
); 
2915     event
.SetCanVeto(TRUE
); 
2916     event
.SetLoggingOff(logOff 
== (long)ENDSESSION_LOGOFF
); 
2918     bool rc 
= wxTheApp
->ProcessEvent(event
); 
2922         // we may end only if the app didn't veto session closing (double 
2924         *mayEnd 
= !event
.GetVeto(); 
2930 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
) 
2932     // do nothing if the session isn't ending 
2937     if ( (this != wxTheApp
->GetTopWindow()) ) 
2940     wxCloseEvent 
event(wxEVT_END_SESSION
, -1); 
2941     event
.SetEventObject(wxTheApp
); 
2942     event
.SetCanVeto(FALSE
); 
2943     event
.SetLoggingOff( (logOff 
== (long)ENDSESSION_LOGOFF
) ); 
2945     return wxTheApp
->ProcessEvent(event
); 
2948 // --------------------------------------------------------------------------- 
2949 // window creation/destruction 
2950 // --------------------------------------------------------------------------- 
2952 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT 
WXUNUSED(cs
), bool *mayCreate
) 
2954     // TODO: should generate this event from WM_NCCREATE 
2955     wxWindowCreateEvent 
event((wxWindow 
*)this); 
2956     (void)GetEventHandler()->ProcessEvent(event
); 
2963 bool wxWindowMSW::HandleDestroy() 
2965     wxWindowDestroyEvent 
event((wxWindow 
*)this); 
2966     (void)GetEventHandler()->ProcessEvent(event
); 
2968     // delete our drop target if we've got one 
2969 #if wxUSE_DRAG_AND_DROP 
2970     if ( m_dropTarget 
!= NULL 
) 
2972         m_dropTarget
->Revoke(m_hWnd
); 
2974         delete m_dropTarget
; 
2975         m_dropTarget 
= NULL
; 
2977 #endif // wxUSE_DRAG_AND_DROP 
2979     // WM_DESTROY handled 
2983 // --------------------------------------------------------------------------- 
2985 // --------------------------------------------------------------------------- 
2987 bool wxWindowMSW::HandleActivate(int state
, 
2988                               bool WXUNUSED(minimized
), 
2989                               WXHWND 
WXUNUSED(activate
)) 
2991     wxActivateEvent 
event(wxEVT_ACTIVATE
, 
2992                           (state 
== WA_ACTIVE
) || (state 
== WA_CLICKACTIVE
), 
2994     event
.SetEventObject(this); 
2996     return GetEventHandler()->ProcessEvent(event
); 
2999 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
) 
3001     // notify the parent keeping track of focus for the kbd navigation 
3002     // purposes that we got it 
3003     wxChildFocusEvent 
eventFocus((wxWindow 
*)this); 
3004     (void)GetEventHandler()->ProcessEvent(eventFocus
); 
3010         m_caret
->OnSetFocus(); 
3012 #endif // wxUSE_CARET 
3015     // If it's a wxTextCtrl don't send the event as it will be done 
3016     // after the control gets to process it from EN_FOCUS handler 
3017     if ( wxDynamicCastThis(wxTextCtrl
) ) 
3021 #endif // wxUSE_TEXTCTRL 
3023     wxFocusEvent 
event(wxEVT_SET_FOCUS
, m_windowId
); 
3024     event
.SetEventObject(this); 
3026     // wxFindWinFromHandle() may return NULL, it is ok 
3027     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3029     return GetEventHandler()->ProcessEvent(event
); 
3032 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
) 
3038         m_caret
->OnKillFocus(); 
3040 #endif // wxUSE_CARET 
3043     // If it's a wxTextCtrl don't send the event as it will be done 
3044     // after the control gets to process it. 
3045     wxTextCtrl 
*ctrl 
= wxDynamicCastThis(wxTextCtrl
); 
3052     wxFocusEvent 
event(wxEVT_KILL_FOCUS
, m_windowId
); 
3053     event
.SetEventObject(this); 
3055     // wxFindWinFromHandle() may return NULL, it is ok 
3056     event
.SetWindow(wxFindWinFromHandle(hwnd
)); 
3058     return GetEventHandler()->ProcessEvent(event
); 
3061 // --------------------------------------------------------------------------- 
3063 // --------------------------------------------------------------------------- 
3065 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
)) 
3067     wxShowEvent 
event(GetId(), show
); 
3068     event
.m_eventObject 
= this; 
3070     return GetEventHandler()->ProcessEvent(event
); 
3073 bool wxWindowMSW::HandleInitDialog(WXHWND 
WXUNUSED(hWndFocus
)) 
3075     wxInitDialogEvent 
event(GetId()); 
3076     event
.m_eventObject 
= this; 
3078     return GetEventHandler()->ProcessEvent(event
); 
3081 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
) 
3083 #ifndef __WXMICROWIN__ 
3084     HDROP hFilesInfo 
= (HDROP
) wParam
; 
3086     // Get the total number of files dropped 
3087     UINT gwFilesDropped 
= ::DragQueryFile
 
3095     wxString 
*files 
= new wxString
[gwFilesDropped
]; 
3096     for ( UINT wIndex 
= 0; wIndex 
< gwFilesDropped
; wIndex
++ ) 
3098         // first get the needed buffer length (+1 for terminating NUL) 
3099         size_t len 
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1; 
3101         // and now get the file name 
3102         ::DragQueryFile(hFilesInfo
, wIndex
, 
3103                         files
[wIndex
].GetWriteBuf(len
), len
); 
3105         files
[wIndex
].UngetWriteBuf(); 
3107     DragFinish (hFilesInfo
); 
3109     wxDropFilesEvent 
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
); 
3110     event
.m_eventObject 
= this; 
3113     DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
); 
3114     event
.m_pos
.x 
= dropPoint
.x
; 
3115     event
.m_pos
.y 
= dropPoint
.y
; 
3117     return GetEventHandler()->ProcessEvent(event
); 
3118 #else // __WXMICROWIN__ 
3123 bool wxWindowMSW::HandleSetCursor(WXHWND 
WXUNUSED(hWnd
), 
3125                                   int WXUNUSED(mouseMsg
)) 
3127 #ifndef __WXMICROWIN__ 
3128     // the logic is as follows: 
3129     // -1. don't set cursor for non client area, including but not limited to 
3130     //     the title bar, scrollbars, &c 
3131     //  0. allow the user to override default behaviour by using EVT_SET_CURSOR 
3132     //  1. if we have the cursor set it unless wxIsBusy() 
3133     //  2. if we're a top level window, set some cursor anyhow 
3134     //  3. if wxIsBusy(), set the busy cursor, otherwise the global one 
3136     if ( nHitTest 
!= HTCLIENT 
) 
3141     HCURSOR hcursor 
= 0; 
3143     // first ask the user code - it may wish to set the cursor in some very 
3144     // specific way (for example, depending on the current position) 
3147     if ( !::GetCursorPos(&pt
) ) 
3149         wxLogLastError(wxT("GetCursorPos")); 
3152     // In WIN16 it doesn't return a value. 
3153     ::GetCursorPos(&pt
); 
3158     ScreenToClient(&x
, &y
); 
3159     wxSetCursorEvent 
event(x
, y
); 
3161     bool processedEvtSetCursor 
= GetEventHandler()->ProcessEvent(event
); 
3162     if ( processedEvtSetCursor 
&& event
.HasCursor() ) 
3164         hcursor 
= GetHcursorOf(event
.GetCursor()); 
3169         bool isBusy 
= wxIsBusy(); 
3171         // the test for processedEvtSetCursor is here to prevent using m_cursor 
3172         // if the user code caught EVT_SET_CURSOR() and returned nothing from 
3173         // it - this is a way to say that our cursor shouldn't be used for this 
3175         if ( !processedEvtSetCursor 
&& m_cursor
.Ok() ) 
3177             hcursor 
= GetHcursorOf(m_cursor
); 
3184                 hcursor 
= wxGetCurrentBusyCursor(); 
3186             else if ( !hcursor 
) 
3188                 const wxCursor 
*cursor 
= wxGetGlobalCursor(); 
3189                 if ( cursor 
&& cursor
->Ok() ) 
3191                     hcursor 
= GetHcursorOf(*cursor
); 
3199         ::SetCursor(hcursor
); 
3201         // cursor set, stop here 
3204 #endif // __WXMICROWIN__ 
3206     // pass up the window chain 
3210 // --------------------------------------------------------------------------- 
3211 // owner drawn stuff 
3212 // --------------------------------------------------------------------------- 
3214 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT 
*itemStruct
) 
3216 #if wxUSE_OWNER_DRAWN 
3218 #if wxUSE_MENUS_NATIVE 
3219     // is it a menu item? 
3220     DRAWITEMSTRUCT 
*pDrawStruct 
= (DRAWITEMSTRUCT 
*)itemStruct
; 
3221     if ( id 
== 0 && pDrawStruct
->CtlType 
== ODT_MENU 
) 
3223         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pDrawStruct
->itemData
); 
3225         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE 
); 
3227         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent 
3228         // the DC from being released 
3229         wxDCTemp 
dc((WXHDC
)pDrawStruct
->hDC
); 
3230         wxRect 
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
, 
3231                     pDrawStruct
->rcItem
.right 
- pDrawStruct
->rcItem
.left
, 
3232                     pDrawStruct
->rcItem
.bottom 
- pDrawStruct
->rcItem
.top
); 
3234         return pMenuItem
->OnDrawItem
 
3238                 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
, 
3239                 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
 
3242 #endif // wxUSE_MENUS_NATIVE 
3245     wxWindow 
*item 
= FindItem(id
); 
3246     if ( item 
&& item
->IsKindOf(CLASSINFO(wxControl
)) ) 
3248         return ((wxControl 
*)item
)->MSWOnDraw(itemStruct
); 
3250 #endif // wxUSE_CONTROLS 
3252 #endif // USE_OWNER_DRAWN 
3257 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT 
*itemStruct
) 
3259 #if wxUSE_OWNER_DRAWN 
3260     // is it a menu item? 
3261     MEASUREITEMSTRUCT 
*pMeasureStruct 
= (MEASUREITEMSTRUCT 
*)itemStruct
; 
3262     if ( id 
== 0 && pMeasureStruct
->CtlType 
== ODT_MENU 
) 
3264         wxMenuItem 
*pMenuItem 
= (wxMenuItem 
*)(pMeasureStruct
->itemData
); 
3266         wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE 
); 
3268         return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
, 
3269                                         &pMeasureStruct
->itemHeight
); 
3272     wxWindow 
*item 
= FindItem(id
); 
3273     if ( item 
&& item
->IsKindOf(CLASSINFO(wxControl
)) ) 
3275         return ((wxControl 
*)item
)->MSWOnMeasure(itemStruct
); 
3277 #endif  // owner-drawn menus 
3281 // --------------------------------------------------------------------------- 
3282 // colours and palettes 
3283 // --------------------------------------------------------------------------- 
3285 bool wxWindowMSW::HandleSysColorChange() 
3287     wxSysColourChangedEvent event
; 
3288     event
.SetEventObject(this); 
3290     (void)GetEventHandler()->ProcessEvent(event
); 
3292     // always let the system carry on the default processing to allow the 
3293     // native controls to react to the colours update 
3297 bool wxWindowMSW::HandleDisplayChange() 
3299     wxDisplayChangedEvent event
; 
3300     event
.SetEventObject(this); 
3302     return GetEventHandler()->ProcessEvent(event
); 
3305 bool wxWindowMSW::HandleCtlColor(WXHBRUSH 
*brush
, 
3313 #ifndef __WXMICROWIN__ 
3314     WXHBRUSH hBrush 
= 0; 
3316     if ( nCtlColor 
== CTLCOLOR_DLG 
) 
3318         hBrush 
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3323         wxControl 
*item 
= (wxControl 
*)FindItemByHWND(pWnd
, TRUE
); 
3325             hBrush 
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
); 
3327 #endif // wxUSE_CONTROLS 
3333 #else // __WXMICROWIN__ 
3338 // Define for each class of dialog and control 
3339 WXHBRUSH 
wxWindowMSW::OnCtlColor(WXHDC 
WXUNUSED(hDC
), 
3340                                  WXHWND 
WXUNUSED(hWnd
), 
3341                                  WXUINT 
WXUNUSED(nCtlColor
), 
3342                                  WXUINT 
WXUNUSED(message
), 
3343                                  WXWPARAM 
WXUNUSED(wParam
), 
3344                                  WXLPARAM 
WXUNUSED(lParam
)) 
3349 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
) 
3352     // same as below except we don't respond to our own messages 
3353     if ( hWndPalChange 
!= GetHWND() ) 
3355         // check to see if we our our parents have a custom palette 
3356         wxWindow 
*win 
= this; 
3357         while ( win 
&& !win
->HasCustomPalette() ) 
3359             win 
= win
->GetParent(); 
3362         if ( win 
&& win
->HasCustomPalette() ) 
3364             // realize the palette to see whether redrawing is needed 
3365             HDC hdc 
= ::GetDC((HWND
) hWndPalChange
); 
3366             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3367                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3369             int result 
= ::RealizePalette(hdc
); 
3371             // restore the palette (before releasing the DC) 
3372             win
->m_palette
.SetHPALETTE((WXHPALETTE
) 
3373                     ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
)); 
3374             ::RealizePalette(hdc
); 
3375             ::ReleaseDC((HWND
) hWndPalChange
, hdc
); 
3377             // now check for the need to redraw 
3379                 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
); 
3383 #endif // wxUSE_PALETTE 
3385     wxPaletteChangedEvent 
event(GetId()); 
3386     event
.SetEventObject(this); 
3387     event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
)); 
3389     return GetEventHandler()->ProcessEvent(event
); 
3392 bool wxWindowMSW::HandleQueryNewPalette() 
3396     // check to see if we our our parents have a custom palette 
3397     wxWindow 
*win 
= this; 
3398     while (!win
->HasCustomPalette() && win
->GetParent()) win 
= win
->GetParent(); 
3399     if (win
->HasCustomPalette()) { 
3400         /* realize the palette to see whether redrawing is needed */ 
3401         HDC hdc 
= GetDC((HWND
) GetHWND()); 
3402         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3403              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) ); 
3405         int result 
= ::RealizePalette(hdc
); 
3406         /* restore the palette (before releasing the DC) */ 
3407         win
->m_palette
.SetHPALETTE( (WXHPALETTE
) 
3408              ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) ); 
3409         ::RealizePalette(hdc
); 
3410         ::ReleaseDC((HWND
) GetHWND(), hdc
); 
3411         /* now check for the need to redraw */ 
3413             ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
); 
3415 #endif // wxUSE_PALETTE 
3417     wxQueryNewPaletteEvent 
event(GetId()); 
3418     event
.SetEventObject(this); 
3420     return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized(); 
3423 // Responds to colour changes: passes event on to children. 
3424 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
3426     // the top level window also reset the standard colour map as it might have 
3427     // changed (there is no need to do it for the non top level windows as we 
3428     // only have to do it once) 
3432         gs_hasStdCmap 
= FALSE
; 
3434     wxWindowList::Node 
*node 
= GetChildren().GetFirst(); 
3437         // Only propagate to non-top-level windows because Windows already 
3438         // sends this event to all top-level ones 
3439         wxWindow 
*win 
= node
->GetData(); 
3440         if ( !win
->IsTopLevel() ) 
3442             // we need to send the real WM_SYSCOLORCHANGE and not just trigger 
3443             // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for 
3444             // the standard controls 
3445             ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0); 
3448         node 
= node
->GetNext(); 
3451     // update the colours we use if they were not set explicitly by the user: 
3452     // this must be done or OnCtlColor() would continue to use the old colours 
3455         m_foregroundColour 
= wxSystemSettings:: 
3456                                 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
); 
3461         m_backgroundColour 
= wxSystemSettings:: 
3462                                 GetSystemColour(wxSYS_COLOUR_BTNFACE
); 
3466 extern wxCOLORMAP 
*wxGetStdColourMap() 
3468     static COLORREF s_stdColours
[wxSTD_COL_MAX
]; 
3469     static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
]; 
3471     if ( !gs_hasStdCmap 
) 
3473         static bool s_coloursInit 
= FALSE
; 
3475         if ( !s_coloursInit 
) 
3477             // When a bitmap is loaded, the RGB values can change (apparently 
3478             // because Windows adjusts them to care for the old programs always 
3479             // using 0xc0c0c0 while the transparent colour for the new Windows 
3480             // versions is different). But we do this adjustment ourselves so 
3481             // we want to avoid Windows' "help" and for this we need to have a 
3482             // reference bitmap which can tell us what the RGB values change 
3484             wxBitmap 
stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); 
3485             if ( stdColourBitmap
.Ok() ) 
3487                 // the pixels in the bitmap must correspond to wxSTD_COL_XXX! 
3488                 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
, 
3489                               _T("forgot to update wxBITMAP_STD_COLOURS!") ); 
3492                 memDC
.SelectObject(stdColourBitmap
); 
3495                 for ( size_t i 
= 0; i 
< WXSIZEOF(s_stdColours
); i
++ ) 
3497                     memDC
.GetPixel(i
, 0, &colour
); 
3498                     s_stdColours
[i
] = wxColourToRGB(colour
); 
3501             else // wxBITMAP_STD_COLOURS couldn't be loaded 
3503                 s_stdColours
[0] = RGB(000,000,000);     // black 
3504                 s_stdColours
[1] = RGB(128,128,128);     // dark grey 
3505                 s_stdColours
[2] = RGB(192,192,192);     // light grey 
3506                 s_stdColours
[3] = RGB(255,255,255);     // white 
3507                 //s_stdColours[4] = RGB(000,000,255);     // blue 
3508                 //s_stdColours[5] = RGB(255,000,255);     // magenta 
3511             s_coloursInit 
= TRUE
; 
3514         gs_hasStdCmap 
= TRUE
; 
3516         // create the colour map 
3517 #define INIT_CMAP_ENTRY(col) \ 
3518             s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \ 
3519             s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col) 
3521         INIT_CMAP_ENTRY(BTNTEXT
); 
3522         INIT_CMAP_ENTRY(BTNSHADOW
); 
3523         INIT_CMAP_ENTRY(BTNFACE
); 
3524         INIT_CMAP_ENTRY(BTNHIGHLIGHT
); 
3526 #undef INIT_CMAP_ENTRY 
3532 // --------------------------------------------------------------------------- 
3534 // --------------------------------------------------------------------------- 
3536 bool wxWindowMSW::HandlePaint() 
3539     HRGN hRegion 
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle 
3541         wxLogLastError(wxT("CreateRectRgn")); 
3542     if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR 
) 
3543         wxLogLastError(wxT("GetUpdateRgn")); 
3545     m_updateRegion 
= wxRegion((WXHRGN
) hRegion
); 
3548     ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
); 
3550     m_updateRegion 
= wxRegion(updateRect
.left
, updateRect
.top
, 
3551                               updateRect
.right 
- updateRect
.left
, 
3552                               updateRect
.bottom 
- updateRect
.top
); 
3555     wxPaintEvent 
event(m_windowId
); 
3556     event
.SetEventObject(this); 
3558     bool processed 
= GetEventHandler()->ProcessEvent(event
); 
3560     // note that we must generate NC event after the normal one as otherwise 
3561     // BeginPaint() will happily overwrite our decorations with the background 
3563     wxNcPaintEvent 
eventNc(m_windowId
); 
3564     eventNc
.SetEventObject(this); 
3565     GetEventHandler()->ProcessEvent(eventNc
); 
3570 // Can be called from an application's OnPaint handler 
3571 void wxWindowMSW::OnPaint(wxPaintEvent
& event
) 
3573 #ifdef __WXUNIVERSAL__ 
3576     HDC hDC 
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject()); 
3579         MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0); 
3584 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
) 
3586     // Prevents flicker when dragging 
3587     if ( ::IsIconic(GetHwnd()) ) 
3593     dc
.SetWindow((wxWindow 
*)this); 
3596     wxEraseEvent 
event(m_windowId
, &dc
); 
3597     event
.SetEventObject(this); 
3598     bool rc 
= GetEventHandler()->ProcessEvent(event
); 
3602     // must be called manually as ~wxDC doesn't do anything for wxDCTemp 
3603     dc
.SelectOldObjects(hdc
); 
3608 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
) 
3611     ::GetClientRect(GetHwnd(), &rect
); 
3613     COLORREF ref 
= PALETTERGB(m_backgroundColour
.Red(), 
3614                               m_backgroundColour
.Green(), 
3615                               m_backgroundColour
.Blue()); 
3616     HBRUSH hBrush 
= ::CreateSolidBrush(ref
); 
3618         wxLogLastError(wxT("CreateSolidBrush")); 
3620     HDC hdc 
= (HDC
)event
.GetDC()->GetHDC(); 
3622     int mode 
= ::SetMapMode(hdc
, MM_TEXT
); 
3624     ::FillRect(hdc
, &rect
, hBrush
); 
3625     ::DeleteObject(hBrush
); 
3626     ::SetMapMode(hdc
, mode
); 
3629 // --------------------------------------------------------------------------- 
3630 // moving and resizing 
3631 // --------------------------------------------------------------------------- 
3633 bool wxWindowMSW::HandleMinimize() 
3635     wxIconizeEvent 
event(m_windowId
); 
3636     event
.SetEventObject(this); 
3638     return GetEventHandler()->ProcessEvent(event
); 
3641 bool wxWindowMSW::HandleMaximize() 
3643     wxMaximizeEvent 
event(m_windowId
); 
3644     event
.SetEventObject(this); 
3646     return GetEventHandler()->ProcessEvent(event
); 
3649 bool wxWindowMSW::HandleMove(int x
, int y
) 
3651     wxMoveEvent 
event(wxPoint(x
, y
), m_windowId
); 
3652     event
.SetEventObject(this); 
3654     return GetEventHandler()->ProcessEvent(event
); 
3657 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT 
WXUNUSED(flag
)) 
3659     wxSizeEvent 
event(wxSize(w
, h
), m_windowId
); 
3660     event
.SetEventObject(this); 
3662     return GetEventHandler()->ProcessEvent(event
); 
3665 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
) 
3667     MINMAXINFO 
*info 
= (MINMAXINFO 
*)mmInfo
; 
3671     int minWidth 
= GetMinWidth(), 
3672         minHeight 
= GetMinHeight(), 
3673         maxWidth 
= GetMaxWidth(), 
3674         maxHeight 
= GetMaxHeight(); 
3676     if ( minWidth 
!= -1 ) 
3678         info
->ptMinTrackSize
.x 
= minWidth
; 
3682     if ( minHeight 
!= -1 ) 
3684         info
->ptMinTrackSize
.y 
= minHeight
; 
3688     if ( maxWidth 
!= -1 ) 
3690         info
->ptMaxTrackSize
.x 
= maxWidth
; 
3694     if ( maxHeight 
!= -1 ) 
3696         info
->ptMaxTrackSize
.y 
= maxHeight
; 
3703 // --------------------------------------------------------------------------- 
3705 // --------------------------------------------------------------------------- 
3707 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
) 
3709 #if wxUSE_MENUS_NATIVE 
3710     if ( !cmd 
&& wxCurrentPopupMenu 
) 
3712         wxMenu 
*popupMenu 
= wxCurrentPopupMenu
; 
3713         wxCurrentPopupMenu 
= NULL
; 
3715         return popupMenu
->MSWCommand(cmd
, id
); 
3717 #endif // wxUSE_MENUS_NATIVE 
3719     wxWindow 
*win 
= NULL
; 
3721     // first try to find it from HWND - this works even with the broken 
3722     // programs using the same ids for different controls 
3725         win 
= wxFindWinFromHandle(control
); 
3731         // must cast to a signed type before comparing with other ids! 
3732         win 
= FindItem((signed short)id
); 
3737         return win
->MSWCommand(cmd
, id
); 
3740     // the messages sent from the in-place edit control used by the treectrl 
3741     // for label editing have id == 0, but they should _not_ be treated as menu 
3742     // messages (they are EN_XXX ones, in fact) so don't translate anything 
3743     // coming from a control to wxEVT_COMMAND_MENU_SELECTED 
3746         // If no child window, it may be an accelerator, e.g. for a popup menu 
3749         wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
); 
3750         event
.SetEventObject(this); 
3754         return GetEventHandler()->ProcessEvent(event
); 
3756 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
3759         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND 
3760         // notifications to its parent which we want to reflect back to 
3762         wxSpinCtrl 
*spin 
= wxSpinCtrl::GetSpinForTextCtrl(control
); 
3763         if ( spin 
&& spin
->ProcessTextCommand(cmd
, id
) ) 
3766 #endif // wxUSE_SPINCTRL 
3771 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM 
WXUNUSED(lParam
)) 
3773     // 4 bits are reserved 
3774     switch ( wParam 
& 0xFFFFFFF0 ) 
3777             return HandleMaximize(); 
3780             return HandleMinimize(); 
3786 // --------------------------------------------------------------------------- 
3788 // --------------------------------------------------------------------------- 
3790 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
, 
3794     // our client coords are not quite the same as Windows ones 
3795     wxPoint pt 
= GetClientAreaOrigin(); 
3796     event
.m_x 
= x 
- pt
.x
; 
3797     event
.m_y 
= y 
- pt
.y
; 
3799     event
.m_shiftDown 
= (flags 
& MK_SHIFT
) != 0; 
3800     event
.m_controlDown 
= (flags 
& MK_CONTROL
) != 0; 
3801     event
.m_leftDown 
= (flags 
& MK_LBUTTON
) != 0; 
3802     event
.m_middleDown 
= (flags 
& MK_MBUTTON
) != 0; 
3803     event
.m_rightDown 
= (flags 
& MK_RBUTTON
) != 0; 
3804     event
.m_altDown 
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0; 
3806     event
.SetTimestamp(s_currentMsg
.time
); 
3807     event
.m_eventObject 
= this; 
3809 #if wxUSE_MOUSEEVENT_HACK 
3812     m_lastMouseEvent 
= event
.GetEventType(); 
3813 #endif // wxUSE_MOUSEEVENT_HACK 
3816 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
3818     // the mouse events take consecutive IDs from WM_MOUSEFIRST to 
3819     // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST 
3820     // from the message id and take the value in the table to get wxWin event 
3822     static const wxEventType eventsMouse
[] = 
3836     wxMouseEvent 
event(eventsMouse
[msg 
- WM_MOUSEMOVE
]); 
3837     InitMouseEvent(event
, x
, y
, flags
); 
3839     return GetEventHandler()->ProcessEvent(event
); 
3842 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
) 
3844     if ( !m_mouseInWindow 
) 
3846         // it would be wrong to assume that just because we get a mouse move 
3847         // event that the mouse is inside the window: although this is usually 
3848         // true, it is not if we had captured the mouse, so we need to check 
3849         // the mouse coordinates here 
3850         if ( !HasCapture() || IsMouseInWindow() ) 
3852             // Generate an ENTER event 
3853             m_mouseInWindow 
= TRUE
; 
3855             wxMouseEvent 
event(wxEVT_ENTER_WINDOW
); 
3856             InitMouseEvent(event
, x
, y
, flags
); 
3858             (void)GetEventHandler()->ProcessEvent(event
); 
3862 #if wxUSE_MOUSEEVENT_HACK 
3863     // Window gets a click down message followed by a mouse move message even 
3864     // if position isn't changed!  We want to discard the trailing move event 
3865     // if x and y are the same. 
3866     if ( (m_lastMouseEvent 
== wxEVT_RIGHT_DOWN 
|| 
3867           m_lastMouseEvent 
== wxEVT_LEFT_DOWN 
|| 
3868           m_lastMouseEvent 
== wxEVT_MIDDLE_DOWN
) && 
3869          (m_lastMouseX 
== x 
&& m_lastMouseY 
== y
) ) 
3871         m_lastMouseEvent 
= wxEVT_MOTION
; 
3875 #endif // wxUSE_MOUSEEVENT_HACK 
3877     return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
); 
3881 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
) 
3883 #if wxUSE_MOUSEWHEEL 
3884     wxMouseEvent 
event(wxEVT_MOUSEWHEEL
); 
3885     InitMouseEvent(event
, 
3886                    GET_X_LPARAM(lParam
), 
3887                    GET_Y_LPARAM(lParam
), 
3889     event
.m_wheelRotation 
= (short)HIWORD(wParam
); 
3890     event
.m_wheelDelta 
= WHEEL_DELTA
; 
3893     static int s_linesPerRotation 
= -1; 
3894     if ( s_linesPerRotation 
== -1 ) 
3896         if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0, 
3897                                      &s_linesPerRotation
, 0)) 
3899             // this is not supposed to happen 
3900             wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)")); 
3902             // the default is 3, so use it if SystemParametersInfo() failed 
3903             s_linesPerRotation 
= 3; 
3907     // no SystemParametersInfo() under Win16 
3908     static const int s_linesPerRotation 
= 3; 
3911     event
.m_linesPerAction 
= s_linesPerRotation
; 
3912     return GetEventHandler()->ProcessEvent(event
); 
3923 // --------------------------------------------------------------------------- 
3924 // keyboard handling 
3925 // --------------------------------------------------------------------------- 
3927 // create the key event of the given type for the given key - used by 
3928 // HandleChar and HandleKeyDown/Up 
3929 wxKeyEvent 
wxWindowMSW::CreateKeyEvent(wxEventType evType
, 
3931                                        WXLPARAM lParam
) const 
3933     wxKeyEvent 
event(evType
); 
3934     event
.SetId(GetId()); 
3935     event
.m_shiftDown 
= wxIsShiftDown(); 
3936     event
.m_controlDown 
= wxIsCtrlDown(); 
3937     event
.m_altDown 
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
; 
3939     event
.m_eventObject 
= (wxWindow 
*)this; // const_cast 
3940     event
.m_keyCode 
= id
; 
3941     event
.SetTimestamp(s_currentMsg
.time
); 
3943     // translate the position to client coords 
3947     GetWindowRect(GetHwnd(),&rect
); 
3957 // isASCII is TRUE only when we're called from WM_CHAR handler and not from 
3959 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
) 
3961     bool ctrlDown 
= FALSE
; 
3966         // If 1 -> 26, translate to CTRL plus a letter. 
3968         if ( (id 
> 0) && (id 
< 27) ) 
3990     else if ( (id 
= wxCharCodeMSWToWX(wParam
)) == 0 ) 
3992         // it's ASCII and will be processed here only when called from 
3993         // WM_CHAR (i.e. when isASCII = TRUE), don't process it now 
3999         wxKeyEvent 
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
)); 
4002             event
.m_controlDown 
= TRUE
; 
4005         if ( GetEventHandler()->ProcessEvent(event
) ) 
4012 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
) 
4014     int id 
= wxCharCodeMSWToWX(wParam
); 
4018         // normal ASCII char 
4022     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4024         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
)); 
4025         if ( GetEventHandler()->ProcessEvent(event
) ) 
4034 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
) 
4036     int id 
= wxCharCodeMSWToWX(wParam
); 
4040         // normal ASCII char 
4044     if ( id 
!= -1 ) // VZ: does this ever happen (FIXME)? 
4046         wxKeyEvent 
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
)); 
4047         if ( GetEventHandler()->ProcessEvent(event
) ) 
4054 // --------------------------------------------------------------------------- 
4056 // --------------------------------------------------------------------------- 
4058 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
) 
4062     if ( flags 
& JOY_BUTTON1CHG 
) 
4063         change 
= wxJOY_BUTTON1
; 
4064     if ( flags 
& JOY_BUTTON2CHG 
) 
4065         change 
= wxJOY_BUTTON2
; 
4066     if ( flags 
& JOY_BUTTON3CHG 
) 
4067         change 
= wxJOY_BUTTON3
; 
4068     if ( flags 
& JOY_BUTTON4CHG 
) 
4069         change 
= wxJOY_BUTTON4
; 
4072     if ( flags 
& JOY_BUTTON1 
) 
4073         buttons 
|= wxJOY_BUTTON1
; 
4074     if ( flags 
& JOY_BUTTON2 
) 
4075         buttons 
|= wxJOY_BUTTON2
; 
4076     if ( flags 
& JOY_BUTTON3 
) 
4077         buttons 
|= wxJOY_BUTTON3
; 
4078     if ( flags 
& JOY_BUTTON4 
) 
4079         buttons 
|= wxJOY_BUTTON4
; 
4081     // the event ids aren't consecutive so we can't use table based lookup 
4083     wxEventType eventType
; 
4088             eventType 
= wxEVT_JOY_MOVE
; 
4093             eventType 
= wxEVT_JOY_MOVE
; 
4098             eventType 
= wxEVT_JOY_ZMOVE
; 
4103             eventType 
= wxEVT_JOY_ZMOVE
; 
4106         case MM_JOY1BUTTONDOWN
: 
4108             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4111         case MM_JOY2BUTTONDOWN
: 
4113             eventType 
= wxEVT_JOY_BUTTON_DOWN
; 
4116         case MM_JOY1BUTTONUP
: 
4118             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4121         case MM_JOY2BUTTONUP
: 
4123             eventType 
= wxEVT_JOY_BUTTON_UP
; 
4127             wxFAIL_MSG(wxT("no such joystick event")); 
4132     wxJoystickEvent 
event(eventType
, buttons
, joystick
, change
); 
4133     event
.SetPosition(wxPoint(x
, y
)); 
4134     event
.SetEventObject(this); 
4136     return GetEventHandler()->ProcessEvent(event
); 
4142 // --------------------------------------------------------------------------- 
4144 // --------------------------------------------------------------------------- 
4146 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
, 
4147                            WXWORD pos
, WXHWND control
) 
4151         wxWindow 
*child 
= wxFindWinFromHandle(control
); 
4153             return child
->MSWOnScroll(orientation
, wParam
, pos
, control
); 
4156     wxScrollWinEvent event
; 
4157     event
.SetPosition(pos
); 
4158     event
.SetOrientation(orientation
); 
4159     event
.m_eventObject 
= this; 
4164         event
.m_eventType 
= wxEVT_SCROLLWIN_TOP
; 
4168         event
.m_eventType 
= wxEVT_SCROLLWIN_BOTTOM
; 
4172         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEUP
; 
4176         event
.m_eventType 
= wxEVT_SCROLLWIN_LINEDOWN
; 
4180         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEUP
; 
4184         event
.m_eventType 
= wxEVT_SCROLLWIN_PAGEDOWN
; 
4187     case SB_THUMBPOSITION
: 
4190         // under Win32, the scrollbar range and position are 32 bit integers, 
4191         // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must 
4192         // explicitly query the scrollbar for the correct position (this must 
4193         // be done only for these two SB_ events as they are the only one 
4194         // carrying the scrollbar position) 
4196             SCROLLINFO scrollInfo
; 
4197             wxZeroMemory(scrollInfo
); 
4198             scrollInfo
.cbSize 
= sizeof(SCROLLINFO
); 
4199             scrollInfo
.fMask 
= SIF_TRACKPOS
; 
4201             if ( !::GetScrollInfo(GetHwnd(), 
4202                                   orientation 
== wxHORIZONTAL 
? SB_HORZ
 
4206                 wxLogLastError(_T("GetScrollInfo")); 
4209             event
.SetPosition(scrollInfo
.nTrackPos
); 
4213         event
.m_eventType 
= wParam 
== SB_THUMBPOSITION
 
4214                                 ? wxEVT_SCROLLWIN_THUMBRELEASE
 
4215                                 : wxEVT_SCROLLWIN_THUMBTRACK
; 
4222     return GetEventHandler()->ProcessEvent(event
); 
4225 // =========================================================================== 
4227 // =========================================================================== 
4229 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont 
*the_font
) 
4232     HDC dc 
= ::GetDC((HWND
) wnd
); 
4237         //    the_font->UseResource(); 
4238         //    the_font->RealizeResource(); 
4239         fnt 
= (HFONT
)((wxFont 
*)the_font
)->GetResourceHandle(); // const_cast 
4241             was 
= (HFONT
) SelectObject(dc
,fnt
); 
4243     GetTextMetrics(dc
, &tm
); 
4244     if ( the_font 
&& fnt 
&& was 
) 
4246         SelectObject(dc
,was
); 
4248     ReleaseDC((HWND
)wnd
, dc
); 
4251         *x 
= tm
.tmAveCharWidth
; 
4253         *y 
= tm
.tmHeight 
+ tm
.tmExternalLeading
; 
4256     //    the_font->ReleaseResource(); 
4259 // Returns 0 if was a normal ASCII value, not a special key. This indicates that 
4260 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. 
4261 int wxCharCodeMSWToWX(int keySym
) 
4266         case VK_CANCEL
:     id 
= WXK_CANCEL
; break; 
4267         case VK_BACK
:       id 
= WXK_BACK
; break; 
4268         case VK_TAB
:        id 
= WXK_TAB
; break; 
4269         case VK_CLEAR
:      id 
= WXK_CLEAR
; break; 
4270         case VK_RETURN
:     id 
= WXK_RETURN
; break; 
4271         case VK_SHIFT
:      id 
= WXK_SHIFT
; break; 
4272         case VK_CONTROL
:    id 
= WXK_CONTROL
; break; 
4273         case VK_MENU 
:      id 
= WXK_MENU
; break; 
4274         case VK_PAUSE
:      id 
= WXK_PAUSE
; break; 
4275         case VK_SPACE
:      id 
= WXK_SPACE
; break; 
4276         case VK_ESCAPE
:     id 
= WXK_ESCAPE
; break; 
4277         case VK_PRIOR
:      id 
= WXK_PRIOR
; break; 
4278         case VK_NEXT 
:      id 
= WXK_NEXT
; break; 
4279         case VK_END
:        id 
= WXK_END
; break; 
4280         case VK_HOME 
:      id 
= WXK_HOME
; break; 
4281         case VK_LEFT 
:      id 
= WXK_LEFT
; break; 
4282         case VK_UP
:         id 
= WXK_UP
; break; 
4283         case VK_RIGHT
:      id 
= WXK_RIGHT
; break; 
4284         case VK_DOWN 
:      id 
= WXK_DOWN
; break; 
4285         case VK_SELECT
:     id 
= WXK_SELECT
; break; 
4286         case VK_PRINT
:      id 
= WXK_PRINT
; break; 
4287         case VK_EXECUTE
:    id 
= WXK_EXECUTE
; break; 
4288         case VK_INSERT
:     id 
= WXK_INSERT
; break; 
4289         case VK_DELETE
:     id 
= WXK_DELETE
; break; 
4290         case VK_HELP 
:      id 
= WXK_HELP
; break; 
4291         case VK_NUMPAD0
:    id 
= WXK_NUMPAD0
; break; 
4292         case VK_NUMPAD1
:    id 
= WXK_NUMPAD1
; break; 
4293         case VK_NUMPAD2
:    id 
= WXK_NUMPAD2
; break; 
4294         case VK_NUMPAD3
:    id 
= WXK_NUMPAD3
; break; 
4295         case VK_NUMPAD4
:    id 
= WXK_NUMPAD4
; break; 
4296         case VK_NUMPAD5
:    id 
= WXK_NUMPAD5
; break; 
4297         case VK_NUMPAD6
:    id 
= WXK_NUMPAD6
; break; 
4298         case VK_NUMPAD7
:    id 
= WXK_NUMPAD7
; break; 
4299         case VK_NUMPAD8
:    id 
= WXK_NUMPAD8
; break; 
4300         case VK_NUMPAD9
:    id 
= WXK_NUMPAD9
; break; 
4301         case VK_MULTIPLY
:   id 
= WXK_NUMPAD_MULTIPLY
; break; 
4302         case VK_ADD
:        id 
= WXK_NUMPAD_ADD
; break; 
4303         case VK_SUBTRACT
:   id 
= WXK_NUMPAD_SUBTRACT
; break; 
4304         case VK_DECIMAL
:    id 
= WXK_NUMPAD_DECIMAL
; break; 
4305         case VK_DIVIDE
:     id 
= WXK_NUMPAD_DIVIDE
; break; 
4306         case VK_F1
:         id 
= WXK_F1
; break; 
4307         case VK_F2
:         id 
= WXK_F2
; break; 
4308         case VK_F3
:         id 
= WXK_F3
; break; 
4309         case VK_F4
:         id 
= WXK_F4
; break; 
4310         case VK_F5
:         id 
= WXK_F5
; break; 
4311         case VK_F6
:         id 
= WXK_F6
; break; 
4312         case VK_F7
:         id 
= WXK_F7
; break; 
4313         case VK_F8
:         id 
= WXK_F8
; break; 
4314         case VK_F9
:         id 
= WXK_F9
; break; 
4315         case VK_F10
:        id 
= WXK_F10
; break; 
4316         case VK_F11
:        id 
= WXK_F11
; break; 
4317         case VK_F12
:        id 
= WXK_F12
; break; 
4318         case VK_F13
:        id 
= WXK_F13
; break; 
4319         case VK_F14
:        id 
= WXK_F14
; break; 
4320         case VK_F15
:        id 
= WXK_F15
; break; 
4321         case VK_F16
:        id 
= WXK_F16
; break; 
4322         case VK_F17
:        id 
= WXK_F17
; break; 
4323         case VK_F18
:        id 
= WXK_F18
; break; 
4324         case VK_F19
:        id 
= WXK_F19
; break; 
4325         case VK_F20
:        id 
= WXK_F20
; break; 
4326         case VK_F21
:        id 
= WXK_F21
; break; 
4327         case VK_F22
:        id 
= WXK_F22
; break; 
4328         case VK_F23
:        id 
= WXK_F23
; break; 
4329         case VK_F24
:        id 
= WXK_F24
; break; 
4330         case VK_NUMLOCK
:    id 
= WXK_NUMLOCK
; break; 
4331         case VK_SCROLL
:     id 
= WXK_SCROLL
; break; 
4339 int wxCharCodeWXToMSW(int id
, bool *isVirtual
) 
4345     case WXK_CANCEL
:    keySym 
= VK_CANCEL
; break; 
4346     case WXK_CLEAR
:     keySym 
= VK_CLEAR
; break; 
4347     case WXK_SHIFT
:     keySym 
= VK_SHIFT
; break; 
4348     case WXK_CONTROL
:   keySym 
= VK_CONTROL
; break; 
4349     case WXK_MENU 
:     keySym 
= VK_MENU
; break; 
4350     case WXK_PAUSE
:     keySym 
= VK_PAUSE
; break; 
4351     case WXK_PRIOR
:     keySym 
= VK_PRIOR
; break; 
4352     case WXK_NEXT 
:     keySym 
= VK_NEXT
; break; 
4353     case WXK_END
:       keySym 
= VK_END
; break; 
4354     case WXK_HOME 
:     keySym 
= VK_HOME
; break; 
4355     case WXK_LEFT 
:     keySym 
= VK_LEFT
; break; 
4356     case WXK_UP
:        keySym 
= VK_UP
; break; 
4357     case WXK_RIGHT
:     keySym 
= VK_RIGHT
; break; 
4358     case WXK_DOWN 
:     keySym 
= VK_DOWN
; break; 
4359     case WXK_SELECT
:    keySym 
= VK_SELECT
; break; 
4360     case WXK_PRINT
:     keySym 
= VK_PRINT
; break; 
4361     case WXK_EXECUTE
:   keySym 
= VK_EXECUTE
; break; 
4362     case WXK_INSERT
:    keySym 
= VK_INSERT
; break; 
4363     case WXK_DELETE
:    keySym 
= VK_DELETE
; break; 
4364     case WXK_HELP 
:     keySym 
= VK_HELP
; break; 
4365     case WXK_NUMPAD0
:   keySym 
= VK_NUMPAD0
; break; 
4366     case WXK_NUMPAD1
:   keySym 
= VK_NUMPAD1
; break; 
4367     case WXK_NUMPAD2
:   keySym 
= VK_NUMPAD2
; break; 
4368     case WXK_NUMPAD3
:   keySym 
= VK_NUMPAD3
; break; 
4369     case WXK_NUMPAD4
:   keySym 
= VK_NUMPAD4
; break; 
4370     case WXK_NUMPAD5
:   keySym 
= VK_NUMPAD5
; break; 
4371     case WXK_NUMPAD6
:   keySym 
= VK_NUMPAD6
; break; 
4372     case WXK_NUMPAD7
:   keySym 
= VK_NUMPAD7
; break; 
4373     case WXK_NUMPAD8
:   keySym 
= VK_NUMPAD8
; break; 
4374     case WXK_NUMPAD9
:   keySym 
= VK_NUMPAD9
; break; 
4375     case WXK_NUMPAD_MULTIPLY
:  keySym 
= VK_MULTIPLY
; break; 
4376     case WXK_NUMPAD_ADD
:       keySym 
= VK_ADD
; break; 
4377     case WXK_NUMPAD_SUBTRACT
:  keySym 
= VK_SUBTRACT
; break; 
4378     case WXK_NUMPAD_DECIMAL
:   keySym 
= VK_DECIMAL
; break; 
4379     case WXK_NUMPAD_DIVIDE
:    keySym 
= VK_DIVIDE
; break; 
4380     case WXK_F1
:        keySym 
= VK_F1
; break; 
4381     case WXK_F2
:        keySym 
= VK_F2
; break; 
4382     case WXK_F3
:        keySym 
= VK_F3
; break; 
4383     case WXK_F4
:        keySym 
= VK_F4
; break; 
4384     case WXK_F5
:        keySym 
= VK_F5
; break; 
4385     case WXK_F6
:        keySym 
= VK_F6
; break; 
4386     case WXK_F7
:        keySym 
= VK_F7
; break; 
4387     case WXK_F8
:        keySym 
= VK_F8
; break; 
4388     case WXK_F9
:        keySym 
= VK_F9
; break; 
4389     case WXK_F10
:       keySym 
= VK_F10
; break; 
4390     case WXK_F11
:       keySym 
= VK_F11
; break; 
4391     case WXK_F12
:       keySym 
= VK_F12
; break; 
4392     case WXK_F13
:       keySym 
= VK_F13
; break; 
4393     case WXK_F14
:       keySym 
= VK_F14
; break; 
4394     case WXK_F15
:       keySym 
= VK_F15
; break; 
4395     case WXK_F16
:       keySym 
= VK_F16
; break; 
4396     case WXK_F17
:       keySym 
= VK_F17
; break; 
4397     case WXK_F18
:       keySym 
= VK_F18
; break; 
4398     case WXK_F19
:       keySym 
= VK_F19
; break; 
4399     case WXK_F20
:       keySym 
= VK_F20
; break; 
4400     case WXK_F21
:       keySym 
= VK_F21
; break; 
4401     case WXK_F22
:       keySym 
= VK_F22
; break; 
4402     case WXK_F23
:       keySym 
= VK_F23
; break; 
4403     case WXK_F24
:       keySym 
= VK_F24
; break; 
4404     case WXK_NUMLOCK
:   keySym 
= VK_NUMLOCK
; break; 
4405     case WXK_SCROLL
:    keySym 
= VK_SCROLL
; break; 
4416 wxWindow 
*wxGetActiveWindow() 
4418     HWND hWnd 
= GetActiveWindow(); 
4421         return wxFindWinFromHandle((WXHWND
) hWnd
); 
4426 extern wxWindow 
*wxGetWindowFromHWND(WXHWND hWnd
) 
4428     HWND hwnd 
= (HWND
)hWnd
; 
4430     // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set 
4431     // by code in msw/radiobox.cpp), for all the others we just search up the 
4433     wxWindow 
*win 
= (wxWindow 
*)NULL
; 
4436         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
4439             // all these hacks only work under Win32 anyhow 
4443             // native radiobuttons return DLGC_RADIOBUTTON here and for any 
4444             // wxWindow class which overrides WM_GETDLGCODE processing to 
4445             // do it as well, win would be already non NULL 
4446             if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON 
) 
4448                 win 
= (wxWindow 
*)::GetWindowLong(hwnd
, GWL_USERDATA
); 
4450             //else: it's a wxRadioButton, not a radiobutton from wxRadioBox 
4451 #endif // wxUSE_RADIOBOX 
4453             // spin control text buddy window should be mapped to spin ctrl 
4454             // itself so try it too 
4455 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) 
4458                 win 
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
); 
4460 #endif // wxUSE_SPINCTRL 
4466     while ( hwnd 
&& !win 
) 
4468         // this is a really ugly hack needed to avoid mistakenly returning the 
4469         // parent frame wxWindow for the find/replace modeless dialog HWND - 
4470         // this, in turn, is needed to call IsDialogMessage() from 
4471         // wxApp::ProcessMessage() as for this we must return NULL from here 
4473         // FIXME: this is clearly not the best way to do it but I think we'll 
4474         //        need to change HWND <-> wxWindow code more heavily than I can 
4475         //        do it now to fix it 
4476 #ifndef __WXMICROWIN__ 
4477         if ( ::GetWindow(hwnd
, GW_OWNER
) ) 
4479             // it's a dialog box, don't go upwards 
4484         hwnd 
= ::GetParent(hwnd
); 
4485         win 
= wxFindWinFromHandle((WXHWND
)hwnd
); 
4491 #ifndef __WXMICROWIN__ 
4493 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE 
4494 // in active frames and dialogs, regardless of where the focus is. 
4495 static HHOOK wxTheKeyboardHook 
= 0; 
4496 static FARPROC wxTheKeyboardHookProc 
= 0; 
4497 int APIENTRY _EXPORT
 
4498 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
); 
4500 void wxSetKeyboardHook(bool doIt
) 
4504         wxTheKeyboardHookProc 
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance()); 
4505         wxTheKeyboardHook 
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(), 
4507 #if defined(__WIN32__) && !defined(__TWIN32__) 
4508             GetCurrentThreadId() 
4509         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? 
4517         UnhookWindowsHookEx(wxTheKeyboardHook
); 
4519         // avoids warning about statement with no effect (FreeProcInstance 
4520         // doesn't do anything under Win32) 
4521 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__) 
4522         FreeProcInstance(wxTheKeyboardHookProc
); 
4527 int APIENTRY _EXPORT
 
4528 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
) 
4530     DWORD hiWord 
= HIWORD(lParam
); 
4531     if ( nCode 
!= HC_NOREMOVE 
&& ((hiWord 
& KF_UP
) == 0) ) 
4533         int id 
= wxCharCodeMSWToWX(wParam
); 
4536             wxKeyEvent 
event(wxEVT_CHAR_HOOK
); 
4537             if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN 
) 
4538                 event
.m_altDown 
= TRUE
; 
4540             event
.m_eventObject 
= NULL
; 
4541             event
.m_keyCode 
= id
; 
4542             event
.m_shiftDown 
= wxIsShiftDown(); 
4543             event
.m_controlDown 
= wxIsCtrlDown(); 
4544             event
.SetTimestamp(s_currentMsg
.time
); 
4546             wxWindow 
*win 
= wxGetActiveWindow(); 
4547             wxEvtHandler 
*handler
; 
4550                 handler 
= win
->GetEventHandler(); 
4551                 event
.SetId(win
->GetId()); 
4559             if ( handler 
&& handler
->ProcessEvent(event
) ) 
4567     return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
); 
4570 #endif // !__WXMICROWIN__ 
4573 const char *wxGetMessageName(int message
) 
4577         case 0x0000: return "WM_NULL"; 
4578         case 0x0001: return "WM_CREATE"; 
4579         case 0x0002: return "WM_DESTROY"; 
4580         case 0x0003: return "WM_MOVE"; 
4581         case 0x0005: return "WM_SIZE"; 
4582         case 0x0006: return "WM_ACTIVATE"; 
4583         case 0x0007: return "WM_SETFOCUS"; 
4584         case 0x0008: return "WM_KILLFOCUS"; 
4585         case 0x000A: return "WM_ENABLE"; 
4586         case 0x000B: return "WM_SETREDRAW"; 
4587         case 0x000C: return "WM_SETTEXT"; 
4588         case 0x000D: return "WM_GETTEXT"; 
4589         case 0x000E: return "WM_GETTEXTLENGTH"; 
4590         case 0x000F: return "WM_PAINT"; 
4591         case 0x0010: return "WM_CLOSE"; 
4592         case 0x0011: return "WM_QUERYENDSESSION"; 
4593         case 0x0012: return "WM_QUIT"; 
4594         case 0x0013: return "WM_QUERYOPEN"; 
4595         case 0x0014: return "WM_ERASEBKGND"; 
4596         case 0x0015: return "WM_SYSCOLORCHANGE"; 
4597         case 0x0016: return "WM_ENDSESSION"; 
4598         case 0x0017: return "WM_SYSTEMERROR"; 
4599         case 0x0018: return "WM_SHOWWINDOW"; 
4600         case 0x0019: return "WM_CTLCOLOR"; 
4601         case 0x001A: return "WM_WININICHANGE"; 
4602         case 0x001B: return "WM_DEVMODECHANGE"; 
4603         case 0x001C: return "WM_ACTIVATEAPP"; 
4604         case 0x001D: return "WM_FONTCHANGE"; 
4605         case 0x001E: return "WM_TIMECHANGE"; 
4606         case 0x001F: return "WM_CANCELMODE"; 
4607         case 0x0020: return "WM_SETCURSOR"; 
4608         case 0x0021: return "WM_MOUSEACTIVATE"; 
4609         case 0x0022: return "WM_CHILDACTIVATE"; 
4610         case 0x0023: return "WM_QUEUESYNC"; 
4611         case 0x0024: return "WM_GETMINMAXINFO"; 
4612         case 0x0026: return "WM_PAINTICON"; 
4613         case 0x0027: return "WM_ICONERASEBKGND"; 
4614         case 0x0028: return "WM_NEXTDLGCTL"; 
4615         case 0x002A: return "WM_SPOOLERSTATUS"; 
4616         case 0x002B: return "WM_DRAWITEM"; 
4617         case 0x002C: return "WM_MEASUREITEM"; 
4618         case 0x002D: return "WM_DELETEITEM"; 
4619         case 0x002E: return "WM_VKEYTOITEM"; 
4620         case 0x002F: return "WM_CHARTOITEM"; 
4621         case 0x0030: return "WM_SETFONT"; 
4622         case 0x0031: return "WM_GETFONT"; 
4623         case 0x0037: return "WM_QUERYDRAGICON"; 
4624         case 0x0039: return "WM_COMPAREITEM"; 
4625         case 0x0041: return "WM_COMPACTING"; 
4626         case 0x0044: return "WM_COMMNOTIFY"; 
4627         case 0x0046: return "WM_WINDOWPOSCHANGING"; 
4628         case 0x0047: return "WM_WINDOWPOSCHANGED"; 
4629         case 0x0048: return "WM_POWER"; 
4632         case 0x004A: return "WM_COPYDATA"; 
4633         case 0x004B: return "WM_CANCELJOURNAL"; 
4634         case 0x004E: return "WM_NOTIFY"; 
4635         case 0x0050: return "WM_INPUTLANGCHANGEREQUEST"; 
4636         case 0x0051: return "WM_INPUTLANGCHANGE"; 
4637         case 0x0052: return "WM_TCARD"; 
4638         case 0x0053: return "WM_HELP"; 
4639         case 0x0054: return "WM_USERCHANGED"; 
4640         case 0x0055: return "WM_NOTIFYFORMAT"; 
4641         case 0x007B: return "WM_CONTEXTMENU"; 
4642         case 0x007C: return "WM_STYLECHANGING"; 
4643         case 0x007D: return "WM_STYLECHANGED"; 
4644         case 0x007E: return "WM_DISPLAYCHANGE"; 
4645         case 0x007F: return "WM_GETICON"; 
4646         case 0x0080: return "WM_SETICON"; 
4649         case 0x0081: return "WM_NCCREATE"; 
4650         case 0x0082: return "WM_NCDESTROY"; 
4651         case 0x0083: return "WM_NCCALCSIZE"; 
4652         case 0x0084: return "WM_NCHITTEST"; 
4653         case 0x0085: return "WM_NCPAINT"; 
4654         case 0x0086: return "WM_NCACTIVATE"; 
4655         case 0x0087: return "WM_GETDLGCODE"; 
4656         case 0x00A0: return "WM_NCMOUSEMOVE"; 
4657         case 0x00A1: return "WM_NCLBUTTONDOWN"; 
4658         case 0x00A2: return "WM_NCLBUTTONUP"; 
4659         case 0x00A3: return "WM_NCLBUTTONDBLCLK"; 
4660         case 0x00A4: return "WM_NCRBUTTONDOWN"; 
4661         case 0x00A5: return "WM_NCRBUTTONUP"; 
4662         case 0x00A6: return "WM_NCRBUTTONDBLCLK"; 
4663         case 0x00A7: return "WM_NCMBUTTONDOWN"; 
4664         case 0x00A8: return "WM_NCMBUTTONUP"; 
4665         case 0x00A9: return "WM_NCMBUTTONDBLCLK"; 
4666         case 0x0100: return "WM_KEYDOWN"; 
4667         case 0x0101: return "WM_KEYUP"; 
4668         case 0x0102: return "WM_CHAR"; 
4669         case 0x0103: return "WM_DEADCHAR"; 
4670         case 0x0104: return "WM_SYSKEYDOWN"; 
4671         case 0x0105: return "WM_SYSKEYUP"; 
4672         case 0x0106: return "WM_SYSCHAR"; 
4673         case 0x0107: return "WM_SYSDEADCHAR"; 
4674         case 0x0108: return "WM_KEYLAST"; 
4677         case 0x010D: return "WM_IME_STARTCOMPOSITION"; 
4678         case 0x010E: return "WM_IME_ENDCOMPOSITION"; 
4679         case 0x010F: return "WM_IME_COMPOSITION"; 
4682         case 0x0110: return "WM_INITDIALOG"; 
4683         case 0x0111: return "WM_COMMAND"; 
4684         case 0x0112: return "WM_SYSCOMMAND"; 
4685         case 0x0113: return "WM_TIMER"; 
4686         case 0x0114: return "WM_HSCROLL"; 
4687         case 0x0115: return "WM_VSCROLL"; 
4688         case 0x0116: return "WM_INITMENU"; 
4689         case 0x0117: return "WM_INITMENUPOPUP"; 
4690         case 0x011F: return "WM_MENUSELECT"; 
4691         case 0x0120: return "WM_MENUCHAR"; 
4692         case 0x0121: return "WM_ENTERIDLE"; 
4693         case 0x0200: return "WM_MOUSEMOVE"; 
4694         case 0x0201: return "WM_LBUTTONDOWN"; 
4695         case 0x0202: return "WM_LBUTTONUP"; 
4696         case 0x0203: return "WM_LBUTTONDBLCLK"; 
4697         case 0x0204: return "WM_RBUTTONDOWN"; 
4698         case 0x0205: return "WM_RBUTTONUP"; 
4699         case 0x0206: return "WM_RBUTTONDBLCLK"; 
4700         case 0x0207: return "WM_MBUTTONDOWN"; 
4701         case 0x0208: return "WM_MBUTTONUP"; 
4702         case 0x0209: return "WM_MBUTTONDBLCLK"; 
4703         case 0x020A: return "WM_MOUSEWHEEL"; 
4704         case 0x0210: return "WM_PARENTNOTIFY"; 
4705         case 0x0211: return "WM_ENTERMENULOOP"; 
4706         case 0x0212: return "WM_EXITMENULOOP"; 
4709         case 0x0213: return "WM_NEXTMENU"; 
4710         case 0x0214: return "WM_SIZING"; 
4711         case 0x0215: return "WM_CAPTURECHANGED"; 
4712         case 0x0216: return "WM_MOVING"; 
4713         case 0x0218: return "WM_POWERBROADCAST"; 
4714         case 0x0219: return "WM_DEVICECHANGE"; 
4717         case 0x0220: return "WM_MDICREATE"; 
4718         case 0x0221: return "WM_MDIDESTROY"; 
4719         case 0x0222: return "WM_MDIACTIVATE"; 
4720         case 0x0223: return "WM_MDIRESTORE"; 
4721         case 0x0224: return "WM_MDINEXT"; 
4722         case 0x0225: return "WM_MDIMAXIMIZE"; 
4723         case 0x0226: return "WM_MDITILE"; 
4724         case 0x0227: return "WM_MDICASCADE"; 
4725         case 0x0228: return "WM_MDIICONARRANGE"; 
4726         case 0x0229: return "WM_MDIGETACTIVE"; 
4727         case 0x0230: return "WM_MDISETMENU"; 
4728         case 0x0233: return "WM_DROPFILES"; 
4731         case 0x0281: return "WM_IME_SETCONTEXT"; 
4732         case 0x0282: return "WM_IME_NOTIFY"; 
4733         case 0x0283: return "WM_IME_CONTROL"; 
4734         case 0x0284: return "WM_IME_COMPOSITIONFULL"; 
4735         case 0x0285: return "WM_IME_SELECT"; 
4736         case 0x0286: return "WM_IME_CHAR"; 
4737         case 0x0290: return "WM_IME_KEYDOWN"; 
4738         case 0x0291: return "WM_IME_KEYUP"; 
4741         case 0x0300: return "WM_CUT"; 
4742         case 0x0301: return "WM_COPY"; 
4743         case 0x0302: return "WM_PASTE"; 
4744         case 0x0303: return "WM_CLEAR"; 
4745         case 0x0304: return "WM_UNDO"; 
4746         case 0x0305: return "WM_RENDERFORMAT"; 
4747         case 0x0306: return "WM_RENDERALLFORMATS"; 
4748         case 0x0307: return "WM_DESTROYCLIPBOARD"; 
4749         case 0x0308: return "WM_DRAWCLIPBOARD"; 
4750         case 0x0309: return "WM_PAINTCLIPBOARD"; 
4751         case 0x030A: return "WM_VSCROLLCLIPBOARD"; 
4752         case 0x030B: return "WM_SIZECLIPBOARD"; 
4753         case 0x030C: return "WM_ASKCBFORMATNAME"; 
4754         case 0x030D: return "WM_CHANGECBCHAIN"; 
4755         case 0x030E: return "WM_HSCROLLCLIPBOARD"; 
4756         case 0x030F: return "WM_QUERYNEWPALETTE"; 
4757         case 0x0310: return "WM_PALETTEISCHANGING"; 
4758         case 0x0311: return "WM_PALETTECHANGED"; 
4761         // common controls messages - although they're not strictly speaking 
4762         // standard, it's nice to decode them nevertheless 
4765         case 0x1000 + 0: return "LVM_GETBKCOLOR"; 
4766         case 0x1000 + 1: return "LVM_SETBKCOLOR"; 
4767         case 0x1000 + 2: return "LVM_GETIMAGELIST"; 
4768         case 0x1000 + 3: return "LVM_SETIMAGELIST"; 
4769         case 0x1000 + 4: return "LVM_GETITEMCOUNT"; 
4770         case 0x1000 + 5: return "LVM_GETITEMA"; 
4771         case 0x1000 + 75: return "LVM_GETITEMW"; 
4772         case 0x1000 + 6: return "LVM_SETITEMA"; 
4773         case 0x1000 + 76: return "LVM_SETITEMW"; 
4774         case 0x1000 + 7: return "LVM_INSERTITEMA"; 
4775         case 0x1000 + 77: return "LVM_INSERTITEMW"; 
4776         case 0x1000 + 8: return "LVM_DELETEITEM"; 
4777         case 0x1000 + 9: return "LVM_DELETEALLITEMS"; 
4778         case 0x1000 + 10: return "LVM_GETCALLBACKMASK"; 
4779         case 0x1000 + 11: return "LVM_SETCALLBACKMASK"; 
4780         case 0x1000 + 12: return "LVM_GETNEXTITEM"; 
4781         case 0x1000 + 13: return "LVM_FINDITEMA"; 
4782         case 0x1000 + 83: return "LVM_FINDITEMW"; 
4783         case 0x1000 + 14: return "LVM_GETITEMRECT"; 
4784         case 0x1000 + 15: return "LVM_SETITEMPOSITION"; 
4785         case 0x1000 + 16: return "LVM_GETITEMPOSITION"; 
4786         case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA"; 
4787         case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW"; 
4788         case 0x1000 + 18: return "LVM_HITTEST"; 
4789         case 0x1000 + 19: return "LVM_ENSUREVISIBLE"; 
4790         case 0x1000 + 20: return "LVM_SCROLL"; 
4791         case 0x1000 + 21: return "LVM_REDRAWITEMS"; 
4792         case 0x1000 + 22: return "LVM_ARRANGE"; 
4793         case 0x1000 + 23: return "LVM_EDITLABELA"; 
4794         case 0x1000 + 118: return "LVM_EDITLABELW"; 
4795         case 0x1000 + 24: return "LVM_GETEDITCONTROL"; 
4796         case 0x1000 + 25: return "LVM_GETCOLUMNA"; 
4797         case 0x1000 + 95: return "LVM_GETCOLUMNW"; 
4798         case 0x1000 + 26: return "LVM_SETCOLUMNA"; 
4799         case 0x1000 + 96: return "LVM_SETCOLUMNW"; 
4800         case 0x1000 + 27: return "LVM_INSERTCOLUMNA"; 
4801         case 0x1000 + 97: return "LVM_INSERTCOLUMNW"; 
4802         case 0x1000 + 28: return "LVM_DELETECOLUMN"; 
4803         case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH"; 
4804         case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH"; 
4805         case 0x1000 + 31: return "LVM_GETHEADER"; 
4806         case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE"; 
4807         case 0x1000 + 34: return "LVM_GETVIEWRECT"; 
4808         case 0x1000 + 35: return "LVM_GETTEXTCOLOR"; 
4809         case 0x1000 + 36: return "LVM_SETTEXTCOLOR"; 
4810         case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR"; 
4811         case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR"; 
4812         case 0x1000 + 39: return "LVM_GETTOPINDEX"; 
4813         case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE"; 
4814         case 0x1000 + 41: return "LVM_GETORIGIN"; 
4815         case 0x1000 + 42: return "LVM_UPDATE"; 
4816         case 0x1000 + 43: return "LVM_SETITEMSTATE"; 
4817         case 0x1000 + 44: return "LVM_GETITEMSTATE"; 
4818         case 0x1000 + 45: return "LVM_GETITEMTEXTA"; 
4819         case 0x1000 + 115: return "LVM_GETITEMTEXTW"; 
4820         case 0x1000 + 46: return "LVM_SETITEMTEXTA"; 
4821         case 0x1000 + 116: return "LVM_SETITEMTEXTW"; 
4822         case 0x1000 + 47: return "LVM_SETITEMCOUNT"; 
4823         case 0x1000 + 48: return "LVM_SORTITEMS"; 
4824         case 0x1000 + 49: return "LVM_SETITEMPOSITION32"; 
4825         case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT"; 
4826         case 0x1000 + 51: return "LVM_GETITEMSPACING"; 
4827         case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA"; 
4828         case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW"; 
4829         case 0x1000 + 53: return "LVM_SETICONSPACING"; 
4830         case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE"; 
4831         case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE"; 
4832         case 0x1000 + 56: return "LVM_GETSUBITEMRECT"; 
4833         case 0x1000 + 57: return "LVM_SUBITEMHITTEST"; 
4834         case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY"; 
4835         case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY"; 
4836         case 0x1000 + 60: return "LVM_SETHOTITEM"; 
4837         case 0x1000 + 61: return "LVM_GETHOTITEM"; 
4838         case 0x1000 + 62: return "LVM_SETHOTCURSOR"; 
4839         case 0x1000 + 63: return "LVM_GETHOTCURSOR"; 
4840         case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT"; 
4841         case 0x1000 + 65: return "LVM_SETWORKAREA"; 
4844         case 0x1100 + 0: return "TVM_INSERTITEMA"; 
4845         case 0x1100 + 50: return "TVM_INSERTITEMW"; 
4846         case 0x1100 + 1: return "TVM_DELETEITEM"; 
4847         case 0x1100 + 2: return "TVM_EXPAND"; 
4848         case 0x1100 + 4: return "TVM_GETITEMRECT"; 
4849         case 0x1100 + 5: return "TVM_GETCOUNT"; 
4850         case 0x1100 + 6: return "TVM_GETINDENT"; 
4851         case 0x1100 + 7: return "TVM_SETINDENT"; 
4852         case 0x1100 + 8: return "TVM_GETIMAGELIST"; 
4853         case 0x1100 + 9: return "TVM_SETIMAGELIST"; 
4854         case 0x1100 + 10: return "TVM_GETNEXTITEM"; 
4855         case 0x1100 + 11: return "TVM_SELECTITEM"; 
4856         case 0x1100 + 12: return "TVM_GETITEMA"; 
4857         case 0x1100 + 62: return "TVM_GETITEMW"; 
4858         case 0x1100 + 13: return "TVM_SETITEMA"; 
4859         case 0x1100 + 63: return "TVM_SETITEMW"; 
4860         case 0x1100 + 14: return "TVM_EDITLABELA"; 
4861         case 0x1100 + 65: return "TVM_EDITLABELW"; 
4862         case 0x1100 + 15: return "TVM_GETEDITCONTROL"; 
4863         case 0x1100 + 16: return "TVM_GETVISIBLECOUNT"; 
4864         case 0x1100 + 17: return "TVM_HITTEST"; 
4865         case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE"; 
4866         case 0x1100 + 19: return "TVM_SORTCHILDREN"; 
4867         case 0x1100 + 20: return "TVM_ENSUREVISIBLE"; 
4868         case 0x1100 + 21: return "TVM_SORTCHILDRENCB"; 
4869         case 0x1100 + 22: return "TVM_ENDEDITLABELNOW"; 
4870         case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA"; 
4871         case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW"; 
4872         case 0x1100 + 24: return "TVM_SETTOOLTIPS"; 
4873         case 0x1100 + 25: return "TVM_GETTOOLTIPS"; 
4876         case 0x1200 + 0: return "HDM_GETITEMCOUNT"; 
4877         case 0x1200 + 1: return "HDM_INSERTITEMA"; 
4878         case 0x1200 + 10: return "HDM_INSERTITEMW"; 
4879         case 0x1200 + 2: return "HDM_DELETEITEM"; 
4880         case 0x1200 + 3: return "HDM_GETITEMA"; 
4881         case 0x1200 + 11: return "HDM_GETITEMW"; 
4882         case 0x1200 + 4: return "HDM_SETITEMA"; 
4883         case 0x1200 + 12: return "HDM_SETITEMW"; 
4884         case 0x1200 + 5: return "HDM_LAYOUT"; 
4885         case 0x1200 + 6: return "HDM_HITTEST"; 
4886         case 0x1200 + 7: return "HDM_GETITEMRECT"; 
4887         case 0x1200 + 8: return "HDM_SETIMAGELIST"; 
4888         case 0x1200 + 9: return "HDM_GETIMAGELIST"; 
4889         case 0x1200 + 15: return "HDM_ORDERTOINDEX"; 
4890         case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE"; 
4891         case 0x1200 + 17: return "HDM_GETORDERARRAY"; 
4892         case 0x1200 + 18: return "HDM_SETORDERARRAY"; 
4893         case 0x1200 + 19: return "HDM_SETHOTDIVIDER"; 
4896         case 0x1300 + 2: return "TCM_GETIMAGELIST"; 
4897         case 0x1300 + 3: return "TCM_SETIMAGELIST"; 
4898         case 0x1300 + 4: return "TCM_GETITEMCOUNT"; 
4899         case 0x1300 + 5: return "TCM_GETITEMA"; 
4900         case 0x1300 + 60: return "TCM_GETITEMW"; 
4901         case 0x1300 + 6: return "TCM_SETITEMA"; 
4902         case 0x1300 + 61: return "TCM_SETITEMW"; 
4903         case 0x1300 + 7: return "TCM_INSERTITEMA"; 
4904         case 0x1300 + 62: return "TCM_INSERTITEMW"; 
4905         case 0x1300 + 8: return "TCM_DELETEITEM"; 
4906         case 0x1300 + 9: return "TCM_DELETEALLITEMS"; 
4907         case 0x1300 + 10: return "TCM_GETITEMRECT"; 
4908         case 0x1300 + 11: return "TCM_GETCURSEL"; 
4909         case 0x1300 + 12: return "TCM_SETCURSEL"; 
4910         case 0x1300 + 13: return "TCM_HITTEST"; 
4911         case 0x1300 + 14: return "TCM_SETITEMEXTRA"; 
4912         case 0x1300 + 40: return "TCM_ADJUSTRECT"; 
4913         case 0x1300 + 41: return "TCM_SETITEMSIZE"; 
4914         case 0x1300 + 42: return "TCM_REMOVEIMAGE"; 
4915         case 0x1300 + 43: return "TCM_SETPADDING"; 
4916         case 0x1300 + 44: return "TCM_GETROWCOUNT"; 
4917         case 0x1300 + 45: return "TCM_GETTOOLTIPS"; 
4918         case 0x1300 + 46: return "TCM_SETTOOLTIPS"; 
4919         case 0x1300 + 47: return "TCM_GETCURFOCUS"; 
4920         case 0x1300 + 48: return "TCM_SETCURFOCUS"; 
4921         case 0x1300 + 49: return "TCM_SETMINTABWIDTH"; 
4922         case 0x1300 + 50: return "TCM_DESELECTALL"; 
4925         case WM_USER
+1: return "TB_ENABLEBUTTON"; 
4926         case WM_USER
+2: return "TB_CHECKBUTTON"; 
4927         case WM_USER
+3: return "TB_PRESSBUTTON"; 
4928         case WM_USER
+4: return "TB_HIDEBUTTON"; 
4929         case WM_USER
+5: return "TB_INDETERMINATE"; 
4930         case WM_USER
+9: return "TB_ISBUTTONENABLED"; 
4931         case WM_USER
+10: return "TB_ISBUTTONCHECKED"; 
4932         case WM_USER
+11: return "TB_ISBUTTONPRESSED"; 
4933         case WM_USER
+12: return "TB_ISBUTTONHIDDEN"; 
4934         case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE"; 
4935         case WM_USER
+17: return "TB_SETSTATE"; 
4936         case WM_USER
+18: return "TB_GETSTATE"; 
4937         case WM_USER
+19: return "TB_ADDBITMAP"; 
4938         case WM_USER
+20: return "TB_ADDBUTTONS"; 
4939         case WM_USER
+21: return "TB_INSERTBUTTON"; 
4940         case WM_USER
+22: return "TB_DELETEBUTTON"; 
4941         case WM_USER
+23: return "TB_GETBUTTON"; 
4942         case WM_USER
+24: return "TB_BUTTONCOUNT"; 
4943         case WM_USER
+25: return "TB_COMMANDTOINDEX"; 
4944         case WM_USER
+26: return "TB_SAVERESTOREA"; 
4945         case WM_USER
+76: return "TB_SAVERESTOREW"; 
4946         case WM_USER
+27: return "TB_CUSTOMIZE"; 
4947         case WM_USER
+28: return "TB_ADDSTRINGA"; 
4948         case WM_USER
+77: return "TB_ADDSTRINGW"; 
4949         case WM_USER
+29: return "TB_GETITEMRECT"; 
4950         case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE"; 
4951         case WM_USER
+31: return "TB_SETBUTTONSIZE"; 
4952         case WM_USER
+32: return "TB_SETBITMAPSIZE"; 
4953         case WM_USER
+33: return "TB_AUTOSIZE"; 
4954         case WM_USER
+35: return "TB_GETTOOLTIPS"; 
4955         case WM_USER
+36: return "TB_SETTOOLTIPS"; 
4956         case WM_USER
+37: return "TB_SETPARENT"; 
4957         case WM_USER
+39: return "TB_SETROWS"; 
4958         case WM_USER
+40: return "TB_GETROWS"; 
4959         case WM_USER
+42: return "TB_SETCMDID"; 
4960         case WM_USER
+43: return "TB_CHANGEBITMAP"; 
4961         case WM_USER
+44: return "TB_GETBITMAP"; 
4962         case WM_USER
+45: return "TB_GETBUTTONTEXTA"; 
4963         case WM_USER
+75: return "TB_GETBUTTONTEXTW"; 
4964         case WM_USER
+46: return "TB_REPLACEBITMAP"; 
4965         case WM_USER
+47: return "TB_SETINDENT"; 
4966         case WM_USER
+48: return "TB_SETIMAGELIST"; 
4967         case WM_USER
+49: return "TB_GETIMAGELIST"; 
4968         case WM_USER
+50: return "TB_LOADIMAGES"; 
4969         case WM_USER
+51: return "TB_GETRECT"; 
4970         case WM_USER
+52: return "TB_SETHOTIMAGELIST"; 
4971         case WM_USER
+53: return "TB_GETHOTIMAGELIST"; 
4972         case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST"; 
4973         case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST"; 
4974         case WM_USER
+56: return "TB_SETSTYLE"; 
4975         case WM_USER
+57: return "TB_GETSTYLE"; 
4976         case WM_USER
+58: return "TB_GETBUTTONSIZE"; 
4977         case WM_USER
+59: return "TB_SETBUTTONWIDTH"; 
4978         case WM_USER
+60: return "TB_SETMAXTEXTROWS"; 
4979         case WM_USER
+61: return "TB_GETTEXTROWS"; 
4980         case WM_USER
+41: return "TB_GETBITMAPFLAGS"; 
4985             static char s_szBuf
[128]; 
4986             sprintf(s_szBuf
, "<unknown message = %d>", message
); 
4990 #endif //__WXDEBUG__ 
4992 static void TranslateKbdEventToMouse(wxWindowMSW 
*win
, 
4993                                      int *x
, int *y
, WPARAM 
*flags
) 
4995     // construct the key mask 
4996     WPARAM
& fwKeys 
= *flags
; 
4998     fwKeys 
= MK_RBUTTON
; 
4999     if ( wxIsCtrlDown() ) 
5000         fwKeys 
|= MK_CONTROL
; 
5001     if ( wxIsShiftDown() ) 
5004     // simulate right mouse button click 
5005     DWORD dwPos 
= ::GetMessagePos(); 
5006     *x 
= GET_X_LPARAM(dwPos
); 
5007     *y 
= GET_Y_LPARAM(dwPos
); 
5009     win
->ScreenToClient(x
, y
); 
5012 static TEXTMETRIC 
wxGetTextMetrics(const wxWindowMSW 
*win
) 
5016     HWND hwnd 
= GetHwndOf(win
); 
5017     HDC hdc 
= ::GetDC(hwnd
); 
5019 #if !wxDIALOG_UNIT_COMPATIBILITY 
5020     // and select the current font into it 
5021     HFONT hfont 
= GetHfontOf(win
->GetFont()); 
5024         hfont 
= (HFONT
)::SelectObject(hdc
, hfont
); 
5028     // finally retrieve the text metrics from it 
5029     GetTextMetrics(hdc
, &tm
); 
5031 #if !wxDIALOG_UNIT_COMPATIBILITY 
5035         (void)::SelectObject(hdc
, hfont
); 
5039     ::ReleaseDC(hwnd
, hdc
); 
5044 // Find the wxWindow at the current mouse position, returning the mouse 
5046 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
)) 
5048     return wxFindWindowAtPoint(wxGetMousePosition()); 
5051 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
5056     HWND hWndHit 
= ::WindowFromPoint(pt2
); 
5058     wxWindow
* win 
= wxFindWinFromHandle((WXHWND
) hWndHit
) ; 
5059     HWND hWnd 
= hWndHit
; 
5061     // Try to find a window with a wxWindow associated with it 
5062     while (!win 
&& (hWnd 
!= 0)) 
5064         hWnd 
= ::GetParent(hWnd
); 
5065         win 
= wxFindWinFromHandle((WXHWND
) hWnd
) ; 
5070 // Get the current mouse position. 
5071 wxPoint 
wxGetMousePosition() 
5074     GetCursorPos( & pt 
); 
5075     return wxPoint(pt
.x
, pt
.y
);