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"
42 #include "wx/layout.h"
43 #include "wx/dialog.h"
45 #include "wx/listbox.h"
46 #include "wx/button.h"
47 #include "wx/msgdlg.h"
48 #include "wx/settings.h"
49 #include "wx/statbox.h"
53 #include "wx/ownerdrw.h"
56 #if wxUSE_DRAG_AND_DROP
60 #include "wx/menuitem.h"
63 #include "wx/msw/private.h"
66 #include "wx/tooltip.h"
74 #include "wx/spinctrl.h"
75 #endif // wxUSE_SPINCTRL
80 #include "wx/textctrl.h"
81 #include "wx/notebook.h"
85 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
94 #if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
98 #elif !defined(__WXMICROWIN__) // broken compiler
100 #include "wx/msw/gnuwin32/extra.h"
104 // This didn't appear in mingw until 2.95.2
106 #define SIF_TRACKPOS 16
110 #ifndef WM_MOUSEWHEEL
111 #define WM_MOUSEWHEEL 0x020A
114 #define WHEEL_DELTA 120
116 #ifndef SPI_GETWHEELSCROLLLINES
117 #define SPI_GETWHEELSCROLLLINES 104
121 // ---------------------------------------------------------------------------
123 // ---------------------------------------------------------------------------
125 // the last Windows message we got (MT-UNSAFE)
126 extern MSG s_currentMsg
;
128 #if wxUSE_MENUS_NATIVE
129 wxMenu
*wxCurrentPopupMenu
= NULL
;
130 #endif // wxUSE_MENUS_NATIVE
132 extern const wxChar
*wxCanvasClassName
;
134 // ---------------------------------------------------------------------------
136 // ---------------------------------------------------------------------------
138 // the window proc for all our windows
139 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
140 WPARAM wParam
, LPARAM lParam
);
143 const char *wxGetMessageName(int message
);
146 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
147 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
148 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
150 // this magical function is used to translate VK_APPS key presses to right
152 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
153 int *x
, int *y
, WPARAM
*flags
);
155 // get the text metrics for the current font
156 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
158 // wrapper around BringWindowToTop() API
159 static inline void wxBringWindowToTop(HWND hwnd
)
161 #ifdef __WXMICROWIN__
162 // It seems that MicroWindows brings the _parent_ of the window to the top,
163 // which can be the wrong one.
165 // activate (set focus to) specified window
168 // raise top level parent to top of z order
169 ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
170 #else // !__WXMICROWIN__
171 if ( !::BringWindowToTop(hwnd
) )
173 wxLogLastError(_T("BringWindowToTop"));
175 #endif // __WXMICROWIN__/!__WXMICROWIN__
178 // ---------------------------------------------------------------------------
180 // ---------------------------------------------------------------------------
182 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
184 #ifdef __WXUNIVERSAL__
185 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
187 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
188 #endif // __WXUNIVERSAL__/__WXMSW__
190 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
191 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
192 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
193 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
194 EVT_IDLE(wxWindowMSW::OnIdle
)
197 // ===========================================================================
199 // ===========================================================================
201 // ---------------------------------------------------------------------------
202 // wxWindow utility functions
203 // ---------------------------------------------------------------------------
205 // Find an item given the MS Windows id
206 wxWindow
*wxWindowMSW::FindItem(long id
) const
209 wxControl
*item
= wxDynamicCastThis(wxControl
);
212 // is it we or one of our "internal" children?
213 if ( item
->GetId() == id
214 #ifndef __WXUNIVERSAL__
215 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
216 #endif // __WXUNIVERSAL__
222 #endif // wxUSE_CONTROLS
224 wxWindowList::Node
*current
= GetChildren().GetFirst();
227 wxWindow
*childWin
= current
->GetData();
229 wxWindow
*wnd
= childWin
->FindItem(id
);
233 current
= current
->GetNext();
239 // Find an item given the MS Windows handle
240 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
242 wxWindowList::Node
*current
= GetChildren().GetFirst();
245 wxWindow
*parent
= current
->GetData();
247 // Do a recursive search.
248 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
254 || parent
->IsKindOf(CLASSINFO(wxControl
))
255 #endif // wxUSE_CONTROLS
258 wxWindow
*item
= current
->GetData();
259 if ( item
->GetHWND() == hWnd
)
263 if ( item
->ContainsHWND(hWnd
) )
268 current
= current
->GetNext();
273 // Default command handler
274 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
279 // ----------------------------------------------------------------------------
280 // constructors and such
281 // ----------------------------------------------------------------------------
283 void wxWindowMSW::Init()
289 m_doubleClickAllowed
= 0;
291 m_isBeingDeleted
= FALSE
;
294 m_mouseInWindow
= FALSE
;
301 // pass WM_GETDLGCODE to DefWindowProc()
306 m_backgroundTransparent
= FALSE
;
308 // as all windows are created with WS_VISIBLE style...
311 #if wxUSE_MOUSEEVENT_HACK
314 m_lastMouseEvent
= -1;
315 #endif // wxUSE_MOUSEEVENT_HACK
319 wxWindowMSW::~wxWindowMSW()
321 m_isBeingDeleted
= TRUE
;
323 #ifndef __WXUNIVERSAL__
324 // VS: make sure there's no wxFrame with last focus set to us:
325 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
327 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
330 if ( frame
->GetLastFocus() == this )
332 frame
->SetLastFocus((wxWindow
*)NULL
);
337 #endif // __WXUNIVERSAL__
339 // VS: destroy children first and _then_ detach *this from its parent.
340 // If we'd do it the other way around, children wouldn't be able
341 // find their parent frame (see above).
345 m_parent
->RemoveChild(this);
349 // VZ: test temp removed to understand what really happens here
350 //if (::IsWindow(GetHwnd()))
352 if ( !::DestroyWindow(GetHwnd()) )
353 wxLogLastError(wxT("DestroyWindow"));
356 // remove hWnd <-> wxWindow association
357 wxRemoveHandleAssociation(this);
361 // real construction (Init() must have been called before!)
362 bool wxWindowMSW::Create(wxWindow
*parent
,
367 const wxString
& name
)
369 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
372 // wxGTK doesn't allow to create controls with static box as the parent so
373 // this will result in a crash when the program is ported to wxGTK - warn
376 // the correct solution is to create the controls as siblings of the
378 wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
),
379 _T("wxStaticBox can't be used as a window parent!") );
380 #endif // wxUSE_STATBOX
382 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
385 parent
->AddChild(this);
387 // all windows are created visible
388 DWORD msflags
= WS_CHILD
| WS_VISIBLE
;
390 #ifdef __WXUNIVERSAL__
391 // no 3d effects, we draw them ourselves
393 #else // !wxUniversal
394 if ( style
& wxCLIP_CHILDREN
)
395 msflags
|= WS_CLIPCHILDREN
;
396 if ( style
& wxCLIP_SIBLINGS
)
397 msflags
|= WS_CLIPSIBLINGS
;
400 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
);
402 // Even with extended styles, need to combine with WS_BORDER
403 // for them to look right.
405 (m_windowStyle
& (wxBORDER
|
411 msflags
|= WS_BORDER
;
414 // calculate the value to return from WM_GETDLGCODE handler
415 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
417 // want everything: i.e. all keys and WM_CHAR message
418 m_lDlgCode
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
419 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
421 #endif // wxUniversal/!wxUniversal
423 if ( style
& wxPOPUP_WINDOW
)
425 // a popup window floats on top of everything
426 exStyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
428 // it is also created hidden as other top level windows
429 msflags
&= ~WS_VISIBLE
;
433 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
);
436 // ---------------------------------------------------------------------------
438 // ---------------------------------------------------------------------------
440 void wxWindowMSW::SetFocus()
442 HWND hWnd
= GetHwnd();
443 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
445 #ifndef __WXMICROWIN__
449 if ( !::SetFocus(hWnd
) )
451 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
452 // was there really an error?
453 DWORD dwRes
= ::GetLastError();
456 HWND hwndFocus
= ::GetFocus();
457 if ( hwndFocus
!= hWnd
)
459 wxLogApiError(_T("SetFocus"), dwRes
);
466 // Get the window with the focus
467 wxWindow
*wxWindowBase::FindFocus()
469 HWND hWnd
= ::GetFocus();
472 return wxGetWindowFromHWND((WXHWND
)hWnd
);
478 bool wxWindowMSW::Enable(bool enable
)
480 if ( !wxWindowBase::Enable(enable
) )
483 HWND hWnd
= GetHwnd();
485 ::EnableWindow(hWnd
, (BOOL
)enable
);
487 // VZ: no, this is a bad idea: imagine that you have a dialog with some
488 // disabled controls and disable it - you really wouldn't like the
489 // disabled controls be reenabled too when you reenable the dialog!
491 wxWindowList::Node
*node
= GetChildren().GetFirst();
494 wxWindow
*child
= node
->GetData();
495 child
->Enable(enable
);
497 node
= node
->GetNext();
504 bool wxWindowMSW::Show(bool show
)
506 if ( !wxWindowBase::Show(show
) )
509 HWND hWnd
= GetHwnd();
510 int cshow
= show
? SW_SHOW
: SW_HIDE
;
511 ::ShowWindow(hWnd
, cshow
);
515 wxBringWindowToTop(hWnd
);
521 // Raise the window to the top of the Z order
522 void wxWindowMSW::Raise()
524 wxBringWindowToTop(GetHwnd());
527 // Lower the window to the bottom of the Z order
528 void wxWindowMSW::Lower()
530 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
531 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
534 void wxWindowMSW::SetTitle( const wxString
& title
)
536 SetWindowText(GetHwnd(), title
.c_str());
539 wxString
wxWindowMSW::GetTitle() const
541 return wxGetWindowText(GetHWND());
544 void wxWindowMSW::CaptureMouse()
546 HWND hWnd
= GetHwnd();
553 void wxWindowMSW::ReleaseMouse()
555 if ( !::ReleaseCapture() )
557 wxLogLastError(_T("ReleaseCapture"));
561 /* static */ wxWindow
*wxWindowBase::GetCapture()
563 HWND hwnd
= ::GetCapture();
564 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
567 bool wxWindowMSW::SetFont(const wxFont
& font
)
569 if ( !wxWindowBase::SetFont(font
) )
575 HWND hWnd
= GetHwnd();
578 WXHANDLE hFont
= m_font
.GetResourceHandle();
580 wxASSERT_MSG( hFont
, wxT("should have valid font") );
582 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
587 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
589 if ( !wxWindowBase::SetCursor(cursor
) )
597 HWND hWnd
= GetHwnd();
599 // Change the cursor NOW if we're within the correct window
601 ::GetCursorPos(&point
);
603 RECT rect
= wxGetWindowRect(hWnd
);
605 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
606 ::SetCursor(GetHcursorOf(m_cursor
));
612 void wxWindowMSW::WarpPointer (int x
, int y
)
614 ClientToScreen(&x
, &y
);
616 if ( !::SetCursorPos(x
, y
) )
618 wxLogLastError(_T("SetCursorPos"));
622 #if WXWIN_COMPATIBILITY
623 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
626 #endif // WXWIN_COMPATIBILITY
628 // ---------------------------------------------------------------------------
630 // ---------------------------------------------------------------------------
632 #if WXWIN_COMPATIBILITY
633 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
635 #if defined(__WIN95__)
639 // Try to adjust the range to cope with page size > 1
640 // - a Windows API quirk
641 int pageSize
= GetScrollPage(orient
);
642 if ( pageSize
> 1 && range
> 0)
644 range1
+= (pageSize
- 1);
650 if ( orient
== wxHORIZONTAL
) {
656 info
.cbSize
= sizeof(SCROLLINFO
);
657 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
661 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
663 HWND hWnd
= GetHwnd();
665 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
668 if ( orient
== wxHORIZONTAL
)
673 HWND hWnd
= GetHwnd();
675 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
679 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
681 #if defined(__WIN95__)
685 if ( orient
== wxHORIZONTAL
) {
693 info
.cbSize
= sizeof(SCROLLINFO
);
696 info
.fMask
= SIF_PAGE
;
698 HWND hWnd
= GetHwnd();
700 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
702 if ( orient
== wxHORIZONTAL
)
709 int wxWindowMSW::OldGetScrollRange(int orient
) const
712 if ( orient
== wxHORIZONTAL
)
717 #if __WATCOMC__ && defined(__WINDOWS_386__)
718 short minPos
, maxPos
;
722 HWND hWnd
= GetHwnd();
725 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
726 #if defined(__WIN95__)
727 // Try to adjust the range to cope with page size > 1
728 // - a Windows API quirk
729 int pageSize
= GetScrollPage(orient
);
732 maxPos
-= (pageSize
- 1);
741 int wxWindowMSW::GetScrollPage(int orient
) const
743 if ( orient
== wxHORIZONTAL
)
749 #endif // WXWIN_COMPATIBILITY
751 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
753 #ifdef __WXMICROWIN__
754 return ::GetScrollPosWX(hWnd
, wOrient
);
756 return ::GetScrollPos(hWnd
, wOrient
);
760 int wxWindowMSW::GetScrollPos(int orient
) const
763 if ( orient
== wxHORIZONTAL
)
768 HWND hWnd
= GetHwnd();
769 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
771 return GetScrollPosition(hWnd
, wOrient
);
774 // This now returns the whole range, not just the number
775 // of positions that we can scroll.
776 int wxWindowMSW::GetScrollRange(int orient
) const
779 if ( orient
== wxHORIZONTAL
)
784 #if __WATCOMC__ && defined(__WINDOWS_386__)
785 short minPos
, maxPos
;
789 HWND hWnd
= GetHwnd();
792 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
793 #if defined(__WIN95__)
794 // Try to adjust the range to cope with page size > 1
795 // - a Windows API quirk
796 int pageSize
= GetScrollThumb(orient
);
799 maxPos
-= (pageSize
- 1);
801 // October 10th: new range concept.
811 int wxWindowMSW::GetScrollThumb(int orient
) const
813 if ( orient
== wxHORIZONTAL
)
819 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
821 HWND hWnd
= GetHwnd();
822 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
824 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
826 #if defined(__WIN95__)
828 info
.cbSize
= sizeof(SCROLLINFO
);
832 info
.fMask
= SIF_POS
;
834 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
836 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
837 #endif // __WIN95__/!__WIN95__
840 // New function that will replace some of the above.
841 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
842 int range
, bool refresh
)
844 #if defined(__WIN95__)
845 int oldRange
= range
- thumbVisible
;
847 int range1
= oldRange
;
849 // Try to adjust the range to cope with page size > 1
850 // - a Windows API quirk
851 int pageSize
= thumbVisible
;
852 if ( pageSize
> 1 && range
> 0)
854 range1
+= (pageSize
- 1);
860 if ( orient
== wxHORIZONTAL
) {
866 info
.cbSize
= sizeof(SCROLLINFO
);
867 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
871 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
873 HWND hWnd
= GetHwnd();
875 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
878 if ( orient
== wxHORIZONTAL
)
883 HWND hWnd
= GetHwnd();
886 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
887 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
890 if ( orient
== wxHORIZONTAL
) {
891 m_xThumbSize
= thumbVisible
;
893 m_yThumbSize
= thumbVisible
;
897 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
902 rect
.left
= prect
->x
;
904 rect
.right
= prect
->x
+ prect
->width
;
905 rect
.bottom
= prect
->y
+ prect
->height
;
908 ::ScrollWindow(GetHwnd(), dx
, dy
, prect
? &rect
: NULL
, NULL
);
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() )
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
&& rectClient
.bottom
== height
)
1548 // how did it happen? maybe OnSize() handler does something really
1549 // strange in this class?
1550 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1555 int widthClient
= width
,
1556 heightClient
= height
;
1558 // Find the difference between the entire window (title bar and all)
1559 // and the client area; add this to the new client size to move the
1562 ::GetWindowRect(GetHwnd(), &rectWin
);
1564 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1565 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1568 point
.x
= rectWin
.left
;
1569 point
.y
= rectWin
.top
;
1571 // MoveWindow positions the child windows relative to the parent, so
1572 // adjust if necessary
1573 if ( !IsTopLevel() )
1575 wxWindow
*parent
= GetParent();
1578 ::ScreenToClient(GetHwndOf(parent
), &point
);
1582 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1586 // For implementation purposes - sometimes decorations make the client area
1588 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1590 return wxPoint(0, 0);
1593 // ---------------------------------------------------------------------------
1595 // ---------------------------------------------------------------------------
1597 int wxWindowMSW::GetCharHeight() const
1599 return wxGetTextMetrics(this).tmHeight
;
1602 int wxWindowMSW::GetCharWidth() const
1604 // +1 is needed because Windows apparently adds it when calculating the
1605 // dialog units size in pixels
1606 #if wxDIALOG_UNIT_COMPATIBILITY
1607 return wxGetTextMetrics(this).tmAveCharWidth
;
1609 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1613 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1615 int *descent
, int *externalLeading
,
1616 const wxFont
*theFont
) const
1618 const wxFont
*fontToUse
= theFont
;
1620 fontToUse
= &m_font
;
1622 HWND hWnd
= GetHwnd();
1623 HDC dc
= ::GetDC(hWnd
);
1627 if ( fontToUse
&& fontToUse
->Ok() )
1629 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1631 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1636 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1637 GetTextMetrics(dc
, &tm
);
1639 if ( fontToUse
&& fnt
&& hfontOld
)
1640 SelectObject(dc
, hfontOld
);
1642 ReleaseDC(hWnd
, dc
);
1649 *descent
= tm
.tmDescent
;
1650 if ( externalLeading
)
1651 *externalLeading
= tm
.tmExternalLeading
;
1654 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1655 // ---------------------------------------------------------------------------
1656 // Caret manipulation
1657 // ---------------------------------------------------------------------------
1659 void wxWindowMSW::CreateCaret(int w
, int h
)
1661 SetCaret(new wxCaret(this, w
, h
));
1664 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1666 wxFAIL_MSG("not implemented");
1669 void wxWindowMSW::ShowCaret(bool show
)
1671 wxCHECK_RET( m_caret
, "no caret to show" );
1673 m_caret
->Show(show
);
1676 void wxWindowMSW::DestroyCaret()
1681 void wxWindowMSW::SetCaretPos(int x
, int y
)
1683 wxCHECK_RET( m_caret
, "no caret to move" );
1685 m_caret
->Move(x
, y
);
1688 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1690 wxCHECK_RET( m_caret
, "no caret to get position of" );
1692 m_caret
->GetPosition(x
, y
);
1694 #endif // wxUSE_CARET
1696 // ---------------------------------------------------------------------------
1698 // ---------------------------------------------------------------------------
1700 #if wxUSE_MENUS_NATIVE
1702 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1703 // immediately, without waiting for the next event loop iteration
1705 // NB: this function should probably be made public later as it can almost
1706 // surely replace wxYield() elsewhere as well
1707 static void wxYieldForCommandsOnly()
1709 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1710 // want to process it here)
1712 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1713 && msg
.message
!= WM_QUIT
)
1715 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1719 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1721 menu
->SetInvokingWindow(this);
1724 HWND hWnd
= GetHwnd();
1725 HMENU hMenu
= GetHmenuOf(menu
);
1729 ::ClientToScreen(hWnd
, &point
);
1730 wxCurrentPopupMenu
= menu
;
1731 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1733 // we need to do it righ now as otherwise the events are never going to be
1734 // sent to wxCurrentPopupMenu from HandleCommand()
1736 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1737 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1738 // destroyed as soon as we return (it can be a local variable in the caller
1739 // for example) and so we do need to process the event immediately
1740 wxYieldForCommandsOnly();
1742 wxCurrentPopupMenu
= NULL
;
1744 menu
->SetInvokingWindow(NULL
);
1749 #endif // wxUSE_MENUS_NATIVE
1751 // ===========================================================================
1752 // pre/post message processing
1753 // ===========================================================================
1755 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1758 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1760 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1763 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1765 // wxUniversal implements tab traversal itself
1766 #ifndef __WXUNIVERSAL__
1767 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1769 // intercept dialog navigation keys
1770 MSG
*msg
= (MSG
*)pMsg
;
1772 // here we try to do all the job which ::IsDialogMessage() usually does
1775 bool bProcess
= TRUE
;
1776 if ( msg
->message
!= WM_KEYDOWN
)
1779 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1784 bool bCtrlDown
= wxIsCtrlDown();
1785 bool bShiftDown
= wxIsShiftDown();
1787 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1788 // don't process it if it's the case (except for Ctrl-Tab/Enter
1789 // combinations which are always processed)
1793 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1796 bool bForward
= TRUE
,
1797 bWindowChange
= FALSE
;
1799 switch ( msg
->wParam
)
1802 // assume that nobody wants Shift-TAB for himself - if we
1803 // don't do it there is no easy way for a control to grab
1804 // TABs but still let Shift-TAB work as navugation key
1805 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1809 // Ctrl-Tab cycles thru notebook pages
1810 bWindowChange
= bCtrlDown
;
1811 bForward
= !bShiftDown
;
1817 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1825 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1831 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1833 // control wants to process Enter itself, don't
1834 // call IsDialogMessage() which would interpret
1838 else if ( lDlgCode
& DLGC_BUTTON
)
1840 // let IsDialogMessage() handle this for all
1841 // buttons except the owner-drawn ones which it
1842 // just seems to ignore
1843 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1844 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1846 // emulate the button click
1847 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1849 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1854 // FIXME: this should be handled by
1855 // wxNavigationKeyEvent handler and not here!!
1859 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1861 if ( btn
&& btn
->IsEnabled() )
1863 // if we do have a default button, do press it
1864 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1868 else // no default button
1869 #endif // wxUSE_BUTTON
1871 // no special function for enter and don't even
1872 // let IsDialogMessage() have it: it seems to
1873 // do something really strange with it
1886 wxNavigationKeyEvent event
;
1887 event
.SetDirection(bForward
);
1888 event
.SetWindowChange(bWindowChange
);
1889 event
.SetEventObject(this);
1891 if ( GetEventHandler()->ProcessEvent(event
) )
1898 // let ::IsDialogMessage() do almost everything and handle just the
1899 // things it doesn't here: Ctrl-TAB for switching notebook pages
1900 if ( msg
->message
== WM_KEYDOWN
)
1902 // don't process system keys here
1903 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1905 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1907 // find the first notebook parent and change its page
1908 wxWindow
*win
= this;
1909 wxNotebook
*nbook
= NULL
;
1910 while ( win
&& !nbook
)
1912 nbook
= wxDynamicCast(win
, wxNotebook
);
1913 win
= win
->GetParent();
1918 bool forward
= !wxIsShiftDown();
1920 nbook
->AdvanceSelection(forward
);
1927 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1929 // IsDialogMessage() did something...
1933 #endif // __WXUNIVERSAL__
1938 // relay mouse move events to the tooltip control
1939 MSG
*msg
= (MSG
*)pMsg
;
1940 if ( msg
->message
== WM_MOUSEMOVE
)
1941 m_tooltip
->RelayEvent(pMsg
);
1943 #endif // wxUSE_TOOLTIPS
1948 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1950 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1951 return m_acceleratorTable
.Translate(this, pMsg
);
1954 #endif // wxUSE_ACCEL
1957 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1959 // preprocess all messages by default
1963 // ---------------------------------------------------------------------------
1964 // message params unpackers (different for Win16 and Win32)
1965 // ---------------------------------------------------------------------------
1969 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1970 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1972 *id
= LOWORD(wParam
);
1973 *hwnd
= (WXHWND
)lParam
;
1974 *cmd
= HIWORD(wParam
);
1977 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1978 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1980 *state
= LOWORD(wParam
);
1981 *minimized
= HIWORD(wParam
);
1982 *hwnd
= (WXHWND
)lParam
;
1985 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1986 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1988 *code
= LOWORD(wParam
);
1989 *pos
= HIWORD(wParam
);
1990 *hwnd
= (WXHWND
)lParam
;
1993 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
1994 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
1996 #ifndef __WXMICROWIN__
1997 *nCtlColor
= CTLCOLOR_BTN
;
1998 *hwnd
= (WXHWND
)lParam
;
1999 *hdc
= (WXHDC
)wParam
;
2003 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2004 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2006 *item
= (WXWORD
)wParam
;
2007 *flags
= HIWORD(wParam
);
2008 *hmenu
= (WXHMENU
)lParam
;
2013 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2014 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2016 *id
= (WXWORD
)wParam
;
2017 *hwnd
= (WXHWND
)LOWORD(lParam
);
2018 *cmd
= HIWORD(lParam
);
2021 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2022 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2024 *state
= (WXWORD
)wParam
;
2025 *minimized
= LOWORD(lParam
);
2026 *hwnd
= (WXHWND
)HIWORD(lParam
);
2029 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2030 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2032 *code
= (WXWORD
)wParam
;
2033 *pos
= LOWORD(lParam
);
2034 *hwnd
= (WXHWND
)HIWORD(lParam
);
2037 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2038 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2040 *hwnd
= (WXHWND
)LOWORD(lParam
);
2041 *nCtlColor
= (int)HIWORD(lParam
);
2042 *hdc
= (WXHDC
)wParam
;
2045 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2046 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2048 *item
= (WXWORD
)wParam
;
2049 *flags
= LOWORD(lParam
);
2050 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2055 // ---------------------------------------------------------------------------
2056 // Main wxWindows window proc and the window proc for wxWindow
2057 // ---------------------------------------------------------------------------
2059 // Hook for new window just as it's being created, when the window isn't yet
2060 // associated with the handle
2061 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2063 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2064 // window being created and insures that it's always unset back later
2065 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2067 gs_winBeingCreated
= winBeingCreated
;
2070 wxWindowCreationHook::~wxWindowCreationHook()
2072 gs_winBeingCreated
= NULL
;
2076 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2078 // trace all messages - useful for the debugging
2080 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2081 wxGetMessageName(message
), wParam
, lParam
);
2082 #endif // __WXDEBUG__
2084 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2086 // when we get the first message for the HWND we just created, we associate
2087 // it with wxWindow stored in gs_winBeingCreated
2088 if ( !wnd
&& gs_winBeingCreated
)
2090 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2091 wnd
= gs_winBeingCreated
;
2092 gs_winBeingCreated
= NULL
;
2093 wnd
->SetHWND((WXHWND
)hWnd
);
2099 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2101 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2106 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2108 // did we process the message?
2109 bool processed
= FALSE
;
2120 // for most messages we should return 0 when we do process the message
2128 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2131 // return 0 to allow window creation
2132 rc
.result
= mayCreate
? 0 : -1;
2138 // never set processed to TRUE and *always* pass WM_DESTROY to
2139 // DefWindowProc() as Windows may do some internal cleanup when
2140 // processing it and failing to pass the message along may cause
2141 // memory and resource leaks!
2142 (void)HandleDestroy();
2146 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2154 // we're not interested in these messages at all
2157 case SIZE_MINIMIZED
:
2158 // we shouldn't send sizev events for these messages as the
2159 // client size may be negative which breaks existing code
2161 // OTOH we might send another (wxMinimizedEvent?) one or
2162 // add an additional parameter to wxSizeEvent if this is
2163 // useful to anybody
2167 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2168 // fall through nevertheless
2170 case SIZE_MAXIMIZED
:
2172 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2177 #ifndef __WXMICROWIN__
2178 case WM_ACTIVATEAPP
:
2179 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2185 WXWORD state
, minimized
;
2187 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2189 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2194 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2198 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2202 processed
= HandlePaint();
2206 // don't let the DefWindowProc() destroy our window - we'll do it
2207 // ourselves in ~wxWindow
2213 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2217 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2218 GET_Y_LPARAM(lParam
),
2222 #if wxUSE_MOUSEWHEEL
2224 processed
= HandleMouseWheel(wParam
, lParam
);
2228 case WM_LBUTTONDOWN
:
2230 case WM_LBUTTONDBLCLK
:
2231 case WM_RBUTTONDOWN
:
2233 case WM_RBUTTONDBLCLK
:
2234 case WM_MBUTTONDOWN
:
2236 case WM_MBUTTONDBLCLK
:
2239 #ifdef __WXMICROWIN__
2240 // MicroWindows seems to ignore the fact that a window is
2241 // disabled. So catch mouse events and throw them away if
2243 wxWindowMSW
* win
= this;
2246 if (!win
->IsEnabled())
2251 win
= win
->GetParent();
2252 if (win
&& win
->IsTopLevel())
2255 #endif // __WXMICROWIN__
2258 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2260 processed
= HandleMouseEvent(message
,
2261 GET_X_LPARAM(lParam
),
2262 GET_Y_LPARAM(lParam
),
2268 #ifdef __WXMICROWIN__
2269 case WM_NCLBUTTONDOWN
:
2270 case WM_NCLBUTTONUP
:
2271 case WM_NCLBUTTONDBLCLK
:
2272 case WM_NCRBUTTONDOWN
:
2273 case WM_NCRBUTTONUP
:
2274 case WM_NCRBUTTONDBLCLK
:
2276 case WM_NCMBUTTONDOWN
:
2277 case WM_NCMBUTTONUP
:
2278 case WM_NCMBUTTONDBLCLK
:
2281 // MicroWindows seems to ignore the fact that a window
2282 // is disabled. So catch mouse events and throw them away if necessary.
2284 wxWindowMSW
* win
= this;
2287 if (!win
->IsEnabled())
2292 win
= win
->GetParent();
2293 if (win
&& win
->IsTopLevel())
2298 #endif // __WXMICROWIN__
2305 case MM_JOY1BUTTONDOWN
:
2306 case MM_JOY2BUTTONDOWN
:
2307 case MM_JOY1BUTTONUP
:
2308 case MM_JOY2BUTTONUP
:
2309 processed
= HandleJoystickEvent(message
,
2310 GET_X_LPARAM(lParam
),
2311 GET_Y_LPARAM(lParam
),
2314 #endif // __WXMICROWIN__
2317 processed
= HandleSysCommand(wParam
, lParam
);
2324 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2326 processed
= HandleCommand(id
, cmd
, hwnd
);
2332 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2336 // for these messages we must return TRUE if process the message
2339 case WM_MEASUREITEM
:
2341 int idCtrl
= (UINT
)wParam
;
2342 if ( message
== WM_DRAWITEM
)
2344 processed
= MSWOnDrawItem(idCtrl
,
2345 (WXDRAWITEMSTRUCT
*)lParam
);
2349 processed
= MSWOnMeasureItem(idCtrl
,
2350 (WXMEASUREITEMSTRUCT
*)lParam
);
2357 #endif // defined(WM_DRAWITEM)
2362 rc
.result
= m_lDlgCode
;
2365 //else: get the dlg code from the DefWindowProc()
2370 // If this has been processed by an event handler,
2371 // return 0 now (we've handled it).
2372 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2379 // we consider these message "not interesting" to OnChar
2380 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2389 // avoid duplicate messages to OnChar for these ASCII keys: they
2390 // will be translated by TranslateMessage() and received in WM_CHAR
2398 // but set processed to FALSE, not TRUE to still pass them to
2399 // the control's default window proc - otherwise built-in
2400 // keyboard handling won't work
2406 // special case of VK_APPS: treat it the same as right mouse
2407 // click because both usually pop up a context menu
2413 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2414 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2424 processed
= HandleChar((WORD
)wParam
, lParam
);
2431 // special case of VK_APPS: treat it the same as right mouse button
2432 if ( wParam
== VK_APPS
)
2437 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2438 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2443 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2448 case WM_CHAR
: // Always an ASCII character
2449 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2457 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2459 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2465 // CTLCOLOR messages are sent by children to query the parent for their
2466 // colors#ifndef __WXMICROWIN__
2467 #ifndef __WXMICROWIN__
2469 case WM_CTLCOLORMSGBOX
:
2470 case WM_CTLCOLOREDIT
:
2471 case WM_CTLCOLORLISTBOX
:
2472 case WM_CTLCOLORBTN
:
2473 case WM_CTLCOLORDLG
:
2474 case WM_CTLCOLORSCROLLBAR
:
2475 case WM_CTLCOLORSTATIC
:
2483 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2485 processed
= HandleCtlColor(&rc
.hBrush
,
2494 #endif // !__WXMICROWIN__
2496 // the return value for this message is ignored
2497 case WM_SYSCOLORCHANGE
:
2498 processed
= HandleSysColorChange();
2501 case WM_PALETTECHANGED
:
2502 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2505 case WM_QUERYNEWPALETTE
:
2506 processed
= HandleQueryNewPalette();
2510 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2513 // we processed the message, i.e. erased the background
2519 processed
= HandleDropFiles(wParam
);
2523 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2527 // we never set focus from here
2532 case WM_QUERYENDSESSION
:
2533 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2537 processed
= HandleEndSession(wParam
!= 0, lParam
);
2540 case WM_GETMINMAXINFO
:
2541 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2545 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2546 LOWORD(lParam
), // hit test
2547 HIWORD(lParam
)); // mouse msg
2551 // returning TRUE stops the DefWindowProc() from further
2552 // processing this message - exactly what we need because we've
2553 // just set the cursor.
2558 #if defined(__WIN32__) && defined(WM_HELP)
2561 HELPINFO
* info
= (HELPINFO
*) lParam
;
2562 // Don't yet process menu help events, just windows
2563 if (info
->iContextType
== HELPINFO_WINDOW
)
2565 wxWindowMSW
* subjectOfHelp
= this;
2566 bool eventProcessed
= FALSE
;
2567 while (subjectOfHelp
&& !eventProcessed
)
2569 wxHelpEvent
helpEvent(wxEVT_HELP
,
2570 subjectOfHelp
->GetId(),
2571 wxPoint(info
->MousePos
.x
,
2572 info
->MousePos
.y
) );
2573 helpEvent
.SetEventObject(this);
2575 GetEventHandler()->ProcessEvent(helpEvent
);
2577 // Go up the window hierarchy until the event is
2579 subjectOfHelp
= subjectOfHelp
->GetParent();
2582 processed
= eventProcessed
;
2584 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2586 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2587 helpEvent
.SetEventObject(this);
2588 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2591 //else: processed is already FALSE
2595 case WM_CONTEXTMENU
:
2597 // we don't convert from screen to client coordinates as
2598 // the event may be handled by a parent window
2599 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2601 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2602 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2607 // unfortunately this doesn't really work as then window which
2608 // doesn't accept focus doesn't get any mouse events neither which
2609 // means it can't get any input at all
2610 #if 0 //def __WXUNIVERSAL__
2612 // we shouldn't allow the windows which don't want to get focus to
2614 if ( !AcceptsFocus() )
2616 rc
.result
= HTTRANSPARENT
;
2620 #endif // __WXUNIVERSAL__
2626 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2627 wxGetMessageName(message
));
2628 #endif // __WXDEBUG__
2629 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2635 // ----------------------------------------------------------------------------
2636 // wxWindow <-> HWND map
2637 // ----------------------------------------------------------------------------
2639 wxWinHashTable
*wxWinHandleHash
= NULL
;
2641 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2643 return wxWinHandleHash
->Get((long)hWnd
);
2646 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2648 // adding NULL hWnd is (first) surely a result of an error and
2649 // (secondly) breaks menu command processing
2650 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2651 wxT("attempt to add a NULL hWnd to window list ignored") );
2653 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2655 if ( oldWin
&& (oldWin
!= win
) )
2657 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2658 hWnd
, win
->GetClassInfo()->GetClassName());
2661 #endif // __WXDEBUG__
2664 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2668 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2670 wxWinHandleHash
->Delete((long)win
->GetHWND());
2673 // ----------------------------------------------------------------------------
2674 // various MSW speciic class dependent functions
2675 // ----------------------------------------------------------------------------
2677 // Default destroyer - override if you destroy it in some other way
2678 // (e.g. with MDI child windows)
2679 void wxWindowMSW::MSWDestroyWindow()
2683 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2686 int& w
, int& h
) const
2688 bool nonDefault
= FALSE
;
2692 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2693 // just as well set it to CW_USEDEFAULT as well
2700 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2706 NB: there used to be some code here which set the initial size of the
2707 window to the client size of the parent if no explicit size was
2708 specified. This was wrong because wxWindows programs often assume
2709 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2710 it. To see why, you should understand that Windows sends WM_SIZE from
2711 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2712 from some base class ctor and so this WM_SIZE is not processed in the
2713 real class' OnSize() (because it's not fully constructed yet and the
2714 event goes to some base class OnSize() instead). So the WM_SIZE we
2715 rely on is the one sent when the parent frame resizes its children
2716 but here is the problem: if the child already has just the right
2717 size, nothing will happen as both wxWindows and Windows check for
2718 this and ignore any attempts to change the window size to the size it
2719 already has - so no WM_SIZE would be sent.
2723 // as abobe, h is not used at all in this case anyhow
2730 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2738 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2739 const wxChar
*title
,
2743 WXDWORD extendedStyle
)
2745 // choose the position/size for the new window
2747 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2749 // find the correct parent HWND
2750 wxWindow
*parent
= GetParent();
2751 bool isChild
= (style
& WS_CHILD
) != 0;
2753 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2755 // popup windows should have desktop as parent because they shouldn't
2756 // be limited to the parents client area as child windows usually are
2757 hParent
= ::GetDesktopWindow();
2761 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2763 // this is either a normal child window or a top level window with
2764 // wxFRAME_TOOL_WINDOW style (see below)
2765 hParent
= GetHwndOf(parent
);
2769 // this is either a window for which no parent was specified (not
2770 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2771 // style: we should use NULL parent HWND for it or it would be
2772 // always on top of its parent which is not what we usually want
2773 // (in fact, we only want it for frames with the special
2774 // wxFRAME_TOOL_WINDOW as above)
2780 // controlId is menu handle for the top level windows, so set it to 0
2781 // unless we're creating a child window
2785 controlId
= GetId();
2787 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2789 style
|= WS_CLIPSIBLINGS
;
2797 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2798 // which is the same but without CS_[HV]REDRAW class styles so using it
2799 // ensures that the window is not fully repainted on each resize
2800 wxString
className(wclass
);
2801 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2803 className
+= wxT("NR");
2806 // do create the window
2807 wxWindowCreationHook
hook(this);
2809 m_hWnd
= (WXHWND
)::CreateWindowEx
2813 title
? title
: wxT(""),
2819 NULL
// no extra data
2824 wxLogSysError(_("Can't create window of class %s"), wclass
);
2829 SubclassWin(m_hWnd
);
2831 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2836 // ===========================================================================
2837 // MSW message handlers
2838 // ===========================================================================
2840 // ---------------------------------------------------------------------------
2842 // ---------------------------------------------------------------------------
2845 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2846 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2848 #ifndef __WXMICROWIN__
2849 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2850 HWND hWnd
= hdr
->hwndFrom
;
2851 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2853 // is this one of our windows?
2856 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2859 // try all our children
2860 wxWindowList::Node
*node
= GetChildren().GetFirst();
2863 wxWindow
*child
= node
->GetData();
2864 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2869 node
= node
->GetNext();
2872 // finally try this window too (catches toolbar case)
2873 return MSWOnNotify(idCtrl
, lParam
, result
);
2874 #else // __WXMICROWIN__
2879 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2881 WXLPARAM
* WXUNUSED(result
))
2884 NMHDR
* hdr
= (NMHDR
*)lParam
;
2885 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2887 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2888 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2893 #endif // wxUSE_TOOLTIPS
2899 // ---------------------------------------------------------------------------
2900 // end session messages
2901 // ---------------------------------------------------------------------------
2903 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2905 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2906 event
.SetEventObject(wxTheApp
);
2907 event
.SetCanVeto(TRUE
);
2908 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2910 bool rc
= wxTheApp
->ProcessEvent(event
);
2914 // we may end only if the app didn't veto session closing (double
2916 *mayEnd
= !event
.GetVeto();
2922 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2924 // do nothing if the session isn't ending
2929 if ( (this != wxTheApp
->GetTopWindow()) )
2932 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2933 event
.SetEventObject(wxTheApp
);
2934 event
.SetCanVeto(FALSE
);
2935 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2937 return wxTheApp
->ProcessEvent(event
);
2940 // ---------------------------------------------------------------------------
2941 // window creation/destruction
2942 // ---------------------------------------------------------------------------
2944 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2946 // TODO: should generate this event from WM_NCCREATE
2947 wxWindowCreateEvent
event((wxWindow
*)this);
2948 (void)GetEventHandler()->ProcessEvent(event
);
2955 bool wxWindowMSW::HandleDestroy()
2957 wxWindowDestroyEvent
event((wxWindow
*)this);
2958 (void)GetEventHandler()->ProcessEvent(event
);
2960 // delete our drop target if we've got one
2961 #if wxUSE_DRAG_AND_DROP
2962 if ( m_dropTarget
!= NULL
)
2964 m_dropTarget
->Revoke(m_hWnd
);
2966 delete m_dropTarget
;
2967 m_dropTarget
= NULL
;
2969 #endif // wxUSE_DRAG_AND_DROP
2971 // WM_DESTROY handled
2975 // ---------------------------------------------------------------------------
2977 // ---------------------------------------------------------------------------
2979 bool wxWindowMSW::HandleActivate(int state
,
2980 bool WXUNUSED(minimized
),
2981 WXHWND
WXUNUSED(activate
))
2983 wxActivateEvent
event(wxEVT_ACTIVATE
,
2984 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
2986 event
.SetEventObject(this);
2988 return GetEventHandler()->ProcessEvent(event
);
2991 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
2993 // notify the parent keeping track of focus for the kbd navigation
2994 // purposes that we got it
2995 wxChildFocusEvent
eventFocus((wxWindow
*)this);
2996 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3002 m_caret
->OnSetFocus();
3004 #endif // wxUSE_CARET
3007 // If it's a wxTextCtrl don't send the event as it will be done
3008 // after the control gets to process it from EN_FOCUS handler
3009 if ( wxDynamicCastThis(wxTextCtrl
) )
3013 #endif // wxUSE_TEXTCTRL
3015 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3016 event
.SetEventObject(this);
3018 // wxFindWinFromHandle() may return NULL, it is ok
3019 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3021 return GetEventHandler()->ProcessEvent(event
);
3024 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3030 m_caret
->OnKillFocus();
3032 #endif // wxUSE_CARET
3035 // If it's a wxTextCtrl don't send the event as it will be done
3036 // after the control gets to process it.
3037 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3044 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3045 event
.SetEventObject(this);
3047 // wxFindWinFromHandle() may return NULL, it is ok
3048 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3050 return GetEventHandler()->ProcessEvent(event
);
3053 // ---------------------------------------------------------------------------
3055 // ---------------------------------------------------------------------------
3057 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3059 wxShowEvent
event(GetId(), show
);
3060 event
.m_eventObject
= this;
3062 return GetEventHandler()->ProcessEvent(event
);
3065 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3067 wxInitDialogEvent
event(GetId());
3068 event
.m_eventObject
= this;
3070 return GetEventHandler()->ProcessEvent(event
);
3073 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3075 #ifndef __WXMICROWIN__
3076 HDROP hFilesInfo
= (HDROP
) wParam
;
3078 // Get the total number of files dropped
3079 UINT gwFilesDropped
= ::DragQueryFile
3087 wxString
*files
= new wxString
[gwFilesDropped
];
3088 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3090 // first get the needed buffer length (+1 for terminating NUL)
3091 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3093 // and now get the file name
3094 ::DragQueryFile(hFilesInfo
, wIndex
,
3095 files
[wIndex
].GetWriteBuf(len
), len
);
3097 files
[wIndex
].UngetWriteBuf();
3099 DragFinish (hFilesInfo
);
3101 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3102 event
.m_eventObject
= this;
3105 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3106 event
.m_pos
.x
= dropPoint
.x
;
3107 event
.m_pos
.y
= dropPoint
.y
;
3109 return GetEventHandler()->ProcessEvent(event
);
3110 #else // __WXMICROWIN__
3115 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3117 int WXUNUSED(mouseMsg
))
3119 #ifndef __WXMICROWIN__
3120 // the logic is as follows:
3121 // -1. don't set cursor for non client area, including but not limited to
3122 // the title bar, scrollbars, &c
3123 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3124 // 1. if we have the cursor set it unless wxIsBusy()
3125 // 2. if we're a top level window, set some cursor anyhow
3126 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3128 if ( nHitTest
!= HTCLIENT
)
3133 HCURSOR hcursor
= 0;
3135 // first ask the user code - it may wish to set the cursor in some very
3136 // specific way (for example, depending on the current position)
3139 if ( !::GetCursorPos(&pt
) )
3141 wxLogLastError(wxT("GetCursorPos"));
3144 // In WIN16 it doesn't return a value.
3145 ::GetCursorPos(&pt
);
3150 ScreenToClient(&x
, &y
);
3151 wxSetCursorEvent
event(x
, y
);
3153 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3154 if ( processedEvtSetCursor
&& event
.HasCursor() )
3156 hcursor
= GetHcursorOf(event
.GetCursor());
3161 bool isBusy
= wxIsBusy();
3163 // the test for processedEvtSetCursor is here to prevent using m_cursor
3164 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3165 // it - this is a way to say that our cursor shouldn't be used for this
3167 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3169 hcursor
= GetHcursorOf(m_cursor
);
3176 hcursor
= wxGetCurrentBusyCursor();
3178 else if ( !hcursor
)
3180 const wxCursor
*cursor
= wxGetGlobalCursor();
3181 if ( cursor
&& cursor
->Ok() )
3183 hcursor
= GetHcursorOf(*cursor
);
3191 ::SetCursor(hcursor
);
3193 // cursor set, stop here
3196 #endif // __WXMICROWIN__
3198 // pass up the window chain
3202 // ---------------------------------------------------------------------------
3203 // owner drawn stuff
3204 // ---------------------------------------------------------------------------
3206 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3208 #if wxUSE_OWNER_DRAWN
3210 #if wxUSE_MENUS_NATIVE
3211 // is it a menu item?
3212 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3213 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3215 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3217 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3219 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3220 // the DC from being released
3221 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3222 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3223 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3224 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3226 return pMenuItem
->OnDrawItem
3230 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3231 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3234 #endif // wxUSE_MENUS_NATIVE
3237 wxWindow
*item
= FindItem(id
);
3238 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3240 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3242 #endif // wxUSE_CONTROLS
3244 #endif // USE_OWNER_DRAWN
3249 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3251 #if wxUSE_OWNER_DRAWN
3252 // is it a menu item?
3253 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3254 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3256 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3258 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3260 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3261 &pMeasureStruct
->itemHeight
);
3264 wxWindow
*item
= FindItem(id
);
3265 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3267 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3269 #endif // owner-drawn menus
3273 // ---------------------------------------------------------------------------
3274 // colours and palettes
3275 // ---------------------------------------------------------------------------
3277 bool wxWindowMSW::HandleSysColorChange()
3279 wxSysColourChangedEvent event
;
3280 event
.SetEventObject(this);
3282 (void)GetEventHandler()->ProcessEvent(event
);
3284 // always let the system carry on the default processing to allow the
3285 // native controls to react to the colours update
3289 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3297 #ifndef __WXMICROWIN__
3298 WXHBRUSH hBrush
= 0;
3300 if ( nCtlColor
== CTLCOLOR_DLG
)
3302 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3307 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3309 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3311 #endif // wxUSE_CONTROLS
3317 #else // __WXMICROWIN__
3322 // Define for each class of dialog and control
3323 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3324 WXHWND
WXUNUSED(hWnd
),
3325 WXUINT
WXUNUSED(nCtlColor
),
3326 WXUINT
WXUNUSED(message
),
3327 WXWPARAM
WXUNUSED(wParam
),
3328 WXLPARAM
WXUNUSED(lParam
))
3333 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3335 wxPaletteChangedEvent
event(GetId());
3336 event
.SetEventObject(this);
3337 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3339 return GetEventHandler()->ProcessEvent(event
);
3342 bool wxWindowMSW::HandleQueryNewPalette()
3344 wxQueryNewPaletteEvent
event(GetId());
3345 event
.SetEventObject(this);
3347 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3350 // Responds to colour changes: passes event on to children.
3351 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3353 wxWindowList::Node
*node
= GetChildren().GetFirst();
3356 // Only propagate to non-top-level windows because Windows already
3357 // sends this event to all top-level ones
3358 wxWindow
*win
= node
->GetData();
3359 if ( !win
->IsTopLevel() )
3361 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3362 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3363 // the standard controls
3364 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3367 node
= node
->GetNext();
3370 // update the colours we use if they were not set explicitly by the user:
3371 // this must be done or OnCtlColor() would continue to use the old colours
3374 m_foregroundColour
= wxSystemSettings::
3375 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3380 m_backgroundColour
= wxSystemSettings::
3381 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3385 // ---------------------------------------------------------------------------
3387 // ---------------------------------------------------------------------------
3389 bool wxWindowMSW::HandlePaint()
3392 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3394 wxLogLastError(wxT("CreateRectRgn"));
3395 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3396 wxLogLastError(wxT("GetUpdateRgn"));
3398 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3401 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3403 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3404 updateRect
.right
- updateRect
.left
,
3405 updateRect
.bottom
- updateRect
.top
);
3408 wxPaintEvent
event(m_windowId
);
3409 event
.SetEventObject(this);
3411 bool processed
= GetEventHandler()->ProcessEvent(event
);
3413 // note that we must generate NC event after the normal one as otherwise
3414 // BeginPaint() will happily overwrite our decorations with the background
3416 wxNcPaintEvent
eventNc(m_windowId
);
3417 eventNc
.SetEventObject(this);
3418 GetEventHandler()->ProcessEvent(eventNc
);
3423 // Can be called from an application's OnPaint handler
3424 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3426 #ifdef __WXUNIVERSAL__
3429 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3432 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3437 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3439 // Prevents flicker when dragging
3440 if ( ::IsIconic(GetHwnd()) )
3446 dc
.SetWindow((wxWindow
*)this);
3449 wxEraseEvent
event(m_windowId
, &dc
);
3450 event
.SetEventObject(this);
3451 bool rc
= GetEventHandler()->ProcessEvent(event
);
3455 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3456 dc
.SelectOldObjects(hdc
);
3461 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3464 ::GetClientRect(GetHwnd(), &rect
);
3466 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3467 m_backgroundColour
.Green(),
3468 m_backgroundColour
.Blue());
3469 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3471 wxLogLastError(wxT("CreateSolidBrush"));
3473 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3475 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3477 ::FillRect(hdc
, &rect
, hBrush
);
3478 ::DeleteObject(hBrush
);
3479 ::SetMapMode(hdc
, mode
);
3482 // ---------------------------------------------------------------------------
3483 // moving and resizing
3484 // ---------------------------------------------------------------------------
3486 bool wxWindowMSW::HandleMinimize()
3488 wxIconizeEvent
event(m_windowId
);
3489 event
.SetEventObject(this);
3491 return GetEventHandler()->ProcessEvent(event
);
3494 bool wxWindowMSW::HandleMaximize()
3496 wxMaximizeEvent
event(m_windowId
);
3497 event
.SetEventObject(this);
3499 return GetEventHandler()->ProcessEvent(event
);
3502 bool wxWindowMSW::HandleMove(int x
, int y
)
3504 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3505 event
.SetEventObject(this);
3507 return GetEventHandler()->ProcessEvent(event
);
3510 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3512 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3513 event
.SetEventObject(this);
3515 return GetEventHandler()->ProcessEvent(event
);
3518 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3520 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3524 if ( m_minWidth
!= -1 )
3526 info
->ptMinTrackSize
.x
= m_minWidth
;
3530 if ( m_minHeight
!= -1 )
3532 info
->ptMinTrackSize
.y
= m_minHeight
;
3536 if ( m_maxWidth
!= -1 )
3538 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3542 if ( m_maxHeight
!= -1 )
3544 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3551 // ---------------------------------------------------------------------------
3553 // ---------------------------------------------------------------------------
3555 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3557 #if wxUSE_MENUS_NATIVE
3558 if ( !cmd
&& wxCurrentPopupMenu
)
3560 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3561 wxCurrentPopupMenu
= NULL
;
3563 return popupMenu
->MSWCommand(cmd
, id
);
3565 #endif // wxUSE_MENUS_NATIVE
3567 wxWindow
*win
= NULL
;
3569 // first try to find it from HWND - this works even with the broken
3570 // programs using the same ids for different controls
3573 win
= wxFindWinFromHandle(control
);
3579 // must cast to a signed type before comparing with other ids!
3580 win
= FindItem((signed short)id
);
3585 return win
->MSWCommand(cmd
, id
);
3588 // the messages sent from the in-place edit control used by the treectrl
3589 // for label editing have id == 0, but they should _not_ be treated as menu
3590 // messages (they are EN_XXX ones, in fact) so don't translate anything
3591 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3594 // If no child window, it may be an accelerator, e.g. for a popup menu
3597 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3598 event
.SetEventObject(this);
3602 return GetEventHandler()->ProcessEvent(event
);
3604 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3607 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3608 // notifications to its parent which we want to reflect back to
3610 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3611 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3614 #endif // wxUSE_SPINCTRL
3619 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3621 // 4 bits are reserved
3622 switch ( wParam
& 0xFFFFFFF0 )
3625 return HandleMaximize();
3628 return HandleMinimize();
3634 // ---------------------------------------------------------------------------
3636 // ---------------------------------------------------------------------------
3638 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3642 // our client coords are not quite the same as Windows ones
3643 wxPoint pt
= GetClientAreaOrigin();
3644 event
.m_x
= x
- pt
.x
;
3645 event
.m_y
= y
- pt
.y
;
3647 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3648 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3649 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3650 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3651 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3652 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3654 event
.SetTimestamp(s_currentMsg
.time
);
3655 event
.m_eventObject
= this;
3657 #if wxUSE_MOUSEEVENT_HACK
3660 m_lastMouseEvent
= event
.GetEventType();
3661 #endif // wxUSE_MOUSEEVENT_HACK
3664 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3666 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3667 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3668 // from the message id and take the value in the table to get wxWin event
3670 static const wxEventType eventsMouse
[] =
3684 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3685 InitMouseEvent(event
, x
, y
, flags
);
3687 return GetEventHandler()->ProcessEvent(event
);
3690 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3692 if ( !m_mouseInWindow
)
3694 // it would be wrong to assume that just because we get a mouse move
3695 // event that the mouse is inside the window: although this is usually
3696 // true, it is not if we had captured the mouse, so we need to check
3697 // the mouse coordinates here
3698 if ( !HasCapture() || IsMouseInWindow() )
3700 // Generate an ENTER event
3701 m_mouseInWindow
= TRUE
;
3703 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3704 InitMouseEvent(event
, x
, y
, flags
);
3706 (void)GetEventHandler()->ProcessEvent(event
);
3710 #if wxUSE_MOUSEEVENT_HACK
3711 // Window gets a click down message followed by a mouse move message even
3712 // if position isn't changed! We want to discard the trailing move event
3713 // if x and y are the same.
3714 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3715 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3716 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3717 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3719 m_lastMouseEvent
= wxEVT_MOTION
;
3723 #endif // wxUSE_MOUSEEVENT_HACK
3725 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3729 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3731 #if wxUSE_MOUSEWHEEL
3732 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3733 InitMouseEvent(event
,
3734 GET_X_LPARAM(lParam
),
3735 GET_Y_LPARAM(lParam
),
3737 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3738 event
.m_wheelDelta
= WHEEL_DELTA
;
3741 static int s_linesPerRotation
= -1;
3742 if ( s_linesPerRotation
== -1 )
3744 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3745 &s_linesPerRotation
, 0))
3747 // this is not supposed to happen
3748 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3750 // the default is 3, so use it if SystemParametersInfo() failed
3751 s_linesPerRotation
= 3;
3755 // no SystemParametersInfo() under Win16
3756 static const int s_linesPerRotation
= 3;
3759 event
.m_linesPerAction
= s_linesPerRotation
;
3760 return GetEventHandler()->ProcessEvent(event
);
3771 // ---------------------------------------------------------------------------
3772 // keyboard handling
3773 // ---------------------------------------------------------------------------
3775 // create the key event of the given type for the given key - used by
3776 // HandleChar and HandleKeyDown/Up
3777 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3779 WXLPARAM lParam
) const
3781 wxKeyEvent
event(evType
);
3782 event
.SetId(GetId());
3783 event
.m_shiftDown
= wxIsShiftDown();
3784 event
.m_controlDown
= wxIsCtrlDown();
3785 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3787 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3788 event
.m_keyCode
= id
;
3789 event
.SetTimestamp(s_currentMsg
.time
);
3791 // translate the position to client coords
3795 GetWindowRect(GetHwnd(),&rect
);
3805 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3807 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3809 bool ctrlDown
= FALSE
;
3814 // If 1 -> 26, translate to CTRL plus a letter.
3816 if ( (id
> 0) && (id
< 27) )
3838 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3840 // it's ASCII and will be processed here only when called from
3841 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3847 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3850 event
.m_controlDown
= TRUE
;
3853 if ( GetEventHandler()->ProcessEvent(event
) )
3860 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3862 int id
= wxCharCodeMSWToWX(wParam
);
3866 // normal ASCII char
3870 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3872 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3873 if ( GetEventHandler()->ProcessEvent(event
) )
3882 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3884 int id
= wxCharCodeMSWToWX(wParam
);
3888 // normal ASCII char
3892 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3894 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3895 if ( GetEventHandler()->ProcessEvent(event
) )
3902 // ---------------------------------------------------------------------------
3904 // ---------------------------------------------------------------------------
3906 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3910 if ( flags
& JOY_BUTTON1CHG
)
3911 change
= wxJOY_BUTTON1
;
3912 if ( flags
& JOY_BUTTON2CHG
)
3913 change
= wxJOY_BUTTON2
;
3914 if ( flags
& JOY_BUTTON3CHG
)
3915 change
= wxJOY_BUTTON3
;
3916 if ( flags
& JOY_BUTTON4CHG
)
3917 change
= wxJOY_BUTTON4
;
3920 if ( flags
& JOY_BUTTON1
)
3921 buttons
|= wxJOY_BUTTON1
;
3922 if ( flags
& JOY_BUTTON2
)
3923 buttons
|= wxJOY_BUTTON2
;
3924 if ( flags
& JOY_BUTTON3
)
3925 buttons
|= wxJOY_BUTTON3
;
3926 if ( flags
& JOY_BUTTON4
)
3927 buttons
|= wxJOY_BUTTON4
;
3929 // the event ids aren't consecutive so we can't use table based lookup
3931 wxEventType eventType
;
3936 eventType
= wxEVT_JOY_MOVE
;
3941 eventType
= wxEVT_JOY_MOVE
;
3946 eventType
= wxEVT_JOY_ZMOVE
;
3951 eventType
= wxEVT_JOY_ZMOVE
;
3954 case MM_JOY1BUTTONDOWN
:
3956 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3959 case MM_JOY2BUTTONDOWN
:
3961 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3964 case MM_JOY1BUTTONUP
:
3966 eventType
= wxEVT_JOY_BUTTON_UP
;
3969 case MM_JOY2BUTTONUP
:
3971 eventType
= wxEVT_JOY_BUTTON_UP
;
3975 wxFAIL_MSG(wxT("no such joystick event"));
3980 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
3981 event
.SetPosition(wxPoint(x
, y
));
3982 event
.SetEventObject(this);
3984 return GetEventHandler()->ProcessEvent(event
);
3990 // ---------------------------------------------------------------------------
3992 // ---------------------------------------------------------------------------
3994 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
3995 WXWORD pos
, WXHWND control
)
3999 wxWindow
*child
= wxFindWinFromHandle(control
);
4001 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4004 wxScrollWinEvent event
;
4005 event
.SetPosition(pos
);
4006 event
.SetOrientation(orientation
);
4007 event
.m_eventObject
= this;
4012 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4016 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4020 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4024 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4028 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4032 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4035 case SB_THUMBPOSITION
:
4038 // under Win32, the scrollbar range and position are 32 bit integers,
4039 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4040 // explicitly query the scrollbar for the correct position (this must
4041 // be done only for these two SB_ events as they are the only one
4042 // carrying the scrollbar position)
4044 SCROLLINFO scrollInfo
;
4045 wxZeroMemory(scrollInfo
);
4046 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4047 scrollInfo
.fMask
= SIF_TRACKPOS
;
4049 if ( !::GetScrollInfo(GetHwnd(),
4050 orientation
== wxHORIZONTAL
? SB_HORZ
4054 wxLogLastError(_T("GetScrollInfo"));
4057 event
.SetPosition(scrollInfo
.nTrackPos
);
4061 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4062 ? wxEVT_SCROLLWIN_THUMBRELEASE
4063 : wxEVT_SCROLLWIN_THUMBTRACK
;
4070 return GetEventHandler()->ProcessEvent(event
);
4073 // ===========================================================================
4075 // ===========================================================================
4077 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4080 HDC dc
= ::GetDC((HWND
) wnd
);
4085 // the_font->UseResource();
4086 // the_font->RealizeResource();
4087 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4089 was
= (HFONT
) SelectObject(dc
,fnt
);
4091 GetTextMetrics(dc
, &tm
);
4092 if ( the_font
&& fnt
&& was
)
4094 SelectObject(dc
,was
);
4096 ReleaseDC((HWND
)wnd
, dc
);
4099 *x
= tm
.tmAveCharWidth
;
4101 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4104 // the_font->ReleaseResource();
4107 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4108 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4109 int wxCharCodeMSWToWX(int keySym
)
4114 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4115 case VK_BACK
: id
= WXK_BACK
; break;
4116 case VK_TAB
: id
= WXK_TAB
; break;
4117 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4118 case VK_RETURN
: id
= WXK_RETURN
; break;
4119 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4120 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4121 case VK_MENU
: id
= WXK_MENU
; break;
4122 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4123 case VK_SPACE
: id
= WXK_SPACE
; break;
4124 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4125 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4126 case VK_NEXT
: id
= WXK_NEXT
; break;
4127 case VK_END
: id
= WXK_END
; break;
4128 case VK_HOME
: id
= WXK_HOME
; break;
4129 case VK_LEFT
: id
= WXK_LEFT
; break;
4130 case VK_UP
: id
= WXK_UP
; break;
4131 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4132 case VK_DOWN
: id
= WXK_DOWN
; break;
4133 case VK_SELECT
: id
= WXK_SELECT
; break;
4134 case VK_PRINT
: id
= WXK_PRINT
; break;
4135 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4136 case VK_INSERT
: id
= WXK_INSERT
; break;
4137 case VK_DELETE
: id
= WXK_DELETE
; break;
4138 case VK_HELP
: id
= WXK_HELP
; break;
4139 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4140 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4141 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4142 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4143 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4144 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4145 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4146 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4147 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4148 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4149 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4150 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4151 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4152 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4153 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4154 case VK_F1
: id
= WXK_F1
; break;
4155 case VK_F2
: id
= WXK_F2
; break;
4156 case VK_F3
: id
= WXK_F3
; break;
4157 case VK_F4
: id
= WXK_F4
; break;
4158 case VK_F5
: id
= WXK_F5
; break;
4159 case VK_F6
: id
= WXK_F6
; break;
4160 case VK_F7
: id
= WXK_F7
; break;
4161 case VK_F8
: id
= WXK_F8
; break;
4162 case VK_F9
: id
= WXK_F9
; break;
4163 case VK_F10
: id
= WXK_F10
; break;
4164 case VK_F11
: id
= WXK_F11
; break;
4165 case VK_F12
: id
= WXK_F12
; break;
4166 case VK_F13
: id
= WXK_F13
; break;
4167 case VK_F14
: id
= WXK_F14
; break;
4168 case VK_F15
: id
= WXK_F15
; break;
4169 case VK_F16
: id
= WXK_F16
; break;
4170 case VK_F17
: id
= WXK_F17
; break;
4171 case VK_F18
: id
= WXK_F18
; break;
4172 case VK_F19
: id
= WXK_F19
; break;
4173 case VK_F20
: id
= WXK_F20
; break;
4174 case VK_F21
: id
= WXK_F21
; break;
4175 case VK_F22
: id
= WXK_F22
; break;
4176 case VK_F23
: id
= WXK_F23
; break;
4177 case VK_F24
: id
= WXK_F24
; break;
4178 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4179 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4187 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4193 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4194 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4195 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4196 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4197 case WXK_MENU
: keySym
= VK_MENU
; break;
4198 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4199 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4200 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4201 case WXK_END
: keySym
= VK_END
; break;
4202 case WXK_HOME
: keySym
= VK_HOME
; break;
4203 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4204 case WXK_UP
: keySym
= VK_UP
; break;
4205 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4206 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4207 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4208 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4209 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4210 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4211 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4212 case WXK_HELP
: keySym
= VK_HELP
; break;
4213 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4214 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4215 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4216 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4217 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4218 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4219 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4220 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4221 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4222 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4223 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4224 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4225 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4226 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4227 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4228 case WXK_F1
: keySym
= VK_F1
; break;
4229 case WXK_F2
: keySym
= VK_F2
; break;
4230 case WXK_F3
: keySym
= VK_F3
; break;
4231 case WXK_F4
: keySym
= VK_F4
; break;
4232 case WXK_F5
: keySym
= VK_F5
; break;
4233 case WXK_F6
: keySym
= VK_F6
; break;
4234 case WXK_F7
: keySym
= VK_F7
; break;
4235 case WXK_F8
: keySym
= VK_F8
; break;
4236 case WXK_F9
: keySym
= VK_F9
; break;
4237 case WXK_F10
: keySym
= VK_F10
; break;
4238 case WXK_F11
: keySym
= VK_F11
; break;
4239 case WXK_F12
: keySym
= VK_F12
; break;
4240 case WXK_F13
: keySym
= VK_F13
; break;
4241 case WXK_F14
: keySym
= VK_F14
; break;
4242 case WXK_F15
: keySym
= VK_F15
; break;
4243 case WXK_F16
: keySym
= VK_F16
; break;
4244 case WXK_F17
: keySym
= VK_F17
; break;
4245 case WXK_F18
: keySym
= VK_F18
; break;
4246 case WXK_F19
: keySym
= VK_F19
; break;
4247 case WXK_F20
: keySym
= VK_F20
; break;
4248 case WXK_F21
: keySym
= VK_F21
; break;
4249 case WXK_F22
: keySym
= VK_F22
; break;
4250 case WXK_F23
: keySym
= VK_F23
; break;
4251 case WXK_F24
: keySym
= VK_F24
; break;
4252 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4253 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4264 wxWindow
*wxGetActiveWindow()
4266 HWND hWnd
= GetActiveWindow();
4269 return wxFindWinFromHandle((WXHWND
) hWnd
);
4274 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4276 HWND hwnd
= (HWND
)hWnd
;
4278 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4279 // by code in msw/radiobox.cpp), for all the others we just search up the
4281 wxWindow
*win
= (wxWindow
*)NULL
;
4284 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4287 // all these hacks only work under Win32 anyhow
4291 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4292 // wxWindow class which overrides WM_GETDLGCODE processing to
4293 // do it as well, win would be already non NULL
4294 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4296 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4298 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4299 #endif // wxUSE_RADIOBOX
4301 // spin control text buddy window should be mapped to spin ctrl
4302 // itself so try it too
4303 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4306 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4308 #endif // wxUSE_SPINCTRL
4314 while ( hwnd
&& !win
)
4316 // this is a really ugly hack needed to avoid mistakenly returning the
4317 // parent frame wxWindow for the find/replace modeless dialog HWND -
4318 // this, in turn, is needed to call IsDialogMessage() from
4319 // wxApp::ProcessMessage() as for this we must return NULL from here
4321 // FIXME: this is clearly not the best way to do it but I think we'll
4322 // need to change HWND <-> wxWindow code more heavily than I can
4323 // do it now to fix it
4324 #ifndef __WXMICROWIN__
4325 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4327 // it's a dialog box, don't go upwards
4332 hwnd
= ::GetParent(hwnd
);
4333 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4339 #ifndef __WXMICROWIN__
4341 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4342 // in active frames and dialogs, regardless of where the focus is.
4343 static HHOOK wxTheKeyboardHook
= 0;
4344 static FARPROC wxTheKeyboardHookProc
= 0;
4345 int APIENTRY _EXPORT
4346 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4348 void wxSetKeyboardHook(bool doIt
)
4352 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4353 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4355 #if defined(__WIN32__) && !defined(__TWIN32__)
4356 GetCurrentThreadId()
4357 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4365 UnhookWindowsHookEx(wxTheKeyboardHook
);
4367 // avoids warning about statement with no effect (FreeProcInstance
4368 // doesn't do anything under Win32)
4369 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4370 FreeProcInstance(wxTheKeyboardHookProc
);
4375 int APIENTRY _EXPORT
4376 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4378 DWORD hiWord
= HIWORD(lParam
);
4379 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4381 int id
= wxCharCodeMSWToWX(wParam
);
4384 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4385 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4386 event
.m_altDown
= TRUE
;
4388 event
.m_eventObject
= NULL
;
4389 event
.m_keyCode
= id
;
4390 event
.m_shiftDown
= wxIsShiftDown();
4391 event
.m_controlDown
= wxIsCtrlDown();
4392 event
.SetTimestamp(s_currentMsg
.time
);
4394 wxWindow
*win
= wxGetActiveWindow();
4395 wxEvtHandler
*handler
;
4398 handler
= win
->GetEventHandler();
4399 event
.SetId(win
->GetId());
4407 if ( handler
&& handler
->ProcessEvent(event
) )
4415 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4418 #endif // !__WXMICROWIN__
4421 const char *wxGetMessageName(int message
)
4425 case 0x0000: return "WM_NULL";
4426 case 0x0001: return "WM_CREATE";
4427 case 0x0002: return "WM_DESTROY";
4428 case 0x0003: return "WM_MOVE";
4429 case 0x0005: return "WM_SIZE";
4430 case 0x0006: return "WM_ACTIVATE";
4431 case 0x0007: return "WM_SETFOCUS";
4432 case 0x0008: return "WM_KILLFOCUS";
4433 case 0x000A: return "WM_ENABLE";
4434 case 0x000B: return "WM_SETREDRAW";
4435 case 0x000C: return "WM_SETTEXT";
4436 case 0x000D: return "WM_GETTEXT";
4437 case 0x000E: return "WM_GETTEXTLENGTH";
4438 case 0x000F: return "WM_PAINT";
4439 case 0x0010: return "WM_CLOSE";
4440 case 0x0011: return "WM_QUERYENDSESSION";
4441 case 0x0012: return "WM_QUIT";
4442 case 0x0013: return "WM_QUERYOPEN";
4443 case 0x0014: return "WM_ERASEBKGND";
4444 case 0x0015: return "WM_SYSCOLORCHANGE";
4445 case 0x0016: return "WM_ENDSESSION";
4446 case 0x0017: return "WM_SYSTEMERROR";
4447 case 0x0018: return "WM_SHOWWINDOW";
4448 case 0x0019: return "WM_CTLCOLOR";
4449 case 0x001A: return "WM_WININICHANGE";
4450 case 0x001B: return "WM_DEVMODECHANGE";
4451 case 0x001C: return "WM_ACTIVATEAPP";
4452 case 0x001D: return "WM_FONTCHANGE";
4453 case 0x001E: return "WM_TIMECHANGE";
4454 case 0x001F: return "WM_CANCELMODE";
4455 case 0x0020: return "WM_SETCURSOR";
4456 case 0x0021: return "WM_MOUSEACTIVATE";
4457 case 0x0022: return "WM_CHILDACTIVATE";
4458 case 0x0023: return "WM_QUEUESYNC";
4459 case 0x0024: return "WM_GETMINMAXINFO";
4460 case 0x0026: return "WM_PAINTICON";
4461 case 0x0027: return "WM_ICONERASEBKGND";
4462 case 0x0028: return "WM_NEXTDLGCTL";
4463 case 0x002A: return "WM_SPOOLERSTATUS";
4464 case 0x002B: return "WM_DRAWITEM";
4465 case 0x002C: return "WM_MEASUREITEM";
4466 case 0x002D: return "WM_DELETEITEM";
4467 case 0x002E: return "WM_VKEYTOITEM";
4468 case 0x002F: return "WM_CHARTOITEM";
4469 case 0x0030: return "WM_SETFONT";
4470 case 0x0031: return "WM_GETFONT";
4471 case 0x0037: return "WM_QUERYDRAGICON";
4472 case 0x0039: return "WM_COMPAREITEM";
4473 case 0x0041: return "WM_COMPACTING";
4474 case 0x0044: return "WM_COMMNOTIFY";
4475 case 0x0046: return "WM_WINDOWPOSCHANGING";
4476 case 0x0047: return "WM_WINDOWPOSCHANGED";
4477 case 0x0048: return "WM_POWER";
4480 case 0x004A: return "WM_COPYDATA";
4481 case 0x004B: return "WM_CANCELJOURNAL";
4482 case 0x004E: return "WM_NOTIFY";
4483 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4484 case 0x0051: return "WM_INPUTLANGCHANGE";
4485 case 0x0052: return "WM_TCARD";
4486 case 0x0053: return "WM_HELP";
4487 case 0x0054: return "WM_USERCHANGED";
4488 case 0x0055: return "WM_NOTIFYFORMAT";
4489 case 0x007B: return "WM_CONTEXTMENU";
4490 case 0x007C: return "WM_STYLECHANGING";
4491 case 0x007D: return "WM_STYLECHANGED";
4492 case 0x007E: return "WM_DISPLAYCHANGE";
4493 case 0x007F: return "WM_GETICON";
4494 case 0x0080: return "WM_SETICON";
4497 case 0x0081: return "WM_NCCREATE";
4498 case 0x0082: return "WM_NCDESTROY";
4499 case 0x0083: return "WM_NCCALCSIZE";
4500 case 0x0084: return "WM_NCHITTEST";
4501 case 0x0085: return "WM_NCPAINT";
4502 case 0x0086: return "WM_NCACTIVATE";
4503 case 0x0087: return "WM_GETDLGCODE";
4504 case 0x00A0: return "WM_NCMOUSEMOVE";
4505 case 0x00A1: return "WM_NCLBUTTONDOWN";
4506 case 0x00A2: return "WM_NCLBUTTONUP";
4507 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4508 case 0x00A4: return "WM_NCRBUTTONDOWN";
4509 case 0x00A5: return "WM_NCRBUTTONUP";
4510 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4511 case 0x00A7: return "WM_NCMBUTTONDOWN";
4512 case 0x00A8: return "WM_NCMBUTTONUP";
4513 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4514 case 0x0100: return "WM_KEYDOWN";
4515 case 0x0101: return "WM_KEYUP";
4516 case 0x0102: return "WM_CHAR";
4517 case 0x0103: return "WM_DEADCHAR";
4518 case 0x0104: return "WM_SYSKEYDOWN";
4519 case 0x0105: return "WM_SYSKEYUP";
4520 case 0x0106: return "WM_SYSCHAR";
4521 case 0x0107: return "WM_SYSDEADCHAR";
4522 case 0x0108: return "WM_KEYLAST";
4525 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4526 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4527 case 0x010F: return "WM_IME_COMPOSITION";
4530 case 0x0110: return "WM_INITDIALOG";
4531 case 0x0111: return "WM_COMMAND";
4532 case 0x0112: return "WM_SYSCOMMAND";
4533 case 0x0113: return "WM_TIMER";
4534 case 0x0114: return "WM_HSCROLL";
4535 case 0x0115: return "WM_VSCROLL";
4536 case 0x0116: return "WM_INITMENU";
4537 case 0x0117: return "WM_INITMENUPOPUP";
4538 case 0x011F: return "WM_MENUSELECT";
4539 case 0x0120: return "WM_MENUCHAR";
4540 case 0x0121: return "WM_ENTERIDLE";
4541 case 0x0200: return "WM_MOUSEMOVE";
4542 case 0x0201: return "WM_LBUTTONDOWN";
4543 case 0x0202: return "WM_LBUTTONUP";
4544 case 0x0203: return "WM_LBUTTONDBLCLK";
4545 case 0x0204: return "WM_RBUTTONDOWN";
4546 case 0x0205: return "WM_RBUTTONUP";
4547 case 0x0206: return "WM_RBUTTONDBLCLK";
4548 case 0x0207: return "WM_MBUTTONDOWN";
4549 case 0x0208: return "WM_MBUTTONUP";
4550 case 0x0209: return "WM_MBUTTONDBLCLK";
4551 case 0x020A: return "WM_MOUSEWHEEL";
4552 case 0x0210: return "WM_PARENTNOTIFY";
4553 case 0x0211: return "WM_ENTERMENULOOP";
4554 case 0x0212: return "WM_EXITMENULOOP";
4557 case 0x0213: return "WM_NEXTMENU";
4558 case 0x0214: return "WM_SIZING";
4559 case 0x0215: return "WM_CAPTURECHANGED";
4560 case 0x0216: return "WM_MOVING";
4561 case 0x0218: return "WM_POWERBROADCAST";
4562 case 0x0219: return "WM_DEVICECHANGE";
4565 case 0x0220: return "WM_MDICREATE";
4566 case 0x0221: return "WM_MDIDESTROY";
4567 case 0x0222: return "WM_MDIACTIVATE";
4568 case 0x0223: return "WM_MDIRESTORE";
4569 case 0x0224: return "WM_MDINEXT";
4570 case 0x0225: return "WM_MDIMAXIMIZE";
4571 case 0x0226: return "WM_MDITILE";
4572 case 0x0227: return "WM_MDICASCADE";
4573 case 0x0228: return "WM_MDIICONARRANGE";
4574 case 0x0229: return "WM_MDIGETACTIVE";
4575 case 0x0230: return "WM_MDISETMENU";
4576 case 0x0233: return "WM_DROPFILES";
4579 case 0x0281: return "WM_IME_SETCONTEXT";
4580 case 0x0282: return "WM_IME_NOTIFY";
4581 case 0x0283: return "WM_IME_CONTROL";
4582 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4583 case 0x0285: return "WM_IME_SELECT";
4584 case 0x0286: return "WM_IME_CHAR";
4585 case 0x0290: return "WM_IME_KEYDOWN";
4586 case 0x0291: return "WM_IME_KEYUP";
4589 case 0x0300: return "WM_CUT";
4590 case 0x0301: return "WM_COPY";
4591 case 0x0302: return "WM_PASTE";
4592 case 0x0303: return "WM_CLEAR";
4593 case 0x0304: return "WM_UNDO";
4594 case 0x0305: return "WM_RENDERFORMAT";
4595 case 0x0306: return "WM_RENDERALLFORMATS";
4596 case 0x0307: return "WM_DESTROYCLIPBOARD";
4597 case 0x0308: return "WM_DRAWCLIPBOARD";
4598 case 0x0309: return "WM_PAINTCLIPBOARD";
4599 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4600 case 0x030B: return "WM_SIZECLIPBOARD";
4601 case 0x030C: return "WM_ASKCBFORMATNAME";
4602 case 0x030D: return "WM_CHANGECBCHAIN";
4603 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4604 case 0x030F: return "WM_QUERYNEWPALETTE";
4605 case 0x0310: return "WM_PALETTEISCHANGING";
4606 case 0x0311: return "WM_PALETTECHANGED";
4609 // common controls messages - although they're not strictly speaking
4610 // standard, it's nice to decode them nevertheless
4613 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4614 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4615 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4616 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4617 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4618 case 0x1000 + 5: return "LVM_GETITEMA";
4619 case 0x1000 + 75: return "LVM_GETITEMW";
4620 case 0x1000 + 6: return "LVM_SETITEMA";
4621 case 0x1000 + 76: return "LVM_SETITEMW";
4622 case 0x1000 + 7: return "LVM_INSERTITEMA";
4623 case 0x1000 + 77: return "LVM_INSERTITEMW";
4624 case 0x1000 + 8: return "LVM_DELETEITEM";
4625 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4626 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4627 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4628 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4629 case 0x1000 + 13: return "LVM_FINDITEMA";
4630 case 0x1000 + 83: return "LVM_FINDITEMW";
4631 case 0x1000 + 14: return "LVM_GETITEMRECT";
4632 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4633 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4634 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4635 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4636 case 0x1000 + 18: return "LVM_HITTEST";
4637 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4638 case 0x1000 + 20: return "LVM_SCROLL";
4639 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4640 case 0x1000 + 22: return "LVM_ARRANGE";
4641 case 0x1000 + 23: return "LVM_EDITLABELA";
4642 case 0x1000 + 118: return "LVM_EDITLABELW";
4643 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4644 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4645 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4646 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4647 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4648 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4649 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4650 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4651 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4652 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4653 case 0x1000 + 31: return "LVM_GETHEADER";
4654 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4655 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4656 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4657 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4658 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4659 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4660 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4661 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4662 case 0x1000 + 41: return "LVM_GETORIGIN";
4663 case 0x1000 + 42: return "LVM_UPDATE";
4664 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4665 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4666 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4667 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4668 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4669 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4670 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4671 case 0x1000 + 48: return "LVM_SORTITEMS";
4672 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4673 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4674 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4675 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4676 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4677 case 0x1000 + 53: return "LVM_SETICONSPACING";
4678 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4679 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4680 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4681 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4682 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4683 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4684 case 0x1000 + 60: return "LVM_SETHOTITEM";
4685 case 0x1000 + 61: return "LVM_GETHOTITEM";
4686 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4687 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4688 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4689 case 0x1000 + 65: return "LVM_SETWORKAREA";
4692 case 0x1100 + 0: return "TVM_INSERTITEMA";
4693 case 0x1100 + 50: return "TVM_INSERTITEMW";
4694 case 0x1100 + 1: return "TVM_DELETEITEM";
4695 case 0x1100 + 2: return "TVM_EXPAND";
4696 case 0x1100 + 4: return "TVM_GETITEMRECT";
4697 case 0x1100 + 5: return "TVM_GETCOUNT";
4698 case 0x1100 + 6: return "TVM_GETINDENT";
4699 case 0x1100 + 7: return "TVM_SETINDENT";
4700 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4701 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4702 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4703 case 0x1100 + 11: return "TVM_SELECTITEM";
4704 case 0x1100 + 12: return "TVM_GETITEMA";
4705 case 0x1100 + 62: return "TVM_GETITEMW";
4706 case 0x1100 + 13: return "TVM_SETITEMA";
4707 case 0x1100 + 63: return "TVM_SETITEMW";
4708 case 0x1100 + 14: return "TVM_EDITLABELA";
4709 case 0x1100 + 65: return "TVM_EDITLABELW";
4710 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4711 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4712 case 0x1100 + 17: return "TVM_HITTEST";
4713 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4714 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4715 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4716 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4717 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4718 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4719 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4720 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4721 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4724 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4725 case 0x1200 + 1: return "HDM_INSERTITEMA";
4726 case 0x1200 + 10: return "HDM_INSERTITEMW";
4727 case 0x1200 + 2: return "HDM_DELETEITEM";
4728 case 0x1200 + 3: return "HDM_GETITEMA";
4729 case 0x1200 + 11: return "HDM_GETITEMW";
4730 case 0x1200 + 4: return "HDM_SETITEMA";
4731 case 0x1200 + 12: return "HDM_SETITEMW";
4732 case 0x1200 + 5: return "HDM_LAYOUT";
4733 case 0x1200 + 6: return "HDM_HITTEST";
4734 case 0x1200 + 7: return "HDM_GETITEMRECT";
4735 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4736 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4737 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4738 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4739 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4740 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4741 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4744 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4745 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4746 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4747 case 0x1300 + 5: return "TCM_GETITEMA";
4748 case 0x1300 + 60: return "TCM_GETITEMW";
4749 case 0x1300 + 6: return "TCM_SETITEMA";
4750 case 0x1300 + 61: return "TCM_SETITEMW";
4751 case 0x1300 + 7: return "TCM_INSERTITEMA";
4752 case 0x1300 + 62: return "TCM_INSERTITEMW";
4753 case 0x1300 + 8: return "TCM_DELETEITEM";
4754 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4755 case 0x1300 + 10: return "TCM_GETITEMRECT";
4756 case 0x1300 + 11: return "TCM_GETCURSEL";
4757 case 0x1300 + 12: return "TCM_SETCURSEL";
4758 case 0x1300 + 13: return "TCM_HITTEST";
4759 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4760 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4761 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4762 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4763 case 0x1300 + 43: return "TCM_SETPADDING";
4764 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4765 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4766 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4767 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4768 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4769 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4770 case 0x1300 + 50: return "TCM_DESELECTALL";
4773 case WM_USER
+1: return "TB_ENABLEBUTTON";
4774 case WM_USER
+2: return "TB_CHECKBUTTON";
4775 case WM_USER
+3: return "TB_PRESSBUTTON";
4776 case WM_USER
+4: return "TB_HIDEBUTTON";
4777 case WM_USER
+5: return "TB_INDETERMINATE";
4778 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4779 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4780 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4781 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4782 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4783 case WM_USER
+17: return "TB_SETSTATE";
4784 case WM_USER
+18: return "TB_GETSTATE";
4785 case WM_USER
+19: return "TB_ADDBITMAP";
4786 case WM_USER
+20: return "TB_ADDBUTTONS";
4787 case WM_USER
+21: return "TB_INSERTBUTTON";
4788 case WM_USER
+22: return "TB_DELETEBUTTON";
4789 case WM_USER
+23: return "TB_GETBUTTON";
4790 case WM_USER
+24: return "TB_BUTTONCOUNT";
4791 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4792 case WM_USER
+26: return "TB_SAVERESTOREA";
4793 case WM_USER
+76: return "TB_SAVERESTOREW";
4794 case WM_USER
+27: return "TB_CUSTOMIZE";
4795 case WM_USER
+28: return "TB_ADDSTRINGA";
4796 case WM_USER
+77: return "TB_ADDSTRINGW";
4797 case WM_USER
+29: return "TB_GETITEMRECT";
4798 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4799 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4800 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4801 case WM_USER
+33: return "TB_AUTOSIZE";
4802 case WM_USER
+35: return "TB_GETTOOLTIPS";
4803 case WM_USER
+36: return "TB_SETTOOLTIPS";
4804 case WM_USER
+37: return "TB_SETPARENT";
4805 case WM_USER
+39: return "TB_SETROWS";
4806 case WM_USER
+40: return "TB_GETROWS";
4807 case WM_USER
+42: return "TB_SETCMDID";
4808 case WM_USER
+43: return "TB_CHANGEBITMAP";
4809 case WM_USER
+44: return "TB_GETBITMAP";
4810 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4811 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4812 case WM_USER
+46: return "TB_REPLACEBITMAP";
4813 case WM_USER
+47: return "TB_SETINDENT";
4814 case WM_USER
+48: return "TB_SETIMAGELIST";
4815 case WM_USER
+49: return "TB_GETIMAGELIST";
4816 case WM_USER
+50: return "TB_LOADIMAGES";
4817 case WM_USER
+51: return "TB_GETRECT";
4818 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4819 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4820 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4821 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4822 case WM_USER
+56: return "TB_SETSTYLE";
4823 case WM_USER
+57: return "TB_GETSTYLE";
4824 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4825 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4826 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4827 case WM_USER
+61: return "TB_GETTEXTROWS";
4828 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4833 static char s_szBuf
[128];
4834 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4838 #endif //__WXDEBUG__
4840 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4841 int *x
, int *y
, WPARAM
*flags
)
4843 // construct the key mask
4844 WPARAM
& fwKeys
= *flags
;
4846 fwKeys
= MK_RBUTTON
;
4847 if ( wxIsCtrlDown() )
4848 fwKeys
|= MK_CONTROL
;
4849 if ( wxIsShiftDown() )
4852 // simulate right mouse button click
4853 DWORD dwPos
= ::GetMessagePos();
4854 *x
= GET_X_LPARAM(dwPos
);
4855 *y
= GET_Y_LPARAM(dwPos
);
4857 win
->ScreenToClient(x
, y
);
4860 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4864 HWND hwnd
= GetHwndOf(win
);
4865 HDC hdc
= ::GetDC(hwnd
);
4867 #if !wxDIALOG_UNIT_COMPATIBILITY
4868 // and select the current font into it
4869 HFONT hfont
= GetHfontOf(win
->GetFont());
4872 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4876 // finally retrieve the text metrics from it
4877 GetTextMetrics(hdc
, &tm
);
4879 #if !wxDIALOG_UNIT_COMPATIBILITY
4883 (void)::SelectObject(hdc
, hfont
);
4887 ::ReleaseDC(hwnd
, hdc
);
4892 // Find the wxWindow at the current mouse position, returning the mouse
4894 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4896 return wxFindWindowAtPoint(wxGetMousePosition());
4899 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4904 HWND hWndHit
= ::WindowFromPoint(pt2
);
4906 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4907 HWND hWnd
= hWndHit
;
4909 // Try to find a window with a wxWindow associated with it
4910 while (!win
&& (hWnd
!= 0))
4912 hWnd
= ::GetParent(hWnd
);
4913 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
4918 // Get the current mouse position.
4919 wxPoint
wxGetMousePosition()
4922 GetCursorPos( & pt
);
4923 return wxPoint(pt
.x
, pt
.y
);