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 // was there really an error?
454 #ifndef __WXMICROWIN__
455 DWORD dwRes
= ::GetLastError();
462 wxLogApiError(_T("SetFocus"), dwRes
);
465 // VZ: just why does this happen sometimes?? any idea?
467 HWND hwndFocus
= ::GetFocus();
468 wxASSERT_MSG( hwndFocus
== hWnd
, _T("SetFocus() didn't work?") );
473 // Get the window with the focus
474 wxWindow
*wxWindowBase::FindFocus()
476 HWND hWnd
= ::GetFocus();
479 return wxGetWindowFromHWND((WXHWND
)hWnd
);
485 bool wxWindowMSW::Enable(bool enable
)
487 if ( !wxWindowBase::Enable(enable
) )
490 HWND hWnd
= GetHwnd();
492 ::EnableWindow(hWnd
, (BOOL
)enable
);
494 // VZ: no, this is a bad idea: imagine that you have a dialog with some
495 // disabled controls and disable it - you really wouldn't like the
496 // disabled controls be reenabled too when you reenable the dialog!
498 wxWindowList::Node
*node
= GetChildren().GetFirst();
501 wxWindow
*child
= node
->GetData();
502 child
->Enable(enable
);
504 node
= node
->GetNext();
511 bool wxWindowMSW::Show(bool show
)
513 if ( !wxWindowBase::Show(show
) )
516 HWND hWnd
= GetHwnd();
517 int cshow
= show
? SW_SHOW
: SW_HIDE
;
518 ::ShowWindow(hWnd
, cshow
);
522 wxBringWindowToTop(hWnd
);
528 // Raise the window to the top of the Z order
529 void wxWindowMSW::Raise()
531 wxBringWindowToTop(GetHwnd());
534 // Lower the window to the bottom of the Z order
535 void wxWindowMSW::Lower()
537 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
538 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
541 void wxWindowMSW::SetTitle( const wxString
& title
)
543 SetWindowText(GetHwnd(), title
.c_str());
546 wxString
wxWindowMSW::GetTitle() const
548 return wxGetWindowText(GetHWND());
551 void wxWindowMSW::CaptureMouse()
553 HWND hWnd
= GetHwnd();
560 void wxWindowMSW::ReleaseMouse()
562 if ( !::ReleaseCapture() )
564 wxLogLastError(_T("ReleaseCapture"));
568 /* static */ wxWindow
*wxWindowBase::GetCapture()
570 HWND hwnd
= ::GetCapture();
571 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
574 bool wxWindowMSW::SetFont(const wxFont
& font
)
576 if ( !wxWindowBase::SetFont(font
) )
582 HWND hWnd
= GetHwnd();
585 WXHANDLE hFont
= m_font
.GetResourceHandle();
587 wxASSERT_MSG( hFont
, wxT("should have valid font") );
589 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
594 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
596 if ( !wxWindowBase::SetCursor(cursor
) )
604 HWND hWnd
= GetHwnd();
606 // Change the cursor NOW if we're within the correct window
608 ::GetCursorPos(&point
);
610 RECT rect
= wxGetWindowRect(hWnd
);
612 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
613 ::SetCursor(GetHcursorOf(m_cursor
));
619 void wxWindowMSW::WarpPointer (int x
, int y
)
621 ClientToScreen(&x
, &y
);
623 if ( !::SetCursorPos(x
, y
) )
625 wxLogLastError(_T("SetCursorPos"));
629 #if WXWIN_COMPATIBILITY
630 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
633 #endif // WXWIN_COMPATIBILITY
635 // ---------------------------------------------------------------------------
637 // ---------------------------------------------------------------------------
639 #if WXWIN_COMPATIBILITY
640 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
642 #if defined(__WIN95__)
646 // Try to adjust the range to cope with page size > 1
647 // - a Windows API quirk
648 int pageSize
= GetScrollPage(orient
);
649 if ( pageSize
> 1 && range
> 0)
651 range1
+= (pageSize
- 1);
657 if ( orient
== wxHORIZONTAL
) {
663 info
.cbSize
= sizeof(SCROLLINFO
);
664 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
668 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
670 HWND hWnd
= GetHwnd();
672 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
675 if ( orient
== wxHORIZONTAL
)
680 HWND hWnd
= GetHwnd();
682 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
686 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
688 #if defined(__WIN95__)
692 if ( orient
== wxHORIZONTAL
) {
700 info
.cbSize
= sizeof(SCROLLINFO
);
703 info
.fMask
= SIF_PAGE
;
705 HWND hWnd
= GetHwnd();
707 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
709 if ( orient
== wxHORIZONTAL
)
716 int wxWindowMSW::OldGetScrollRange(int orient
) const
719 if ( orient
== wxHORIZONTAL
)
724 #if __WATCOMC__ && defined(__WINDOWS_386__)
725 short minPos
, maxPos
;
729 HWND hWnd
= GetHwnd();
732 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
733 #if defined(__WIN95__)
734 // Try to adjust the range to cope with page size > 1
735 // - a Windows API quirk
736 int pageSize
= GetScrollPage(orient
);
739 maxPos
-= (pageSize
- 1);
748 int wxWindowMSW::GetScrollPage(int orient
) const
750 if ( orient
== wxHORIZONTAL
)
756 #endif // WXWIN_COMPATIBILITY
758 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
760 #ifdef __WXMICROWIN__
761 return ::GetScrollPosWX(hWnd
, wOrient
);
763 return ::GetScrollPos(hWnd
, wOrient
);
767 int wxWindowMSW::GetScrollPos(int orient
) const
770 if ( orient
== wxHORIZONTAL
)
775 HWND hWnd
= GetHwnd();
776 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
778 return GetScrollPosition(hWnd
, wOrient
);
781 // This now returns the whole range, not just the number
782 // of positions that we can scroll.
783 int wxWindowMSW::GetScrollRange(int orient
) const
786 if ( orient
== wxHORIZONTAL
)
791 #if __WATCOMC__ && defined(__WINDOWS_386__)
792 short minPos
, maxPos
;
796 HWND hWnd
= GetHwnd();
799 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
800 #if defined(__WIN95__)
801 // Try to adjust the range to cope with page size > 1
802 // - a Windows API quirk
803 int pageSize
= GetScrollThumb(orient
);
806 maxPos
-= (pageSize
- 1);
808 // October 10th: new range concept.
818 int wxWindowMSW::GetScrollThumb(int orient
) const
820 if ( orient
== wxHORIZONTAL
)
826 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
828 HWND hWnd
= GetHwnd();
829 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
831 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
833 #if defined(__WIN95__)
835 info
.cbSize
= sizeof(SCROLLINFO
);
839 info
.fMask
= SIF_POS
;
841 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
843 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
844 #endif // __WIN95__/!__WIN95__
847 // New function that will replace some of the above.
848 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
849 int range
, bool refresh
)
851 #if defined(__WIN95__)
852 int oldRange
= range
- thumbVisible
;
854 int range1
= oldRange
;
856 // Try to adjust the range to cope with page size > 1
857 // - a Windows API quirk
858 int pageSize
= thumbVisible
;
859 if ( pageSize
> 1 && range
> 0)
861 range1
+= (pageSize
- 1);
867 if ( orient
== wxHORIZONTAL
) {
873 info
.cbSize
= sizeof(SCROLLINFO
);
874 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
878 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
880 HWND hWnd
= GetHwnd();
882 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
885 if ( orient
== wxHORIZONTAL
)
890 HWND hWnd
= GetHwnd();
893 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
894 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
897 if ( orient
== wxHORIZONTAL
) {
898 m_xThumbSize
= thumbVisible
;
900 m_yThumbSize
= thumbVisible
;
904 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
909 rect
.left
= prect
->x
;
911 rect
.right
= prect
->x
+ prect
->width
;
912 rect
.bottom
= prect
->y
+ prect
->height
;
915 ::ScrollWindow(GetHwnd(), dx
, dy
, prect
? &rect
: NULL
, NULL
);
918 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
920 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
923 for ( int n
= 0; n
< count
; n
++ )
925 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
927 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
930 // don't bother to continue, we're already at top/bottom
937 return pos
!= posStart
;
940 bool wxWindowMSW::ScrollLines(int lines
)
942 bool down
= lines
> 0;
944 return ScrollVertically(GetHwnd(),
945 down
? SB_LINEDOWN
: SB_LINEUP
,
946 down
? lines
: -lines
);
949 bool wxWindowMSW::ScrollPages(int pages
)
951 bool down
= pages
> 0;
953 return ScrollVertically(GetHwnd(),
954 down
? SB_PAGEDOWN
: SB_PAGEUP
,
955 down
? pages
: -pages
);
958 // ---------------------------------------------------------------------------
960 // ---------------------------------------------------------------------------
962 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
964 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
966 HWND hwnd
= (HWND
)hWnd
;
967 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
969 wxAssociateWinWithHandle(hwnd
, this);
971 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
973 // we don't need to subclass the window of our own class (in the Windows
974 // sense of the word)
975 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
977 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
981 // don't bother restoring it neither
986 void wxWindowMSW::UnsubclassWin()
988 wxRemoveHandleAssociation(this);
990 // Restore old Window proc
991 HWND hwnd
= GetHwnd();
996 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
1000 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
1002 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1005 m_oldWndProc
= NULL
;
1010 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
1012 #if wxUSE_UNICODE_MSLU
1013 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
1014 // because it doesn't return pointer to the real wnd proc but rather a handle
1015 // of a fake proc that does Unicode<->ANSI translation.
1017 // The hack bellow works, because WNDCLASS contains original window handler
1018 // rather that the unicows fake one. This may not be on purpose, though; if
1019 // it stops working with future versions of unicows.dll, we can override
1020 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
1021 // Unicows_RegisterClass to our own versions that keep track of
1022 // fake<->real wnd proc mapping.
1024 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
1025 // with RegisterClass!!
1027 static wxChar buffer
[512];
1030 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1031 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1032 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1034 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1039 // Make a Windows extended style from the given wxWindows window style
1040 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1042 WXDWORD exStyle
= 0;
1043 if ( style
& wxTRANSPARENT_WINDOW
)
1044 exStyle
|= WS_EX_TRANSPARENT
;
1046 if ( !eliminateBorders
)
1048 if ( style
& wxSUNKEN_BORDER
)
1049 exStyle
|= WS_EX_CLIENTEDGE
;
1050 if ( style
& wxDOUBLE_BORDER
)
1051 exStyle
|= WS_EX_DLGMODALFRAME
;
1052 #if defined(__WIN95__)
1053 if ( style
& wxRAISED_BORDER
)
1054 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1055 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1056 if ( style
& wxSTATIC_BORDER
)
1057 exStyle
|= WS_EX_STATICEDGE
;
1064 // Determines whether native 3D effects or CTL3D should be used,
1065 // applying a default border style if required, and returning an extended
1066 // style to pass to CreateWindowEx.
1067 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1070 // If matches certain criteria, then assume no 3D effects
1071 // unless specifically requested (dealt with in MakeExtendedStyle)
1074 || !IsKindOf(CLASSINFO(wxControl
))
1075 #endif // wxUSE_CONTROLS
1076 || (m_windowStyle
& wxNO_BORDER
) )
1079 return MakeExtendedStyle(m_windowStyle
);
1082 // Determine whether we should be using 3D effects or not.
1083 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1085 // 1) App can specify global 3D effects
1086 *want3D
= wxTheApp
->GetAuto3D();
1088 // 2) If the parent is being drawn with user colours, or simple border specified,
1089 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1090 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1093 // 3) Control can override this global setting by defining
1094 // a border style, e.g. wxSUNKEN_BORDER
1095 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1098 // 4) If it's a special border, CTL3D can't cope so we want a native border
1099 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1100 (m_windowStyle
& wxSTATIC_BORDER
) )
1103 nativeBorder
= TRUE
;
1106 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1107 // effects from extended style
1110 nativeBorder
= FALSE
;
1113 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1115 // If we want 3D, but haven't specified a border here,
1116 // apply the default border style specified.
1117 // TODO what about non-Win95 WIN32? Does it have borders?
1118 #if defined(__WIN95__) && !wxUSE_CTL3D
1119 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1120 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1121 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1127 #if WXWIN_COMPATIBILITY
1128 // If nothing defined for this, try the parent.
1129 // E.g. we may be a button loaded from a resource, with no callback function
1131 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1133 if ( GetEventHandler()->ProcessEvent(event
) )
1136 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1138 #endif // WXWIN_COMPATIBILITY_2
1140 #if WXWIN_COMPATIBILITY
1141 wxObject
* wxWindowMSW::GetChild(int number
) const
1143 // Return a pointer to the Nth object in the Panel
1144 wxNode
*node
= GetChildren().First();
1147 node
= node
->Next();
1150 wxObject
*obj
= (wxObject
*)node
->Data();
1156 #endif // WXWIN_COMPATIBILITY
1158 // Setup background and foreground colours correctly
1159 void wxWindowMSW::SetupColours()
1162 SetBackgroundColour(GetParent()->GetBackgroundColour());
1165 bool wxWindowMSW::IsMouseInWindow() const
1167 // get the mouse position
1169 ::GetCursorPos(&pt
);
1171 // find the window which currently has the cursor and go up the window
1172 // chain until we find this window - or exhaust it
1173 HWND hwnd
= ::WindowFromPoint(pt
);
1174 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1175 hwnd
= ::GetParent(hwnd
);
1177 return hwnd
!= NULL
;
1180 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1182 // Check if we need to send a LEAVE event
1183 if ( m_mouseInWindow
)
1185 if ( !IsMouseInWindow() )
1187 // Generate a LEAVE event
1188 m_mouseInWindow
= FALSE
;
1190 // Unfortunately the mouse button and keyboard state may have
1191 // changed by the time the OnIdle function is called, so 'state'
1192 // may be meaningless.
1194 if ( wxIsShiftDown() )
1196 if ( wxIsCtrlDown() )
1197 state
|= MK_CONTROL
;
1198 if ( GetKeyState( VK_LBUTTON
) )
1199 state
|= MK_LBUTTON
;
1200 if ( GetKeyState( VK_MBUTTON
) )
1201 state
|= MK_MBUTTON
;
1202 if ( GetKeyState( VK_RBUTTON
) )
1203 state
|= MK_RBUTTON
;
1206 if ( !::GetCursorPos(&pt
) )
1208 wxLogLastError(_T("GetCursorPos"));
1211 // we need to have client coordinates here for symmetry with
1212 // wxEVT_ENTER_WINDOW
1213 RECT rect
= wxGetWindowRect(GetHwnd());
1217 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1218 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1220 (void)GetEventHandler()->ProcessEvent(event2
);
1227 // Set this window to be the child of 'parent'.
1228 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1230 if ( !wxWindowBase::Reparent(parent
) )
1233 HWND hWndChild
= GetHwnd();
1234 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1236 ::SetParent(hWndChild
, hWndParent
);
1241 void wxWindowMSW::Clear()
1243 wxClientDC
dc((wxWindow
*)this);
1244 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1245 dc
.SetBackground(brush
);
1249 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1251 #ifndef __WXMICROWIN__
1252 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1256 void wxWindowMSW::Freeze()
1258 SendSetRedraw(GetHwnd(), FALSE
);
1261 void wxWindowMSW::Thaw()
1263 SendSetRedraw(GetHwnd(), TRUE
);
1265 // we need to refresh everything or otherwise he invalidated area is not
1270 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1272 HWND hWnd
= GetHwnd();
1278 mswRect
.left
= rect
->x
;
1279 mswRect
.top
= rect
->y
;
1280 mswRect
.right
= rect
->x
+ rect
->width
;
1281 mswRect
.bottom
= rect
->y
+ rect
->height
;
1283 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1286 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1290 void wxWindowMSW::Update()
1292 if ( !::UpdateWindow(GetHwnd()) )
1294 wxLogLastError(_T("UpdateWindow"));
1297 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1298 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1299 // handler needs to be really drawn right now
1304 // ---------------------------------------------------------------------------
1306 // ---------------------------------------------------------------------------
1308 #if wxUSE_DRAG_AND_DROP
1310 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1312 if ( m_dropTarget
!= 0 ) {
1313 m_dropTarget
->Revoke(m_hWnd
);
1314 delete m_dropTarget
;
1317 m_dropTarget
= pDropTarget
;
1318 if ( m_dropTarget
!= 0 )
1319 m_dropTarget
->Register(m_hWnd
);
1322 #endif // wxUSE_DRAG_AND_DROP
1324 // old style file-manager drag&drop support: we retain the old-style
1325 // DragAcceptFiles in parallel with SetDropTarget.
1326 void wxWindowMSW::DragAcceptFiles(bool accept
)
1328 HWND hWnd
= GetHwnd();
1330 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1333 // ----------------------------------------------------------------------------
1335 // ----------------------------------------------------------------------------
1339 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1341 wxWindowBase::DoSetToolTip(tooltip
);
1344 m_tooltip
->SetWindow(this);
1347 #endif // wxUSE_TOOLTIPS
1349 // ---------------------------------------------------------------------------
1350 // moving and resizing
1351 // ---------------------------------------------------------------------------
1354 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1356 RECT rect
= wxGetWindowRect(GetHwnd());
1359 *x
= rect
.right
- rect
.left
;
1361 *y
= rect
.bottom
- rect
.top
;
1364 // Get size *available for subwindows* i.e. excluding menu bar etc.
1365 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1367 RECT rect
= wxGetClientRect(GetHwnd());
1375 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1377 RECT rect
= wxGetWindowRect(GetHwnd());
1380 point
.x
= rect
.left
;
1383 // we do the adjustments with respect to the parent only for the "real"
1384 // children, not for the dialogs/frames
1385 if ( !IsTopLevel() )
1387 HWND hParentWnd
= 0;
1388 wxWindow
*parent
= GetParent();
1390 hParentWnd
= GetWinHwnd(parent
);
1392 // Since we now have the absolute screen coords, if there's a parent we
1393 // must subtract its top left corner
1396 ::ScreenToClient(hParentWnd
, &point
);
1401 // We may be faking the client origin. So a window that's really at (0,
1402 // 30) may appear (to wxWin apps) to be at (0, 0).
1403 wxPoint
pt(parent
->GetClientAreaOrigin());
1415 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1423 ::ScreenToClient(GetHwnd(), &pt
);
1431 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1439 ::ClientToScreen(GetHwnd(), &pt
);
1447 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1449 // TODO: is this consistent with other platforms?
1450 // Still, negative width or height shouldn't be allowed
1455 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1457 wxLogLastError(wxT("MoveWindow"));
1461 // set the size of the window: if the dimensions are positive, just use them,
1462 // but if any of them is equal to -1, it means that we must find the value for
1463 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1464 // which case -1 is a valid value for x and y)
1466 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1467 // the width/height to best suit our contents, otherwise we reuse the current
1469 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1471 // get the current size and position...
1472 int currentX
, currentY
;
1473 GetPosition(¤tX
, ¤tY
);
1474 int currentW
,currentH
;
1475 GetSize(¤tW
, ¤tH
);
1477 // ... and don't do anything (avoiding flicker) if it's already ok
1478 if ( x
== currentX
&& y
== currentY
&&
1479 width
== currentW
&& height
== currentH
)
1484 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1486 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1489 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1491 wxSize
size(-1, -1);
1494 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1496 size
= DoGetBestSize();
1501 // just take the current one
1508 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1512 size
= DoGetBestSize();
1514 //else: already called DoGetBestSize() above
1520 // just take the current one
1525 DoMoveWindow(x
, y
, width
, height
);
1528 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1530 // setting the client size is less obvious than it it could have been
1531 // because in the result of changing the total size the window scrollbar
1532 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1533 // will not be correct as the difference between the total and client size
1534 // changes - so we keep changing it until we get it right
1536 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1537 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1538 // may become 3 if the window had 0 size originally and so we didn't
1539 // calculate the scrollbar correction correctly during the first iteration)
1540 // but just to be on the safe side we check for it instead of making it an
1541 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1542 for ( int i
= 0; i
< 4; i
++ )
1545 ::GetClientRect(GetHwnd(), &rectClient
);
1547 // if the size is already ok, stop here (rectClient.left = top = 0)
1548 if ( rectClient
.right
== width
&& rectClient
.bottom
== height
)
1555 // how did it happen? maybe OnSize() handler does something really
1556 // strange in this class?
1557 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1562 int widthClient
= width
,
1563 heightClient
= height
;
1565 // Find the difference between the entire window (title bar and all)
1566 // and the client area; add this to the new client size to move the
1569 ::GetWindowRect(GetHwnd(), &rectWin
);
1571 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1572 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1575 point
.x
= rectWin
.left
;
1576 point
.y
= rectWin
.top
;
1578 // MoveWindow positions the child windows relative to the parent, so
1579 // adjust if necessary
1580 if ( !IsTopLevel() )
1582 wxWindow
*parent
= GetParent();
1585 ::ScreenToClient(GetHwndOf(parent
), &point
);
1589 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1593 // For implementation purposes - sometimes decorations make the client area
1595 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1597 return wxPoint(0, 0);
1600 // ---------------------------------------------------------------------------
1602 // ---------------------------------------------------------------------------
1604 int wxWindowMSW::GetCharHeight() const
1606 return wxGetTextMetrics(this).tmHeight
;
1609 int wxWindowMSW::GetCharWidth() const
1611 // +1 is needed because Windows apparently adds it when calculating the
1612 // dialog units size in pixels
1613 #if wxDIALOG_UNIT_COMPATIBILITY
1614 return wxGetTextMetrics(this).tmAveCharWidth
;
1616 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1620 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1622 int *descent
, int *externalLeading
,
1623 const wxFont
*theFont
) const
1625 const wxFont
*fontToUse
= theFont
;
1627 fontToUse
= &m_font
;
1629 HWND hWnd
= GetHwnd();
1630 HDC dc
= ::GetDC(hWnd
);
1634 if ( fontToUse
&& fontToUse
->Ok() )
1636 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1638 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1643 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1644 GetTextMetrics(dc
, &tm
);
1646 if ( fontToUse
&& fnt
&& hfontOld
)
1647 SelectObject(dc
, hfontOld
);
1649 ReleaseDC(hWnd
, dc
);
1656 *descent
= tm
.tmDescent
;
1657 if ( externalLeading
)
1658 *externalLeading
= tm
.tmExternalLeading
;
1661 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1662 // ---------------------------------------------------------------------------
1663 // Caret manipulation
1664 // ---------------------------------------------------------------------------
1666 void wxWindowMSW::CreateCaret(int w
, int h
)
1668 SetCaret(new wxCaret(this, w
, h
));
1671 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1673 wxFAIL_MSG("not implemented");
1676 void wxWindowMSW::ShowCaret(bool show
)
1678 wxCHECK_RET( m_caret
, "no caret to show" );
1680 m_caret
->Show(show
);
1683 void wxWindowMSW::DestroyCaret()
1688 void wxWindowMSW::SetCaretPos(int x
, int y
)
1690 wxCHECK_RET( m_caret
, "no caret to move" );
1692 m_caret
->Move(x
, y
);
1695 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1697 wxCHECK_RET( m_caret
, "no caret to get position of" );
1699 m_caret
->GetPosition(x
, y
);
1701 #endif // wxUSE_CARET
1703 // ---------------------------------------------------------------------------
1705 // ---------------------------------------------------------------------------
1707 #if wxUSE_MENUS_NATIVE
1709 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1710 // immediately, without waiting for the next event loop iteration
1712 // NB: this function should probably be made public later as it can almost
1713 // surely replace wxYield() elsewhere as well
1714 static void wxYieldForCommandsOnly()
1716 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1717 // want to process it here)
1719 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1720 && msg
.message
!= WM_QUIT
)
1722 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1726 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1728 menu
->SetInvokingWindow(this);
1731 HWND hWnd
= GetHwnd();
1732 HMENU hMenu
= GetHmenuOf(menu
);
1736 ::ClientToScreen(hWnd
, &point
);
1737 wxCurrentPopupMenu
= menu
;
1738 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1740 // we need to do it righ now as otherwise the events are never going to be
1741 // sent to wxCurrentPopupMenu from HandleCommand()
1743 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1744 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1745 // destroyed as soon as we return (it can be a local variable in the caller
1746 // for example) and so we do need to process the event immediately
1747 wxYieldForCommandsOnly();
1749 wxCurrentPopupMenu
= NULL
;
1751 menu
->SetInvokingWindow(NULL
);
1756 #endif // wxUSE_MENUS_NATIVE
1758 // ===========================================================================
1759 // pre/post message processing
1760 // ===========================================================================
1762 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1765 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1767 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1770 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1772 // wxUniversal implements tab traversal itself
1773 #ifndef __WXUNIVERSAL__
1774 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1776 // intercept dialog navigation keys
1777 MSG
*msg
= (MSG
*)pMsg
;
1779 // here we try to do all the job which ::IsDialogMessage() usually does
1782 bool bProcess
= TRUE
;
1783 if ( msg
->message
!= WM_KEYDOWN
)
1786 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1791 bool bCtrlDown
= wxIsCtrlDown();
1792 bool bShiftDown
= wxIsShiftDown();
1794 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1795 // don't process it if it's the case (except for Ctrl-Tab/Enter
1796 // combinations which are always processed)
1800 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1803 bool bForward
= TRUE
,
1804 bWindowChange
= FALSE
;
1806 switch ( msg
->wParam
)
1809 // assume that nobody wants Shift-TAB for himself - if we
1810 // don't do it there is no easy way for a control to grab
1811 // TABs but still let Shift-TAB work as navugation key
1812 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1816 // Ctrl-Tab cycles thru notebook pages
1817 bWindowChange
= bCtrlDown
;
1818 bForward
= !bShiftDown
;
1824 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1832 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1838 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1840 // control wants to process Enter itself, don't
1841 // call IsDialogMessage() which would interpret
1845 else if ( lDlgCode
& DLGC_BUTTON
)
1847 // let IsDialogMessage() handle this for all
1848 // buttons except the owner-drawn ones which it
1849 // just seems to ignore
1850 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1851 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1853 // emulate the button click
1854 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1856 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1861 // FIXME: this should be handled by
1862 // wxNavigationKeyEvent handler and not here!!
1866 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1868 if ( btn
&& btn
->IsEnabled() )
1870 // if we do have a default button, do press it
1871 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1875 else // no default button
1876 #endif // wxUSE_BUTTON
1878 // no special function for enter and don't even
1879 // let IsDialogMessage() have it: it seems to
1880 // do something really strange with it
1893 wxNavigationKeyEvent event
;
1894 event
.SetDirection(bForward
);
1895 event
.SetWindowChange(bWindowChange
);
1896 event
.SetEventObject(this);
1898 if ( GetEventHandler()->ProcessEvent(event
) )
1905 // let ::IsDialogMessage() do almost everything and handle just the
1906 // things it doesn't here: Ctrl-TAB for switching notebook pages
1907 if ( msg
->message
== WM_KEYDOWN
)
1909 // don't process system keys here
1910 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1912 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1914 // find the first notebook parent and change its page
1915 wxWindow
*win
= this;
1916 wxNotebook
*nbook
= NULL
;
1917 while ( win
&& !nbook
)
1919 nbook
= wxDynamicCast(win
, wxNotebook
);
1920 win
= win
->GetParent();
1925 bool forward
= !wxIsShiftDown();
1927 nbook
->AdvanceSelection(forward
);
1934 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1936 // IsDialogMessage() did something...
1940 #endif // __WXUNIVERSAL__
1945 // relay mouse move events to the tooltip control
1946 MSG
*msg
= (MSG
*)pMsg
;
1947 if ( msg
->message
== WM_MOUSEMOVE
)
1948 m_tooltip
->RelayEvent(pMsg
);
1950 #endif // wxUSE_TOOLTIPS
1955 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1957 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1958 return m_acceleratorTable
.Translate(this, pMsg
);
1961 #endif // wxUSE_ACCEL
1964 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1966 // preprocess all messages by default
1970 // ---------------------------------------------------------------------------
1971 // message params unpackers (different for Win16 and Win32)
1972 // ---------------------------------------------------------------------------
1976 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1977 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1979 *id
= LOWORD(wParam
);
1980 *hwnd
= (WXHWND
)lParam
;
1981 *cmd
= HIWORD(wParam
);
1984 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1985 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1987 *state
= LOWORD(wParam
);
1988 *minimized
= HIWORD(wParam
);
1989 *hwnd
= (WXHWND
)lParam
;
1992 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1993 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1995 *code
= LOWORD(wParam
);
1996 *pos
= HIWORD(wParam
);
1997 *hwnd
= (WXHWND
)lParam
;
2000 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2001 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2003 #ifndef __WXMICROWIN__
2004 *nCtlColor
= CTLCOLOR_BTN
;
2005 *hwnd
= (WXHWND
)lParam
;
2006 *hdc
= (WXHDC
)wParam
;
2010 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2011 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2013 *item
= (WXWORD
)wParam
;
2014 *flags
= HIWORD(wParam
);
2015 *hmenu
= (WXHMENU
)lParam
;
2020 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2021 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2023 *id
= (WXWORD
)wParam
;
2024 *hwnd
= (WXHWND
)LOWORD(lParam
);
2025 *cmd
= HIWORD(lParam
);
2028 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2029 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2031 *state
= (WXWORD
)wParam
;
2032 *minimized
= LOWORD(lParam
);
2033 *hwnd
= (WXHWND
)HIWORD(lParam
);
2036 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2037 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2039 *code
= (WXWORD
)wParam
;
2040 *pos
= LOWORD(lParam
);
2041 *hwnd
= (WXHWND
)HIWORD(lParam
);
2044 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2045 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2047 *hwnd
= (WXHWND
)LOWORD(lParam
);
2048 *nCtlColor
= (int)HIWORD(lParam
);
2049 *hdc
= (WXHDC
)wParam
;
2052 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2053 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2055 *item
= (WXWORD
)wParam
;
2056 *flags
= LOWORD(lParam
);
2057 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2062 // ---------------------------------------------------------------------------
2063 // Main wxWindows window proc and the window proc for wxWindow
2064 // ---------------------------------------------------------------------------
2066 // Hook for new window just as it's being created, when the window isn't yet
2067 // associated with the handle
2068 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2070 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2071 // window being created and insures that it's always unset back later
2072 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2074 gs_winBeingCreated
= winBeingCreated
;
2077 wxWindowCreationHook::~wxWindowCreationHook()
2079 gs_winBeingCreated
= NULL
;
2083 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2085 // trace all messages - useful for the debugging
2087 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2088 wxGetMessageName(message
), wParam
, lParam
);
2089 #endif // __WXDEBUG__
2091 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2093 // when we get the first message for the HWND we just created, we associate
2094 // it with wxWindow stored in gs_winBeingCreated
2095 if ( !wnd
&& gs_winBeingCreated
)
2097 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2098 wnd
= gs_winBeingCreated
;
2099 gs_winBeingCreated
= NULL
;
2100 wnd
->SetHWND((WXHWND
)hWnd
);
2106 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2108 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2113 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2115 // did we process the message?
2116 bool processed
= FALSE
;
2127 // for most messages we should return 0 when we do process the message
2135 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2138 // return 0 to allow window creation
2139 rc
.result
= mayCreate
? 0 : -1;
2145 // never set processed to TRUE and *always* pass WM_DESTROY to
2146 // DefWindowProc() as Windows may do some internal cleanup when
2147 // processing it and failing to pass the message along may cause
2148 // memory and resource leaks!
2149 (void)HandleDestroy();
2153 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2161 // we're not interested in these messages at all
2164 case SIZE_MINIMIZED
:
2165 // we shouldn't send sizev events for these messages as the
2166 // client size may be negative which breaks existing code
2168 // OTOH we might send another (wxMinimizedEvent?) one or
2169 // add an additional parameter to wxSizeEvent if this is
2170 // useful to anybody
2174 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2175 // fall through nevertheless
2177 case SIZE_MAXIMIZED
:
2179 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2184 #ifndef __WXMICROWIN__
2185 case WM_ACTIVATEAPP
:
2186 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2192 WXWORD state
, minimized
;
2194 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2196 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2201 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2205 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2209 processed
= HandlePaint();
2213 // don't let the DefWindowProc() destroy our window - we'll do it
2214 // ourselves in ~wxWindow
2220 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2224 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2225 GET_Y_LPARAM(lParam
),
2229 #if wxUSE_MOUSEWHEEL
2231 processed
= HandleMouseWheel(wParam
, lParam
);
2235 case WM_LBUTTONDOWN
:
2237 case WM_LBUTTONDBLCLK
:
2238 case WM_RBUTTONDOWN
:
2240 case WM_RBUTTONDBLCLK
:
2241 case WM_MBUTTONDOWN
:
2243 case WM_MBUTTONDBLCLK
:
2246 #ifdef __WXMICROWIN__
2247 // MicroWindows seems to ignore the fact that a window is
2248 // disabled. So catch mouse events and throw them away if
2250 wxWindowMSW
* win
= this;
2253 if (!win
->IsEnabled())
2258 win
= win
->GetParent();
2259 if (win
&& win
->IsTopLevel())
2262 #endif // __WXMICROWIN__
2265 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2267 processed
= HandleMouseEvent(message
,
2268 GET_X_LPARAM(lParam
),
2269 GET_Y_LPARAM(lParam
),
2275 #ifdef __WXMICROWIN__
2276 case WM_NCLBUTTONDOWN
:
2277 case WM_NCLBUTTONUP
:
2278 case WM_NCLBUTTONDBLCLK
:
2279 case WM_NCRBUTTONDOWN
:
2280 case WM_NCRBUTTONUP
:
2281 case WM_NCRBUTTONDBLCLK
:
2283 case WM_NCMBUTTONDOWN
:
2284 case WM_NCMBUTTONUP
:
2285 case WM_NCMBUTTONDBLCLK
:
2288 // MicroWindows seems to ignore the fact that a window
2289 // is disabled. So catch mouse events and throw them away if necessary.
2291 wxWindowMSW
* win
= this;
2294 if (!win
->IsEnabled())
2299 win
= win
->GetParent();
2300 if (win
&& win
->IsTopLevel())
2305 #endif // __WXMICROWIN__
2312 case MM_JOY1BUTTONDOWN
:
2313 case MM_JOY2BUTTONDOWN
:
2314 case MM_JOY1BUTTONUP
:
2315 case MM_JOY2BUTTONUP
:
2316 processed
= HandleJoystickEvent(message
,
2317 GET_X_LPARAM(lParam
),
2318 GET_Y_LPARAM(lParam
),
2321 #endif // __WXMICROWIN__
2324 processed
= HandleSysCommand(wParam
, lParam
);
2331 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2333 processed
= HandleCommand(id
, cmd
, hwnd
);
2339 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2343 // for these messages we must return TRUE if process the message
2346 case WM_MEASUREITEM
:
2348 int idCtrl
= (UINT
)wParam
;
2349 if ( message
== WM_DRAWITEM
)
2351 processed
= MSWOnDrawItem(idCtrl
,
2352 (WXDRAWITEMSTRUCT
*)lParam
);
2356 processed
= MSWOnMeasureItem(idCtrl
,
2357 (WXMEASUREITEMSTRUCT
*)lParam
);
2364 #endif // defined(WM_DRAWITEM)
2369 rc
.result
= m_lDlgCode
;
2372 //else: get the dlg code from the DefWindowProc()
2377 // If this has been processed by an event handler,
2378 // return 0 now (we've handled it).
2379 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2386 // we consider these message "not interesting" to OnChar
2387 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2396 // avoid duplicate messages to OnChar for these ASCII keys: they
2397 // will be translated by TranslateMessage() and received in WM_CHAR
2405 // but set processed to FALSE, not TRUE to still pass them to
2406 // the control's default window proc - otherwise built-in
2407 // keyboard handling won't work
2413 // special case of VK_APPS: treat it the same as right mouse
2414 // click because both usually pop up a context menu
2420 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2421 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2431 processed
= HandleChar((WORD
)wParam
, lParam
);
2438 // special case of VK_APPS: treat it the same as right mouse button
2439 if ( wParam
== VK_APPS
)
2444 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2445 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2450 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2455 case WM_CHAR
: // Always an ASCII character
2456 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2464 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2466 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2472 // CTLCOLOR messages are sent by children to query the parent for their
2473 // colors#ifndef __WXMICROWIN__
2474 #ifndef __WXMICROWIN__
2476 case WM_CTLCOLORMSGBOX
:
2477 case WM_CTLCOLOREDIT
:
2478 case WM_CTLCOLORLISTBOX
:
2479 case WM_CTLCOLORBTN
:
2480 case WM_CTLCOLORDLG
:
2481 case WM_CTLCOLORSCROLLBAR
:
2482 case WM_CTLCOLORSTATIC
:
2490 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2492 processed
= HandleCtlColor(&rc
.hBrush
,
2501 #endif // !__WXMICROWIN__
2503 // the return value for this message is ignored
2504 case WM_SYSCOLORCHANGE
:
2505 processed
= HandleSysColorChange();
2508 case WM_PALETTECHANGED
:
2509 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2512 case WM_QUERYNEWPALETTE
:
2513 processed
= HandleQueryNewPalette();
2517 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2520 // we processed the message, i.e. erased the background
2526 processed
= HandleDropFiles(wParam
);
2530 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2534 // we never set focus from here
2539 case WM_QUERYENDSESSION
:
2540 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2544 processed
= HandleEndSession(wParam
!= 0, lParam
);
2547 case WM_GETMINMAXINFO
:
2548 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2552 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2553 LOWORD(lParam
), // hit test
2554 HIWORD(lParam
)); // mouse msg
2558 // returning TRUE stops the DefWindowProc() from further
2559 // processing this message - exactly what we need because we've
2560 // just set the cursor.
2565 #if defined(__WIN32__) && defined(WM_HELP)
2568 HELPINFO
* info
= (HELPINFO
*) lParam
;
2569 // Don't yet process menu help events, just windows
2570 if (info
->iContextType
== HELPINFO_WINDOW
)
2572 wxWindowMSW
* subjectOfHelp
= this;
2573 bool eventProcessed
= FALSE
;
2574 while (subjectOfHelp
&& !eventProcessed
)
2576 wxHelpEvent
helpEvent(wxEVT_HELP
,
2577 subjectOfHelp
->GetId(),
2578 wxPoint(info
->MousePos
.x
,
2579 info
->MousePos
.y
) );
2580 helpEvent
.SetEventObject(this);
2582 GetEventHandler()->ProcessEvent(helpEvent
);
2584 // Go up the window hierarchy until the event is
2586 subjectOfHelp
= subjectOfHelp
->GetParent();
2589 processed
= eventProcessed
;
2591 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2593 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2594 helpEvent
.SetEventObject(this);
2595 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2598 //else: processed is already FALSE
2602 case WM_CONTEXTMENU
:
2604 // we don't convert from screen to client coordinates as
2605 // the event may be handled by a parent window
2606 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2608 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2609 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2614 // unfortunately this doesn't really work as then window which
2615 // doesn't accept focus doesn't get any mouse events neither which
2616 // means it can't get any input at all
2617 #if 0 //def __WXUNIVERSAL__
2619 // we shouldn't allow the windows which don't want to get focus to
2621 if ( !AcceptsFocus() )
2623 rc
.result
= HTTRANSPARENT
;
2627 #endif // __WXUNIVERSAL__
2633 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2634 wxGetMessageName(message
));
2635 #endif // __WXDEBUG__
2636 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2642 // ----------------------------------------------------------------------------
2643 // wxWindow <-> HWND map
2644 // ----------------------------------------------------------------------------
2646 wxWinHashTable
*wxWinHandleHash
= NULL
;
2648 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2650 return wxWinHandleHash
->Get((long)hWnd
);
2653 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2655 // adding NULL hWnd is (first) surely a result of an error and
2656 // (secondly) breaks menu command processing
2657 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2658 wxT("attempt to add a NULL hWnd to window list ignored") );
2660 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2662 if ( oldWin
&& (oldWin
!= win
) )
2664 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2665 hWnd
, win
->GetClassInfo()->GetClassName());
2668 #endif // __WXDEBUG__
2671 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2675 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2677 wxWinHandleHash
->Delete((long)win
->GetHWND());
2680 // ----------------------------------------------------------------------------
2681 // various MSW speciic class dependent functions
2682 // ----------------------------------------------------------------------------
2684 // Default destroyer - override if you destroy it in some other way
2685 // (e.g. with MDI child windows)
2686 void wxWindowMSW::MSWDestroyWindow()
2690 void wxWindowMSW::MSWDetachWindowMenu()
2692 #ifndef __WXUNIVERSAL__
2696 HMENU hMenu
= (HMENU
)m_hMenu
;
2698 int N
= ::GetMenuItemCount(hMenu
);
2699 for ( int i
= 0; i
< N
; i
++ )
2701 if ( !::GetMenuString(hMenu
, i
, buf
, WXSIZEOF(buf
), MF_BYPOSITION
) )
2703 wxLogLastError(wxT("GetMenuString"));
2708 if ( wxStrcmp(buf
, _("&Window")) == 0 )
2710 if ( !::RemoveMenu(hMenu
, i
, MF_BYPOSITION
) )
2712 wxLogLastError(wxT("RemoveMenu"));
2719 #endif // __WXUNIVERSAL__
2722 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2725 int& w
, int& h
) const
2727 bool nonDefault
= FALSE
;
2731 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2732 // just as well set it to CW_USEDEFAULT as well
2739 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2745 NB: there used to be some code here which set the initial size of the
2746 window to the client size of the parent if no explicit size was
2747 specified. This was wrong because wxWindows programs often assume
2748 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2749 it. To see why, you should understand that Windows sends WM_SIZE from
2750 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2751 from some base class ctor and so this WM_SIZE is not processed in the
2752 real class' OnSize() (because it's not fully constructed yet and the
2753 event goes to some base class OnSize() instead). So the WM_SIZE we
2754 rely on is the one sent when the parent frame resizes its children
2755 but here is the problem: if the child already has just the right
2756 size, nothing will happen as both wxWindows and Windows check for
2757 this and ignore any attempts to change the window size to the size it
2758 already has - so no WM_SIZE would be sent.
2762 // as abobe, h is not used at all in this case anyhow
2769 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2777 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2778 const wxChar
*title
,
2782 WXDWORD extendedStyle
)
2784 // choose the position/size for the new window
2786 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2788 // find the correct parent HWND
2789 wxWindow
*parent
= GetParent();
2790 bool isChild
= (style
& WS_CHILD
) != 0;
2792 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2794 // popup windows should have desktop as parent because they shouldn't
2795 // be limited to the parents client area as child windows usually are
2796 hParent
= ::GetDesktopWindow();
2800 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2802 // this is either a normal child window or a top level window with
2803 // wxFRAME_TOOL_WINDOW style (see below)
2804 hParent
= GetHwndOf(parent
);
2808 // this is either a window for which no parent was specified (not
2809 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2810 // style: we should use NULL parent HWND for it or it would be
2811 // always on top of its parent which is not what we usually want
2812 // (in fact, we only want it for frames with the special
2813 // wxFRAME_TOOL_WINDOW as above)
2819 // controlId is menu handle for the top level windows, so set it to 0
2820 // unless we're creating a child window
2824 controlId
= GetId();
2826 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2828 style
|= WS_CLIPSIBLINGS
;
2836 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2837 // which is the same but without CS_[HV]REDRAW class styles so using it
2838 // ensures that the window is not fully repainted on each resize
2839 wxString
className(wclass
);
2840 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2842 className
+= wxT("NR");
2845 // do create the window
2846 wxWindowCreationHook
hook(this);
2848 m_hWnd
= (WXHWND
)::CreateWindowEx
2852 title
? title
: wxT(""),
2858 NULL
// no extra data
2863 wxLogSysError(_("Can't create window of class %s"), wclass
);
2868 SubclassWin(m_hWnd
);
2870 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2875 // ===========================================================================
2876 // MSW message handlers
2877 // ===========================================================================
2879 // ---------------------------------------------------------------------------
2881 // ---------------------------------------------------------------------------
2884 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2885 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2887 #ifndef __WXMICROWIN__
2888 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2889 HWND hWnd
= hdr
->hwndFrom
;
2890 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2892 // is this one of our windows?
2895 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2898 // try all our children
2899 wxWindowList::Node
*node
= GetChildren().GetFirst();
2902 wxWindow
*child
= node
->GetData();
2903 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2908 node
= node
->GetNext();
2911 // finally try this window too (catches toolbar case)
2912 return MSWOnNotify(idCtrl
, lParam
, result
);
2913 #else // __WXMICROWIN__
2918 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2920 WXLPARAM
* WXUNUSED(result
))
2923 NMHDR
* hdr
= (NMHDR
*)lParam
;
2924 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2926 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2927 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2932 #endif // wxUSE_TOOLTIPS
2938 // ---------------------------------------------------------------------------
2939 // end session messages
2940 // ---------------------------------------------------------------------------
2942 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2944 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2945 event
.SetEventObject(wxTheApp
);
2946 event
.SetCanVeto(TRUE
);
2947 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2949 bool rc
= wxTheApp
->ProcessEvent(event
);
2953 // we may end only if the app didn't veto session closing (double
2955 *mayEnd
= !event
.GetVeto();
2961 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2963 // do nothing if the session isn't ending
2968 if ( (this != wxTheApp
->GetTopWindow()) )
2971 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2972 event
.SetEventObject(wxTheApp
);
2973 event
.SetCanVeto(FALSE
);
2974 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2976 return wxTheApp
->ProcessEvent(event
);
2979 // ---------------------------------------------------------------------------
2980 // window creation/destruction
2981 // ---------------------------------------------------------------------------
2983 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2985 // TODO: should generate this event from WM_NCCREATE
2986 wxWindowCreateEvent
event((wxWindow
*)this);
2987 (void)GetEventHandler()->ProcessEvent(event
);
2994 bool wxWindowMSW::HandleDestroy()
2996 wxWindowDestroyEvent
event((wxWindow
*)this);
2997 (void)GetEventHandler()->ProcessEvent(event
);
2999 // delete our drop target if we've got one
3000 #if wxUSE_DRAG_AND_DROP
3001 if ( m_dropTarget
!= NULL
)
3003 m_dropTarget
->Revoke(m_hWnd
);
3005 delete m_dropTarget
;
3006 m_dropTarget
= NULL
;
3008 #endif // wxUSE_DRAG_AND_DROP
3010 // WM_DESTROY handled
3014 // ---------------------------------------------------------------------------
3016 // ---------------------------------------------------------------------------
3018 bool wxWindowMSW::HandleActivate(int state
,
3019 bool WXUNUSED(minimized
),
3020 WXHWND
WXUNUSED(activate
))
3022 wxActivateEvent
event(wxEVT_ACTIVATE
,
3023 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3025 event
.SetEventObject(this);
3027 return GetEventHandler()->ProcessEvent(event
);
3030 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3032 // notify the parent keeping track of focus for the kbd navigation
3033 // purposes that we got it
3034 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3035 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3041 m_caret
->OnSetFocus();
3043 #endif // wxUSE_CARET
3046 // If it's a wxTextCtrl don't send the event as it will be done
3047 // after the control gets to process it from EN_FOCUS handler
3048 if ( wxDynamicCastThis(wxTextCtrl
) )
3052 #endif // wxUSE_TEXTCTRL
3054 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3055 event
.SetEventObject(this);
3057 // wxFindWinFromHandle() may return NULL, it is ok
3058 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3060 return GetEventHandler()->ProcessEvent(event
);
3063 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3069 m_caret
->OnKillFocus();
3071 #endif // wxUSE_CARET
3074 // If it's a wxTextCtrl don't send the event as it will be done
3075 // after the control gets to process it.
3076 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3083 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3084 event
.SetEventObject(this);
3086 // wxFindWinFromHandle() may return NULL, it is ok
3087 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3089 return GetEventHandler()->ProcessEvent(event
);
3092 // ---------------------------------------------------------------------------
3094 // ---------------------------------------------------------------------------
3096 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3098 wxShowEvent
event(GetId(), show
);
3099 event
.m_eventObject
= this;
3101 return GetEventHandler()->ProcessEvent(event
);
3104 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3106 wxInitDialogEvent
event(GetId());
3107 event
.m_eventObject
= this;
3109 return GetEventHandler()->ProcessEvent(event
);
3112 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3114 #ifndef __WXMICROWIN__
3115 HDROP hFilesInfo
= (HDROP
) wParam
;
3117 // Get the total number of files dropped
3118 UINT gwFilesDropped
= ::DragQueryFile
3126 wxString
*files
= new wxString
[gwFilesDropped
];
3127 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3129 // first get the needed buffer length (+1 for terminating NUL)
3130 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3132 // and now get the file name
3133 ::DragQueryFile(hFilesInfo
, wIndex
,
3134 files
[wIndex
].GetWriteBuf(len
), len
);
3136 files
[wIndex
].UngetWriteBuf();
3138 DragFinish (hFilesInfo
);
3140 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3141 event
.m_eventObject
= this;
3144 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3145 event
.m_pos
.x
= dropPoint
.x
;
3146 event
.m_pos
.y
= dropPoint
.y
;
3148 return GetEventHandler()->ProcessEvent(event
);
3149 #else // __WXMICROWIN__
3154 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3156 int WXUNUSED(mouseMsg
))
3158 #ifndef __WXMICROWIN__
3159 // the logic is as follows:
3160 // -1. don't set cursor for non client area, including but not limited to
3161 // the title bar, scrollbars, &c
3162 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3163 // 1. if we have the cursor set it unless wxIsBusy()
3164 // 2. if we're a top level window, set some cursor anyhow
3165 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3167 if ( nHitTest
!= HTCLIENT
)
3172 HCURSOR hcursor
= 0;
3174 // first ask the user code - it may wish to set the cursor in some very
3175 // specific way (for example, depending on the current position)
3178 if ( !::GetCursorPos(&pt
) )
3180 wxLogLastError(wxT("GetCursorPos"));
3183 // In WIN16 it doesn't return a value.
3184 ::GetCursorPos(&pt
);
3189 ScreenToClient(&x
, &y
);
3190 wxSetCursorEvent
event(x
, y
);
3192 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3193 if ( processedEvtSetCursor
&& event
.HasCursor() )
3195 hcursor
= GetHcursorOf(event
.GetCursor());
3200 bool isBusy
= wxIsBusy();
3202 // the test for processedEvtSetCursor is here to prevent using m_cursor
3203 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3204 // it - this is a way to say that our cursor shouldn't be used for this
3206 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3208 hcursor
= GetHcursorOf(m_cursor
);
3215 hcursor
= wxGetCurrentBusyCursor();
3217 else if ( !hcursor
)
3219 const wxCursor
*cursor
= wxGetGlobalCursor();
3220 if ( cursor
&& cursor
->Ok() )
3222 hcursor
= GetHcursorOf(*cursor
);
3230 ::SetCursor(hcursor
);
3232 // cursor set, stop here
3235 #endif // __WXMICROWIN__
3237 // pass up the window chain
3241 // ---------------------------------------------------------------------------
3242 // owner drawn stuff
3243 // ---------------------------------------------------------------------------
3245 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3247 #if wxUSE_OWNER_DRAWN
3249 #if wxUSE_MENUS_NATIVE
3250 // is it a menu item?
3251 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3252 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3254 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3256 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3258 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3259 // the DC from being released
3260 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3261 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3262 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3263 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3265 return pMenuItem
->OnDrawItem
3269 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3270 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3273 #endif // wxUSE_MENUS_NATIVE
3276 wxWindow
*item
= FindItem(id
);
3277 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3279 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3281 #endif // wxUSE_CONTROLS
3283 #endif // USE_OWNER_DRAWN
3288 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3290 #if wxUSE_OWNER_DRAWN
3291 // is it a menu item?
3292 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3293 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3295 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3297 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3299 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3300 &pMeasureStruct
->itemHeight
);
3303 wxWindow
*item
= FindItem(id
);
3304 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3306 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3308 #endif // owner-drawn menus
3312 // ---------------------------------------------------------------------------
3313 // colours and palettes
3314 // ---------------------------------------------------------------------------
3316 bool wxWindowMSW::HandleSysColorChange()
3318 wxSysColourChangedEvent event
;
3319 event
.SetEventObject(this);
3321 (void)GetEventHandler()->ProcessEvent(event
);
3323 // always let the system carry on the default processing to allow the
3324 // native controls to react to the colours update
3328 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3336 #ifndef __WXMICROWIN__
3337 WXHBRUSH hBrush
= 0;
3339 if ( nCtlColor
== CTLCOLOR_DLG
)
3341 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3346 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3348 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3350 #endif // wxUSE_CONTROLS
3356 #else // __WXMICROWIN__
3361 // Define for each class of dialog and control
3362 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3363 WXHWND
WXUNUSED(hWnd
),
3364 WXUINT
WXUNUSED(nCtlColor
),
3365 WXUINT
WXUNUSED(message
),
3366 WXWPARAM
WXUNUSED(wParam
),
3367 WXLPARAM
WXUNUSED(lParam
))
3372 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3374 wxPaletteChangedEvent
event(GetId());
3375 event
.SetEventObject(this);
3376 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3378 return GetEventHandler()->ProcessEvent(event
);
3381 bool wxWindowMSW::HandleQueryNewPalette()
3383 wxQueryNewPaletteEvent
event(GetId());
3384 event
.SetEventObject(this);
3386 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3389 // Responds to colour changes: passes event on to children.
3390 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3392 wxWindowList::Node
*node
= GetChildren().GetFirst();
3395 // Only propagate to non-top-level windows because Windows already
3396 // sends this event to all top-level ones
3397 wxWindow
*win
= node
->GetData();
3398 if ( !win
->IsTopLevel() )
3400 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3401 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3402 // the standard controls
3403 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3406 node
= node
->GetNext();
3409 // update the colours we use if they were not set explicitly by the user:
3410 // this must be done or OnCtlColor() would continue to use the old colours
3413 m_foregroundColour
= wxSystemSettings::
3414 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3419 m_backgroundColour
= wxSystemSettings::
3420 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3424 // ---------------------------------------------------------------------------
3426 // ---------------------------------------------------------------------------
3428 bool wxWindowMSW::HandlePaint()
3431 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3433 wxLogLastError(wxT("CreateRectRgn"));
3434 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3435 wxLogLastError(wxT("GetUpdateRgn"));
3437 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3440 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3442 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3443 updateRect
.right
- updateRect
.left
,
3444 updateRect
.bottom
- updateRect
.top
);
3447 wxPaintEvent
event(m_windowId
);
3448 event
.SetEventObject(this);
3450 bool processed
= GetEventHandler()->ProcessEvent(event
);
3452 // note that we must generate NC event after the normal one as otherwise
3453 // BeginPaint() will happily overwrite our decorations with the background
3455 wxNcPaintEvent
eventNc(m_windowId
);
3456 eventNc
.SetEventObject(this);
3457 GetEventHandler()->ProcessEvent(eventNc
);
3462 // Can be called from an application's OnPaint handler
3463 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3465 #ifdef __WXUNIVERSAL__
3468 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3471 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3476 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3478 // Prevents flicker when dragging
3479 if ( ::IsIconic(GetHwnd()) )
3485 dc
.SetWindow((wxWindow
*)this);
3488 wxEraseEvent
event(m_windowId
, &dc
);
3489 event
.SetEventObject(this);
3490 bool rc
= GetEventHandler()->ProcessEvent(event
);
3494 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3495 dc
.SelectOldObjects(hdc
);
3500 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3503 ::GetClientRect(GetHwnd(), &rect
);
3505 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3506 m_backgroundColour
.Green(),
3507 m_backgroundColour
.Blue());
3508 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3510 wxLogLastError(wxT("CreateSolidBrush"));
3512 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3514 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3516 ::FillRect(hdc
, &rect
, hBrush
);
3517 ::DeleteObject(hBrush
);
3518 ::SetMapMode(hdc
, mode
);
3521 // ---------------------------------------------------------------------------
3522 // moving and resizing
3523 // ---------------------------------------------------------------------------
3525 bool wxWindowMSW::HandleMinimize()
3527 wxIconizeEvent
event(m_windowId
);
3528 event
.SetEventObject(this);
3530 return GetEventHandler()->ProcessEvent(event
);
3533 bool wxWindowMSW::HandleMaximize()
3535 wxMaximizeEvent
event(m_windowId
);
3536 event
.SetEventObject(this);
3538 return GetEventHandler()->ProcessEvent(event
);
3541 bool wxWindowMSW::HandleMove(int x
, int y
)
3543 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3544 event
.SetEventObject(this);
3546 return GetEventHandler()->ProcessEvent(event
);
3549 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3551 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3552 event
.SetEventObject(this);
3554 return GetEventHandler()->ProcessEvent(event
);
3557 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3559 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3563 if ( m_minWidth
!= -1 )
3565 info
->ptMinTrackSize
.x
= m_minWidth
;
3569 if ( m_minHeight
!= -1 )
3571 info
->ptMinTrackSize
.y
= m_minHeight
;
3575 if ( m_maxWidth
!= -1 )
3577 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3581 if ( m_maxHeight
!= -1 )
3583 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3590 // ---------------------------------------------------------------------------
3592 // ---------------------------------------------------------------------------
3594 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3596 #if wxUSE_MENUS_NATIVE
3597 if ( !cmd
&& wxCurrentPopupMenu
)
3599 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3600 wxCurrentPopupMenu
= NULL
;
3602 return popupMenu
->MSWCommand(cmd
, id
);
3604 #endif // wxUSE_MENUS_NATIVE
3606 wxWindow
*win
= NULL
;
3608 // first try to find it from HWND - this works even with the broken
3609 // programs using the same ids for different controls
3612 win
= wxFindWinFromHandle(control
);
3618 // must cast to a signed type before comparing with other ids!
3619 win
= FindItem((signed short)id
);
3624 return win
->MSWCommand(cmd
, id
);
3627 // the messages sent from the in-place edit control used by the treectrl
3628 // for label editing have id == 0, but they should _not_ be treated as menu
3629 // messages (they are EN_XXX ones, in fact) so don't translate anything
3630 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3633 // If no child window, it may be an accelerator, e.g. for a popup menu
3636 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3637 event
.SetEventObject(this);
3641 return GetEventHandler()->ProcessEvent(event
);
3643 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3646 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3647 // notifications to its parent which we want to reflect back to
3649 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3650 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3653 #endif // wxUSE_SPINCTRL
3658 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3660 // 4 bits are reserved
3661 switch ( wParam
& 0xFFFFFFF0 )
3664 return HandleMaximize();
3667 return HandleMinimize();
3673 // ---------------------------------------------------------------------------
3675 // ---------------------------------------------------------------------------
3677 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3681 // our client coords are not quite the same as Windows ones
3682 wxPoint pt
= GetClientAreaOrigin();
3683 event
.m_x
= x
- pt
.x
;
3684 event
.m_y
= y
- pt
.y
;
3686 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3687 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3688 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3689 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3690 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3691 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3693 event
.SetTimestamp(s_currentMsg
.time
);
3694 event
.m_eventObject
= this;
3696 #if wxUSE_MOUSEEVENT_HACK
3699 m_lastMouseEvent
= event
.GetEventType();
3700 #endif // wxUSE_MOUSEEVENT_HACK
3703 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3705 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3706 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3707 // from the message id and take the value in the table to get wxWin event
3709 static const wxEventType eventsMouse
[] =
3723 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3724 InitMouseEvent(event
, x
, y
, flags
);
3726 return GetEventHandler()->ProcessEvent(event
);
3729 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3731 if ( !m_mouseInWindow
)
3733 // it would be wrong to assume that just because we get a mouse move
3734 // event that the mouse is inside the window: although this is usually
3735 // true, it is not if we had captured the mouse, so we need to check
3736 // the mouse coordinates here
3737 if ( !HasCapture() || IsMouseInWindow() )
3739 // Generate an ENTER event
3740 m_mouseInWindow
= TRUE
;
3742 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3743 InitMouseEvent(event
, x
, y
, flags
);
3745 (void)GetEventHandler()->ProcessEvent(event
);
3749 #if wxUSE_MOUSEEVENT_HACK
3750 // Window gets a click down message followed by a mouse move message even
3751 // if position isn't changed! We want to discard the trailing move event
3752 // if x and y are the same.
3753 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3754 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3755 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3756 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3758 m_lastMouseEvent
= wxEVT_MOTION
;
3762 #endif // wxUSE_MOUSEEVENT_HACK
3764 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3768 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3770 #if wxUSE_MOUSEWHEEL
3771 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3772 InitMouseEvent(event
,
3773 GET_X_LPARAM(lParam
),
3774 GET_Y_LPARAM(lParam
),
3776 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3777 event
.m_wheelDelta
= WHEEL_DELTA
;
3780 static int s_linesPerRotation
= -1;
3781 if ( s_linesPerRotation
== -1 )
3783 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3784 &s_linesPerRotation
, 0))
3786 // this is not supposed to happen
3787 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3789 // the default is 3, so use it if SystemParametersInfo() failed
3790 s_linesPerRotation
= 3;
3794 // no SystemParametersInfo() under Win16
3795 static const int s_linesPerRotation
= 3;
3798 event
.m_linesPerAction
= s_linesPerRotation
;
3799 return GetEventHandler()->ProcessEvent(event
);
3810 // ---------------------------------------------------------------------------
3811 // keyboard handling
3812 // ---------------------------------------------------------------------------
3814 // create the key event of the given type for the given key - used by
3815 // HandleChar and HandleKeyDown/Up
3816 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3818 WXLPARAM lParam
) const
3820 wxKeyEvent
event(evType
);
3821 event
.SetId(GetId());
3822 event
.m_shiftDown
= wxIsShiftDown();
3823 event
.m_controlDown
= wxIsCtrlDown();
3824 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3826 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3827 event
.m_keyCode
= id
;
3828 event
.SetTimestamp(s_currentMsg
.time
);
3830 // translate the position to client coords
3834 GetWindowRect(GetHwnd(),&rect
);
3844 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3846 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3848 bool ctrlDown
= FALSE
;
3853 // If 1 -> 26, translate to CTRL plus a letter.
3855 if ( (id
> 0) && (id
< 27) )
3877 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3879 // it's ASCII and will be processed here only when called from
3880 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3886 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3889 event
.m_controlDown
= TRUE
;
3892 if ( GetEventHandler()->ProcessEvent(event
) )
3899 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3901 int id
= wxCharCodeMSWToWX(wParam
);
3905 // normal ASCII char
3909 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3911 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3912 if ( GetEventHandler()->ProcessEvent(event
) )
3921 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3923 int id
= wxCharCodeMSWToWX(wParam
);
3927 // normal ASCII char
3931 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3933 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3934 if ( GetEventHandler()->ProcessEvent(event
) )
3941 // ---------------------------------------------------------------------------
3943 // ---------------------------------------------------------------------------
3945 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3949 if ( flags
& JOY_BUTTON1CHG
)
3950 change
= wxJOY_BUTTON1
;
3951 if ( flags
& JOY_BUTTON2CHG
)
3952 change
= wxJOY_BUTTON2
;
3953 if ( flags
& JOY_BUTTON3CHG
)
3954 change
= wxJOY_BUTTON3
;
3955 if ( flags
& JOY_BUTTON4CHG
)
3956 change
= wxJOY_BUTTON4
;
3959 if ( flags
& JOY_BUTTON1
)
3960 buttons
|= wxJOY_BUTTON1
;
3961 if ( flags
& JOY_BUTTON2
)
3962 buttons
|= wxJOY_BUTTON2
;
3963 if ( flags
& JOY_BUTTON3
)
3964 buttons
|= wxJOY_BUTTON3
;
3965 if ( flags
& JOY_BUTTON4
)
3966 buttons
|= wxJOY_BUTTON4
;
3968 // the event ids aren't consecutive so we can't use table based lookup
3970 wxEventType eventType
;
3975 eventType
= wxEVT_JOY_MOVE
;
3980 eventType
= wxEVT_JOY_MOVE
;
3985 eventType
= wxEVT_JOY_ZMOVE
;
3990 eventType
= wxEVT_JOY_ZMOVE
;
3993 case MM_JOY1BUTTONDOWN
:
3995 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3998 case MM_JOY2BUTTONDOWN
:
4000 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4003 case MM_JOY1BUTTONUP
:
4005 eventType
= wxEVT_JOY_BUTTON_UP
;
4008 case MM_JOY2BUTTONUP
:
4010 eventType
= wxEVT_JOY_BUTTON_UP
;
4014 wxFAIL_MSG(wxT("no such joystick event"));
4019 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4020 event
.SetPosition(wxPoint(x
, y
));
4021 event
.SetEventObject(this);
4023 return GetEventHandler()->ProcessEvent(event
);
4029 // ---------------------------------------------------------------------------
4031 // ---------------------------------------------------------------------------
4033 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4034 WXWORD pos
, WXHWND control
)
4038 wxWindow
*child
= wxFindWinFromHandle(control
);
4040 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4043 wxScrollWinEvent event
;
4044 event
.SetPosition(pos
);
4045 event
.SetOrientation(orientation
);
4046 event
.m_eventObject
= this;
4051 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4055 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4059 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4063 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4067 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4071 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4074 case SB_THUMBPOSITION
:
4077 // under Win32, the scrollbar range and position are 32 bit integers,
4078 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4079 // explicitly query the scrollbar for the correct position (this must
4080 // be done only for these two SB_ events as they are the only one
4081 // carrying the scrollbar position)
4083 SCROLLINFO scrollInfo
;
4084 wxZeroMemory(scrollInfo
);
4085 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4086 scrollInfo
.fMask
= SIF_TRACKPOS
;
4088 if ( !::GetScrollInfo(GetHwnd(),
4089 orientation
== wxHORIZONTAL
? SB_HORZ
4093 wxLogLastError(_T("GetScrollInfo"));
4096 event
.SetPosition(scrollInfo
.nTrackPos
);
4100 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4101 ? wxEVT_SCROLLWIN_THUMBRELEASE
4102 : wxEVT_SCROLLWIN_THUMBTRACK
;
4109 return GetEventHandler()->ProcessEvent(event
);
4112 // ===========================================================================
4114 // ===========================================================================
4116 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4119 HDC dc
= ::GetDC((HWND
) wnd
);
4124 // the_font->UseResource();
4125 // the_font->RealizeResource();
4126 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4128 was
= (HFONT
) SelectObject(dc
,fnt
);
4130 GetTextMetrics(dc
, &tm
);
4131 if ( the_font
&& fnt
&& was
)
4133 SelectObject(dc
,was
);
4135 ReleaseDC((HWND
)wnd
, dc
);
4138 *x
= tm
.tmAveCharWidth
;
4140 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4143 // the_font->ReleaseResource();
4146 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4147 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4148 int wxCharCodeMSWToWX(int keySym
)
4153 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4154 case VK_BACK
: id
= WXK_BACK
; break;
4155 case VK_TAB
: id
= WXK_TAB
; break;
4156 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4157 case VK_RETURN
: id
= WXK_RETURN
; break;
4158 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4159 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4160 case VK_MENU
: id
= WXK_MENU
; break;
4161 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4162 case VK_SPACE
: id
= WXK_SPACE
; break;
4163 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4164 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4165 case VK_NEXT
: id
= WXK_NEXT
; break;
4166 case VK_END
: id
= WXK_END
; break;
4167 case VK_HOME
: id
= WXK_HOME
; break;
4168 case VK_LEFT
: id
= WXK_LEFT
; break;
4169 case VK_UP
: id
= WXK_UP
; break;
4170 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4171 case VK_DOWN
: id
= WXK_DOWN
; break;
4172 case VK_SELECT
: id
= WXK_SELECT
; break;
4173 case VK_PRINT
: id
= WXK_PRINT
; break;
4174 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4175 case VK_INSERT
: id
= WXK_INSERT
; break;
4176 case VK_DELETE
: id
= WXK_DELETE
; break;
4177 case VK_HELP
: id
= WXK_HELP
; break;
4178 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4179 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4180 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4181 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4182 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4183 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4184 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4185 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4186 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4187 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4188 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4189 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4190 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4191 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4192 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4193 case VK_F1
: id
= WXK_F1
; break;
4194 case VK_F2
: id
= WXK_F2
; break;
4195 case VK_F3
: id
= WXK_F3
; break;
4196 case VK_F4
: id
= WXK_F4
; break;
4197 case VK_F5
: id
= WXK_F5
; break;
4198 case VK_F6
: id
= WXK_F6
; break;
4199 case VK_F7
: id
= WXK_F7
; break;
4200 case VK_F8
: id
= WXK_F8
; break;
4201 case VK_F9
: id
= WXK_F9
; break;
4202 case VK_F10
: id
= WXK_F10
; break;
4203 case VK_F11
: id
= WXK_F11
; break;
4204 case VK_F12
: id
= WXK_F12
; break;
4205 case VK_F13
: id
= WXK_F13
; break;
4206 case VK_F14
: id
= WXK_F14
; break;
4207 case VK_F15
: id
= WXK_F15
; break;
4208 case VK_F16
: id
= WXK_F16
; break;
4209 case VK_F17
: id
= WXK_F17
; break;
4210 case VK_F18
: id
= WXK_F18
; break;
4211 case VK_F19
: id
= WXK_F19
; break;
4212 case VK_F20
: id
= WXK_F20
; break;
4213 case VK_F21
: id
= WXK_F21
; break;
4214 case VK_F22
: id
= WXK_F22
; break;
4215 case VK_F23
: id
= WXK_F23
; break;
4216 case VK_F24
: id
= WXK_F24
; break;
4217 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4218 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4226 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4232 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4233 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4234 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4235 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4236 case WXK_MENU
: keySym
= VK_MENU
; break;
4237 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4238 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4239 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4240 case WXK_END
: keySym
= VK_END
; break;
4241 case WXK_HOME
: keySym
= VK_HOME
; break;
4242 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4243 case WXK_UP
: keySym
= VK_UP
; break;
4244 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4245 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4246 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4247 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4248 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4249 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4250 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4251 case WXK_HELP
: keySym
= VK_HELP
; break;
4252 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4253 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4254 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4255 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4256 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4257 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4258 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4259 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4260 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4261 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4262 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4263 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4264 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4265 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4266 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4267 case WXK_F1
: keySym
= VK_F1
; break;
4268 case WXK_F2
: keySym
= VK_F2
; break;
4269 case WXK_F3
: keySym
= VK_F3
; break;
4270 case WXK_F4
: keySym
= VK_F4
; break;
4271 case WXK_F5
: keySym
= VK_F5
; break;
4272 case WXK_F6
: keySym
= VK_F6
; break;
4273 case WXK_F7
: keySym
= VK_F7
; break;
4274 case WXK_F8
: keySym
= VK_F8
; break;
4275 case WXK_F9
: keySym
= VK_F9
; break;
4276 case WXK_F10
: keySym
= VK_F10
; break;
4277 case WXK_F11
: keySym
= VK_F11
; break;
4278 case WXK_F12
: keySym
= VK_F12
; break;
4279 case WXK_F13
: keySym
= VK_F13
; break;
4280 case WXK_F14
: keySym
= VK_F14
; break;
4281 case WXK_F15
: keySym
= VK_F15
; break;
4282 case WXK_F16
: keySym
= VK_F16
; break;
4283 case WXK_F17
: keySym
= VK_F17
; break;
4284 case WXK_F18
: keySym
= VK_F18
; break;
4285 case WXK_F19
: keySym
= VK_F19
; break;
4286 case WXK_F20
: keySym
= VK_F20
; break;
4287 case WXK_F21
: keySym
= VK_F21
; break;
4288 case WXK_F22
: keySym
= VK_F22
; break;
4289 case WXK_F23
: keySym
= VK_F23
; break;
4290 case WXK_F24
: keySym
= VK_F24
; break;
4291 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4292 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4303 wxWindow
*wxGetActiveWindow()
4305 HWND hWnd
= GetActiveWindow();
4308 return wxFindWinFromHandle((WXHWND
) hWnd
);
4313 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4315 HWND hwnd
= (HWND
)hWnd
;
4317 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4318 // by code in msw/radiobox.cpp), for all the others we just search up the
4320 wxWindow
*win
= (wxWindow
*)NULL
;
4323 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4326 // all these hacks only work under Win32 anyhow
4330 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4331 // wxWindow class which overrides WM_GETDLGCODE processing to
4332 // do it as well, win would be already non NULL
4333 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4335 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4337 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4338 #endif // wxUSE_RADIOBOX
4340 // spin control text buddy window should be mapped to spin ctrl
4341 // itself so try it too
4342 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4345 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4347 #endif // wxUSE_SPINCTRL
4353 while ( hwnd
&& !win
)
4355 // this is a really ugly hack needed to avoid mistakenly returning the
4356 // parent frame wxWindow for the find/replace modeless dialog HWND -
4357 // this, in turn, is needed to call IsDialogMessage() from
4358 // wxApp::ProcessMessage() as for this we must return NULL from here
4360 // FIXME: this is clearly not the best way to do it but I think we'll
4361 // need to change HWND <-> wxWindow code more heavily than I can
4362 // do it now to fix it
4363 #ifndef __WXMICROWIN__
4364 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4366 // it's a dialog box, don't go upwards
4371 hwnd
= ::GetParent(hwnd
);
4372 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4378 #ifndef __WXMICROWIN__
4380 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4381 // in active frames and dialogs, regardless of where the focus is.
4382 static HHOOK wxTheKeyboardHook
= 0;
4383 static FARPROC wxTheKeyboardHookProc
= 0;
4384 int APIENTRY _EXPORT
4385 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4387 void wxSetKeyboardHook(bool doIt
)
4391 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4392 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4394 #if defined(__WIN32__) && !defined(__TWIN32__)
4395 GetCurrentThreadId()
4396 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4404 UnhookWindowsHookEx(wxTheKeyboardHook
);
4406 // avoids warning about statement with no effect (FreeProcInstance
4407 // doesn't do anything under Win32)
4408 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4409 FreeProcInstance(wxTheKeyboardHookProc
);
4414 int APIENTRY _EXPORT
4415 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4417 DWORD hiWord
= HIWORD(lParam
);
4418 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4420 int id
= wxCharCodeMSWToWX(wParam
);
4423 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4424 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4425 event
.m_altDown
= TRUE
;
4427 event
.m_eventObject
= NULL
;
4428 event
.m_keyCode
= id
;
4429 event
.m_shiftDown
= wxIsShiftDown();
4430 event
.m_controlDown
= wxIsCtrlDown();
4431 event
.SetTimestamp(s_currentMsg
.time
);
4433 wxWindow
*win
= wxGetActiveWindow();
4434 wxEvtHandler
*handler
;
4437 handler
= win
->GetEventHandler();
4438 event
.SetId(win
->GetId());
4446 if ( handler
&& handler
->ProcessEvent(event
) )
4454 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4457 #endif // !__WXMICROWIN__
4460 const char *wxGetMessageName(int message
)
4464 case 0x0000: return "WM_NULL";
4465 case 0x0001: return "WM_CREATE";
4466 case 0x0002: return "WM_DESTROY";
4467 case 0x0003: return "WM_MOVE";
4468 case 0x0005: return "WM_SIZE";
4469 case 0x0006: return "WM_ACTIVATE";
4470 case 0x0007: return "WM_SETFOCUS";
4471 case 0x0008: return "WM_KILLFOCUS";
4472 case 0x000A: return "WM_ENABLE";
4473 case 0x000B: return "WM_SETREDRAW";
4474 case 0x000C: return "WM_SETTEXT";
4475 case 0x000D: return "WM_GETTEXT";
4476 case 0x000E: return "WM_GETTEXTLENGTH";
4477 case 0x000F: return "WM_PAINT";
4478 case 0x0010: return "WM_CLOSE";
4479 case 0x0011: return "WM_QUERYENDSESSION";
4480 case 0x0012: return "WM_QUIT";
4481 case 0x0013: return "WM_QUERYOPEN";
4482 case 0x0014: return "WM_ERASEBKGND";
4483 case 0x0015: return "WM_SYSCOLORCHANGE";
4484 case 0x0016: return "WM_ENDSESSION";
4485 case 0x0017: return "WM_SYSTEMERROR";
4486 case 0x0018: return "WM_SHOWWINDOW";
4487 case 0x0019: return "WM_CTLCOLOR";
4488 case 0x001A: return "WM_WININICHANGE";
4489 case 0x001B: return "WM_DEVMODECHANGE";
4490 case 0x001C: return "WM_ACTIVATEAPP";
4491 case 0x001D: return "WM_FONTCHANGE";
4492 case 0x001E: return "WM_TIMECHANGE";
4493 case 0x001F: return "WM_CANCELMODE";
4494 case 0x0020: return "WM_SETCURSOR";
4495 case 0x0021: return "WM_MOUSEACTIVATE";
4496 case 0x0022: return "WM_CHILDACTIVATE";
4497 case 0x0023: return "WM_QUEUESYNC";
4498 case 0x0024: return "WM_GETMINMAXINFO";
4499 case 0x0026: return "WM_PAINTICON";
4500 case 0x0027: return "WM_ICONERASEBKGND";
4501 case 0x0028: return "WM_NEXTDLGCTL";
4502 case 0x002A: return "WM_SPOOLERSTATUS";
4503 case 0x002B: return "WM_DRAWITEM";
4504 case 0x002C: return "WM_MEASUREITEM";
4505 case 0x002D: return "WM_DELETEITEM";
4506 case 0x002E: return "WM_VKEYTOITEM";
4507 case 0x002F: return "WM_CHARTOITEM";
4508 case 0x0030: return "WM_SETFONT";
4509 case 0x0031: return "WM_GETFONT";
4510 case 0x0037: return "WM_QUERYDRAGICON";
4511 case 0x0039: return "WM_COMPAREITEM";
4512 case 0x0041: return "WM_COMPACTING";
4513 case 0x0044: return "WM_COMMNOTIFY";
4514 case 0x0046: return "WM_WINDOWPOSCHANGING";
4515 case 0x0047: return "WM_WINDOWPOSCHANGED";
4516 case 0x0048: return "WM_POWER";
4519 case 0x004A: return "WM_COPYDATA";
4520 case 0x004B: return "WM_CANCELJOURNAL";
4521 case 0x004E: return "WM_NOTIFY";
4522 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4523 case 0x0051: return "WM_INPUTLANGCHANGE";
4524 case 0x0052: return "WM_TCARD";
4525 case 0x0053: return "WM_HELP";
4526 case 0x0054: return "WM_USERCHANGED";
4527 case 0x0055: return "WM_NOTIFYFORMAT";
4528 case 0x007B: return "WM_CONTEXTMENU";
4529 case 0x007C: return "WM_STYLECHANGING";
4530 case 0x007D: return "WM_STYLECHANGED";
4531 case 0x007E: return "WM_DISPLAYCHANGE";
4532 case 0x007F: return "WM_GETICON";
4533 case 0x0080: return "WM_SETICON";
4536 case 0x0081: return "WM_NCCREATE";
4537 case 0x0082: return "WM_NCDESTROY";
4538 case 0x0083: return "WM_NCCALCSIZE";
4539 case 0x0084: return "WM_NCHITTEST";
4540 case 0x0085: return "WM_NCPAINT";
4541 case 0x0086: return "WM_NCACTIVATE";
4542 case 0x0087: return "WM_GETDLGCODE";
4543 case 0x00A0: return "WM_NCMOUSEMOVE";
4544 case 0x00A1: return "WM_NCLBUTTONDOWN";
4545 case 0x00A2: return "WM_NCLBUTTONUP";
4546 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4547 case 0x00A4: return "WM_NCRBUTTONDOWN";
4548 case 0x00A5: return "WM_NCRBUTTONUP";
4549 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4550 case 0x00A7: return "WM_NCMBUTTONDOWN";
4551 case 0x00A8: return "WM_NCMBUTTONUP";
4552 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4553 case 0x0100: return "WM_KEYDOWN";
4554 case 0x0101: return "WM_KEYUP";
4555 case 0x0102: return "WM_CHAR";
4556 case 0x0103: return "WM_DEADCHAR";
4557 case 0x0104: return "WM_SYSKEYDOWN";
4558 case 0x0105: return "WM_SYSKEYUP";
4559 case 0x0106: return "WM_SYSCHAR";
4560 case 0x0107: return "WM_SYSDEADCHAR";
4561 case 0x0108: return "WM_KEYLAST";
4564 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4565 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4566 case 0x010F: return "WM_IME_COMPOSITION";
4569 case 0x0110: return "WM_INITDIALOG";
4570 case 0x0111: return "WM_COMMAND";
4571 case 0x0112: return "WM_SYSCOMMAND";
4572 case 0x0113: return "WM_TIMER";
4573 case 0x0114: return "WM_HSCROLL";
4574 case 0x0115: return "WM_VSCROLL";
4575 case 0x0116: return "WM_INITMENU";
4576 case 0x0117: return "WM_INITMENUPOPUP";
4577 case 0x011F: return "WM_MENUSELECT";
4578 case 0x0120: return "WM_MENUCHAR";
4579 case 0x0121: return "WM_ENTERIDLE";
4580 case 0x0200: return "WM_MOUSEMOVE";
4581 case 0x0201: return "WM_LBUTTONDOWN";
4582 case 0x0202: return "WM_LBUTTONUP";
4583 case 0x0203: return "WM_LBUTTONDBLCLK";
4584 case 0x0204: return "WM_RBUTTONDOWN";
4585 case 0x0205: return "WM_RBUTTONUP";
4586 case 0x0206: return "WM_RBUTTONDBLCLK";
4587 case 0x0207: return "WM_MBUTTONDOWN";
4588 case 0x0208: return "WM_MBUTTONUP";
4589 case 0x0209: return "WM_MBUTTONDBLCLK";
4590 case 0x020A: return "WM_MOUSEWHEEL";
4591 case 0x0210: return "WM_PARENTNOTIFY";
4592 case 0x0211: return "WM_ENTERMENULOOP";
4593 case 0x0212: return "WM_EXITMENULOOP";
4596 case 0x0213: return "WM_NEXTMENU";
4597 case 0x0214: return "WM_SIZING";
4598 case 0x0215: return "WM_CAPTURECHANGED";
4599 case 0x0216: return "WM_MOVING";
4600 case 0x0218: return "WM_POWERBROADCAST";
4601 case 0x0219: return "WM_DEVICECHANGE";
4604 case 0x0220: return "WM_MDICREATE";
4605 case 0x0221: return "WM_MDIDESTROY";
4606 case 0x0222: return "WM_MDIACTIVATE";
4607 case 0x0223: return "WM_MDIRESTORE";
4608 case 0x0224: return "WM_MDINEXT";
4609 case 0x0225: return "WM_MDIMAXIMIZE";
4610 case 0x0226: return "WM_MDITILE";
4611 case 0x0227: return "WM_MDICASCADE";
4612 case 0x0228: return "WM_MDIICONARRANGE";
4613 case 0x0229: return "WM_MDIGETACTIVE";
4614 case 0x0230: return "WM_MDISETMENU";
4615 case 0x0233: return "WM_DROPFILES";
4618 case 0x0281: return "WM_IME_SETCONTEXT";
4619 case 0x0282: return "WM_IME_NOTIFY";
4620 case 0x0283: return "WM_IME_CONTROL";
4621 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4622 case 0x0285: return "WM_IME_SELECT";
4623 case 0x0286: return "WM_IME_CHAR";
4624 case 0x0290: return "WM_IME_KEYDOWN";
4625 case 0x0291: return "WM_IME_KEYUP";
4628 case 0x0300: return "WM_CUT";
4629 case 0x0301: return "WM_COPY";
4630 case 0x0302: return "WM_PASTE";
4631 case 0x0303: return "WM_CLEAR";
4632 case 0x0304: return "WM_UNDO";
4633 case 0x0305: return "WM_RENDERFORMAT";
4634 case 0x0306: return "WM_RENDERALLFORMATS";
4635 case 0x0307: return "WM_DESTROYCLIPBOARD";
4636 case 0x0308: return "WM_DRAWCLIPBOARD";
4637 case 0x0309: return "WM_PAINTCLIPBOARD";
4638 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4639 case 0x030B: return "WM_SIZECLIPBOARD";
4640 case 0x030C: return "WM_ASKCBFORMATNAME";
4641 case 0x030D: return "WM_CHANGECBCHAIN";
4642 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4643 case 0x030F: return "WM_QUERYNEWPALETTE";
4644 case 0x0310: return "WM_PALETTEISCHANGING";
4645 case 0x0311: return "WM_PALETTECHANGED";
4648 // common controls messages - although they're not strictly speaking
4649 // standard, it's nice to decode them nevertheless
4652 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4653 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4654 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4655 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4656 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4657 case 0x1000 + 5: return "LVM_GETITEMA";
4658 case 0x1000 + 75: return "LVM_GETITEMW";
4659 case 0x1000 + 6: return "LVM_SETITEMA";
4660 case 0x1000 + 76: return "LVM_SETITEMW";
4661 case 0x1000 + 7: return "LVM_INSERTITEMA";
4662 case 0x1000 + 77: return "LVM_INSERTITEMW";
4663 case 0x1000 + 8: return "LVM_DELETEITEM";
4664 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4665 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4666 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4667 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4668 case 0x1000 + 13: return "LVM_FINDITEMA";
4669 case 0x1000 + 83: return "LVM_FINDITEMW";
4670 case 0x1000 + 14: return "LVM_GETITEMRECT";
4671 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4672 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4673 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4674 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4675 case 0x1000 + 18: return "LVM_HITTEST";
4676 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4677 case 0x1000 + 20: return "LVM_SCROLL";
4678 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4679 case 0x1000 + 22: return "LVM_ARRANGE";
4680 case 0x1000 + 23: return "LVM_EDITLABELA";
4681 case 0x1000 + 118: return "LVM_EDITLABELW";
4682 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4683 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4684 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4685 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4686 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4687 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4688 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4689 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4690 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4691 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4692 case 0x1000 + 31: return "LVM_GETHEADER";
4693 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4694 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4695 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4696 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4697 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4698 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4699 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4700 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4701 case 0x1000 + 41: return "LVM_GETORIGIN";
4702 case 0x1000 + 42: return "LVM_UPDATE";
4703 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4704 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4705 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4706 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4707 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4708 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4709 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4710 case 0x1000 + 48: return "LVM_SORTITEMS";
4711 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4712 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4713 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4714 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4715 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4716 case 0x1000 + 53: return "LVM_SETICONSPACING";
4717 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4718 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4719 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4720 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4721 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4722 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4723 case 0x1000 + 60: return "LVM_SETHOTITEM";
4724 case 0x1000 + 61: return "LVM_GETHOTITEM";
4725 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4726 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4727 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4728 case 0x1000 + 65: return "LVM_SETWORKAREA";
4731 case 0x1100 + 0: return "TVM_INSERTITEMA";
4732 case 0x1100 + 50: return "TVM_INSERTITEMW";
4733 case 0x1100 + 1: return "TVM_DELETEITEM";
4734 case 0x1100 + 2: return "TVM_EXPAND";
4735 case 0x1100 + 4: return "TVM_GETITEMRECT";
4736 case 0x1100 + 5: return "TVM_GETCOUNT";
4737 case 0x1100 + 6: return "TVM_GETINDENT";
4738 case 0x1100 + 7: return "TVM_SETINDENT";
4739 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4740 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4741 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4742 case 0x1100 + 11: return "TVM_SELECTITEM";
4743 case 0x1100 + 12: return "TVM_GETITEMA";
4744 case 0x1100 + 62: return "TVM_GETITEMW";
4745 case 0x1100 + 13: return "TVM_SETITEMA";
4746 case 0x1100 + 63: return "TVM_SETITEMW";
4747 case 0x1100 + 14: return "TVM_EDITLABELA";
4748 case 0x1100 + 65: return "TVM_EDITLABELW";
4749 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4750 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4751 case 0x1100 + 17: return "TVM_HITTEST";
4752 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4753 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4754 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4755 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4756 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4757 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4758 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4759 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4760 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4763 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4764 case 0x1200 + 1: return "HDM_INSERTITEMA";
4765 case 0x1200 + 10: return "HDM_INSERTITEMW";
4766 case 0x1200 + 2: return "HDM_DELETEITEM";
4767 case 0x1200 + 3: return "HDM_GETITEMA";
4768 case 0x1200 + 11: return "HDM_GETITEMW";
4769 case 0x1200 + 4: return "HDM_SETITEMA";
4770 case 0x1200 + 12: return "HDM_SETITEMW";
4771 case 0x1200 + 5: return "HDM_LAYOUT";
4772 case 0x1200 + 6: return "HDM_HITTEST";
4773 case 0x1200 + 7: return "HDM_GETITEMRECT";
4774 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4775 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4776 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4777 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4778 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4779 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4780 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4783 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4784 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4785 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4786 case 0x1300 + 5: return "TCM_GETITEMA";
4787 case 0x1300 + 60: return "TCM_GETITEMW";
4788 case 0x1300 + 6: return "TCM_SETITEMA";
4789 case 0x1300 + 61: return "TCM_SETITEMW";
4790 case 0x1300 + 7: return "TCM_INSERTITEMA";
4791 case 0x1300 + 62: return "TCM_INSERTITEMW";
4792 case 0x1300 + 8: return "TCM_DELETEITEM";
4793 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4794 case 0x1300 + 10: return "TCM_GETITEMRECT";
4795 case 0x1300 + 11: return "TCM_GETCURSEL";
4796 case 0x1300 + 12: return "TCM_SETCURSEL";
4797 case 0x1300 + 13: return "TCM_HITTEST";
4798 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4799 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4800 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4801 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4802 case 0x1300 + 43: return "TCM_SETPADDING";
4803 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4804 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4805 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4806 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4807 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4808 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4809 case 0x1300 + 50: return "TCM_DESELECTALL";
4812 case WM_USER
+1: return "TB_ENABLEBUTTON";
4813 case WM_USER
+2: return "TB_CHECKBUTTON";
4814 case WM_USER
+3: return "TB_PRESSBUTTON";
4815 case WM_USER
+4: return "TB_HIDEBUTTON";
4816 case WM_USER
+5: return "TB_INDETERMINATE";
4817 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4818 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4819 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4820 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4821 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4822 case WM_USER
+17: return "TB_SETSTATE";
4823 case WM_USER
+18: return "TB_GETSTATE";
4824 case WM_USER
+19: return "TB_ADDBITMAP";
4825 case WM_USER
+20: return "TB_ADDBUTTONS";
4826 case WM_USER
+21: return "TB_INSERTBUTTON";
4827 case WM_USER
+22: return "TB_DELETEBUTTON";
4828 case WM_USER
+23: return "TB_GETBUTTON";
4829 case WM_USER
+24: return "TB_BUTTONCOUNT";
4830 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4831 case WM_USER
+26: return "TB_SAVERESTOREA";
4832 case WM_USER
+76: return "TB_SAVERESTOREW";
4833 case WM_USER
+27: return "TB_CUSTOMIZE";
4834 case WM_USER
+28: return "TB_ADDSTRINGA";
4835 case WM_USER
+77: return "TB_ADDSTRINGW";
4836 case WM_USER
+29: return "TB_GETITEMRECT";
4837 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4838 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4839 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4840 case WM_USER
+33: return "TB_AUTOSIZE";
4841 case WM_USER
+35: return "TB_GETTOOLTIPS";
4842 case WM_USER
+36: return "TB_SETTOOLTIPS";
4843 case WM_USER
+37: return "TB_SETPARENT";
4844 case WM_USER
+39: return "TB_SETROWS";
4845 case WM_USER
+40: return "TB_GETROWS";
4846 case WM_USER
+42: return "TB_SETCMDID";
4847 case WM_USER
+43: return "TB_CHANGEBITMAP";
4848 case WM_USER
+44: return "TB_GETBITMAP";
4849 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4850 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4851 case WM_USER
+46: return "TB_REPLACEBITMAP";
4852 case WM_USER
+47: return "TB_SETINDENT";
4853 case WM_USER
+48: return "TB_SETIMAGELIST";
4854 case WM_USER
+49: return "TB_GETIMAGELIST";
4855 case WM_USER
+50: return "TB_LOADIMAGES";
4856 case WM_USER
+51: return "TB_GETRECT";
4857 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4858 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4859 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4860 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4861 case WM_USER
+56: return "TB_SETSTYLE";
4862 case WM_USER
+57: return "TB_GETSTYLE";
4863 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4864 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4865 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4866 case WM_USER
+61: return "TB_GETTEXTROWS";
4867 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4872 static char s_szBuf
[128];
4873 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4877 #endif //__WXDEBUG__
4879 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4880 int *x
, int *y
, WPARAM
*flags
)
4882 // construct the key mask
4883 WPARAM
& fwKeys
= *flags
;
4885 fwKeys
= MK_RBUTTON
;
4886 if ( wxIsCtrlDown() )
4887 fwKeys
|= MK_CONTROL
;
4888 if ( wxIsShiftDown() )
4891 // simulate right mouse button click
4892 DWORD dwPos
= ::GetMessagePos();
4893 *x
= GET_X_LPARAM(dwPos
);
4894 *y
= GET_Y_LPARAM(dwPos
);
4896 win
->ScreenToClient(x
, y
);
4899 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4903 HWND hwnd
= GetHwndOf(win
);
4904 HDC hdc
= ::GetDC(hwnd
);
4906 #if !wxDIALOG_UNIT_COMPATIBILITY
4907 // and select the current font into it
4908 HFONT hfont
= GetHfontOf(win
->GetFont());
4911 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4915 // finally retrieve the text metrics from it
4916 GetTextMetrics(hdc
, &tm
);
4918 #if !wxDIALOG_UNIT_COMPATIBILITY
4922 (void)::SelectObject(hdc
, hfont
);
4926 ::ReleaseDC(hwnd
, hdc
);
4931 // Find the wxWindow at the current mouse position, returning the mouse
4933 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4935 return wxFindWindowAtPoint(wxGetMousePosition());
4938 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4943 HWND hWndHit
= ::WindowFromPoint(pt2
);
4945 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4946 HWND hWnd
= hWndHit
;
4948 // Try to find a window with a wxWindow associated with it
4949 while (!win
&& (hWnd
!= 0))
4951 hWnd
= ::GetParent(hWnd
);
4952 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
4957 // Get the current mouse position.
4958 wxPoint
wxGetMousePosition()
4961 GetCursorPos( & pt
);
4962 return wxPoint(pt
.x
, pt
.y
);