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 MSWDetachWindowMenu();
325 #ifndef __WXUNIVERSAL__
326 // VS: make sure there's no wxFrame with last focus set to us:
327 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
329 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
332 if ( frame
->GetLastFocus() == this )
334 frame
->SetLastFocus((wxWindow
*)NULL
);
339 #endif // __WXUNIVERSAL__
341 // VS: destroy children first and _then_ detach *this from its parent.
342 // If we'd do it the other way around, children wouldn't be able
343 // find their parent frame (see above).
347 m_parent
->RemoveChild(this);
351 // VZ: test temp removed to understand what really happens here
352 //if (::IsWindow(GetHwnd()))
354 if ( !::DestroyWindow(GetHwnd()) )
355 wxLogLastError(wxT("DestroyWindow"));
358 // remove hWnd <-> wxWindow association
359 wxRemoveHandleAssociation(this);
363 // real construction (Init() must have been called before!)
364 bool wxWindowMSW::Create(wxWindow
*parent
,
369 const wxString
& name
)
371 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
374 // wxGTK doesn't allow to create controls with static box as the parent so
375 // this will result in a crash when the program is ported to wxGTK - warn
378 // the correct solution is to create the controls as siblings of the
380 wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
),
381 _T("wxStaticBox can't be used as a window parent!") );
382 #endif // wxUSE_STATBOX
384 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
387 parent
->AddChild(this);
389 // all windows are created visible
390 DWORD msflags
= WS_CHILD
| WS_VISIBLE
;
392 #ifdef __WXUNIVERSAL__
393 // no 3d effects, we draw them ourselves
395 #else // !wxUniversal
396 if ( style
& wxCLIP_CHILDREN
)
397 msflags
|= WS_CLIPCHILDREN
;
398 if ( style
& wxCLIP_SIBLINGS
)
399 msflags
|= WS_CLIPSIBLINGS
;
402 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
);
404 // Even with extended styles, need to combine with WS_BORDER
405 // for them to look right.
407 (m_windowStyle
& (wxBORDER
|
413 msflags
|= WS_BORDER
;
416 // calculate the value to return from WM_GETDLGCODE handler
417 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
419 // want everything: i.e. all keys and WM_CHAR message
420 m_lDlgCode
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
421 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
423 #endif // wxUniversal/!wxUniversal
425 if ( style
& wxPOPUP_WINDOW
)
427 // a popup window floats on top of everything
428 exStyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
430 // it is also created hidden as other top level windows
431 msflags
&= ~WS_VISIBLE
;
435 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
);
438 // ---------------------------------------------------------------------------
440 // ---------------------------------------------------------------------------
442 void wxWindowMSW::SetFocus()
444 HWND hWnd
= GetHwnd();
445 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
447 #ifndef __WXMICROWIN__
451 if ( !::SetFocus(hWnd
) )
453 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
454 // was there really an error?
455 DWORD dwRes
= ::GetLastError();
458 HWND hwndFocus
= ::GetFocus();
459 if ( hwndFocus
!= hWnd
)
461 wxLogApiError(_T("SetFocus"), dwRes
);
468 // Get the window with the focus
469 wxWindow
*wxWindowBase::FindFocus()
471 HWND hWnd
= ::GetFocus();
474 return wxGetWindowFromHWND((WXHWND
)hWnd
);
480 bool wxWindowMSW::Enable(bool enable
)
482 if ( !wxWindowBase::Enable(enable
) )
485 HWND hWnd
= GetHwnd();
487 ::EnableWindow(hWnd
, (BOOL
)enable
);
489 // VZ: no, this is a bad idea: imagine that you have a dialog with some
490 // disabled controls and disable it - you really wouldn't like the
491 // disabled controls be reenabled too when you reenable the dialog!
493 wxWindowList::Node
*node
= GetChildren().GetFirst();
496 wxWindow
*child
= node
->GetData();
497 child
->Enable(enable
);
499 node
= node
->GetNext();
506 bool wxWindowMSW::Show(bool show
)
508 if ( !wxWindowBase::Show(show
) )
511 HWND hWnd
= GetHwnd();
512 int cshow
= show
? SW_SHOW
: SW_HIDE
;
513 ::ShowWindow(hWnd
, cshow
);
517 wxBringWindowToTop(hWnd
);
523 // Raise the window to the top of the Z order
524 void wxWindowMSW::Raise()
526 wxBringWindowToTop(GetHwnd());
529 // Lower the window to the bottom of the Z order
530 void wxWindowMSW::Lower()
532 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
533 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
536 void wxWindowMSW::SetTitle( const wxString
& title
)
538 SetWindowText(GetHwnd(), title
.c_str());
541 wxString
wxWindowMSW::GetTitle() const
543 return wxGetWindowText(GetHWND());
546 void wxWindowMSW::CaptureMouse()
548 HWND hWnd
= GetHwnd();
555 void wxWindowMSW::ReleaseMouse()
557 if ( !::ReleaseCapture() )
559 wxLogLastError(_T("ReleaseCapture"));
563 /* static */ wxWindow
*wxWindowBase::GetCapture()
565 HWND hwnd
= ::GetCapture();
566 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
569 bool wxWindowMSW::SetFont(const wxFont
& font
)
571 if ( !wxWindowBase::SetFont(font
) )
577 HWND hWnd
= GetHwnd();
580 WXHANDLE hFont
= m_font
.GetResourceHandle();
582 wxASSERT_MSG( hFont
, wxT("should have valid font") );
584 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
589 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
591 if ( !wxWindowBase::SetCursor(cursor
) )
599 HWND hWnd
= GetHwnd();
601 // Change the cursor NOW if we're within the correct window
603 ::GetCursorPos(&point
);
605 RECT rect
= wxGetWindowRect(hWnd
);
607 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
608 ::SetCursor(GetHcursorOf(m_cursor
));
614 void wxWindowMSW::WarpPointer (int x
, int y
)
616 ClientToScreen(&x
, &y
);
618 if ( !::SetCursorPos(x
, y
) )
620 wxLogLastError(_T("SetCursorPos"));
624 #if WXWIN_COMPATIBILITY
625 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
628 #endif // WXWIN_COMPATIBILITY
630 // ---------------------------------------------------------------------------
632 // ---------------------------------------------------------------------------
634 #if WXWIN_COMPATIBILITY
635 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
637 #if defined(__WIN95__)
641 // Try to adjust the range to cope with page size > 1
642 // - a Windows API quirk
643 int pageSize
= GetScrollPage(orient
);
644 if ( pageSize
> 1 && range
> 0)
646 range1
+= (pageSize
- 1);
652 if ( orient
== wxHORIZONTAL
) {
658 info
.cbSize
= sizeof(SCROLLINFO
);
659 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
663 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
665 HWND hWnd
= GetHwnd();
667 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
670 if ( orient
== wxHORIZONTAL
)
675 HWND hWnd
= GetHwnd();
677 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
681 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
683 #if defined(__WIN95__)
687 if ( orient
== wxHORIZONTAL
) {
695 info
.cbSize
= sizeof(SCROLLINFO
);
698 info
.fMask
= SIF_PAGE
;
700 HWND hWnd
= GetHwnd();
702 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
704 if ( orient
== wxHORIZONTAL
)
711 int wxWindowMSW::OldGetScrollRange(int orient
) const
714 if ( orient
== wxHORIZONTAL
)
719 #if __WATCOMC__ && defined(__WINDOWS_386__)
720 short minPos
, maxPos
;
724 HWND hWnd
= GetHwnd();
727 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
728 #if defined(__WIN95__)
729 // Try to adjust the range to cope with page size > 1
730 // - a Windows API quirk
731 int pageSize
= GetScrollPage(orient
);
734 maxPos
-= (pageSize
- 1);
743 int wxWindowMSW::GetScrollPage(int orient
) const
745 if ( orient
== wxHORIZONTAL
)
751 #endif // WXWIN_COMPATIBILITY
753 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
755 #ifdef __WXMICROWIN__
756 return ::GetScrollPosWX(hWnd
, wOrient
);
758 return ::GetScrollPos(hWnd
, wOrient
);
762 int wxWindowMSW::GetScrollPos(int orient
) const
765 if ( orient
== wxHORIZONTAL
)
770 HWND hWnd
= GetHwnd();
771 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
773 return GetScrollPosition(hWnd
, wOrient
);
776 // This now returns the whole range, not just the number
777 // of positions that we can scroll.
778 int wxWindowMSW::GetScrollRange(int orient
) const
781 if ( orient
== wxHORIZONTAL
)
786 #if __WATCOMC__ && defined(__WINDOWS_386__)
787 short minPos
, maxPos
;
791 HWND hWnd
= GetHwnd();
794 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
795 #if defined(__WIN95__)
796 // Try to adjust the range to cope with page size > 1
797 // - a Windows API quirk
798 int pageSize
= GetScrollThumb(orient
);
801 maxPos
-= (pageSize
- 1);
803 // October 10th: new range concept.
813 int wxWindowMSW::GetScrollThumb(int orient
) const
815 if ( orient
== wxHORIZONTAL
)
821 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
823 HWND hWnd
= GetHwnd();
824 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
826 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
828 #if defined(__WIN95__)
830 info
.cbSize
= sizeof(SCROLLINFO
);
834 info
.fMask
= SIF_POS
;
836 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
838 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
839 #endif // __WIN95__/!__WIN95__
842 // New function that will replace some of the above.
843 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
844 int range
, bool refresh
)
846 #if defined(__WIN95__)
847 int oldRange
= range
- thumbVisible
;
849 int range1
= oldRange
;
851 // Try to adjust the range to cope with page size > 1
852 // - a Windows API quirk
853 int pageSize
= thumbVisible
;
854 if ( pageSize
> 1 && range
> 0)
856 range1
+= (pageSize
- 1);
862 if ( orient
== wxHORIZONTAL
) {
868 info
.cbSize
= sizeof(SCROLLINFO
);
869 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
873 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
875 HWND hWnd
= GetHwnd();
877 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
880 if ( orient
== wxHORIZONTAL
)
885 HWND hWnd
= GetHwnd();
888 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
889 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
892 if ( orient
== wxHORIZONTAL
) {
893 m_xThumbSize
= thumbVisible
;
895 m_yThumbSize
= thumbVisible
;
899 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
904 rect
.left
= prect
->x
;
906 rect
.right
= prect
->x
+ prect
->width
;
907 rect
.bottom
= prect
->y
+ prect
->height
;
910 ::ScrollWindow(GetHwnd(), dx
, dy
, prect
? &rect
: NULL
, NULL
);
913 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
915 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
918 for ( int n
= 0; n
< count
; n
++ )
920 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
922 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
925 // don't bother to continue, we're already at top/bottom
932 return pos
!= posStart
;
935 bool wxWindowMSW::ScrollLines(int lines
)
937 bool down
= lines
> 0;
939 return ScrollVertically(GetHwnd(),
940 down
? SB_LINEDOWN
: SB_LINEUP
,
941 down
? lines
: -lines
);
944 bool wxWindowMSW::ScrollPages(int pages
)
946 bool down
= pages
> 0;
948 return ScrollVertically(GetHwnd(),
949 down
? SB_PAGEDOWN
: SB_PAGEUP
,
950 down
? pages
: -pages
);
953 // ---------------------------------------------------------------------------
955 // ---------------------------------------------------------------------------
957 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
959 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
961 HWND hwnd
= (HWND
)hWnd
;
962 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
964 wxAssociateWinWithHandle(hwnd
, this);
966 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
968 // we don't need to subclass the window of our own class (in the Windows
969 // sense of the word)
970 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
972 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
976 // don't bother restoring it neither
981 void wxWindowMSW::UnsubclassWin()
983 wxRemoveHandleAssociation(this);
985 // Restore old Window proc
986 HWND hwnd
= GetHwnd();
991 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
995 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
997 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1000 m_oldWndProc
= NULL
;
1005 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
1007 #if wxUSE_UNICODE_MSLU
1008 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
1009 // because it doesn't return pointer to the real wnd proc but rather a handle
1010 // of a fake proc that does Unicode<->ANSI translation.
1012 // The hack bellow works, because WNDCLASS contains original window handler
1013 // rather that the unicows fake one. This may not be on purpose, though; if
1014 // it stops working with future versions of unicows.dll, we can override
1015 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
1016 // Unicows_RegisterClass to our own versions that keep track of
1017 // fake<->real wnd proc mapping.
1019 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
1020 // with RegisterClass!!
1022 static wxChar buffer
[512];
1025 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1026 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1027 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1029 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1034 // Make a Windows extended style from the given wxWindows window style
1035 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1037 WXDWORD exStyle
= 0;
1038 if ( style
& wxTRANSPARENT_WINDOW
)
1039 exStyle
|= WS_EX_TRANSPARENT
;
1041 if ( !eliminateBorders
)
1043 if ( style
& wxSUNKEN_BORDER
)
1044 exStyle
|= WS_EX_CLIENTEDGE
;
1045 if ( style
& wxDOUBLE_BORDER
)
1046 exStyle
|= WS_EX_DLGMODALFRAME
;
1047 #if defined(__WIN95__)
1048 if ( style
& wxRAISED_BORDER
)
1049 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1050 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1051 if ( style
& wxSTATIC_BORDER
)
1052 exStyle
|= WS_EX_STATICEDGE
;
1059 // Determines whether native 3D effects or CTL3D should be used,
1060 // applying a default border style if required, and returning an extended
1061 // style to pass to CreateWindowEx.
1062 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1065 // If matches certain criteria, then assume no 3D effects
1066 // unless specifically requested (dealt with in MakeExtendedStyle)
1069 || !IsKindOf(CLASSINFO(wxControl
))
1070 #endif // wxUSE_CONTROLS
1071 || (m_windowStyle
& wxNO_BORDER
) )
1074 return MakeExtendedStyle(m_windowStyle
);
1077 // Determine whether we should be using 3D effects or not.
1078 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1080 // 1) App can specify global 3D effects
1081 *want3D
= wxTheApp
->GetAuto3D();
1083 // 2) If the parent is being drawn with user colours, or simple border specified,
1084 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1085 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1088 // 3) Control can override this global setting by defining
1089 // a border style, e.g. wxSUNKEN_BORDER
1090 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1093 // 4) If it's a special border, CTL3D can't cope so we want a native border
1094 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1095 (m_windowStyle
& wxSTATIC_BORDER
) )
1098 nativeBorder
= TRUE
;
1101 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1102 // effects from extended style
1105 nativeBorder
= FALSE
;
1108 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1110 // If we want 3D, but haven't specified a border here,
1111 // apply the default border style specified.
1112 // TODO what about non-Win95 WIN32? Does it have borders?
1113 #if defined(__WIN95__) && !wxUSE_CTL3D
1114 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1115 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1116 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1122 #if WXWIN_COMPATIBILITY
1123 // If nothing defined for this, try the parent.
1124 // E.g. we may be a button loaded from a resource, with no callback function
1126 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1128 if ( GetEventHandler()->ProcessEvent(event
) )
1131 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1133 #endif // WXWIN_COMPATIBILITY_2
1135 #if WXWIN_COMPATIBILITY
1136 wxObject
* wxWindowMSW::GetChild(int number
) const
1138 // Return a pointer to the Nth object in the Panel
1139 wxNode
*node
= GetChildren().First();
1142 node
= node
->Next();
1145 wxObject
*obj
= (wxObject
*)node
->Data();
1151 #endif // WXWIN_COMPATIBILITY
1153 // Setup background and foreground colours correctly
1154 void wxWindowMSW::SetupColours()
1157 SetBackgroundColour(GetParent()->GetBackgroundColour());
1160 bool wxWindowMSW::IsMouseInWindow() const
1162 // get the mouse position
1164 ::GetCursorPos(&pt
);
1166 // find the window which currently has the cursor and go up the window
1167 // chain until we find this window - or exhaust it
1168 HWND hwnd
= ::WindowFromPoint(pt
);
1169 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1170 hwnd
= ::GetParent(hwnd
);
1172 return hwnd
!= NULL
;
1175 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1177 // Check if we need to send a LEAVE event
1178 if ( m_mouseInWindow
)
1180 if ( !IsMouseInWindow() )
1182 // Generate a LEAVE event
1183 m_mouseInWindow
= FALSE
;
1185 // Unfortunately the mouse button and keyboard state may have
1186 // changed by the time the OnIdle function is called, so 'state'
1187 // may be meaningless.
1189 if ( wxIsShiftDown() )
1191 if ( wxIsCtrlDown() )
1192 state
|= MK_CONTROL
;
1193 if ( GetKeyState( VK_LBUTTON
) )
1194 state
|= MK_LBUTTON
;
1195 if ( GetKeyState( VK_MBUTTON
) )
1196 state
|= MK_MBUTTON
;
1197 if ( GetKeyState( VK_RBUTTON
) )
1198 state
|= MK_RBUTTON
;
1201 if ( !::GetCursorPos(&pt
) )
1203 wxLogLastError(_T("GetCursorPos"));
1206 // we need to have client coordinates here for symmetry with
1207 // wxEVT_ENTER_WINDOW
1208 RECT rect
= wxGetWindowRect(GetHwnd());
1212 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1213 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1215 (void)GetEventHandler()->ProcessEvent(event2
);
1222 // Set this window to be the child of 'parent'.
1223 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1225 if ( !wxWindowBase::Reparent(parent
) )
1228 HWND hWndChild
= GetHwnd();
1229 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1231 ::SetParent(hWndChild
, hWndParent
);
1236 void wxWindowMSW::Clear()
1238 wxClientDC
dc((wxWindow
*)this);
1239 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1240 dc
.SetBackground(brush
);
1244 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1246 #ifndef __WXMICROWIN__
1247 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1251 void wxWindowMSW::Freeze()
1253 SendSetRedraw(GetHwnd(), FALSE
);
1256 void wxWindowMSW::Thaw()
1258 SendSetRedraw(GetHwnd(), TRUE
);
1260 // we need to refresh everything or otherwise he invalidated area is not
1265 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1267 HWND hWnd
= GetHwnd();
1273 mswRect
.left
= rect
->x
;
1274 mswRect
.top
= rect
->y
;
1275 mswRect
.right
= rect
->x
+ rect
->width
;
1276 mswRect
.bottom
= rect
->y
+ rect
->height
;
1278 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1281 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1285 void wxWindowMSW::Update()
1287 if ( !::UpdateWindow(GetHwnd()) )
1289 wxLogLastError(_T("UpdateWindow"));
1292 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1293 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1294 // handler needs to be really drawn right now
1299 // ---------------------------------------------------------------------------
1301 // ---------------------------------------------------------------------------
1303 #if wxUSE_DRAG_AND_DROP
1305 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1307 if ( m_dropTarget
!= 0 ) {
1308 m_dropTarget
->Revoke(m_hWnd
);
1309 delete m_dropTarget
;
1312 m_dropTarget
= pDropTarget
;
1313 if ( m_dropTarget
!= 0 )
1314 m_dropTarget
->Register(m_hWnd
);
1317 #endif // wxUSE_DRAG_AND_DROP
1319 // old style file-manager drag&drop support: we retain the old-style
1320 // DragAcceptFiles in parallel with SetDropTarget.
1321 void wxWindowMSW::DragAcceptFiles(bool accept
)
1323 HWND hWnd
= GetHwnd();
1325 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1328 // ----------------------------------------------------------------------------
1330 // ----------------------------------------------------------------------------
1334 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1336 wxWindowBase::DoSetToolTip(tooltip
);
1339 m_tooltip
->SetWindow(this);
1342 #endif // wxUSE_TOOLTIPS
1344 // ---------------------------------------------------------------------------
1345 // moving and resizing
1346 // ---------------------------------------------------------------------------
1349 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1351 RECT rect
= wxGetWindowRect(GetHwnd());
1354 *x
= rect
.right
- rect
.left
;
1356 *y
= rect
.bottom
- rect
.top
;
1359 // Get size *available for subwindows* i.e. excluding menu bar etc.
1360 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1362 RECT rect
= wxGetClientRect(GetHwnd());
1370 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1372 RECT rect
= wxGetWindowRect(GetHwnd());
1375 point
.x
= rect
.left
;
1378 // we do the adjustments with respect to the parent only for the "real"
1379 // children, not for the dialogs/frames
1380 if ( !IsTopLevel() )
1382 HWND hParentWnd
= 0;
1383 wxWindow
*parent
= GetParent();
1385 hParentWnd
= GetWinHwnd(parent
);
1387 // Since we now have the absolute screen coords, if there's a parent we
1388 // must subtract its top left corner
1391 ::ScreenToClient(hParentWnd
, &point
);
1396 // We may be faking the client origin. So a window that's really at (0,
1397 // 30) may appear (to wxWin apps) to be at (0, 0).
1398 wxPoint
pt(parent
->GetClientAreaOrigin());
1410 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1418 ::ScreenToClient(GetHwnd(), &pt
);
1426 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1434 ::ClientToScreen(GetHwnd(), &pt
);
1442 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1444 // TODO: is this consistent with other platforms?
1445 // Still, negative width or height shouldn't be allowed
1450 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1452 wxLogLastError(wxT("MoveWindow"));
1456 // set the size of the window: if the dimensions are positive, just use them,
1457 // but if any of them is equal to -1, it means that we must find the value for
1458 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1459 // which case -1 is a valid value for x and y)
1461 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1462 // the width/height to best suit our contents, otherwise we reuse the current
1464 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1466 // get the current size and position...
1467 int currentX
, currentY
;
1468 GetPosition(¤tX
, ¤tY
);
1469 int currentW
,currentH
;
1470 GetSize(¤tW
, ¤tH
);
1472 // ... and don't do anything (avoiding flicker) if it's already ok
1473 if ( x
== currentX
&& y
== currentY
&&
1474 width
== currentW
&& height
== currentH
)
1479 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1481 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1484 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1486 wxSize
size(-1, -1);
1489 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1491 size
= DoGetBestSize();
1496 // just take the current one
1503 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1507 size
= DoGetBestSize();
1509 //else: already called DoGetBestSize() above
1515 // just take the current one
1520 DoMoveWindow(x
, y
, width
, height
);
1523 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1525 // setting the client size is less obvious than it it could have been
1526 // because in the result of changing the total size the window scrollbar
1527 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1528 // will not be correct as the difference between the total and client size
1529 // changes - so we keep changing it until we get it right
1531 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1532 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1533 // may become 3 if the window had 0 size originally and so we didn't
1534 // calculate the scrollbar correction correctly during the first iteration)
1535 // but just to be on the safe side we check for it instead of making it an
1536 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1537 for ( int i
= 0; i
< 4; i
++ )
1540 ::GetClientRect(GetHwnd(), &rectClient
);
1542 // if the size is already ok, stop here (rectClient.left = top = 0)
1543 if ( rectClient
.right
== width
&& rectClient
.bottom
== height
)
1550 // how did it happen? maybe OnSize() handler does something really
1551 // strange in this class?
1552 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1557 int widthClient
= width
,
1558 heightClient
= height
;
1560 // Find the difference between the entire window (title bar and all)
1561 // and the client area; add this to the new client size to move the
1564 ::GetWindowRect(GetHwnd(), &rectWin
);
1566 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1567 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1570 point
.x
= rectWin
.left
;
1571 point
.y
= rectWin
.top
;
1573 // MoveWindow positions the child windows relative to the parent, so
1574 // adjust if necessary
1575 if ( !IsTopLevel() )
1577 wxWindow
*parent
= GetParent();
1580 ::ScreenToClient(GetHwndOf(parent
), &point
);
1584 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1588 // For implementation purposes - sometimes decorations make the client area
1590 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1592 return wxPoint(0, 0);
1595 // ---------------------------------------------------------------------------
1597 // ---------------------------------------------------------------------------
1599 int wxWindowMSW::GetCharHeight() const
1601 return wxGetTextMetrics(this).tmHeight
;
1604 int wxWindowMSW::GetCharWidth() const
1606 // +1 is needed because Windows apparently adds it when calculating the
1607 // dialog units size in pixels
1608 #if wxDIALOG_UNIT_COMPATIBILITY
1609 return wxGetTextMetrics(this).tmAveCharWidth
;
1611 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1615 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1617 int *descent
, int *externalLeading
,
1618 const wxFont
*theFont
) const
1620 const wxFont
*fontToUse
= theFont
;
1622 fontToUse
= &m_font
;
1624 HWND hWnd
= GetHwnd();
1625 HDC dc
= ::GetDC(hWnd
);
1629 if ( fontToUse
&& fontToUse
->Ok() )
1631 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1633 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1638 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1639 GetTextMetrics(dc
, &tm
);
1641 if ( fontToUse
&& fnt
&& hfontOld
)
1642 SelectObject(dc
, hfontOld
);
1644 ReleaseDC(hWnd
, dc
);
1651 *descent
= tm
.tmDescent
;
1652 if ( externalLeading
)
1653 *externalLeading
= tm
.tmExternalLeading
;
1656 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1657 // ---------------------------------------------------------------------------
1658 // Caret manipulation
1659 // ---------------------------------------------------------------------------
1661 void wxWindowMSW::CreateCaret(int w
, int h
)
1663 SetCaret(new wxCaret(this, w
, h
));
1666 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1668 wxFAIL_MSG("not implemented");
1671 void wxWindowMSW::ShowCaret(bool show
)
1673 wxCHECK_RET( m_caret
, "no caret to show" );
1675 m_caret
->Show(show
);
1678 void wxWindowMSW::DestroyCaret()
1683 void wxWindowMSW::SetCaretPos(int x
, int y
)
1685 wxCHECK_RET( m_caret
, "no caret to move" );
1687 m_caret
->Move(x
, y
);
1690 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1692 wxCHECK_RET( m_caret
, "no caret to get position of" );
1694 m_caret
->GetPosition(x
, y
);
1696 #endif // wxUSE_CARET
1698 // ---------------------------------------------------------------------------
1700 // ---------------------------------------------------------------------------
1702 #if wxUSE_MENUS_NATIVE
1704 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1705 // immediately, without waiting for the next event loop iteration
1707 // NB: this function should probably be made public later as it can almost
1708 // surely replace wxYield() elsewhere as well
1709 static void wxYieldForCommandsOnly()
1711 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1712 // want to process it here)
1714 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1715 && msg
.message
!= WM_QUIT
)
1717 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1721 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1723 menu
->SetInvokingWindow(this);
1726 HWND hWnd
= GetHwnd();
1727 HMENU hMenu
= GetHmenuOf(menu
);
1731 ::ClientToScreen(hWnd
, &point
);
1732 wxCurrentPopupMenu
= menu
;
1733 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1735 // we need to do it righ now as otherwise the events are never going to be
1736 // sent to wxCurrentPopupMenu from HandleCommand()
1738 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1739 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1740 // destroyed as soon as we return (it can be a local variable in the caller
1741 // for example) and so we do need to process the event immediately
1742 wxYieldForCommandsOnly();
1744 wxCurrentPopupMenu
= NULL
;
1746 menu
->SetInvokingWindow(NULL
);
1751 #endif // wxUSE_MENUS_NATIVE
1753 // ===========================================================================
1754 // pre/post message processing
1755 // ===========================================================================
1757 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1760 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1762 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1765 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1767 // wxUniversal implements tab traversal itself
1768 #ifndef __WXUNIVERSAL__
1769 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1771 // intercept dialog navigation keys
1772 MSG
*msg
= (MSG
*)pMsg
;
1774 // here we try to do all the job which ::IsDialogMessage() usually does
1777 bool bProcess
= TRUE
;
1778 if ( msg
->message
!= WM_KEYDOWN
)
1781 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1786 bool bCtrlDown
= wxIsCtrlDown();
1787 bool bShiftDown
= wxIsShiftDown();
1789 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1790 // don't process it if it's the case (except for Ctrl-Tab/Enter
1791 // combinations which are always processed)
1795 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1798 bool bForward
= TRUE
,
1799 bWindowChange
= FALSE
;
1801 switch ( msg
->wParam
)
1804 // assume that nobody wants Shift-TAB for himself - if we
1805 // don't do it there is no easy way for a control to grab
1806 // TABs but still let Shift-TAB work as navugation key
1807 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1811 // Ctrl-Tab cycles thru notebook pages
1812 bWindowChange
= bCtrlDown
;
1813 bForward
= !bShiftDown
;
1819 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1827 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1833 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1835 // control wants to process Enter itself, don't
1836 // call IsDialogMessage() which would interpret
1840 else if ( lDlgCode
& DLGC_BUTTON
)
1842 // let IsDialogMessage() handle this for all
1843 // buttons except the owner-drawn ones which it
1844 // just seems to ignore
1845 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1846 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1848 // emulate the button click
1849 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1851 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1856 // FIXME: this should be handled by
1857 // wxNavigationKeyEvent handler and not here!!
1861 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1863 if ( btn
&& btn
->IsEnabled() )
1865 // if we do have a default button, do press it
1866 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1870 else // no default button
1871 #endif // wxUSE_BUTTON
1873 // no special function for enter and don't even
1874 // let IsDialogMessage() have it: it seems to
1875 // do something really strange with it
1888 wxNavigationKeyEvent event
;
1889 event
.SetDirection(bForward
);
1890 event
.SetWindowChange(bWindowChange
);
1891 event
.SetEventObject(this);
1893 if ( GetEventHandler()->ProcessEvent(event
) )
1900 // let ::IsDialogMessage() do almost everything and handle just the
1901 // things it doesn't here: Ctrl-TAB for switching notebook pages
1902 if ( msg
->message
== WM_KEYDOWN
)
1904 // don't process system keys here
1905 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1907 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1909 // find the first notebook parent and change its page
1910 wxWindow
*win
= this;
1911 wxNotebook
*nbook
= NULL
;
1912 while ( win
&& !nbook
)
1914 nbook
= wxDynamicCast(win
, wxNotebook
);
1915 win
= win
->GetParent();
1920 bool forward
= !wxIsShiftDown();
1922 nbook
->AdvanceSelection(forward
);
1929 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1931 // IsDialogMessage() did something...
1935 #endif // __WXUNIVERSAL__
1940 // relay mouse move events to the tooltip control
1941 MSG
*msg
= (MSG
*)pMsg
;
1942 if ( msg
->message
== WM_MOUSEMOVE
)
1943 m_tooltip
->RelayEvent(pMsg
);
1945 #endif // wxUSE_TOOLTIPS
1950 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1952 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1953 return m_acceleratorTable
.Translate(this, pMsg
);
1956 #endif // wxUSE_ACCEL
1959 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1961 // preprocess all messages by default
1965 // ---------------------------------------------------------------------------
1966 // message params unpackers (different for Win16 and Win32)
1967 // ---------------------------------------------------------------------------
1971 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1972 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1974 *id
= LOWORD(wParam
);
1975 *hwnd
= (WXHWND
)lParam
;
1976 *cmd
= HIWORD(wParam
);
1979 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1980 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1982 *state
= LOWORD(wParam
);
1983 *minimized
= HIWORD(wParam
);
1984 *hwnd
= (WXHWND
)lParam
;
1987 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1988 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1990 *code
= LOWORD(wParam
);
1991 *pos
= HIWORD(wParam
);
1992 *hwnd
= (WXHWND
)lParam
;
1995 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
1996 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
1998 #ifndef __WXMICROWIN__
1999 *nCtlColor
= CTLCOLOR_BTN
;
2000 *hwnd
= (WXHWND
)lParam
;
2001 *hdc
= (WXHDC
)wParam
;
2005 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2006 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2008 *item
= (WXWORD
)wParam
;
2009 *flags
= HIWORD(wParam
);
2010 *hmenu
= (WXHMENU
)lParam
;
2015 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2016 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2018 *id
= (WXWORD
)wParam
;
2019 *hwnd
= (WXHWND
)LOWORD(lParam
);
2020 *cmd
= HIWORD(lParam
);
2023 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2024 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2026 *state
= (WXWORD
)wParam
;
2027 *minimized
= LOWORD(lParam
);
2028 *hwnd
= (WXHWND
)HIWORD(lParam
);
2031 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2032 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2034 *code
= (WXWORD
)wParam
;
2035 *pos
= LOWORD(lParam
);
2036 *hwnd
= (WXHWND
)HIWORD(lParam
);
2039 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2040 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2042 *hwnd
= (WXHWND
)LOWORD(lParam
);
2043 *nCtlColor
= (int)HIWORD(lParam
);
2044 *hdc
= (WXHDC
)wParam
;
2047 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2048 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2050 *item
= (WXWORD
)wParam
;
2051 *flags
= LOWORD(lParam
);
2052 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2057 // ---------------------------------------------------------------------------
2058 // Main wxWindows window proc and the window proc for wxWindow
2059 // ---------------------------------------------------------------------------
2061 // Hook for new window just as it's being created, when the window isn't yet
2062 // associated with the handle
2063 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2065 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2066 // window being created and insures that it's always unset back later
2067 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2069 gs_winBeingCreated
= winBeingCreated
;
2072 wxWindowCreationHook::~wxWindowCreationHook()
2074 gs_winBeingCreated
= NULL
;
2078 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2080 // trace all messages - useful for the debugging
2082 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2083 wxGetMessageName(message
), wParam
, lParam
);
2084 #endif // __WXDEBUG__
2086 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2088 // when we get the first message for the HWND we just created, we associate
2089 // it with wxWindow stored in gs_winBeingCreated
2090 if ( !wnd
&& gs_winBeingCreated
)
2092 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2093 wnd
= gs_winBeingCreated
;
2094 gs_winBeingCreated
= NULL
;
2095 wnd
->SetHWND((WXHWND
)hWnd
);
2101 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2103 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2108 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2110 // did we process the message?
2111 bool processed
= FALSE
;
2122 // for most messages we should return 0 when we do process the message
2130 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2133 // return 0 to allow window creation
2134 rc
.result
= mayCreate
? 0 : -1;
2140 // never set processed to TRUE and *always* pass WM_DESTROY to
2141 // DefWindowProc() as Windows may do some internal cleanup when
2142 // processing it and failing to pass the message along may cause
2143 // memory and resource leaks!
2144 (void)HandleDestroy();
2148 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2156 // we're not interested in these messages at all
2159 case SIZE_MINIMIZED
:
2160 // we shouldn't send sizev events for these messages as the
2161 // client size may be negative which breaks existing code
2163 // OTOH we might send another (wxMinimizedEvent?) one or
2164 // add an additional parameter to wxSizeEvent if this is
2165 // useful to anybody
2169 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2170 // fall through nevertheless
2172 case SIZE_MAXIMIZED
:
2174 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2179 #ifndef __WXMICROWIN__
2180 case WM_ACTIVATEAPP
:
2181 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2187 WXWORD state
, minimized
;
2189 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2191 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2196 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2200 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2204 processed
= HandlePaint();
2208 // don't let the DefWindowProc() destroy our window - we'll do it
2209 // ourselves in ~wxWindow
2215 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2219 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2220 GET_Y_LPARAM(lParam
),
2224 #if wxUSE_MOUSEWHEEL
2226 processed
= HandleMouseWheel(wParam
, lParam
);
2230 case WM_LBUTTONDOWN
:
2232 case WM_LBUTTONDBLCLK
:
2233 case WM_RBUTTONDOWN
:
2235 case WM_RBUTTONDBLCLK
:
2236 case WM_MBUTTONDOWN
:
2238 case WM_MBUTTONDBLCLK
:
2241 #ifdef __WXMICROWIN__
2242 // MicroWindows seems to ignore the fact that a window is
2243 // disabled. So catch mouse events and throw them away if
2245 wxWindowMSW
* win
= this;
2248 if (!win
->IsEnabled())
2253 win
= win
->GetParent();
2254 if (win
&& win
->IsTopLevel())
2257 #endif // __WXMICROWIN__
2260 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2262 processed
= HandleMouseEvent(message
,
2263 GET_X_LPARAM(lParam
),
2264 GET_Y_LPARAM(lParam
),
2270 #ifdef __WXMICROWIN__
2271 case WM_NCLBUTTONDOWN
:
2272 case WM_NCLBUTTONUP
:
2273 case WM_NCLBUTTONDBLCLK
:
2274 case WM_NCRBUTTONDOWN
:
2275 case WM_NCRBUTTONUP
:
2276 case WM_NCRBUTTONDBLCLK
:
2278 case WM_NCMBUTTONDOWN
:
2279 case WM_NCMBUTTONUP
:
2280 case WM_NCMBUTTONDBLCLK
:
2283 // MicroWindows seems to ignore the fact that a window
2284 // is disabled. So catch mouse events and throw them away if necessary.
2286 wxWindowMSW
* win
= this;
2289 if (!win
->IsEnabled())
2294 win
= win
->GetParent();
2295 if (win
&& win
->IsTopLevel())
2300 #endif // __WXMICROWIN__
2307 case MM_JOY1BUTTONDOWN
:
2308 case MM_JOY2BUTTONDOWN
:
2309 case MM_JOY1BUTTONUP
:
2310 case MM_JOY2BUTTONUP
:
2311 processed
= HandleJoystickEvent(message
,
2312 GET_X_LPARAM(lParam
),
2313 GET_Y_LPARAM(lParam
),
2316 #endif // __WXMICROWIN__
2319 processed
= HandleSysCommand(wParam
, lParam
);
2326 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2328 processed
= HandleCommand(id
, cmd
, hwnd
);
2334 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2338 // for these messages we must return TRUE if process the message
2341 case WM_MEASUREITEM
:
2343 int idCtrl
= (UINT
)wParam
;
2344 if ( message
== WM_DRAWITEM
)
2346 processed
= MSWOnDrawItem(idCtrl
,
2347 (WXDRAWITEMSTRUCT
*)lParam
);
2351 processed
= MSWOnMeasureItem(idCtrl
,
2352 (WXMEASUREITEMSTRUCT
*)lParam
);
2359 #endif // defined(WM_DRAWITEM)
2364 rc
.result
= m_lDlgCode
;
2367 //else: get the dlg code from the DefWindowProc()
2372 // If this has been processed by an event handler,
2373 // return 0 now (we've handled it).
2374 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2381 // we consider these message "not interesting" to OnChar
2382 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2391 // avoid duplicate messages to OnChar for these ASCII keys: they
2392 // will be translated by TranslateMessage() and received in WM_CHAR
2400 // but set processed to FALSE, not TRUE to still pass them to
2401 // the control's default window proc - otherwise built-in
2402 // keyboard handling won't work
2408 // special case of VK_APPS: treat it the same as right mouse
2409 // click because both usually pop up a context menu
2415 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2416 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2426 processed
= HandleChar((WORD
)wParam
, lParam
);
2433 // special case of VK_APPS: treat it the same as right mouse button
2434 if ( wParam
== VK_APPS
)
2439 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2440 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2445 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2450 case WM_CHAR
: // Always an ASCII character
2451 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2459 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2461 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2467 // CTLCOLOR messages are sent by children to query the parent for their
2468 // colors#ifndef __WXMICROWIN__
2469 #ifndef __WXMICROWIN__
2471 case WM_CTLCOLORMSGBOX
:
2472 case WM_CTLCOLOREDIT
:
2473 case WM_CTLCOLORLISTBOX
:
2474 case WM_CTLCOLORBTN
:
2475 case WM_CTLCOLORDLG
:
2476 case WM_CTLCOLORSCROLLBAR
:
2477 case WM_CTLCOLORSTATIC
:
2485 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2487 processed
= HandleCtlColor(&rc
.hBrush
,
2496 #endif // !__WXMICROWIN__
2498 // the return value for this message is ignored
2499 case WM_SYSCOLORCHANGE
:
2500 processed
= HandleSysColorChange();
2503 case WM_PALETTECHANGED
:
2504 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2507 case WM_QUERYNEWPALETTE
:
2508 processed
= HandleQueryNewPalette();
2512 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2515 // we processed the message, i.e. erased the background
2521 processed
= HandleDropFiles(wParam
);
2525 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2529 // we never set focus from here
2534 case WM_QUERYENDSESSION
:
2535 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2539 processed
= HandleEndSession(wParam
!= 0, lParam
);
2542 case WM_GETMINMAXINFO
:
2543 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2547 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2548 LOWORD(lParam
), // hit test
2549 HIWORD(lParam
)); // mouse msg
2553 // returning TRUE stops the DefWindowProc() from further
2554 // processing this message - exactly what we need because we've
2555 // just set the cursor.
2560 #if defined(__WIN32__) && defined(WM_HELP)
2563 HELPINFO
* info
= (HELPINFO
*) lParam
;
2564 // Don't yet process menu help events, just windows
2565 if (info
->iContextType
== HELPINFO_WINDOW
)
2567 wxWindowMSW
* subjectOfHelp
= this;
2568 bool eventProcessed
= FALSE
;
2569 while (subjectOfHelp
&& !eventProcessed
)
2571 wxHelpEvent
helpEvent(wxEVT_HELP
,
2572 subjectOfHelp
->GetId(),
2573 wxPoint(info
->MousePos
.x
,
2574 info
->MousePos
.y
) );
2575 helpEvent
.SetEventObject(this);
2577 GetEventHandler()->ProcessEvent(helpEvent
);
2579 // Go up the window hierarchy until the event is
2581 subjectOfHelp
= subjectOfHelp
->GetParent();
2584 processed
= eventProcessed
;
2586 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2588 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2589 helpEvent
.SetEventObject(this);
2590 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2593 //else: processed is already FALSE
2597 case WM_CONTEXTMENU
:
2599 // we don't convert from screen to client coordinates as
2600 // the event may be handled by a parent window
2601 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2603 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2604 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2609 // unfortunately this doesn't really work as then window which
2610 // doesn't accept focus doesn't get any mouse events neither which
2611 // means it can't get any input at all
2612 #if 0 //def __WXUNIVERSAL__
2614 // we shouldn't allow the windows which don't want to get focus to
2616 if ( !AcceptsFocus() )
2618 rc
.result
= HTTRANSPARENT
;
2622 #endif // __WXUNIVERSAL__
2628 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2629 wxGetMessageName(message
));
2630 #endif // __WXDEBUG__
2631 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2637 // ----------------------------------------------------------------------------
2638 // wxWindow <-> HWND map
2639 // ----------------------------------------------------------------------------
2641 wxWinHashTable
*wxWinHandleHash
= NULL
;
2643 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2645 return wxWinHandleHash
->Get((long)hWnd
);
2648 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2650 // adding NULL hWnd is (first) surely a result of an error and
2651 // (secondly) breaks menu command processing
2652 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2653 wxT("attempt to add a NULL hWnd to window list ignored") );
2655 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2657 if ( oldWin
&& (oldWin
!= win
) )
2659 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2660 hWnd
, win
->GetClassInfo()->GetClassName());
2663 #endif // __WXDEBUG__
2666 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2670 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2672 wxWinHandleHash
->Delete((long)win
->GetHWND());
2675 // ----------------------------------------------------------------------------
2676 // various MSW speciic class dependent functions
2677 // ----------------------------------------------------------------------------
2679 // Default destroyer - override if you destroy it in some other way
2680 // (e.g. with MDI child windows)
2681 void wxWindowMSW::MSWDestroyWindow()
2685 void wxWindowMSW::MSWDetachWindowMenu()
2687 #ifndef __WXUNIVERSAL__
2691 HMENU hMenu
= (HMENU
)m_hMenu
;
2693 int N
= ::GetMenuItemCount(hMenu
);
2694 for ( int i
= 0; i
< N
; i
++ )
2696 if ( !::GetMenuString(hMenu
, i
, buf
, WXSIZEOF(buf
), MF_BYPOSITION
) )
2698 wxLogLastError(wxT("GetMenuString"));
2703 if ( wxStrcmp(buf
, _("&Window")) == 0 )
2705 if ( !::RemoveMenu(hMenu
, i
, MF_BYPOSITION
) )
2707 wxLogLastError(wxT("RemoveMenu"));
2714 #endif // __WXUNIVERSAL__
2717 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2720 int& w
, int& h
) const
2722 bool nonDefault
= FALSE
;
2726 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2727 // just as well set it to CW_USEDEFAULT as well
2734 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2740 NB: there used to be some code here which set the initial size of the
2741 window to the client size of the parent if no explicit size was
2742 specified. This was wrong because wxWindows programs often assume
2743 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2744 it. To see why, you should understand that Windows sends WM_SIZE from
2745 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2746 from some base class ctor and so this WM_SIZE is not processed in the
2747 real class' OnSize() (because it's not fully constructed yet and the
2748 event goes to some base class OnSize() instead). So the WM_SIZE we
2749 rely on is the one sent when the parent frame resizes its children
2750 but here is the problem: if the child already has just the right
2751 size, nothing will happen as both wxWindows and Windows check for
2752 this and ignore any attempts to change the window size to the size it
2753 already has - so no WM_SIZE would be sent.
2757 // as abobe, h is not used at all in this case anyhow
2764 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2772 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2773 const wxChar
*title
,
2777 WXDWORD extendedStyle
)
2779 // choose the position/size for the new window
2781 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2783 // find the correct parent HWND
2784 wxWindow
*parent
= GetParent();
2785 bool isChild
= (style
& WS_CHILD
) != 0;
2787 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2789 // popup windows should have desktop as parent because they shouldn't
2790 // be limited to the parents client area as child windows usually are
2791 hParent
= ::GetDesktopWindow();
2795 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2797 // this is either a normal child window or a top level window with
2798 // wxFRAME_TOOL_WINDOW style (see below)
2799 hParent
= GetHwndOf(parent
);
2803 // this is either a window for which no parent was specified (not
2804 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2805 // style: we should use NULL parent HWND for it or it would be
2806 // always on top of its parent which is not what we usually want
2807 // (in fact, we only want it for frames with the special
2808 // wxFRAME_TOOL_WINDOW as above)
2814 // controlId is menu handle for the top level windows, so set it to 0
2815 // unless we're creating a child window
2819 controlId
= GetId();
2821 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2823 style
|= WS_CLIPSIBLINGS
;
2831 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2832 // which is the same but without CS_[HV]REDRAW class styles so using it
2833 // ensures that the window is not fully repainted on each resize
2834 wxString
className(wclass
);
2835 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2837 className
+= wxT("NR");
2840 // do create the window
2841 wxWindowCreationHook
hook(this);
2843 m_hWnd
= (WXHWND
)::CreateWindowEx
2847 title
? title
: wxT(""),
2853 NULL
// no extra data
2858 wxLogSysError(_("Can't create window of class %s"), wclass
);
2863 SubclassWin(m_hWnd
);
2865 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2870 // ===========================================================================
2871 // MSW message handlers
2872 // ===========================================================================
2874 // ---------------------------------------------------------------------------
2876 // ---------------------------------------------------------------------------
2879 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2880 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2882 #ifndef __WXMICROWIN__
2883 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2884 HWND hWnd
= hdr
->hwndFrom
;
2885 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2887 // is this one of our windows?
2890 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2893 // try all our children
2894 wxWindowList::Node
*node
= GetChildren().GetFirst();
2897 wxWindow
*child
= node
->GetData();
2898 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2903 node
= node
->GetNext();
2906 // finally try this window too (catches toolbar case)
2907 return MSWOnNotify(idCtrl
, lParam
, result
);
2908 #else // __WXMICROWIN__
2913 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2915 WXLPARAM
* WXUNUSED(result
))
2918 NMHDR
* hdr
= (NMHDR
*)lParam
;
2919 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2921 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2922 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2927 #endif // wxUSE_TOOLTIPS
2933 // ---------------------------------------------------------------------------
2934 // end session messages
2935 // ---------------------------------------------------------------------------
2937 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2939 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2940 event
.SetEventObject(wxTheApp
);
2941 event
.SetCanVeto(TRUE
);
2942 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2944 bool rc
= wxTheApp
->ProcessEvent(event
);
2948 // we may end only if the app didn't veto session closing (double
2950 *mayEnd
= !event
.GetVeto();
2956 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2958 // do nothing if the session isn't ending
2963 if ( (this != wxTheApp
->GetTopWindow()) )
2966 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2967 event
.SetEventObject(wxTheApp
);
2968 event
.SetCanVeto(FALSE
);
2969 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2971 return wxTheApp
->ProcessEvent(event
);
2974 // ---------------------------------------------------------------------------
2975 // window creation/destruction
2976 // ---------------------------------------------------------------------------
2978 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2980 // TODO: should generate this event from WM_NCCREATE
2981 wxWindowCreateEvent
event((wxWindow
*)this);
2982 (void)GetEventHandler()->ProcessEvent(event
);
2989 bool wxWindowMSW::HandleDestroy()
2991 wxWindowDestroyEvent
event((wxWindow
*)this);
2992 (void)GetEventHandler()->ProcessEvent(event
);
2994 // delete our drop target if we've got one
2995 #if wxUSE_DRAG_AND_DROP
2996 if ( m_dropTarget
!= NULL
)
2998 m_dropTarget
->Revoke(m_hWnd
);
3000 delete m_dropTarget
;
3001 m_dropTarget
= NULL
;
3003 #endif // wxUSE_DRAG_AND_DROP
3005 // WM_DESTROY handled
3009 // ---------------------------------------------------------------------------
3011 // ---------------------------------------------------------------------------
3013 bool wxWindowMSW::HandleActivate(int state
,
3014 bool WXUNUSED(minimized
),
3015 WXHWND
WXUNUSED(activate
))
3017 wxActivateEvent
event(wxEVT_ACTIVATE
,
3018 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3020 event
.SetEventObject(this);
3022 return GetEventHandler()->ProcessEvent(event
);
3025 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3027 // notify the parent keeping track of focus for the kbd navigation
3028 // purposes that we got it
3029 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3030 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3036 m_caret
->OnSetFocus();
3038 #endif // wxUSE_CARET
3041 // If it's a wxTextCtrl don't send the event as it will be done
3042 // after the control gets to process it from EN_FOCUS handler
3043 if ( wxDynamicCastThis(wxTextCtrl
) )
3047 #endif // wxUSE_TEXTCTRL
3049 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3050 event
.SetEventObject(this);
3052 // wxFindWinFromHandle() may return NULL, it is ok
3053 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3055 return GetEventHandler()->ProcessEvent(event
);
3058 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3064 m_caret
->OnKillFocus();
3066 #endif // wxUSE_CARET
3069 // If it's a wxTextCtrl don't send the event as it will be done
3070 // after the control gets to process it.
3071 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3078 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3079 event
.SetEventObject(this);
3081 // wxFindWinFromHandle() may return NULL, it is ok
3082 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3084 return GetEventHandler()->ProcessEvent(event
);
3087 // ---------------------------------------------------------------------------
3089 // ---------------------------------------------------------------------------
3091 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3093 wxShowEvent
event(GetId(), show
);
3094 event
.m_eventObject
= this;
3096 return GetEventHandler()->ProcessEvent(event
);
3099 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3101 wxInitDialogEvent
event(GetId());
3102 event
.m_eventObject
= this;
3104 return GetEventHandler()->ProcessEvent(event
);
3107 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3109 #ifndef __WXMICROWIN__
3110 HDROP hFilesInfo
= (HDROP
) wParam
;
3112 // Get the total number of files dropped
3113 UINT gwFilesDropped
= ::DragQueryFile
3121 wxString
*files
= new wxString
[gwFilesDropped
];
3122 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3124 // first get the needed buffer length (+1 for terminating NUL)
3125 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3127 // and now get the file name
3128 ::DragQueryFile(hFilesInfo
, wIndex
,
3129 files
[wIndex
].GetWriteBuf(len
), len
);
3131 files
[wIndex
].UngetWriteBuf();
3133 DragFinish (hFilesInfo
);
3135 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3136 event
.m_eventObject
= this;
3139 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3140 event
.m_pos
.x
= dropPoint
.x
;
3141 event
.m_pos
.y
= dropPoint
.y
;
3143 return GetEventHandler()->ProcessEvent(event
);
3144 #else // __WXMICROWIN__
3149 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3151 int WXUNUSED(mouseMsg
))
3153 #ifndef __WXMICROWIN__
3154 // the logic is as follows:
3155 // -1. don't set cursor for non client area, including but not limited to
3156 // the title bar, scrollbars, &c
3157 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3158 // 1. if we have the cursor set it unless wxIsBusy()
3159 // 2. if we're a top level window, set some cursor anyhow
3160 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3162 if ( nHitTest
!= HTCLIENT
)
3167 HCURSOR hcursor
= 0;
3169 // first ask the user code - it may wish to set the cursor in some very
3170 // specific way (for example, depending on the current position)
3173 if ( !::GetCursorPos(&pt
) )
3175 wxLogLastError(wxT("GetCursorPos"));
3178 // In WIN16 it doesn't return a value.
3179 ::GetCursorPos(&pt
);
3184 ScreenToClient(&x
, &y
);
3185 wxSetCursorEvent
event(x
, y
);
3187 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3188 if ( processedEvtSetCursor
&& event
.HasCursor() )
3190 hcursor
= GetHcursorOf(event
.GetCursor());
3195 bool isBusy
= wxIsBusy();
3197 // the test for processedEvtSetCursor is here to prevent using m_cursor
3198 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3199 // it - this is a way to say that our cursor shouldn't be used for this
3201 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3203 hcursor
= GetHcursorOf(m_cursor
);
3210 hcursor
= wxGetCurrentBusyCursor();
3212 else if ( !hcursor
)
3214 const wxCursor
*cursor
= wxGetGlobalCursor();
3215 if ( cursor
&& cursor
->Ok() )
3217 hcursor
= GetHcursorOf(*cursor
);
3225 ::SetCursor(hcursor
);
3227 // cursor set, stop here
3230 #endif // __WXMICROWIN__
3232 // pass up the window chain
3236 // ---------------------------------------------------------------------------
3237 // owner drawn stuff
3238 // ---------------------------------------------------------------------------
3240 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3242 #if wxUSE_OWNER_DRAWN
3244 #if wxUSE_MENUS_NATIVE
3245 // is it a menu item?
3246 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3247 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3249 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3251 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3253 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3254 // the DC from being released
3255 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3256 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3257 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3258 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3260 return pMenuItem
->OnDrawItem
3264 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3265 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3268 #endif // wxUSE_MENUS_NATIVE
3271 wxWindow
*item
= FindItem(id
);
3272 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3274 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3276 #endif // wxUSE_CONTROLS
3278 #endif // USE_OWNER_DRAWN
3283 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3285 #if wxUSE_OWNER_DRAWN
3286 // is it a menu item?
3287 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3288 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3290 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3292 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3294 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3295 &pMeasureStruct
->itemHeight
);
3298 wxWindow
*item
= FindItem(id
);
3299 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3301 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3303 #endif // owner-drawn menus
3307 // ---------------------------------------------------------------------------
3308 // colours and palettes
3309 // ---------------------------------------------------------------------------
3311 bool wxWindowMSW::HandleSysColorChange()
3313 wxSysColourChangedEvent event
;
3314 event
.SetEventObject(this);
3316 (void)GetEventHandler()->ProcessEvent(event
);
3318 // always let the system carry on the default processing to allow the
3319 // native controls to react to the colours update
3323 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3331 #ifndef __WXMICROWIN__
3332 WXHBRUSH hBrush
= 0;
3334 if ( nCtlColor
== CTLCOLOR_DLG
)
3336 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3341 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3343 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3345 #endif // wxUSE_CONTROLS
3351 #else // __WXMICROWIN__
3356 // Define for each class of dialog and control
3357 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3358 WXHWND
WXUNUSED(hWnd
),
3359 WXUINT
WXUNUSED(nCtlColor
),
3360 WXUINT
WXUNUSED(message
),
3361 WXWPARAM
WXUNUSED(wParam
),
3362 WXLPARAM
WXUNUSED(lParam
))
3367 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3369 wxPaletteChangedEvent
event(GetId());
3370 event
.SetEventObject(this);
3371 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3373 return GetEventHandler()->ProcessEvent(event
);
3376 bool wxWindowMSW::HandleQueryNewPalette()
3378 wxQueryNewPaletteEvent
event(GetId());
3379 event
.SetEventObject(this);
3381 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3384 // Responds to colour changes: passes event on to children.
3385 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3387 wxWindowList::Node
*node
= GetChildren().GetFirst();
3390 // Only propagate to non-top-level windows because Windows already
3391 // sends this event to all top-level ones
3392 wxWindow
*win
= node
->GetData();
3393 if ( !win
->IsTopLevel() )
3395 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3396 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3397 // the standard controls
3398 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3401 node
= node
->GetNext();
3404 // update the colours we use if they were not set explicitly by the user:
3405 // this must be done or OnCtlColor() would continue to use the old colours
3408 m_foregroundColour
= wxSystemSettings::
3409 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3414 m_backgroundColour
= wxSystemSettings::
3415 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3419 // ---------------------------------------------------------------------------
3421 // ---------------------------------------------------------------------------
3423 bool wxWindowMSW::HandlePaint()
3426 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3428 wxLogLastError(wxT("CreateRectRgn"));
3429 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3430 wxLogLastError(wxT("GetUpdateRgn"));
3432 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3435 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3437 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3438 updateRect
.right
- updateRect
.left
,
3439 updateRect
.bottom
- updateRect
.top
);
3442 wxPaintEvent
event(m_windowId
);
3443 event
.SetEventObject(this);
3445 bool processed
= GetEventHandler()->ProcessEvent(event
);
3447 // note that we must generate NC event after the normal one as otherwise
3448 // BeginPaint() will happily overwrite our decorations with the background
3450 wxNcPaintEvent
eventNc(m_windowId
);
3451 eventNc
.SetEventObject(this);
3452 GetEventHandler()->ProcessEvent(eventNc
);
3457 // Can be called from an application's OnPaint handler
3458 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3460 #ifdef __WXUNIVERSAL__
3463 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3466 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3471 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3473 // Prevents flicker when dragging
3474 if ( ::IsIconic(GetHwnd()) )
3480 dc
.SetWindow((wxWindow
*)this);
3483 wxEraseEvent
event(m_windowId
, &dc
);
3484 event
.SetEventObject(this);
3485 bool rc
= GetEventHandler()->ProcessEvent(event
);
3489 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3490 dc
.SelectOldObjects(hdc
);
3495 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3498 ::GetClientRect(GetHwnd(), &rect
);
3500 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3501 m_backgroundColour
.Green(),
3502 m_backgroundColour
.Blue());
3503 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3505 wxLogLastError(wxT("CreateSolidBrush"));
3507 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3509 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3511 ::FillRect(hdc
, &rect
, hBrush
);
3512 ::DeleteObject(hBrush
);
3513 ::SetMapMode(hdc
, mode
);
3516 // ---------------------------------------------------------------------------
3517 // moving and resizing
3518 // ---------------------------------------------------------------------------
3520 bool wxWindowMSW::HandleMinimize()
3522 wxIconizeEvent
event(m_windowId
);
3523 event
.SetEventObject(this);
3525 return GetEventHandler()->ProcessEvent(event
);
3528 bool wxWindowMSW::HandleMaximize()
3530 wxMaximizeEvent
event(m_windowId
);
3531 event
.SetEventObject(this);
3533 return GetEventHandler()->ProcessEvent(event
);
3536 bool wxWindowMSW::HandleMove(int x
, int y
)
3538 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3539 event
.SetEventObject(this);
3541 return GetEventHandler()->ProcessEvent(event
);
3544 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3546 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3547 event
.SetEventObject(this);
3549 return GetEventHandler()->ProcessEvent(event
);
3552 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3554 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3558 if ( m_minWidth
!= -1 )
3560 info
->ptMinTrackSize
.x
= m_minWidth
;
3564 if ( m_minHeight
!= -1 )
3566 info
->ptMinTrackSize
.y
= m_minHeight
;
3570 if ( m_maxWidth
!= -1 )
3572 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3576 if ( m_maxHeight
!= -1 )
3578 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3585 // ---------------------------------------------------------------------------
3587 // ---------------------------------------------------------------------------
3589 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3591 #if wxUSE_MENUS_NATIVE
3592 if ( !cmd
&& wxCurrentPopupMenu
)
3594 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3595 wxCurrentPopupMenu
= NULL
;
3597 return popupMenu
->MSWCommand(cmd
, id
);
3599 #endif // wxUSE_MENUS_NATIVE
3601 wxWindow
*win
= NULL
;
3603 // first try to find it from HWND - this works even with the broken
3604 // programs using the same ids for different controls
3607 win
= wxFindWinFromHandle(control
);
3613 // must cast to a signed type before comparing with other ids!
3614 win
= FindItem((signed short)id
);
3619 return win
->MSWCommand(cmd
, id
);
3622 // the messages sent from the in-place edit control used by the treectrl
3623 // for label editing have id == 0, but they should _not_ be treated as menu
3624 // messages (they are EN_XXX ones, in fact) so don't translate anything
3625 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3628 // If no child window, it may be an accelerator, e.g. for a popup menu
3631 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3632 event
.SetEventObject(this);
3636 return GetEventHandler()->ProcessEvent(event
);
3638 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3641 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3642 // notifications to its parent which we want to reflect back to
3644 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3645 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3648 #endif // wxUSE_SPINCTRL
3653 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3655 // 4 bits are reserved
3656 switch ( wParam
& 0xFFFFFFF0 )
3659 return HandleMaximize();
3662 return HandleMinimize();
3668 // ---------------------------------------------------------------------------
3670 // ---------------------------------------------------------------------------
3672 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3676 // our client coords are not quite the same as Windows ones
3677 wxPoint pt
= GetClientAreaOrigin();
3678 event
.m_x
= x
- pt
.x
;
3679 event
.m_y
= y
- pt
.y
;
3681 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3682 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3683 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3684 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3685 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3686 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3688 event
.SetTimestamp(s_currentMsg
.time
);
3689 event
.m_eventObject
= this;
3691 #if wxUSE_MOUSEEVENT_HACK
3694 m_lastMouseEvent
= event
.GetEventType();
3695 #endif // wxUSE_MOUSEEVENT_HACK
3698 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3700 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3701 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3702 // from the message id and take the value in the table to get wxWin event
3704 static const wxEventType eventsMouse
[] =
3718 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3719 InitMouseEvent(event
, x
, y
, flags
);
3721 return GetEventHandler()->ProcessEvent(event
);
3724 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3726 if ( !m_mouseInWindow
)
3728 // it would be wrong to assume that just because we get a mouse move
3729 // event that the mouse is inside the window: although this is usually
3730 // true, it is not if we had captured the mouse, so we need to check
3731 // the mouse coordinates here
3732 if ( !HasCapture() || IsMouseInWindow() )
3734 // Generate an ENTER event
3735 m_mouseInWindow
= TRUE
;
3737 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3738 InitMouseEvent(event
, x
, y
, flags
);
3740 (void)GetEventHandler()->ProcessEvent(event
);
3744 #if wxUSE_MOUSEEVENT_HACK
3745 // Window gets a click down message followed by a mouse move message even
3746 // if position isn't changed! We want to discard the trailing move event
3747 // if x and y are the same.
3748 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3749 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3750 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3751 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3753 m_lastMouseEvent
= wxEVT_MOTION
;
3757 #endif // wxUSE_MOUSEEVENT_HACK
3759 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3763 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3765 #if wxUSE_MOUSEWHEEL
3766 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3767 InitMouseEvent(event
,
3768 GET_X_LPARAM(lParam
),
3769 GET_Y_LPARAM(lParam
),
3771 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3772 event
.m_wheelDelta
= WHEEL_DELTA
;
3775 static int s_linesPerRotation
= -1;
3776 if ( s_linesPerRotation
== -1 )
3778 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3779 &s_linesPerRotation
, 0))
3781 // this is not supposed to happen
3782 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3784 // the default is 3, so use it if SystemParametersInfo() failed
3785 s_linesPerRotation
= 3;
3789 // no SystemParametersInfo() under Win16
3790 static const int s_linesPerRotation
= 3;
3793 event
.m_linesPerAction
= s_linesPerRotation
;
3794 return GetEventHandler()->ProcessEvent(event
);
3805 // ---------------------------------------------------------------------------
3806 // keyboard handling
3807 // ---------------------------------------------------------------------------
3809 // create the key event of the given type for the given key - used by
3810 // HandleChar and HandleKeyDown/Up
3811 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3813 WXLPARAM lParam
) const
3815 wxKeyEvent
event(evType
);
3816 event
.SetId(GetId());
3817 event
.m_shiftDown
= wxIsShiftDown();
3818 event
.m_controlDown
= wxIsCtrlDown();
3819 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3821 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3822 event
.m_keyCode
= id
;
3823 event
.SetTimestamp(s_currentMsg
.time
);
3825 // translate the position to client coords
3829 GetWindowRect(GetHwnd(),&rect
);
3839 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3841 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3843 bool ctrlDown
= FALSE
;
3848 // If 1 -> 26, translate to CTRL plus a letter.
3850 if ( (id
> 0) && (id
< 27) )
3872 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3874 // it's ASCII and will be processed here only when called from
3875 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3881 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3884 event
.m_controlDown
= TRUE
;
3887 if ( GetEventHandler()->ProcessEvent(event
) )
3894 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3896 int id
= wxCharCodeMSWToWX(wParam
);
3900 // normal ASCII char
3904 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3906 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3907 if ( GetEventHandler()->ProcessEvent(event
) )
3916 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3918 int id
= wxCharCodeMSWToWX(wParam
);
3922 // normal ASCII char
3926 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3928 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3929 if ( GetEventHandler()->ProcessEvent(event
) )
3936 // ---------------------------------------------------------------------------
3938 // ---------------------------------------------------------------------------
3940 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3944 if ( flags
& JOY_BUTTON1CHG
)
3945 change
= wxJOY_BUTTON1
;
3946 if ( flags
& JOY_BUTTON2CHG
)
3947 change
= wxJOY_BUTTON2
;
3948 if ( flags
& JOY_BUTTON3CHG
)
3949 change
= wxJOY_BUTTON3
;
3950 if ( flags
& JOY_BUTTON4CHG
)
3951 change
= wxJOY_BUTTON4
;
3954 if ( flags
& JOY_BUTTON1
)
3955 buttons
|= wxJOY_BUTTON1
;
3956 if ( flags
& JOY_BUTTON2
)
3957 buttons
|= wxJOY_BUTTON2
;
3958 if ( flags
& JOY_BUTTON3
)
3959 buttons
|= wxJOY_BUTTON3
;
3960 if ( flags
& JOY_BUTTON4
)
3961 buttons
|= wxJOY_BUTTON4
;
3963 // the event ids aren't consecutive so we can't use table based lookup
3965 wxEventType eventType
;
3970 eventType
= wxEVT_JOY_MOVE
;
3975 eventType
= wxEVT_JOY_MOVE
;
3980 eventType
= wxEVT_JOY_ZMOVE
;
3985 eventType
= wxEVT_JOY_ZMOVE
;
3988 case MM_JOY1BUTTONDOWN
:
3990 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3993 case MM_JOY2BUTTONDOWN
:
3995 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3998 case MM_JOY1BUTTONUP
:
4000 eventType
= wxEVT_JOY_BUTTON_UP
;
4003 case MM_JOY2BUTTONUP
:
4005 eventType
= wxEVT_JOY_BUTTON_UP
;
4009 wxFAIL_MSG(wxT("no such joystick event"));
4014 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4015 event
.SetPosition(wxPoint(x
, y
));
4016 event
.SetEventObject(this);
4018 return GetEventHandler()->ProcessEvent(event
);
4024 // ---------------------------------------------------------------------------
4026 // ---------------------------------------------------------------------------
4028 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4029 WXWORD pos
, WXHWND control
)
4033 wxWindow
*child
= wxFindWinFromHandle(control
);
4035 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4038 wxScrollWinEvent event
;
4039 event
.SetPosition(pos
);
4040 event
.SetOrientation(orientation
);
4041 event
.m_eventObject
= this;
4046 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4050 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4054 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4058 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4062 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4066 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4069 case SB_THUMBPOSITION
:
4072 // under Win32, the scrollbar range and position are 32 bit integers,
4073 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4074 // explicitly query the scrollbar for the correct position (this must
4075 // be done only for these two SB_ events as they are the only one
4076 // carrying the scrollbar position)
4078 SCROLLINFO scrollInfo
;
4079 wxZeroMemory(scrollInfo
);
4080 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4081 scrollInfo
.fMask
= SIF_TRACKPOS
;
4083 if ( !::GetScrollInfo(GetHwnd(),
4084 orientation
== wxHORIZONTAL
? SB_HORZ
4088 wxLogLastError(_T("GetScrollInfo"));
4091 event
.SetPosition(scrollInfo
.nTrackPos
);
4095 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4096 ? wxEVT_SCROLLWIN_THUMBRELEASE
4097 : wxEVT_SCROLLWIN_THUMBTRACK
;
4104 return GetEventHandler()->ProcessEvent(event
);
4107 // ===========================================================================
4109 // ===========================================================================
4111 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4114 HDC dc
= ::GetDC((HWND
) wnd
);
4119 // the_font->UseResource();
4120 // the_font->RealizeResource();
4121 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4123 was
= (HFONT
) SelectObject(dc
,fnt
);
4125 GetTextMetrics(dc
, &tm
);
4126 if ( the_font
&& fnt
&& was
)
4128 SelectObject(dc
,was
);
4130 ReleaseDC((HWND
)wnd
, dc
);
4133 *x
= tm
.tmAveCharWidth
;
4135 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4138 // the_font->ReleaseResource();
4141 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4142 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4143 int wxCharCodeMSWToWX(int keySym
)
4148 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4149 case VK_BACK
: id
= WXK_BACK
; break;
4150 case VK_TAB
: id
= WXK_TAB
; break;
4151 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4152 case VK_RETURN
: id
= WXK_RETURN
; break;
4153 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4154 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4155 case VK_MENU
: id
= WXK_MENU
; break;
4156 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4157 case VK_SPACE
: id
= WXK_SPACE
; break;
4158 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4159 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4160 case VK_NEXT
: id
= WXK_NEXT
; break;
4161 case VK_END
: id
= WXK_END
; break;
4162 case VK_HOME
: id
= WXK_HOME
; break;
4163 case VK_LEFT
: id
= WXK_LEFT
; break;
4164 case VK_UP
: id
= WXK_UP
; break;
4165 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4166 case VK_DOWN
: id
= WXK_DOWN
; break;
4167 case VK_SELECT
: id
= WXK_SELECT
; break;
4168 case VK_PRINT
: id
= WXK_PRINT
; break;
4169 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4170 case VK_INSERT
: id
= WXK_INSERT
; break;
4171 case VK_DELETE
: id
= WXK_DELETE
; break;
4172 case VK_HELP
: id
= WXK_HELP
; break;
4173 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4174 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4175 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4176 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4177 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4178 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4179 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4180 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4181 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4182 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4183 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4184 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4185 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4186 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4187 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4188 case VK_F1
: id
= WXK_F1
; break;
4189 case VK_F2
: id
= WXK_F2
; break;
4190 case VK_F3
: id
= WXK_F3
; break;
4191 case VK_F4
: id
= WXK_F4
; break;
4192 case VK_F5
: id
= WXK_F5
; break;
4193 case VK_F6
: id
= WXK_F6
; break;
4194 case VK_F7
: id
= WXK_F7
; break;
4195 case VK_F8
: id
= WXK_F8
; break;
4196 case VK_F9
: id
= WXK_F9
; break;
4197 case VK_F10
: id
= WXK_F10
; break;
4198 case VK_F11
: id
= WXK_F11
; break;
4199 case VK_F12
: id
= WXK_F12
; break;
4200 case VK_F13
: id
= WXK_F13
; break;
4201 case VK_F14
: id
= WXK_F14
; break;
4202 case VK_F15
: id
= WXK_F15
; break;
4203 case VK_F16
: id
= WXK_F16
; break;
4204 case VK_F17
: id
= WXK_F17
; break;
4205 case VK_F18
: id
= WXK_F18
; break;
4206 case VK_F19
: id
= WXK_F19
; break;
4207 case VK_F20
: id
= WXK_F20
; break;
4208 case VK_F21
: id
= WXK_F21
; break;
4209 case VK_F22
: id
= WXK_F22
; break;
4210 case VK_F23
: id
= WXK_F23
; break;
4211 case VK_F24
: id
= WXK_F24
; break;
4212 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4213 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4221 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4227 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4228 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4229 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4230 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4231 case WXK_MENU
: keySym
= VK_MENU
; break;
4232 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4233 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4234 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4235 case WXK_END
: keySym
= VK_END
; break;
4236 case WXK_HOME
: keySym
= VK_HOME
; break;
4237 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4238 case WXK_UP
: keySym
= VK_UP
; break;
4239 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4240 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4241 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4242 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4243 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4244 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4245 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4246 case WXK_HELP
: keySym
= VK_HELP
; break;
4247 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4248 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4249 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4250 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4251 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4252 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4253 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4254 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4255 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4256 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4257 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4258 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4259 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4260 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4261 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4262 case WXK_F1
: keySym
= VK_F1
; break;
4263 case WXK_F2
: keySym
= VK_F2
; break;
4264 case WXK_F3
: keySym
= VK_F3
; break;
4265 case WXK_F4
: keySym
= VK_F4
; break;
4266 case WXK_F5
: keySym
= VK_F5
; break;
4267 case WXK_F6
: keySym
= VK_F6
; break;
4268 case WXK_F7
: keySym
= VK_F7
; break;
4269 case WXK_F8
: keySym
= VK_F8
; break;
4270 case WXK_F9
: keySym
= VK_F9
; break;
4271 case WXK_F10
: keySym
= VK_F10
; break;
4272 case WXK_F11
: keySym
= VK_F11
; break;
4273 case WXK_F12
: keySym
= VK_F12
; break;
4274 case WXK_F13
: keySym
= VK_F13
; break;
4275 case WXK_F14
: keySym
= VK_F14
; break;
4276 case WXK_F15
: keySym
= VK_F15
; break;
4277 case WXK_F16
: keySym
= VK_F16
; break;
4278 case WXK_F17
: keySym
= VK_F17
; break;
4279 case WXK_F18
: keySym
= VK_F18
; break;
4280 case WXK_F19
: keySym
= VK_F19
; break;
4281 case WXK_F20
: keySym
= VK_F20
; break;
4282 case WXK_F21
: keySym
= VK_F21
; break;
4283 case WXK_F22
: keySym
= VK_F22
; break;
4284 case WXK_F23
: keySym
= VK_F23
; break;
4285 case WXK_F24
: keySym
= VK_F24
; break;
4286 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4287 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4298 wxWindow
*wxGetActiveWindow()
4300 HWND hWnd
= GetActiveWindow();
4303 return wxFindWinFromHandle((WXHWND
) hWnd
);
4308 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4310 HWND hwnd
= (HWND
)hWnd
;
4312 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4313 // by code in msw/radiobox.cpp), for all the others we just search up the
4315 wxWindow
*win
= (wxWindow
*)NULL
;
4318 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4321 // all these hacks only work under Win32 anyhow
4325 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4326 // wxWindow class which overrides WM_GETDLGCODE processing to
4327 // do it as well, win would be already non NULL
4328 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4330 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4332 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4333 #endif // wxUSE_RADIOBOX
4335 // spin control text buddy window should be mapped to spin ctrl
4336 // itself so try it too
4337 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4340 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4342 #endif // wxUSE_SPINCTRL
4348 while ( hwnd
&& !win
)
4350 // this is a really ugly hack needed to avoid mistakenly returning the
4351 // parent frame wxWindow for the find/replace modeless dialog HWND -
4352 // this, in turn, is needed to call IsDialogMessage() from
4353 // wxApp::ProcessMessage() as for this we must return NULL from here
4355 // FIXME: this is clearly not the best way to do it but I think we'll
4356 // need to change HWND <-> wxWindow code more heavily than I can
4357 // do it now to fix it
4358 #ifndef __WXMICROWIN__
4359 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4361 // it's a dialog box, don't go upwards
4366 hwnd
= ::GetParent(hwnd
);
4367 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4373 #ifndef __WXMICROWIN__
4375 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4376 // in active frames and dialogs, regardless of where the focus is.
4377 static HHOOK wxTheKeyboardHook
= 0;
4378 static FARPROC wxTheKeyboardHookProc
= 0;
4379 int APIENTRY _EXPORT
4380 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4382 void wxSetKeyboardHook(bool doIt
)
4386 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4387 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4389 #if defined(__WIN32__) && !defined(__TWIN32__)
4390 GetCurrentThreadId()
4391 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4399 UnhookWindowsHookEx(wxTheKeyboardHook
);
4401 // avoids warning about statement with no effect (FreeProcInstance
4402 // doesn't do anything under Win32)
4403 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4404 FreeProcInstance(wxTheKeyboardHookProc
);
4409 int APIENTRY _EXPORT
4410 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4412 DWORD hiWord
= HIWORD(lParam
);
4413 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4415 int id
= wxCharCodeMSWToWX(wParam
);
4418 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4419 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4420 event
.m_altDown
= TRUE
;
4422 event
.m_eventObject
= NULL
;
4423 event
.m_keyCode
= id
;
4424 event
.m_shiftDown
= wxIsShiftDown();
4425 event
.m_controlDown
= wxIsCtrlDown();
4426 event
.SetTimestamp(s_currentMsg
.time
);
4428 wxWindow
*win
= wxGetActiveWindow();
4429 wxEvtHandler
*handler
;
4432 handler
= win
->GetEventHandler();
4433 event
.SetId(win
->GetId());
4441 if ( handler
&& handler
->ProcessEvent(event
) )
4449 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4452 #endif // !__WXMICROWIN__
4455 const char *wxGetMessageName(int message
)
4459 case 0x0000: return "WM_NULL";
4460 case 0x0001: return "WM_CREATE";
4461 case 0x0002: return "WM_DESTROY";
4462 case 0x0003: return "WM_MOVE";
4463 case 0x0005: return "WM_SIZE";
4464 case 0x0006: return "WM_ACTIVATE";
4465 case 0x0007: return "WM_SETFOCUS";
4466 case 0x0008: return "WM_KILLFOCUS";
4467 case 0x000A: return "WM_ENABLE";
4468 case 0x000B: return "WM_SETREDRAW";
4469 case 0x000C: return "WM_SETTEXT";
4470 case 0x000D: return "WM_GETTEXT";
4471 case 0x000E: return "WM_GETTEXTLENGTH";
4472 case 0x000F: return "WM_PAINT";
4473 case 0x0010: return "WM_CLOSE";
4474 case 0x0011: return "WM_QUERYENDSESSION";
4475 case 0x0012: return "WM_QUIT";
4476 case 0x0013: return "WM_QUERYOPEN";
4477 case 0x0014: return "WM_ERASEBKGND";
4478 case 0x0015: return "WM_SYSCOLORCHANGE";
4479 case 0x0016: return "WM_ENDSESSION";
4480 case 0x0017: return "WM_SYSTEMERROR";
4481 case 0x0018: return "WM_SHOWWINDOW";
4482 case 0x0019: return "WM_CTLCOLOR";
4483 case 0x001A: return "WM_WININICHANGE";
4484 case 0x001B: return "WM_DEVMODECHANGE";
4485 case 0x001C: return "WM_ACTIVATEAPP";
4486 case 0x001D: return "WM_FONTCHANGE";
4487 case 0x001E: return "WM_TIMECHANGE";
4488 case 0x001F: return "WM_CANCELMODE";
4489 case 0x0020: return "WM_SETCURSOR";
4490 case 0x0021: return "WM_MOUSEACTIVATE";
4491 case 0x0022: return "WM_CHILDACTIVATE";
4492 case 0x0023: return "WM_QUEUESYNC";
4493 case 0x0024: return "WM_GETMINMAXINFO";
4494 case 0x0026: return "WM_PAINTICON";
4495 case 0x0027: return "WM_ICONERASEBKGND";
4496 case 0x0028: return "WM_NEXTDLGCTL";
4497 case 0x002A: return "WM_SPOOLERSTATUS";
4498 case 0x002B: return "WM_DRAWITEM";
4499 case 0x002C: return "WM_MEASUREITEM";
4500 case 0x002D: return "WM_DELETEITEM";
4501 case 0x002E: return "WM_VKEYTOITEM";
4502 case 0x002F: return "WM_CHARTOITEM";
4503 case 0x0030: return "WM_SETFONT";
4504 case 0x0031: return "WM_GETFONT";
4505 case 0x0037: return "WM_QUERYDRAGICON";
4506 case 0x0039: return "WM_COMPAREITEM";
4507 case 0x0041: return "WM_COMPACTING";
4508 case 0x0044: return "WM_COMMNOTIFY";
4509 case 0x0046: return "WM_WINDOWPOSCHANGING";
4510 case 0x0047: return "WM_WINDOWPOSCHANGED";
4511 case 0x0048: return "WM_POWER";
4514 case 0x004A: return "WM_COPYDATA";
4515 case 0x004B: return "WM_CANCELJOURNAL";
4516 case 0x004E: return "WM_NOTIFY";
4517 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4518 case 0x0051: return "WM_INPUTLANGCHANGE";
4519 case 0x0052: return "WM_TCARD";
4520 case 0x0053: return "WM_HELP";
4521 case 0x0054: return "WM_USERCHANGED";
4522 case 0x0055: return "WM_NOTIFYFORMAT";
4523 case 0x007B: return "WM_CONTEXTMENU";
4524 case 0x007C: return "WM_STYLECHANGING";
4525 case 0x007D: return "WM_STYLECHANGED";
4526 case 0x007E: return "WM_DISPLAYCHANGE";
4527 case 0x007F: return "WM_GETICON";
4528 case 0x0080: return "WM_SETICON";
4531 case 0x0081: return "WM_NCCREATE";
4532 case 0x0082: return "WM_NCDESTROY";
4533 case 0x0083: return "WM_NCCALCSIZE";
4534 case 0x0084: return "WM_NCHITTEST";
4535 case 0x0085: return "WM_NCPAINT";
4536 case 0x0086: return "WM_NCACTIVATE";
4537 case 0x0087: return "WM_GETDLGCODE";
4538 case 0x00A0: return "WM_NCMOUSEMOVE";
4539 case 0x00A1: return "WM_NCLBUTTONDOWN";
4540 case 0x00A2: return "WM_NCLBUTTONUP";
4541 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4542 case 0x00A4: return "WM_NCRBUTTONDOWN";
4543 case 0x00A5: return "WM_NCRBUTTONUP";
4544 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4545 case 0x00A7: return "WM_NCMBUTTONDOWN";
4546 case 0x00A8: return "WM_NCMBUTTONUP";
4547 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4548 case 0x0100: return "WM_KEYDOWN";
4549 case 0x0101: return "WM_KEYUP";
4550 case 0x0102: return "WM_CHAR";
4551 case 0x0103: return "WM_DEADCHAR";
4552 case 0x0104: return "WM_SYSKEYDOWN";
4553 case 0x0105: return "WM_SYSKEYUP";
4554 case 0x0106: return "WM_SYSCHAR";
4555 case 0x0107: return "WM_SYSDEADCHAR";
4556 case 0x0108: return "WM_KEYLAST";
4559 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4560 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4561 case 0x010F: return "WM_IME_COMPOSITION";
4564 case 0x0110: return "WM_INITDIALOG";
4565 case 0x0111: return "WM_COMMAND";
4566 case 0x0112: return "WM_SYSCOMMAND";
4567 case 0x0113: return "WM_TIMER";
4568 case 0x0114: return "WM_HSCROLL";
4569 case 0x0115: return "WM_VSCROLL";
4570 case 0x0116: return "WM_INITMENU";
4571 case 0x0117: return "WM_INITMENUPOPUP";
4572 case 0x011F: return "WM_MENUSELECT";
4573 case 0x0120: return "WM_MENUCHAR";
4574 case 0x0121: return "WM_ENTERIDLE";
4575 case 0x0200: return "WM_MOUSEMOVE";
4576 case 0x0201: return "WM_LBUTTONDOWN";
4577 case 0x0202: return "WM_LBUTTONUP";
4578 case 0x0203: return "WM_LBUTTONDBLCLK";
4579 case 0x0204: return "WM_RBUTTONDOWN";
4580 case 0x0205: return "WM_RBUTTONUP";
4581 case 0x0206: return "WM_RBUTTONDBLCLK";
4582 case 0x0207: return "WM_MBUTTONDOWN";
4583 case 0x0208: return "WM_MBUTTONUP";
4584 case 0x0209: return "WM_MBUTTONDBLCLK";
4585 case 0x020A: return "WM_MOUSEWHEEL";
4586 case 0x0210: return "WM_PARENTNOTIFY";
4587 case 0x0211: return "WM_ENTERMENULOOP";
4588 case 0x0212: return "WM_EXITMENULOOP";
4591 case 0x0213: return "WM_NEXTMENU";
4592 case 0x0214: return "WM_SIZING";
4593 case 0x0215: return "WM_CAPTURECHANGED";
4594 case 0x0216: return "WM_MOVING";
4595 case 0x0218: return "WM_POWERBROADCAST";
4596 case 0x0219: return "WM_DEVICECHANGE";
4599 case 0x0220: return "WM_MDICREATE";
4600 case 0x0221: return "WM_MDIDESTROY";
4601 case 0x0222: return "WM_MDIACTIVATE";
4602 case 0x0223: return "WM_MDIRESTORE";
4603 case 0x0224: return "WM_MDINEXT";
4604 case 0x0225: return "WM_MDIMAXIMIZE";
4605 case 0x0226: return "WM_MDITILE";
4606 case 0x0227: return "WM_MDICASCADE";
4607 case 0x0228: return "WM_MDIICONARRANGE";
4608 case 0x0229: return "WM_MDIGETACTIVE";
4609 case 0x0230: return "WM_MDISETMENU";
4610 case 0x0233: return "WM_DROPFILES";
4613 case 0x0281: return "WM_IME_SETCONTEXT";
4614 case 0x0282: return "WM_IME_NOTIFY";
4615 case 0x0283: return "WM_IME_CONTROL";
4616 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4617 case 0x0285: return "WM_IME_SELECT";
4618 case 0x0286: return "WM_IME_CHAR";
4619 case 0x0290: return "WM_IME_KEYDOWN";
4620 case 0x0291: return "WM_IME_KEYUP";
4623 case 0x0300: return "WM_CUT";
4624 case 0x0301: return "WM_COPY";
4625 case 0x0302: return "WM_PASTE";
4626 case 0x0303: return "WM_CLEAR";
4627 case 0x0304: return "WM_UNDO";
4628 case 0x0305: return "WM_RENDERFORMAT";
4629 case 0x0306: return "WM_RENDERALLFORMATS";
4630 case 0x0307: return "WM_DESTROYCLIPBOARD";
4631 case 0x0308: return "WM_DRAWCLIPBOARD";
4632 case 0x0309: return "WM_PAINTCLIPBOARD";
4633 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4634 case 0x030B: return "WM_SIZECLIPBOARD";
4635 case 0x030C: return "WM_ASKCBFORMATNAME";
4636 case 0x030D: return "WM_CHANGECBCHAIN";
4637 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4638 case 0x030F: return "WM_QUERYNEWPALETTE";
4639 case 0x0310: return "WM_PALETTEISCHANGING";
4640 case 0x0311: return "WM_PALETTECHANGED";
4643 // common controls messages - although they're not strictly speaking
4644 // standard, it's nice to decode them nevertheless
4647 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4648 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4649 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4650 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4651 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4652 case 0x1000 + 5: return "LVM_GETITEMA";
4653 case 0x1000 + 75: return "LVM_GETITEMW";
4654 case 0x1000 + 6: return "LVM_SETITEMA";
4655 case 0x1000 + 76: return "LVM_SETITEMW";
4656 case 0x1000 + 7: return "LVM_INSERTITEMA";
4657 case 0x1000 + 77: return "LVM_INSERTITEMW";
4658 case 0x1000 + 8: return "LVM_DELETEITEM";
4659 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4660 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4661 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4662 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4663 case 0x1000 + 13: return "LVM_FINDITEMA";
4664 case 0x1000 + 83: return "LVM_FINDITEMW";
4665 case 0x1000 + 14: return "LVM_GETITEMRECT";
4666 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4667 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4668 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4669 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4670 case 0x1000 + 18: return "LVM_HITTEST";
4671 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4672 case 0x1000 + 20: return "LVM_SCROLL";
4673 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4674 case 0x1000 + 22: return "LVM_ARRANGE";
4675 case 0x1000 + 23: return "LVM_EDITLABELA";
4676 case 0x1000 + 118: return "LVM_EDITLABELW";
4677 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4678 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4679 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4680 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4681 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4682 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4683 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4684 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4685 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4686 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4687 case 0x1000 + 31: return "LVM_GETHEADER";
4688 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4689 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4690 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4691 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4692 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4693 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4694 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4695 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4696 case 0x1000 + 41: return "LVM_GETORIGIN";
4697 case 0x1000 + 42: return "LVM_UPDATE";
4698 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4699 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4700 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4701 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4702 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4703 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4704 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4705 case 0x1000 + 48: return "LVM_SORTITEMS";
4706 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4707 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4708 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4709 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4710 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4711 case 0x1000 + 53: return "LVM_SETICONSPACING";
4712 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4713 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4714 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4715 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4716 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4717 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4718 case 0x1000 + 60: return "LVM_SETHOTITEM";
4719 case 0x1000 + 61: return "LVM_GETHOTITEM";
4720 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4721 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4722 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4723 case 0x1000 + 65: return "LVM_SETWORKAREA";
4726 case 0x1100 + 0: return "TVM_INSERTITEMA";
4727 case 0x1100 + 50: return "TVM_INSERTITEMW";
4728 case 0x1100 + 1: return "TVM_DELETEITEM";
4729 case 0x1100 + 2: return "TVM_EXPAND";
4730 case 0x1100 + 4: return "TVM_GETITEMRECT";
4731 case 0x1100 + 5: return "TVM_GETCOUNT";
4732 case 0x1100 + 6: return "TVM_GETINDENT";
4733 case 0x1100 + 7: return "TVM_SETINDENT";
4734 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4735 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4736 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4737 case 0x1100 + 11: return "TVM_SELECTITEM";
4738 case 0x1100 + 12: return "TVM_GETITEMA";
4739 case 0x1100 + 62: return "TVM_GETITEMW";
4740 case 0x1100 + 13: return "TVM_SETITEMA";
4741 case 0x1100 + 63: return "TVM_SETITEMW";
4742 case 0x1100 + 14: return "TVM_EDITLABELA";
4743 case 0x1100 + 65: return "TVM_EDITLABELW";
4744 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4745 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4746 case 0x1100 + 17: return "TVM_HITTEST";
4747 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4748 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4749 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4750 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4751 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4752 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4753 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4754 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4755 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4758 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4759 case 0x1200 + 1: return "HDM_INSERTITEMA";
4760 case 0x1200 + 10: return "HDM_INSERTITEMW";
4761 case 0x1200 + 2: return "HDM_DELETEITEM";
4762 case 0x1200 + 3: return "HDM_GETITEMA";
4763 case 0x1200 + 11: return "HDM_GETITEMW";
4764 case 0x1200 + 4: return "HDM_SETITEMA";
4765 case 0x1200 + 12: return "HDM_SETITEMW";
4766 case 0x1200 + 5: return "HDM_LAYOUT";
4767 case 0x1200 + 6: return "HDM_HITTEST";
4768 case 0x1200 + 7: return "HDM_GETITEMRECT";
4769 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4770 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4771 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4772 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4773 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4774 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4775 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4778 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4779 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4780 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4781 case 0x1300 + 5: return "TCM_GETITEMA";
4782 case 0x1300 + 60: return "TCM_GETITEMW";
4783 case 0x1300 + 6: return "TCM_SETITEMA";
4784 case 0x1300 + 61: return "TCM_SETITEMW";
4785 case 0x1300 + 7: return "TCM_INSERTITEMA";
4786 case 0x1300 + 62: return "TCM_INSERTITEMW";
4787 case 0x1300 + 8: return "TCM_DELETEITEM";
4788 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4789 case 0x1300 + 10: return "TCM_GETITEMRECT";
4790 case 0x1300 + 11: return "TCM_GETCURSEL";
4791 case 0x1300 + 12: return "TCM_SETCURSEL";
4792 case 0x1300 + 13: return "TCM_HITTEST";
4793 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4794 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4795 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4796 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4797 case 0x1300 + 43: return "TCM_SETPADDING";
4798 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4799 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4800 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4801 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4802 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4803 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4804 case 0x1300 + 50: return "TCM_DESELECTALL";
4807 case WM_USER
+1: return "TB_ENABLEBUTTON";
4808 case WM_USER
+2: return "TB_CHECKBUTTON";
4809 case WM_USER
+3: return "TB_PRESSBUTTON";
4810 case WM_USER
+4: return "TB_HIDEBUTTON";
4811 case WM_USER
+5: return "TB_INDETERMINATE";
4812 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4813 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4814 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4815 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4816 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4817 case WM_USER
+17: return "TB_SETSTATE";
4818 case WM_USER
+18: return "TB_GETSTATE";
4819 case WM_USER
+19: return "TB_ADDBITMAP";
4820 case WM_USER
+20: return "TB_ADDBUTTONS";
4821 case WM_USER
+21: return "TB_INSERTBUTTON";
4822 case WM_USER
+22: return "TB_DELETEBUTTON";
4823 case WM_USER
+23: return "TB_GETBUTTON";
4824 case WM_USER
+24: return "TB_BUTTONCOUNT";
4825 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4826 case WM_USER
+26: return "TB_SAVERESTOREA";
4827 case WM_USER
+76: return "TB_SAVERESTOREW";
4828 case WM_USER
+27: return "TB_CUSTOMIZE";
4829 case WM_USER
+28: return "TB_ADDSTRINGA";
4830 case WM_USER
+77: return "TB_ADDSTRINGW";
4831 case WM_USER
+29: return "TB_GETITEMRECT";
4832 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4833 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4834 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4835 case WM_USER
+33: return "TB_AUTOSIZE";
4836 case WM_USER
+35: return "TB_GETTOOLTIPS";
4837 case WM_USER
+36: return "TB_SETTOOLTIPS";
4838 case WM_USER
+37: return "TB_SETPARENT";
4839 case WM_USER
+39: return "TB_SETROWS";
4840 case WM_USER
+40: return "TB_GETROWS";
4841 case WM_USER
+42: return "TB_SETCMDID";
4842 case WM_USER
+43: return "TB_CHANGEBITMAP";
4843 case WM_USER
+44: return "TB_GETBITMAP";
4844 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4845 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4846 case WM_USER
+46: return "TB_REPLACEBITMAP";
4847 case WM_USER
+47: return "TB_SETINDENT";
4848 case WM_USER
+48: return "TB_SETIMAGELIST";
4849 case WM_USER
+49: return "TB_GETIMAGELIST";
4850 case WM_USER
+50: return "TB_LOADIMAGES";
4851 case WM_USER
+51: return "TB_GETRECT";
4852 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4853 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4854 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4855 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4856 case WM_USER
+56: return "TB_SETSTYLE";
4857 case WM_USER
+57: return "TB_GETSTYLE";
4858 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4859 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4860 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4861 case WM_USER
+61: return "TB_GETTEXTROWS";
4862 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4867 static char s_szBuf
[128];
4868 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4872 #endif //__WXDEBUG__
4874 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4875 int *x
, int *y
, WPARAM
*flags
)
4877 // construct the key mask
4878 WPARAM
& fwKeys
= *flags
;
4880 fwKeys
= MK_RBUTTON
;
4881 if ( wxIsCtrlDown() )
4882 fwKeys
|= MK_CONTROL
;
4883 if ( wxIsShiftDown() )
4886 // simulate right mouse button click
4887 DWORD dwPos
= ::GetMessagePos();
4888 *x
= GET_X_LPARAM(dwPos
);
4889 *y
= GET_Y_LPARAM(dwPos
);
4891 win
->ScreenToClient(x
, y
);
4894 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4898 HWND hwnd
= GetHwndOf(win
);
4899 HDC hdc
= ::GetDC(hwnd
);
4901 #if !wxDIALOG_UNIT_COMPATIBILITY
4902 // and select the current font into it
4903 HFONT hfont
= GetHfontOf(win
->GetFont());
4906 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4910 // finally retrieve the text metrics from it
4911 GetTextMetrics(hdc
, &tm
);
4913 #if !wxDIALOG_UNIT_COMPATIBILITY
4917 (void)::SelectObject(hdc
, hfont
);
4921 ::ReleaseDC(hwnd
, hdc
);
4926 // Find the wxWindow at the current mouse position, returning the mouse
4928 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4930 return wxFindWindowAtPoint(wxGetMousePosition());
4933 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4938 HWND hWndHit
= ::WindowFromPoint(pt2
);
4940 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4941 HWND hWnd
= hWndHit
;
4943 // Try to find a window with a wxWindow associated with it
4944 while (!win
&& (hWnd
!= 0))
4946 hWnd
= ::GetParent(hWnd
);
4947 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
4952 // Get the current mouse position.
4953 wxPoint
wxGetMousePosition()
4956 GetCursorPos( & pt
);
4957 return wxPoint(pt
.x
, pt
.y
);