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( !wxDynamicCastThis(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 #if defined(__WIN95__)
832 if ( orient
== wxHORIZONTAL
) {
838 info
.cbSize
= sizeof(SCROLLINFO
);
842 info
.fMask
= SIF_POS
;
844 HWND hWnd
= GetHwnd();
846 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
849 if ( orient
== wxHORIZONTAL
)
854 HWND hWnd
= GetHwnd();
856 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
860 // New function that will replace some of the above.
861 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
862 int range
, bool refresh
)
864 #if defined(__WIN95__)
865 int oldRange
= range
- thumbVisible
;
867 int range1
= oldRange
;
869 // Try to adjust the range to cope with page size > 1
870 // - a Windows API quirk
871 int pageSize
= thumbVisible
;
872 if ( pageSize
> 1 && range
> 0)
874 range1
+= (pageSize
- 1);
880 if ( orient
== wxHORIZONTAL
) {
886 info
.cbSize
= sizeof(SCROLLINFO
);
887 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
891 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
893 HWND hWnd
= GetHwnd();
895 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
898 if ( orient
== wxHORIZONTAL
)
903 HWND hWnd
= GetHwnd();
906 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
907 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
910 if ( orient
== wxHORIZONTAL
) {
911 m_xThumbSize
= thumbVisible
;
913 m_yThumbSize
= thumbVisible
;
917 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
922 rect
.left
= prect
->x
;
924 rect
.right
= prect
->x
+ prect
->width
;
925 rect
.bottom
= prect
->y
+ prect
->height
;
928 ::ScrollWindow(GetHwnd(), dx
, dy
, prect
? &rect
: NULL
, NULL
);
931 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
933 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
936 for ( int n
= 0; n
< count
; n
++ )
938 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
940 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
943 // don't bother to continue, we're already at top/bottom
950 return pos
!= posStart
;
953 bool wxWindowMSW::ScrollLines(int lines
)
955 bool down
= lines
> 0;
957 return ScrollVertically(GetHwnd(),
958 down
? SB_LINEDOWN
: SB_LINEUP
,
959 down
? lines
: -lines
);
962 bool wxWindowMSW::ScrollPages(int pages
)
964 bool down
= pages
> 0;
966 return ScrollVertically(GetHwnd(),
967 down
? SB_PAGEDOWN
: SB_PAGEUP
,
968 down
? pages
: -pages
);
971 // ---------------------------------------------------------------------------
973 // ---------------------------------------------------------------------------
975 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
977 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
979 HWND hwnd
= (HWND
)hWnd
;
980 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
982 wxAssociateWinWithHandle(hwnd
, this);
984 m_oldWndProc
= (WXFARPROC
)::GetWindowLong(hwnd
, GWL_WNDPROC
);
986 // we don't need to subclass the window of our own class (in the Windows
987 // sense of the word)
988 if ( (WXFARPROC
) m_oldWndProc
!= (WXFARPROC
) wxWndProc
)
990 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
994 // don't bother restoring it neither
999 void wxWindowMSW::UnsubclassWin()
1001 wxRemoveHandleAssociation(this);
1003 // Restore old Window proc
1004 HWND hwnd
= GetHwnd();
1009 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
1013 FARPROC wndProc
= (FARPROC
)::GetWindowLong(hwnd
, GWL_WNDPROC
);
1014 if ( wndProc
!= (FARPROC
) m_oldWndProc
)
1016 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1019 m_oldWndProc
= NULL
;
1024 // Make a Windows extended style from the given wxWindows window style
1025 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1027 WXDWORD exStyle
= 0;
1028 if ( style
& wxTRANSPARENT_WINDOW
)
1029 exStyle
|= WS_EX_TRANSPARENT
;
1031 if ( !eliminateBorders
)
1033 if ( style
& wxSUNKEN_BORDER
)
1034 exStyle
|= WS_EX_CLIENTEDGE
;
1035 if ( style
& wxDOUBLE_BORDER
)
1036 exStyle
|= WS_EX_DLGMODALFRAME
;
1037 #if defined(__WIN95__)
1038 if ( style
& wxRAISED_BORDER
)
1039 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1040 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1041 if ( style
& wxSTATIC_BORDER
)
1042 exStyle
|= WS_EX_STATICEDGE
;
1049 // Determines whether native 3D effects or CTL3D should be used,
1050 // applying a default border style if required, and returning an extended
1051 // style to pass to CreateWindowEx.
1052 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1055 // If matches certain criteria, then assume no 3D effects
1056 // unless specifically requested (dealt with in MakeExtendedStyle)
1059 || !IsKindOf(CLASSINFO(wxControl
))
1060 #endif // wxUSE_CONTROLS
1061 || (m_windowStyle
& wxNO_BORDER
) )
1064 return MakeExtendedStyle(m_windowStyle
);
1067 // Determine whether we should be using 3D effects or not.
1068 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1070 // 1) App can specify global 3D effects
1071 *want3D
= wxTheApp
->GetAuto3D();
1073 // 2) If the parent is being drawn with user colours, or simple border specified,
1074 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1075 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1078 // 3) Control can override this global setting by defining
1079 // a border style, e.g. wxSUNKEN_BORDER
1080 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1083 // 4) If it's a special border, CTL3D can't cope so we want a native border
1084 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1085 (m_windowStyle
& wxSTATIC_BORDER
) )
1088 nativeBorder
= TRUE
;
1091 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1092 // effects from extended style
1095 nativeBorder
= FALSE
;
1098 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1100 // If we want 3D, but haven't specified a border here,
1101 // apply the default border style specified.
1102 // TODO what about non-Win95 WIN32? Does it have borders?
1103 #if defined(__WIN95__) && !wxUSE_CTL3D
1104 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1105 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1106 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1112 #if WXWIN_COMPATIBILITY
1113 // If nothing defined for this, try the parent.
1114 // E.g. we may be a button loaded from a resource, with no callback function
1116 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1118 if ( GetEventHandler()->ProcessEvent(event
) )
1121 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1123 #endif // WXWIN_COMPATIBILITY_2
1125 #if WXWIN_COMPATIBILITY
1126 wxObject
* wxWindowMSW::GetChild(int number
) const
1128 // Return a pointer to the Nth object in the Panel
1129 wxNode
*node
= GetChildren().First();
1132 node
= node
->Next();
1135 wxObject
*obj
= (wxObject
*)node
->Data();
1141 #endif // WXWIN_COMPATIBILITY
1143 // Setup background and foreground colours correctly
1144 void wxWindowMSW::SetupColours()
1147 SetBackgroundColour(GetParent()->GetBackgroundColour());
1150 bool wxWindowMSW::IsMouseInWindow() const
1152 // get the mouse position
1154 ::GetCursorPos(&pt
);
1156 // find the window which currently has the cursor and go up the window
1157 // chain until we find this window - or exhaust it
1158 HWND hwnd
= ::WindowFromPoint(pt
);
1159 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1160 hwnd
= ::GetParent(hwnd
);
1162 return hwnd
!= NULL
;
1165 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1167 // Check if we need to send a LEAVE event
1168 if ( m_mouseInWindow
)
1170 if ( !IsMouseInWindow() )
1172 // Generate a LEAVE event
1173 m_mouseInWindow
= FALSE
;
1175 // Unfortunately the mouse button and keyboard state may have
1176 // changed by the time the OnIdle function is called, so 'state'
1177 // may be meaningless.
1179 if ( wxIsShiftDown() )
1181 if ( wxIsCtrlDown() )
1182 state
|= MK_CONTROL
;
1183 if ( GetKeyState( VK_LBUTTON
) )
1184 state
|= MK_LBUTTON
;
1185 if ( GetKeyState( VK_MBUTTON
) )
1186 state
|= MK_MBUTTON
;
1187 if ( GetKeyState( VK_RBUTTON
) )
1188 state
|= MK_RBUTTON
;
1191 if ( !::GetCursorPos(&pt
) )
1193 wxLogLastError(_T("GetCursorPos"));
1196 // we need to have client coordinates here for symmetry with
1197 // wxEVT_ENTER_WINDOW
1198 RECT rect
= wxGetWindowRect(GetHwnd());
1202 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1203 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1205 (void)GetEventHandler()->ProcessEvent(event2
);
1212 // Set this window to be the child of 'parent'.
1213 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1215 if ( !wxWindowBase::Reparent(parent
) )
1218 HWND hWndChild
= GetHwnd();
1219 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1221 ::SetParent(hWndChild
, hWndParent
);
1226 void wxWindowMSW::Clear()
1228 wxClientDC
dc((wxWindow
*)this);
1229 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1230 dc
.SetBackground(brush
);
1234 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1236 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1239 void wxWindowMSW::Freeze()
1241 SendSetRedraw(GetHwnd(), FALSE
);
1244 void wxWindowMSW::Thaw()
1246 SendSetRedraw(GetHwnd(), TRUE
);
1248 // we need to refresh everything or otherwise he invalidated area is not
1253 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1255 HWND hWnd
= GetHwnd();
1261 mswRect
.left
= rect
->x
;
1262 mswRect
.top
= rect
->y
;
1263 mswRect
.right
= rect
->x
+ rect
->width
;
1264 mswRect
.bottom
= rect
->y
+ rect
->height
;
1266 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1269 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1273 void wxWindowMSW::Update()
1275 if ( !::UpdateWindow(GetHwnd()) )
1277 wxLogLastError(_T("UpdateWindow"));
1280 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1281 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1282 // handler needs to be really drawn right now
1287 // ---------------------------------------------------------------------------
1289 // ---------------------------------------------------------------------------
1291 #if wxUSE_DRAG_AND_DROP
1293 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1295 if ( m_dropTarget
!= 0 ) {
1296 m_dropTarget
->Revoke(m_hWnd
);
1297 delete m_dropTarget
;
1300 m_dropTarget
= pDropTarget
;
1301 if ( m_dropTarget
!= 0 )
1302 m_dropTarget
->Register(m_hWnd
);
1305 #endif // wxUSE_DRAG_AND_DROP
1307 // old style file-manager drag&drop support: we retain the old-style
1308 // DragAcceptFiles in parallel with SetDropTarget.
1309 void wxWindowMSW::DragAcceptFiles(bool accept
)
1311 HWND hWnd
= GetHwnd();
1313 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1316 // ----------------------------------------------------------------------------
1318 // ----------------------------------------------------------------------------
1322 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1324 wxWindowBase::DoSetToolTip(tooltip
);
1327 m_tooltip
->SetWindow(this);
1330 #endif // wxUSE_TOOLTIPS
1332 // ---------------------------------------------------------------------------
1333 // moving and resizing
1334 // ---------------------------------------------------------------------------
1337 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1339 RECT rect
= wxGetWindowRect(GetHwnd());
1342 *x
= rect
.right
- rect
.left
;
1344 *y
= rect
.bottom
- rect
.top
;
1347 // Get size *available for subwindows* i.e. excluding menu bar etc.
1348 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1350 RECT rect
= wxGetClientRect(GetHwnd());
1358 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1360 RECT rect
= wxGetWindowRect(GetHwnd());
1363 point
.x
= rect
.left
;
1366 // we do the adjustments with respect to the parent only for the "real"
1367 // children, not for the dialogs/frames
1368 if ( !IsTopLevel() )
1370 HWND hParentWnd
= 0;
1371 wxWindow
*parent
= GetParent();
1373 hParentWnd
= GetWinHwnd(parent
);
1375 // Since we now have the absolute screen coords, if there's a parent we
1376 // must subtract its top left corner
1379 ::ScreenToClient(hParentWnd
, &point
);
1384 // We may be faking the client origin. So a window that's really at (0,
1385 // 30) may appear (to wxWin apps) to be at (0, 0).
1386 wxPoint
pt(parent
->GetClientAreaOrigin());
1398 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1406 ::ScreenToClient(GetHwnd(), &pt
);
1414 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1422 ::ClientToScreen(GetHwnd(), &pt
);
1430 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1432 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1434 wxLogLastError(wxT("MoveWindow"));
1438 // set the size of the window: if the dimensions are positive, just use them,
1439 // but if any of them is equal to -1, it means that we must find the value for
1440 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1441 // which case -1 is a valid value for x and y)
1443 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1444 // the width/height to best suit our contents, otherwise we reuse the current
1446 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1448 // get the current size and position...
1449 int currentX
, currentY
;
1450 GetPosition(¤tX
, ¤tY
);
1451 int currentW
,currentH
;
1452 GetSize(¤tW
, ¤tH
);
1454 // ... and don't do anything (avoiding flicker) if it's already ok
1455 if ( x
== currentX
&& y
== currentY
&&
1456 width
== currentW
&& height
== currentH
)
1461 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1463 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1466 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1468 wxSize
size(-1, -1);
1471 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1473 size
= DoGetBestSize();
1478 // just take the current one
1485 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1489 size
= DoGetBestSize();
1491 //else: already called DoGetBestSize() above
1497 // just take the current one
1502 DoMoveWindow(x
, y
, width
, height
);
1505 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1507 wxWindow
*parent
= GetParent();
1508 HWND hWnd
= GetHwnd();
1509 HWND hParentWnd
= (HWND
) 0;
1511 hParentWnd
= (HWND
) parent
->GetHWND();
1514 ::GetClientRect(hWnd
, &rect
);
1517 GetWindowRect(hWnd
, &rect2
);
1519 // Find the difference between the entire window (title bar and all)
1520 // and the client area; add this to the new client size to move the
1522 int actual_width
= rect2
.right
- rect2
.left
- rect
.right
+ width
;
1523 int actual_height
= rect2
.bottom
- rect2
.top
- rect
.bottom
+ height
;
1525 // If there's a parent, must subtract the parent's top left corner
1526 // since MoveWindow moves relative to the parent
1529 point
.x
= rect2
.left
;
1530 point
.y
= rect2
.top
;
1533 ::ScreenToClient(hParentWnd
, &point
);
1536 DoMoveWindow(point
.x
, point
.y
, actual_width
, actual_height
);
1538 wxSizeEvent
event(wxSize(width
, height
), m_windowId
);
1539 event
.SetEventObject(this);
1540 GetEventHandler()->ProcessEvent(event
);
1543 // For implementation purposes - sometimes decorations make the client area
1545 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1547 return wxPoint(0, 0);
1550 // ---------------------------------------------------------------------------
1552 // ---------------------------------------------------------------------------
1554 int wxWindowMSW::GetCharHeight() const
1556 return wxGetTextMetrics(this).tmHeight
;
1559 int wxWindowMSW::GetCharWidth() const
1561 // +1 is needed because Windows apparently adds it when calculating the
1562 // dialog units size in pixels
1563 #if wxDIALOG_UNIT_COMPATIBILITY
1564 return wxGetTextMetrics(this).tmAveCharWidth
;
1566 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1570 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1572 int *descent
, int *externalLeading
,
1573 const wxFont
*theFont
) const
1575 const wxFont
*fontToUse
= theFont
;
1577 fontToUse
= &m_font
;
1579 HWND hWnd
= GetHwnd();
1580 HDC dc
= ::GetDC(hWnd
);
1584 if ( fontToUse
&& fontToUse
->Ok() )
1586 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1588 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1593 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1594 GetTextMetrics(dc
, &tm
);
1596 if ( fontToUse
&& fnt
&& hfontOld
)
1597 SelectObject(dc
, hfontOld
);
1599 ReleaseDC(hWnd
, dc
);
1606 *descent
= tm
.tmDescent
;
1607 if ( externalLeading
)
1608 *externalLeading
= tm
.tmExternalLeading
;
1611 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1612 // ---------------------------------------------------------------------------
1613 // Caret manipulation
1614 // ---------------------------------------------------------------------------
1616 void wxWindowMSW::CreateCaret(int w
, int h
)
1618 SetCaret(new wxCaret(this, w
, h
));
1621 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1623 wxFAIL_MSG("not implemented");
1626 void wxWindowMSW::ShowCaret(bool show
)
1628 wxCHECK_RET( m_caret
, "no caret to show" );
1630 m_caret
->Show(show
);
1633 void wxWindowMSW::DestroyCaret()
1638 void wxWindowMSW::SetCaretPos(int x
, int y
)
1640 wxCHECK_RET( m_caret
, "no caret to move" );
1642 m_caret
->Move(x
, y
);
1645 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1647 wxCHECK_RET( m_caret
, "no caret to get position of" );
1649 m_caret
->GetPosition(x
, y
);
1651 #endif // wxUSE_CARET
1653 // ---------------------------------------------------------------------------
1655 // ---------------------------------------------------------------------------
1657 #if wxUSE_MENUS_NATIVE
1659 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1660 // immediately, without waiting for the next event loop iteration
1662 // NB: this function should probably be made public later as it can almost
1663 // surely replace wxYield() elsewhere as well
1664 static void wxYieldForCommandsOnly()
1666 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1667 // want to process it here)
1669 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1670 && msg
.message
!= WM_QUIT
)
1672 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1676 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1678 menu
->SetInvokingWindow(this);
1681 HWND hWnd
= GetHwnd();
1682 HMENU hMenu
= GetHmenuOf(menu
);
1686 ::ClientToScreen(hWnd
, &point
);
1687 wxCurrentPopupMenu
= menu
;
1688 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1690 // we need to do it righ now as otherwise the events are never going to be
1691 // sent to wxCurrentPopupMenu from HandleCommand()
1693 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1694 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1695 // destroyed as soon as we return (it can be a local variable in the caller
1696 // for example) and so we do need to process the event immediately
1697 wxYieldForCommandsOnly();
1699 wxCurrentPopupMenu
= NULL
;
1701 menu
->SetInvokingWindow(NULL
);
1706 #endif // wxUSE_MENUS_NATIVE
1708 // ===========================================================================
1709 // pre/post message processing
1710 // ===========================================================================
1712 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1715 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1717 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1720 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1722 // wxUniversal implements tab traversal itself
1723 #ifndef __WXUNIVERSAL__
1724 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1726 // intercept dialog navigation keys
1727 MSG
*msg
= (MSG
*)pMsg
;
1729 // here we try to do all the job which ::IsDialogMessage() usually does
1732 bool bProcess
= TRUE
;
1733 if ( msg
->message
!= WM_KEYDOWN
)
1736 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1741 bool bCtrlDown
= wxIsCtrlDown();
1742 bool bShiftDown
= wxIsShiftDown();
1744 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1745 // don't process it if it's the case (except for Ctrl-Tab/Enter
1746 // combinations which are always processed)
1750 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1753 bool bForward
= TRUE
,
1754 bWindowChange
= FALSE
;
1756 switch ( msg
->wParam
)
1759 // assume that nobody wants Shift-TAB for himself - if we
1760 // don't do it there is no easy way for a control to grab
1761 // TABs but still let Shift-TAB work as navugation key
1762 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1766 // Ctrl-Tab cycles thru notebook pages
1767 bWindowChange
= bCtrlDown
;
1768 bForward
= !bShiftDown
;
1774 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1782 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1788 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1790 // control wants to process Enter itself, don't
1791 // call IsDialogMessage() which would interpret
1795 else if ( lDlgCode
& DLGC_BUTTON
)
1797 // let IsDialogMessage() handle this for all
1798 // buttons except the owner-drawn ones which it
1799 // just seems to ignore
1800 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1801 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1803 // emulate the button click
1804 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1806 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1811 // FIXME: this should be handled by
1812 // wxNavigationKeyEvent handler and not here!!
1816 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1818 if ( btn
&& btn
->IsEnabled() )
1820 // if we do have a default button, do press it
1821 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1825 else // no default button
1826 #endif // wxUSE_BUTTON
1828 // no special function for enter and don't even
1829 // let IsDialogMessage() have it: it seems to
1830 // do something really strange with it
1843 wxNavigationKeyEvent event
;
1844 event
.SetDirection(bForward
);
1845 event
.SetWindowChange(bWindowChange
);
1846 event
.SetEventObject(this);
1848 if ( GetEventHandler()->ProcessEvent(event
) )
1855 // let ::IsDialogMessage() do almost everything and handle just the
1856 // things it doesn't here: Ctrl-TAB for switching notebook pages
1857 if ( msg
->message
== WM_KEYDOWN
)
1859 // don't process system keys here
1860 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1862 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1864 // find the first notebook parent and change its page
1865 wxWindow
*win
= this;
1866 wxNotebook
*nbook
= NULL
;
1867 while ( win
&& !nbook
)
1869 nbook
= wxDynamicCast(win
, wxNotebook
);
1870 win
= win
->GetParent();
1875 bool forward
= !wxIsShiftDown();
1877 nbook
->AdvanceSelection(forward
);
1884 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1886 // IsDialogMessage() did something...
1890 #endif // __WXUNIVERSAL__
1895 // relay mouse move events to the tooltip control
1896 MSG
*msg
= (MSG
*)pMsg
;
1897 if ( msg
->message
== WM_MOUSEMOVE
)
1898 m_tooltip
->RelayEvent(pMsg
);
1900 #endif // wxUSE_TOOLTIPS
1905 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1907 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1908 return m_acceleratorTable
.Translate(this, pMsg
);
1911 #endif // wxUSE_ACCEL
1914 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1916 // preprocess all messages by default
1920 // ---------------------------------------------------------------------------
1921 // message params unpackers (different for Win16 and Win32)
1922 // ---------------------------------------------------------------------------
1926 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1927 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1929 *id
= LOWORD(wParam
);
1930 *hwnd
= (WXHWND
)lParam
;
1931 *cmd
= HIWORD(wParam
);
1934 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1935 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1937 *state
= LOWORD(wParam
);
1938 *minimized
= HIWORD(wParam
);
1939 *hwnd
= (WXHWND
)lParam
;
1942 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1943 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1945 *code
= LOWORD(wParam
);
1946 *pos
= HIWORD(wParam
);
1947 *hwnd
= (WXHWND
)lParam
;
1950 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
1951 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
1953 #ifndef __WXMICROWIN__
1954 *nCtlColor
= CTLCOLOR_BTN
;
1955 *hwnd
= (WXHWND
)lParam
;
1956 *hdc
= (WXHDC
)wParam
;
1960 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
1961 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
1963 *item
= (WXWORD
)wParam
;
1964 *flags
= HIWORD(wParam
);
1965 *hmenu
= (WXHMENU
)lParam
;
1970 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1971 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
1973 *id
= (WXWORD
)wParam
;
1974 *hwnd
= (WXHWND
)LOWORD(lParam
);
1975 *cmd
= HIWORD(lParam
);
1978 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1979 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1981 *state
= (WXWORD
)wParam
;
1982 *minimized
= LOWORD(lParam
);
1983 *hwnd
= (WXHWND
)HIWORD(lParam
);
1986 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1987 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1989 *code
= (WXWORD
)wParam
;
1990 *pos
= LOWORD(lParam
);
1991 *hwnd
= (WXHWND
)HIWORD(lParam
);
1994 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
1995 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
1997 *hwnd
= (WXHWND
)LOWORD(lParam
);
1998 *nCtlColor
= (int)HIWORD(lParam
);
1999 *hdc
= (WXHDC
)wParam
;
2002 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2003 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2005 *item
= (WXWORD
)wParam
;
2006 *flags
= LOWORD(lParam
);
2007 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2012 // ---------------------------------------------------------------------------
2013 // Main wxWindows window proc and the window proc for wxWindow
2014 // ---------------------------------------------------------------------------
2016 // Hook for new window just as it's being created, when the window isn't yet
2017 // associated with the handle
2018 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2020 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2021 // window being created and insures that it's always unset back later
2022 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2024 gs_winBeingCreated
= winBeingCreated
;
2027 wxWindowCreationHook::~wxWindowCreationHook()
2029 gs_winBeingCreated
= NULL
;
2033 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2035 // trace all messages - useful for the debugging
2037 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2038 wxGetMessageName(message
), wParam
, lParam
);
2039 #endif // __WXDEBUG__
2041 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2043 // when we get the first message for the HWND we just created, we associate
2044 // it with wxWindow stored in gs_winBeingCreated
2045 if ( !wnd
&& gs_winBeingCreated
)
2047 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2048 wnd
= gs_winBeingCreated
;
2049 gs_winBeingCreated
= NULL
;
2050 wnd
->SetHWND((WXHWND
)hWnd
);
2056 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2058 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2063 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2065 // did we process the message?
2066 bool processed
= FALSE
;
2077 // for most messages we should return 0 when we do process the message
2085 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2088 // return 0 to allow window creation
2089 rc
.result
= mayCreate
? 0 : -1;
2095 // never set processed to TRUE and *always* pass WM_DESTROY to
2096 // DefWindowProc() as Windows may do some internal cleanup when
2097 // processing it and failing to pass the message along may cause
2098 // memory and resource leaks!
2099 (void)HandleDestroy();
2103 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2111 // we're not interested in these messages at all
2114 case SIZE_MINIMIZED
:
2115 // we shouldn't send sizev events for these messages as the
2116 // client size may be negative which breaks existing code
2118 // OTOH we might send another (wxMinimizedEvent?) one or
2119 // add an additional parameter to wxSizeEvent if this is
2120 // useful to anybody
2124 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2125 // fall through nevertheless
2127 case SIZE_MAXIMIZED
:
2129 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2134 #ifndef __WXMICROWIN__
2135 case WM_ACTIVATEAPP
:
2136 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2142 WXWORD state
, minimized
;
2144 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2146 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2151 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2155 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2159 processed
= HandlePaint();
2163 // don't let the DefWindowProc() destroy our window - we'll do it
2164 // ourselves in ~wxWindow
2170 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2174 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2175 GET_Y_LPARAM(lParam
),
2179 #if wxUSE_MOUSEWHEEL
2181 processed
= HandleMouseWheel(wParam
, lParam
);
2185 case WM_LBUTTONDOWN
:
2187 case WM_LBUTTONDBLCLK
:
2188 case WM_RBUTTONDOWN
:
2190 case WM_RBUTTONDBLCLK
:
2191 case WM_MBUTTONDOWN
:
2193 case WM_MBUTTONDBLCLK
:
2196 #ifdef __WXMICROWIN__
2197 // MicroWindows seems to ignore the fact that a window is
2198 // disabled. So catch mouse events and throw them away if
2200 wxWindowMSW
* win
= this;
2203 if (!win
->IsEnabled())
2208 win
= win
->GetParent();
2209 if (win
&& win
->IsTopLevel())
2212 #endif // __WXMICROWIN__
2215 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2217 processed
= HandleMouseEvent(message
,
2218 GET_X_LPARAM(lParam
),
2219 GET_Y_LPARAM(lParam
),
2225 #ifdef __WXMICROWIN__
2226 case WM_NCLBUTTONDOWN
:
2227 case WM_NCLBUTTONUP
:
2228 case WM_NCLBUTTONDBLCLK
:
2229 case WM_NCRBUTTONDOWN
:
2230 case WM_NCRBUTTONUP
:
2231 case WM_NCRBUTTONDBLCLK
:
2233 case WM_NCMBUTTONDOWN
:
2234 case WM_NCMBUTTONUP
:
2235 case WM_NCMBUTTONDBLCLK
:
2238 // MicroWindows seems to ignore the fact that a window
2239 // is disabled. So catch mouse events and throw them away if necessary.
2241 wxWindowMSW
* win
= this;
2244 if (!win
->IsEnabled())
2249 win
= win
->GetParent();
2250 if (win
&& win
->IsTopLevel())
2255 #endif // __WXMICROWIN__
2262 case MM_JOY1BUTTONDOWN
:
2263 case MM_JOY2BUTTONDOWN
:
2264 case MM_JOY1BUTTONUP
:
2265 case MM_JOY2BUTTONUP
:
2266 processed
= HandleJoystickEvent(message
,
2267 GET_X_LPARAM(lParam
),
2268 GET_Y_LPARAM(lParam
),
2271 #endif // __WXMICROWIN__
2274 processed
= HandleSysCommand(wParam
, lParam
);
2281 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2283 processed
= HandleCommand(id
, cmd
, hwnd
);
2289 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2293 // for these messages we must return TRUE if process the message
2296 case WM_MEASUREITEM
:
2298 int idCtrl
= (UINT
)wParam
;
2299 if ( message
== WM_DRAWITEM
)
2301 processed
= MSWOnDrawItem(idCtrl
,
2302 (WXDRAWITEMSTRUCT
*)lParam
);
2306 processed
= MSWOnMeasureItem(idCtrl
,
2307 (WXMEASUREITEMSTRUCT
*)lParam
);
2314 #endif // defined(WM_DRAWITEM)
2319 rc
.result
= m_lDlgCode
;
2322 //else: get the dlg code from the DefWindowProc()
2327 // If this has been processed by an event handler,
2328 // return 0 now (we've handled it).
2329 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2336 // we consider these message "not interesting" to OnChar
2337 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2346 // avoid duplicate messages to OnChar for these ASCII keys: they
2347 // will be translated by TranslateMessage() and received in WM_CHAR
2355 // but set processed to FALSE, not TRUE to still pass them to
2356 // the control's default window proc - otherwise built-in
2357 // keyboard handling won't work
2363 // special case of VK_APPS: treat it the same as right mouse
2364 // click because both usually pop up a context menu
2370 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2371 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2381 processed
= HandleChar((WORD
)wParam
, lParam
);
2388 // special case of VK_APPS: treat it the same as right mouse button
2389 if ( wParam
== VK_APPS
)
2394 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2395 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2400 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2405 case WM_CHAR
: // Always an ASCII character
2406 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2414 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2416 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2422 // CTLCOLOR messages are sent by children to query the parent for their
2423 // colors#ifndef __WXMICROWIN__
2424 #ifndef __WXMICROWIN__
2426 case WM_CTLCOLORMSGBOX
:
2427 case WM_CTLCOLOREDIT
:
2428 case WM_CTLCOLORLISTBOX
:
2429 case WM_CTLCOLORBTN
:
2430 case WM_CTLCOLORDLG
:
2431 case WM_CTLCOLORSCROLLBAR
:
2432 case WM_CTLCOLORSTATIC
:
2440 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2442 processed
= HandleCtlColor(&rc
.hBrush
,
2451 #endif // !__WXMICROWIN__
2453 // the return value for this message is ignored
2454 case WM_SYSCOLORCHANGE
:
2455 processed
= HandleSysColorChange();
2458 case WM_PALETTECHANGED
:
2459 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2462 case WM_QUERYNEWPALETTE
:
2463 processed
= HandleQueryNewPalette();
2467 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2470 // we processed the message, i.e. erased the background
2476 processed
= HandleDropFiles(wParam
);
2480 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2484 // we never set focus from here
2489 case WM_QUERYENDSESSION
:
2490 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2494 processed
= HandleEndSession(wParam
!= 0, lParam
);
2497 case WM_GETMINMAXINFO
:
2498 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2502 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2503 LOWORD(lParam
), // hit test
2504 HIWORD(lParam
)); // mouse msg
2508 // returning TRUE stops the DefWindowProc() from further
2509 // processing this message - exactly what we need because we've
2510 // just set the cursor.
2515 #if defined(__WIN32__) && defined(WM_HELP)
2518 HELPINFO
* info
= (HELPINFO
*) lParam
;
2519 // Don't yet process menu help events, just windows
2520 if (info
->iContextType
== HELPINFO_WINDOW
)
2522 wxWindowMSW
* subjectOfHelp
= this;
2523 bool eventProcessed
= FALSE
;
2524 while (subjectOfHelp
&& !eventProcessed
)
2526 wxHelpEvent
helpEvent(wxEVT_HELP
,
2527 subjectOfHelp
->GetId(),
2528 wxPoint(info
->MousePos
.x
,
2529 info
->MousePos
.y
) );
2530 helpEvent
.SetEventObject(this);
2532 GetEventHandler()->ProcessEvent(helpEvent
);
2534 // Go up the window hierarchy until the event is
2536 subjectOfHelp
= subjectOfHelp
->GetParent();
2539 processed
= eventProcessed
;
2541 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2543 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2544 helpEvent
.SetEventObject(this);
2545 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2548 //else: processed is already FALSE
2552 case WM_CONTEXTMENU
:
2554 // we don't convert from screen to client coordinates as
2555 // the event may be handled by a parent window
2556 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2558 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2559 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2564 // unfortunately this doesn't really work as then window which
2565 // doesn't accept focus doesn't get any mouse events neither which
2566 // means it can't get any input at all
2567 #if 0 //def __WXUNIVERSAL__
2569 // we shouldn't allow the windows which don't want to get focus to
2571 if ( !AcceptsFocus() )
2573 rc
.result
= HTTRANSPARENT
;
2577 #endif // __WXUNIVERSAL__
2583 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2584 wxGetMessageName(message
));
2585 #endif // __WXDEBUG__
2586 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2592 // ----------------------------------------------------------------------------
2593 // wxWindow <-> HWND map
2594 // ----------------------------------------------------------------------------
2596 wxWinHashTable
*wxWinHandleHash
= NULL
;
2598 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2600 return wxWinHandleHash
->Get((long)hWnd
);
2603 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2605 // adding NULL hWnd is (first) surely a result of an error and
2606 // (secondly) breaks menu command processing
2607 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2608 wxT("attempt to add a NULL hWnd to window list ignored") );
2610 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2612 if ( oldWin
&& (oldWin
!= win
) )
2614 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2615 hWnd
, win
->GetClassInfo()->GetClassName());
2618 #endif // __WXDEBUG__
2621 wxWinHandleHash
->Put((long)hWnd
, win
);
2625 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2627 wxWinHandleHash
->Delete((long)win
->GetHWND());
2630 // ----------------------------------------------------------------------------
2631 // various MSW speciic class dependent functions
2632 // ----------------------------------------------------------------------------
2634 // Default destroyer - override if you destroy it in some other way
2635 // (e.g. with MDI child windows)
2636 void wxWindowMSW::MSWDestroyWindow()
2640 void wxWindowMSW::MSWDetachWindowMenu()
2642 #ifndef __WXUNIVERSAL__
2646 HMENU hMenu
= (HMENU
)m_hMenu
;
2648 int N
= ::GetMenuItemCount(hMenu
);
2649 for ( int i
= 0; i
< N
; i
++ )
2651 if ( !::GetMenuString(hMenu
, i
, buf
, WXSIZEOF(buf
), MF_BYPOSITION
) )
2653 wxLogLastError(wxT("GetMenuString"));
2658 if ( wxStrcmp(buf
, _("&Window")) == 0 )
2660 if ( !::RemoveMenu(hMenu
, i
, MF_BYPOSITION
) )
2662 wxLogLastError(wxT("RemoveMenu"));
2669 #endif // __WXUNIVERSAL__
2672 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2675 int& w
, int& h
) const
2677 bool nonDefault
= FALSE
;
2681 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2682 // just as well set it to CW_USEDEFAULT as well
2689 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2695 NB: there used to be some code here which set the initial size of the
2696 window to the client size of the parent if no explicit size was
2697 specified. This was wrong because wxWindows programs often assume
2698 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2699 it. To see why, you should understand that Windows sends WM_SIZE from
2700 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2701 from some base class ctor and so this WM_SIZE is not processed in the
2702 real class' OnSize() (because it's not fully constructed yet and the
2703 event goes to some base class OnSize() instead). So the WM_SIZE we
2704 rely on is the one sent when the parent frame resizes its children
2705 but here is the problem: if the child already has just the right
2706 size, nothing will happen as both wxWindows and Windows check for
2707 this and ignore any attempts to change the window size to the size it
2708 already has - so no WM_SIZE would be sent.
2712 // as abobe, h is not used at all in this case anyhow
2719 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2727 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2728 const wxChar
*title
,
2732 WXDWORD extendedStyle
)
2734 // choose the position/size for the new window
2736 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2738 // find the correct parent HWND
2739 wxWindow
*parent
= GetParent();
2740 bool isChild
= (style
& WS_CHILD
) != 0;
2742 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2744 // popup windows should have desktop as parent because they shouldn't
2745 // be limited to the parents client area as child windows usually are
2746 hParent
= ::GetDesktopWindow();
2750 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2752 // this is either a normal child window or a top level window with
2753 // wxFRAME_TOOL_WINDOW style (see below)
2754 hParent
= GetHwndOf(parent
);
2758 // this is either a window for which no parent was specified (not
2759 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2760 // style: we should use NULL parent HWND for it or it would be
2761 // always on top of its parent which is not what we usually want
2762 // (in fact, we only want it for frames with the special
2763 // wxFRAME_TOOL_WINDOW as above)
2769 // controlId is menu handle for the top level windows, so set it to 0
2770 // unless we're creating a child window
2774 controlId
= GetId();
2776 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2778 style
|= WS_CLIPSIBLINGS
;
2786 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2787 // which is the same but without CS_[HV]REDRAW class styles so using it
2788 // ensures that the window is not fully repainted on each resize
2789 wxString
className(wclass
);
2790 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2792 className
+= wxT("NR");
2795 // do create the window
2796 wxWindowCreationHook
hook(this);
2798 m_hWnd
= (WXHWND
)::CreateWindowEx
2802 title
? title
: wxT(""),
2808 NULL
// no extra data
2813 wxLogSysError(_("Can't create window of class %s"), wclass
);
2818 SubclassWin(m_hWnd
);
2820 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2825 // ===========================================================================
2826 // MSW message handlers
2827 // ===========================================================================
2829 // ---------------------------------------------------------------------------
2831 // ---------------------------------------------------------------------------
2834 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2835 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2837 #ifndef __WXMICROWIN__
2838 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2839 HWND hWnd
= hdr
->hwndFrom
;
2840 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2842 // is this one of our windows?
2845 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2848 // try all our children
2849 wxWindowList::Node
*node
= GetChildren().GetFirst();
2852 wxWindow
*child
= node
->GetData();
2853 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2858 node
= node
->GetNext();
2861 // finally try this window too (catches toolbar case)
2862 return MSWOnNotify(idCtrl
, lParam
, result
);
2863 #else // __WXMICROWIN__
2868 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2870 WXLPARAM
* WXUNUSED(result
))
2873 NMHDR
* hdr
= (NMHDR
*)lParam
;
2874 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2876 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2877 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2882 #endif // wxUSE_TOOLTIPS
2888 // ---------------------------------------------------------------------------
2889 // end session messages
2890 // ---------------------------------------------------------------------------
2892 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2894 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2895 event
.SetEventObject(wxTheApp
);
2896 event
.SetCanVeto(TRUE
);
2897 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2899 bool rc
= wxTheApp
->ProcessEvent(event
);
2903 // we may end only if the app didn't veto session closing (double
2905 *mayEnd
= !event
.GetVeto();
2911 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2913 // do nothing if the session isn't ending
2918 if ( (this != wxTheApp
->GetTopWindow()) )
2921 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2922 event
.SetEventObject(wxTheApp
);
2923 event
.SetCanVeto(FALSE
);
2924 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2926 return wxTheApp
->ProcessEvent(event
);
2929 // ---------------------------------------------------------------------------
2930 // window creation/destruction
2931 // ---------------------------------------------------------------------------
2933 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2935 // TODO: should generate this event from WM_NCCREATE
2936 wxWindowCreateEvent
event((wxWindow
*)this);
2937 (void)GetEventHandler()->ProcessEvent(event
);
2944 bool wxWindowMSW::HandleDestroy()
2946 wxWindowDestroyEvent
event((wxWindow
*)this);
2947 (void)GetEventHandler()->ProcessEvent(event
);
2949 // delete our drop target if we've got one
2950 #if wxUSE_DRAG_AND_DROP
2951 if ( m_dropTarget
!= NULL
)
2953 m_dropTarget
->Revoke(m_hWnd
);
2955 delete m_dropTarget
;
2956 m_dropTarget
= NULL
;
2958 #endif // wxUSE_DRAG_AND_DROP
2960 // WM_DESTROY handled
2964 // ---------------------------------------------------------------------------
2966 // ---------------------------------------------------------------------------
2968 bool wxWindowMSW::HandleActivate(int state
,
2969 bool WXUNUSED(minimized
),
2970 WXHWND
WXUNUSED(activate
))
2972 wxActivateEvent
event(wxEVT_ACTIVATE
,
2973 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
2975 event
.SetEventObject(this);
2977 return GetEventHandler()->ProcessEvent(event
);
2980 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
2982 // notify the parent keeping track of focus for the kbd navigation
2983 // purposes that we got it
2984 wxChildFocusEvent
eventFocus((wxWindow
*)this);
2985 (void)GetEventHandler()->ProcessEvent(eventFocus
);
2991 m_caret
->OnSetFocus();
2993 #endif // wxUSE_CARET
2996 // If it's a wxTextCtrl don't send the event as it will be done
2997 // after the control gets to process it from EN_FOCUS handler
2998 if ( wxDynamicCastThis(wxTextCtrl
) )
3002 #endif // wxUSE_TEXTCTRL
3004 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3005 event
.SetEventObject(this);
3007 // wxFindWinFromHandle() may return NULL, it is ok
3008 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3010 return GetEventHandler()->ProcessEvent(event
);
3013 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3019 m_caret
->OnKillFocus();
3021 #endif // wxUSE_CARET
3024 // If it's a wxTextCtrl don't send the event as it will be done
3025 // after the control gets to process it.
3026 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3033 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3034 event
.SetEventObject(this);
3036 // wxFindWinFromHandle() may return NULL, it is ok
3037 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3039 return GetEventHandler()->ProcessEvent(event
);
3042 // ---------------------------------------------------------------------------
3044 // ---------------------------------------------------------------------------
3046 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3048 wxShowEvent
event(GetId(), show
);
3049 event
.m_eventObject
= this;
3051 return GetEventHandler()->ProcessEvent(event
);
3054 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3056 wxInitDialogEvent
event(GetId());
3057 event
.m_eventObject
= this;
3059 return GetEventHandler()->ProcessEvent(event
);
3062 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3064 #ifndef __WXMICROWIN__
3065 HDROP hFilesInfo
= (HDROP
) wParam
;
3067 // Get the total number of files dropped
3068 UINT gwFilesDropped
= ::DragQueryFile
3076 wxString
*files
= new wxString
[gwFilesDropped
];
3077 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3079 // first get the needed buffer length (+1 for terminating NUL)
3080 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3082 // and now get the file name
3083 ::DragQueryFile(hFilesInfo
, wIndex
,
3084 files
[wIndex
].GetWriteBuf(len
), len
);
3086 files
[wIndex
].UngetWriteBuf();
3088 DragFinish (hFilesInfo
);
3090 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3091 event
.m_eventObject
= this;
3094 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3095 event
.m_pos
.x
= dropPoint
.x
;
3096 event
.m_pos
.y
= dropPoint
.y
;
3098 return GetEventHandler()->ProcessEvent(event
);
3099 #else // __WXMICROWIN__
3104 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3106 int WXUNUSED(mouseMsg
))
3108 #ifndef __WXMICROWIN__
3109 // the logic is as follows:
3110 // -1. don't set cursor for non client area, including but not limited to
3111 // the title bar, scrollbars, &c
3112 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3113 // 1. if we have the cursor set it unless wxIsBusy()
3114 // 2. if we're a top level window, set some cursor anyhow
3115 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3117 if ( nHitTest
!= HTCLIENT
)
3122 HCURSOR hcursor
= 0;
3124 // first ask the user code - it may wish to set the cursor in some very
3125 // specific way (for example, depending on the current position)
3128 if ( !::GetCursorPos(&pt
) )
3130 wxLogLastError(wxT("GetCursorPos"));
3133 // In WIN16 it doesn't return a value.
3134 ::GetCursorPos(&pt
);
3139 ScreenToClient(&x
, &y
);
3140 wxSetCursorEvent
event(x
, y
);
3142 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3143 if ( processedEvtSetCursor
&& event
.HasCursor() )
3145 hcursor
= GetHcursorOf(event
.GetCursor());
3150 bool isBusy
= wxIsBusy();
3152 // the test for processedEvtSetCursor is here to prevent using m_cursor
3153 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3154 // it - this is a way to say that our cursor shouldn't be used for this
3156 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3158 hcursor
= GetHcursorOf(m_cursor
);
3165 hcursor
= wxGetCurrentBusyCursor();
3167 else if ( !hcursor
)
3169 const wxCursor
*cursor
= wxGetGlobalCursor();
3170 if ( cursor
&& cursor
->Ok() )
3172 hcursor
= GetHcursorOf(*cursor
);
3180 ::SetCursor(hcursor
);
3182 // cursor set, stop here
3185 #endif // __WXMICROWIN__
3187 // pass up the window chain
3191 // ---------------------------------------------------------------------------
3192 // owner drawn stuff
3193 // ---------------------------------------------------------------------------
3195 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3197 #if wxUSE_OWNER_DRAWN
3199 #if wxUSE_MENUS_NATIVE
3200 // is it a menu item?
3201 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3202 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3204 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3206 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3208 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3209 // the DC from being released
3210 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3211 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3212 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3213 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3215 return pMenuItem
->OnDrawItem
3219 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3220 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3223 #endif // wxUSE_MENUS_NATIVE
3226 wxWindow
*item
= FindItem(id
);
3227 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3229 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3231 #endif // wxUSE_CONTROLS
3233 #endif // USE_OWNER_DRAWN
3238 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3240 #if wxUSE_OWNER_DRAWN
3241 // is it a menu item?
3242 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3243 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3245 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3247 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3249 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3250 &pMeasureStruct
->itemHeight
);
3253 wxWindow
*item
= FindItem(id
);
3254 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3256 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3258 #endif // owner-drawn menus
3262 // ---------------------------------------------------------------------------
3263 // colours and palettes
3264 // ---------------------------------------------------------------------------
3266 bool wxWindowMSW::HandleSysColorChange()
3268 wxSysColourChangedEvent event
;
3269 event
.SetEventObject(this);
3271 return GetEventHandler()->ProcessEvent(event
);
3274 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3282 #ifndef __WXMICROWIN__
3283 WXHBRUSH hBrush
= 0;
3285 if ( nCtlColor
== CTLCOLOR_DLG
)
3287 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3292 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3294 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3296 #endif // wxUSE_CONTROLS
3302 #else // __WXMICROWIN__
3307 // Define for each class of dialog and control
3308 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3309 WXHWND
WXUNUSED(hWnd
),
3310 WXUINT
WXUNUSED(nCtlColor
),
3311 WXUINT
WXUNUSED(message
),
3312 WXWPARAM
WXUNUSED(wParam
),
3313 WXLPARAM
WXUNUSED(lParam
))
3318 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3320 wxPaletteChangedEvent
event(GetId());
3321 event
.SetEventObject(this);
3322 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3324 return GetEventHandler()->ProcessEvent(event
);
3327 bool wxWindowMSW::HandleQueryNewPalette()
3329 wxQueryNewPaletteEvent
event(GetId());
3330 event
.SetEventObject(this);
3332 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3335 // Responds to colour changes: passes event on to children.
3336 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3338 wxNode
*node
= GetChildren().First();
3341 // Only propagate to non-top-level windows
3342 wxWindow
*win
= (wxWindow
*)node
->Data();
3343 if ( win
->GetParent() )
3345 wxSysColourChangedEvent event2
;
3346 event
.m_eventObject
= win
;
3347 win
->GetEventHandler()->ProcessEvent(event2
);
3350 node
= node
->Next();
3354 // ---------------------------------------------------------------------------
3356 // ---------------------------------------------------------------------------
3358 bool wxWindowMSW::HandlePaint()
3361 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3363 wxLogLastError(wxT("CreateRectRgn"));
3364 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3365 wxLogLastError(wxT("GetUpdateRgn"));
3367 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3370 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3372 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3373 updateRect
.right
- updateRect
.left
,
3374 updateRect
.bottom
- updateRect
.top
);
3377 wxPaintEvent
event(m_windowId
);
3378 event
.SetEventObject(this);
3380 bool processed
= GetEventHandler()->ProcessEvent(event
);
3382 // note that we must generate NC event after the normal one as otherwise
3383 // BeginPaint() will happily overwrite our decorations with the background
3385 wxNcPaintEvent
eventNc(m_windowId
);
3386 eventNc
.SetEventObject(this);
3387 GetEventHandler()->ProcessEvent(eventNc
);
3392 // Can be called from an application's OnPaint handler
3393 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3395 #ifdef __WXUNIVERSAL__
3398 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3401 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3406 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3408 // Prevents flicker when dragging
3409 if ( ::IsIconic(GetHwnd()) )
3415 dc
.SetWindow((wxWindow
*)this);
3418 wxEraseEvent
event(m_windowId
, &dc
);
3419 event
.SetEventObject(this);
3420 bool rc
= GetEventHandler()->ProcessEvent(event
);
3424 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3425 dc
.SelectOldObjects(hdc
);
3430 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3433 ::GetClientRect(GetHwnd(), &rect
);
3435 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3436 m_backgroundColour
.Green(),
3437 m_backgroundColour
.Blue());
3438 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3440 wxLogLastError(wxT("CreateSolidBrush"));
3442 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3444 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3446 ::FillRect(hdc
, &rect
, hBrush
);
3447 ::DeleteObject(hBrush
);
3448 ::SetMapMode(hdc
, mode
);
3451 // ---------------------------------------------------------------------------
3452 // moving and resizing
3453 // ---------------------------------------------------------------------------
3455 bool wxWindowMSW::HandleMinimize()
3457 wxIconizeEvent
event(m_windowId
);
3458 event
.SetEventObject(this);
3460 return GetEventHandler()->ProcessEvent(event
);
3463 bool wxWindowMSW::HandleMaximize()
3465 wxMaximizeEvent
event(m_windowId
);
3466 event
.SetEventObject(this);
3468 return GetEventHandler()->ProcessEvent(event
);
3471 bool wxWindowMSW::HandleMove(int x
, int y
)
3473 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3474 event
.SetEventObject(this);
3476 return GetEventHandler()->ProcessEvent(event
);
3479 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3481 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3482 event
.SetEventObject(this);
3484 return GetEventHandler()->ProcessEvent(event
);
3487 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3489 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3493 if ( m_minWidth
!= -1 )
3495 info
->ptMinTrackSize
.x
= m_minWidth
;
3499 if ( m_minHeight
!= -1 )
3501 info
->ptMinTrackSize
.y
= m_minHeight
;
3505 if ( m_maxWidth
!= -1 )
3507 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3511 if ( m_maxHeight
!= -1 )
3513 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3520 // ---------------------------------------------------------------------------
3522 // ---------------------------------------------------------------------------
3524 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3526 #if wxUSE_MENUS_NATIVE
3527 if ( !cmd
&& wxCurrentPopupMenu
)
3529 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3530 wxCurrentPopupMenu
= NULL
;
3532 return popupMenu
->MSWCommand(cmd
, id
);
3534 #endif // wxUSE_MENUS_NATIVE
3536 wxWindow
*win
= NULL
;
3537 if ( cmd
== 0 || cmd
== 1 ) // menu or accel - use id
3539 // must cast to a signed type before comparing with other ids!
3540 win
= FindItem((signed short)id
);
3543 if ( !win
&& control
)
3545 // find it from HWND - this works even with the broken programs using
3546 // the same ids for different controls
3547 win
= wxFindWinFromHandle(control
);
3552 return win
->MSWCommand(cmd
, id
);
3555 // the messages sent from the in-place edit control used by the treectrl
3556 // for label editing have id == 0, but they should _not_ be treated as menu
3557 // messages (they are EN_XXX ones, in fact) so don't translate anything
3558 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3561 // If no child window, it may be an accelerator, e.g. for a popup menu
3564 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3565 event
.SetEventObject(this);
3569 return GetEventHandler()->ProcessEvent(event
);
3571 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3574 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3575 // notifications to its parent which we want to reflect back to
3577 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3578 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3581 #endif // wxUSE_SPINCTRL
3586 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3588 // 4 bits are reserved
3589 switch ( wParam
& 0xFFFFFFF0 )
3592 return HandleMaximize();
3595 return HandleMinimize();
3601 // ---------------------------------------------------------------------------
3603 // ---------------------------------------------------------------------------
3605 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3609 // our client coords are not quite the same as Windows ones
3610 wxPoint pt
= GetClientAreaOrigin();
3611 event
.m_x
= x
- pt
.x
;
3612 event
.m_y
= y
- pt
.y
;
3614 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3615 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3616 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3617 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3618 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3619 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3621 event
.SetTimestamp(s_currentMsg
.time
);
3622 event
.m_eventObject
= this;
3624 #if wxUSE_MOUSEEVENT_HACK
3627 m_lastMouseEvent
= event
.GetEventType();
3628 #endif // wxUSE_MOUSEEVENT_HACK
3631 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3633 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3634 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3635 // from the message id and take the value in the table to get wxWin event
3637 static const wxEventType eventsMouse
[] =
3651 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3652 InitMouseEvent(event
, x
, y
, flags
);
3654 return GetEventHandler()->ProcessEvent(event
);
3657 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3659 if ( !m_mouseInWindow
)
3661 // it would be wrong to assume that just because we get a mouse move
3662 // event that the mouse is inside the window: although this is usually
3663 // true, it is not if we had captured the mouse, so we need to check
3664 // the mouse coordinates here
3665 if ( !HasCapture() || IsMouseInWindow() )
3667 // Generate an ENTER event
3668 m_mouseInWindow
= TRUE
;
3670 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3671 InitMouseEvent(event
, x
, y
, flags
);
3673 (void)GetEventHandler()->ProcessEvent(event
);
3677 #if wxUSE_MOUSEEVENT_HACK
3678 // Window gets a click down message followed by a mouse move message even
3679 // if position isn't changed! We want to discard the trailing move event
3680 // if x and y are the same.
3681 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3682 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3683 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3684 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3686 m_lastMouseEvent
= wxEVT_MOTION
;
3690 #endif // wxUSE_MOUSEEVENT_HACK
3692 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3696 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3698 #if wxUSE_MOUSEWHEEL
3699 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3700 InitMouseEvent(event
,
3701 GET_X_LPARAM(lParam
),
3702 GET_Y_LPARAM(lParam
),
3704 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3705 event
.m_wheelDelta
= WHEEL_DELTA
;
3708 static int s_linesPerRotation
= -1;
3709 if ( s_linesPerRotation
== -1 )
3711 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3712 &s_linesPerRotation
, 0))
3714 // this is not supposed to happen
3715 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3717 // the default is 3, so use it if SystemParametersInfo() failed
3718 s_linesPerRotation
= 3;
3722 // no SystemParametersInfo() under Win16
3723 static const int s_linesPerRotation
= 3;
3726 event
.m_linesPerAction
= s_linesPerRotation
;
3727 return GetEventHandler()->ProcessEvent(event
);
3738 // ---------------------------------------------------------------------------
3739 // keyboard handling
3740 // ---------------------------------------------------------------------------
3742 // create the key event of the given type for the given key - used by
3743 // HandleChar and HandleKeyDown/Up
3744 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3746 WXLPARAM lParam
) const
3748 wxKeyEvent
event(evType
);
3749 event
.SetId(GetId());
3750 event
.m_shiftDown
= wxIsShiftDown();
3751 event
.m_controlDown
= wxIsCtrlDown();
3752 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3754 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3755 event
.m_keyCode
= id
;
3756 event
.SetTimestamp(s_currentMsg
.time
);
3758 // translate the position to client coords
3762 GetWindowRect(GetHwnd(),&rect
);
3772 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3774 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3776 bool ctrlDown
= FALSE
;
3781 // If 1 -> 26, translate to CTRL plus a letter.
3783 if ( (id
> 0) && (id
< 27) )
3805 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3807 // it's ASCII and will be processed here only when called from
3808 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3814 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3817 event
.m_controlDown
= TRUE
;
3820 if ( GetEventHandler()->ProcessEvent(event
) )
3827 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3829 int id
= wxCharCodeMSWToWX(wParam
);
3833 // normal ASCII char
3837 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3839 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3840 if ( GetEventHandler()->ProcessEvent(event
) )
3849 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3851 int id
= wxCharCodeMSWToWX(wParam
);
3855 // normal ASCII char
3859 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3861 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3862 if ( GetEventHandler()->ProcessEvent(event
) )
3869 // ---------------------------------------------------------------------------
3871 // ---------------------------------------------------------------------------
3873 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3877 if ( flags
& JOY_BUTTON1CHG
)
3878 change
= wxJOY_BUTTON1
;
3879 if ( flags
& JOY_BUTTON2CHG
)
3880 change
= wxJOY_BUTTON2
;
3881 if ( flags
& JOY_BUTTON3CHG
)
3882 change
= wxJOY_BUTTON3
;
3883 if ( flags
& JOY_BUTTON4CHG
)
3884 change
= wxJOY_BUTTON4
;
3887 if ( flags
& JOY_BUTTON1
)
3888 buttons
|= wxJOY_BUTTON1
;
3889 if ( flags
& JOY_BUTTON2
)
3890 buttons
|= wxJOY_BUTTON2
;
3891 if ( flags
& JOY_BUTTON3
)
3892 buttons
|= wxJOY_BUTTON3
;
3893 if ( flags
& JOY_BUTTON4
)
3894 buttons
|= wxJOY_BUTTON4
;
3896 // the event ids aren't consecutive so we can't use table based lookup
3898 wxEventType eventType
;
3903 eventType
= wxEVT_JOY_MOVE
;
3908 eventType
= wxEVT_JOY_MOVE
;
3913 eventType
= wxEVT_JOY_ZMOVE
;
3918 eventType
= wxEVT_JOY_ZMOVE
;
3921 case MM_JOY1BUTTONDOWN
:
3923 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3926 case MM_JOY2BUTTONDOWN
:
3928 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3931 case MM_JOY1BUTTONUP
:
3933 eventType
= wxEVT_JOY_BUTTON_UP
;
3936 case MM_JOY2BUTTONUP
:
3938 eventType
= wxEVT_JOY_BUTTON_UP
;
3942 wxFAIL_MSG(wxT("no such joystick event"));
3947 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
3948 event
.SetPosition(wxPoint(x
, y
));
3949 event
.SetEventObject(this);
3951 return GetEventHandler()->ProcessEvent(event
);
3957 // ---------------------------------------------------------------------------
3959 // ---------------------------------------------------------------------------
3961 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
3962 WXWORD pos
, WXHWND control
)
3966 wxWindow
*child
= wxFindWinFromHandle(control
);
3968 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
3971 wxScrollWinEvent event
;
3972 event
.SetPosition(pos
);
3973 event
.SetOrientation(orientation
);
3974 event
.m_eventObject
= this;
3979 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
3983 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
3987 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
3991 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
3995 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
3999 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4002 case SB_THUMBPOSITION
:
4005 // under Win32, the scrollbar range and position are 32 bit integers,
4006 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4007 // explicitly query the scrollbar for the correct position (this must
4008 // be done only for these two SB_ events as they are the only one
4009 // carrying the scrollbar position)
4011 SCROLLINFO scrollInfo
;
4012 wxZeroMemory(scrollInfo
);
4013 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4014 scrollInfo
.fMask
= SIF_TRACKPOS
;
4016 if ( !::GetScrollInfo(GetHwnd(),
4017 orientation
== wxHORIZONTAL
? SB_HORZ
4021 wxLogLastError(_T("GetScrollInfo"));
4024 event
.SetPosition(scrollInfo
.nTrackPos
);
4028 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4029 ? wxEVT_SCROLLWIN_THUMBRELEASE
4030 : wxEVT_SCROLLWIN_THUMBTRACK
;
4037 return GetEventHandler()->ProcessEvent(event
);
4040 // ===========================================================================
4042 // ===========================================================================
4044 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4047 HDC dc
= ::GetDC((HWND
) wnd
);
4052 // the_font->UseResource();
4053 // the_font->RealizeResource();
4054 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4056 was
= (HFONT
) SelectObject(dc
,fnt
);
4058 GetTextMetrics(dc
, &tm
);
4059 if ( the_font
&& fnt
&& was
)
4061 SelectObject(dc
,was
);
4063 ReleaseDC((HWND
)wnd
, dc
);
4066 *x
= tm
.tmAveCharWidth
;
4068 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4071 // the_font->ReleaseResource();
4074 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4075 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4076 int wxCharCodeMSWToWX(int keySym
)
4081 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4082 case VK_BACK
: id
= WXK_BACK
; break;
4083 case VK_TAB
: id
= WXK_TAB
; break;
4084 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4085 case VK_RETURN
: id
= WXK_RETURN
; break;
4086 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4087 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4088 case VK_MENU
: id
= WXK_MENU
; break;
4089 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4090 case VK_SPACE
: id
= WXK_SPACE
; break;
4091 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4092 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4093 case VK_NEXT
: id
= WXK_NEXT
; break;
4094 case VK_END
: id
= WXK_END
; break;
4095 case VK_HOME
: id
= WXK_HOME
; break;
4096 case VK_LEFT
: id
= WXK_LEFT
; break;
4097 case VK_UP
: id
= WXK_UP
; break;
4098 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4099 case VK_DOWN
: id
= WXK_DOWN
; break;
4100 case VK_SELECT
: id
= WXK_SELECT
; break;
4101 case VK_PRINT
: id
= WXK_PRINT
; break;
4102 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4103 case VK_INSERT
: id
= WXK_INSERT
; break;
4104 case VK_DELETE
: id
= WXK_DELETE
; break;
4105 case VK_HELP
: id
= WXK_HELP
; break;
4106 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4107 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4108 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4109 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4110 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4111 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4112 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4113 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4114 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4115 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4116 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4117 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4118 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4119 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4120 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4121 case VK_F1
: id
= WXK_F1
; break;
4122 case VK_F2
: id
= WXK_F2
; break;
4123 case VK_F3
: id
= WXK_F3
; break;
4124 case VK_F4
: id
= WXK_F4
; break;
4125 case VK_F5
: id
= WXK_F5
; break;
4126 case VK_F6
: id
= WXK_F6
; break;
4127 case VK_F7
: id
= WXK_F7
; break;
4128 case VK_F8
: id
= WXK_F8
; break;
4129 case VK_F9
: id
= WXK_F9
; break;
4130 case VK_F10
: id
= WXK_F10
; break;
4131 case VK_F11
: id
= WXK_F11
; break;
4132 case VK_F12
: id
= WXK_F12
; break;
4133 case VK_F13
: id
= WXK_F13
; break;
4134 case VK_F14
: id
= WXK_F14
; break;
4135 case VK_F15
: id
= WXK_F15
; break;
4136 case VK_F16
: id
= WXK_F16
; break;
4137 case VK_F17
: id
= WXK_F17
; break;
4138 case VK_F18
: id
= WXK_F18
; break;
4139 case VK_F19
: id
= WXK_F19
; break;
4140 case VK_F20
: id
= WXK_F20
; break;
4141 case VK_F21
: id
= WXK_F21
; break;
4142 case VK_F22
: id
= WXK_F22
; break;
4143 case VK_F23
: id
= WXK_F23
; break;
4144 case VK_F24
: id
= WXK_F24
; break;
4145 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4146 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4154 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4160 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4161 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4162 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4163 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4164 case WXK_MENU
: keySym
= VK_MENU
; break;
4165 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4166 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4167 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4168 case WXK_END
: keySym
= VK_END
; break;
4169 case WXK_HOME
: keySym
= VK_HOME
; break;
4170 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4171 case WXK_UP
: keySym
= VK_UP
; break;
4172 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4173 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4174 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4175 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4176 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4177 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4178 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4179 case WXK_HELP
: keySym
= VK_HELP
; break;
4180 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4181 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4182 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4183 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4184 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4185 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4186 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4187 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4188 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4189 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4190 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4191 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4192 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4193 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4194 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4195 case WXK_F1
: keySym
= VK_F1
; break;
4196 case WXK_F2
: keySym
= VK_F2
; break;
4197 case WXK_F3
: keySym
= VK_F3
; break;
4198 case WXK_F4
: keySym
= VK_F4
; break;
4199 case WXK_F5
: keySym
= VK_F5
; break;
4200 case WXK_F6
: keySym
= VK_F6
; break;
4201 case WXK_F7
: keySym
= VK_F7
; break;
4202 case WXK_F8
: keySym
= VK_F8
; break;
4203 case WXK_F9
: keySym
= VK_F9
; break;
4204 case WXK_F10
: keySym
= VK_F10
; break;
4205 case WXK_F11
: keySym
= VK_F11
; break;
4206 case WXK_F12
: keySym
= VK_F12
; break;
4207 case WXK_F13
: keySym
= VK_F13
; break;
4208 case WXK_F14
: keySym
= VK_F14
; break;
4209 case WXK_F15
: keySym
= VK_F15
; break;
4210 case WXK_F16
: keySym
= VK_F16
; break;
4211 case WXK_F17
: keySym
= VK_F17
; break;
4212 case WXK_F18
: keySym
= VK_F18
; break;
4213 case WXK_F19
: keySym
= VK_F19
; break;
4214 case WXK_F20
: keySym
= VK_F20
; break;
4215 case WXK_F21
: keySym
= VK_F21
; break;
4216 case WXK_F22
: keySym
= VK_F22
; break;
4217 case WXK_F23
: keySym
= VK_F23
; break;
4218 case WXK_F24
: keySym
= VK_F24
; break;
4219 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4220 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4231 wxWindow
*wxGetActiveWindow()
4233 HWND hWnd
= GetActiveWindow();
4236 return wxFindWinFromHandle((WXHWND
) hWnd
);
4241 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4243 HWND hwnd
= (HWND
)hWnd
;
4245 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4246 // by code in msw/radiobox.cpp), for all the others we just search up the
4248 wxWindow
*win
= (wxWindow
*)NULL
;
4251 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4254 // all these hacks only work under Win32 anyhow
4258 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4259 // wxWindow class which overrides WM_GETDLGCODE processing to
4260 // do it as well, win would be already non NULL
4261 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4263 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4265 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4266 #endif // wxUSE_RADIOBOX
4268 // spin control text buddy window should be mapped to spin ctrl
4269 // itself so try it too
4270 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4273 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4275 #endif // wxUSE_SPINCTRL
4281 while ( hwnd
&& !win
)
4283 // this is a really ugly hack needed to avoid mistakenly returning the
4284 // parent frame wxWindow for the find/replace modeless dialog HWND -
4285 // this, in turn, is needed to call IsDialogMessage() from
4286 // wxApp::ProcessMessage() as for this we must return NULL from here
4288 // FIXME: this is clearly not the best way to do it but I think we'll
4289 // need to change HWND <-> wxWindow code more heavily than I can
4290 // do it now to fix it
4291 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4293 // it's a dialog box, don't go upwards
4297 hwnd
= ::GetParent(hwnd
);
4298 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4304 #ifndef __WXMICROWIN__
4306 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4307 // in active frames and dialogs, regardless of where the focus is.
4308 static HHOOK wxTheKeyboardHook
= 0;
4309 static FARPROC wxTheKeyboardHookProc
= 0;
4310 int APIENTRY _EXPORT
4311 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4313 void wxSetKeyboardHook(bool doIt
)
4317 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4318 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4320 #if defined(__WIN32__) && !defined(__TWIN32__)
4321 GetCurrentThreadId()
4322 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4330 UnhookWindowsHookEx(wxTheKeyboardHook
);
4332 // avoids warning about statement with no effect (FreeProcInstance
4333 // doesn't do anything under Win32)
4334 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4335 FreeProcInstance(wxTheKeyboardHookProc
);
4340 int APIENTRY _EXPORT
4341 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4343 DWORD hiWord
= HIWORD(lParam
);
4344 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4346 int id
= wxCharCodeMSWToWX(wParam
);
4349 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4350 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4351 event
.m_altDown
= TRUE
;
4353 event
.m_eventObject
= NULL
;
4354 event
.m_keyCode
= id
;
4355 event
.m_shiftDown
= wxIsShiftDown();
4356 event
.m_controlDown
= wxIsCtrlDown();
4357 event
.SetTimestamp(s_currentMsg
.time
);
4359 wxWindow
*win
= wxGetActiveWindow();
4360 wxEvtHandler
*handler
;
4363 handler
= win
->GetEventHandler();
4364 event
.SetId(win
->GetId());
4372 if ( handler
&& handler
->ProcessEvent(event
) )
4380 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4383 #endif // !__WXMICROWIN__
4386 const char *wxGetMessageName(int message
)
4390 case 0x0000: return "WM_NULL";
4391 case 0x0001: return "WM_CREATE";
4392 case 0x0002: return "WM_DESTROY";
4393 case 0x0003: return "WM_MOVE";
4394 case 0x0005: return "WM_SIZE";
4395 case 0x0006: return "WM_ACTIVATE";
4396 case 0x0007: return "WM_SETFOCUS";
4397 case 0x0008: return "WM_KILLFOCUS";
4398 case 0x000A: return "WM_ENABLE";
4399 case 0x000B: return "WM_SETREDRAW";
4400 case 0x000C: return "WM_SETTEXT";
4401 case 0x000D: return "WM_GETTEXT";
4402 case 0x000E: return "WM_GETTEXTLENGTH";
4403 case 0x000F: return "WM_PAINT";
4404 case 0x0010: return "WM_CLOSE";
4405 case 0x0011: return "WM_QUERYENDSESSION";
4406 case 0x0012: return "WM_QUIT";
4407 case 0x0013: return "WM_QUERYOPEN";
4408 case 0x0014: return "WM_ERASEBKGND";
4409 case 0x0015: return "WM_SYSCOLORCHANGE";
4410 case 0x0016: return "WM_ENDSESSION";
4411 case 0x0017: return "WM_SYSTEMERROR";
4412 case 0x0018: return "WM_SHOWWINDOW";
4413 case 0x0019: return "WM_CTLCOLOR";
4414 case 0x001A: return "WM_WININICHANGE";
4415 case 0x001B: return "WM_DEVMODECHANGE";
4416 case 0x001C: return "WM_ACTIVATEAPP";
4417 case 0x001D: return "WM_FONTCHANGE";
4418 case 0x001E: return "WM_TIMECHANGE";
4419 case 0x001F: return "WM_CANCELMODE";
4420 case 0x0020: return "WM_SETCURSOR";
4421 case 0x0021: return "WM_MOUSEACTIVATE";
4422 case 0x0022: return "WM_CHILDACTIVATE";
4423 case 0x0023: return "WM_QUEUESYNC";
4424 case 0x0024: return "WM_GETMINMAXINFO";
4425 case 0x0026: return "WM_PAINTICON";
4426 case 0x0027: return "WM_ICONERASEBKGND";
4427 case 0x0028: return "WM_NEXTDLGCTL";
4428 case 0x002A: return "WM_SPOOLERSTATUS";
4429 case 0x002B: return "WM_DRAWITEM";
4430 case 0x002C: return "WM_MEASUREITEM";
4431 case 0x002D: return "WM_DELETEITEM";
4432 case 0x002E: return "WM_VKEYTOITEM";
4433 case 0x002F: return "WM_CHARTOITEM";
4434 case 0x0030: return "WM_SETFONT";
4435 case 0x0031: return "WM_GETFONT";
4436 case 0x0037: return "WM_QUERYDRAGICON";
4437 case 0x0039: return "WM_COMPAREITEM";
4438 case 0x0041: return "WM_COMPACTING";
4439 case 0x0044: return "WM_COMMNOTIFY";
4440 case 0x0046: return "WM_WINDOWPOSCHANGING";
4441 case 0x0047: return "WM_WINDOWPOSCHANGED";
4442 case 0x0048: return "WM_POWER";
4445 case 0x004A: return "WM_COPYDATA";
4446 case 0x004B: return "WM_CANCELJOURNAL";
4447 case 0x004E: return "WM_NOTIFY";
4448 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4449 case 0x0051: return "WM_INPUTLANGCHANGE";
4450 case 0x0052: return "WM_TCARD";
4451 case 0x0053: return "WM_HELP";
4452 case 0x0054: return "WM_USERCHANGED";
4453 case 0x0055: return "WM_NOTIFYFORMAT";
4454 case 0x007B: return "WM_CONTEXTMENU";
4455 case 0x007C: return "WM_STYLECHANGING";
4456 case 0x007D: return "WM_STYLECHANGED";
4457 case 0x007E: return "WM_DISPLAYCHANGE";
4458 case 0x007F: return "WM_GETICON";
4459 case 0x0080: return "WM_SETICON";
4462 case 0x0081: return "WM_NCCREATE";
4463 case 0x0082: return "WM_NCDESTROY";
4464 case 0x0083: return "WM_NCCALCSIZE";
4465 case 0x0084: return "WM_NCHITTEST";
4466 case 0x0085: return "WM_NCPAINT";
4467 case 0x0086: return "WM_NCACTIVATE";
4468 case 0x0087: return "WM_GETDLGCODE";
4469 case 0x00A0: return "WM_NCMOUSEMOVE";
4470 case 0x00A1: return "WM_NCLBUTTONDOWN";
4471 case 0x00A2: return "WM_NCLBUTTONUP";
4472 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4473 case 0x00A4: return "WM_NCRBUTTONDOWN";
4474 case 0x00A5: return "WM_NCRBUTTONUP";
4475 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4476 case 0x00A7: return "WM_NCMBUTTONDOWN";
4477 case 0x00A8: return "WM_NCMBUTTONUP";
4478 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4479 case 0x0100: return "WM_KEYDOWN";
4480 case 0x0101: return "WM_KEYUP";
4481 case 0x0102: return "WM_CHAR";
4482 case 0x0103: return "WM_DEADCHAR";
4483 case 0x0104: return "WM_SYSKEYDOWN";
4484 case 0x0105: return "WM_SYSKEYUP";
4485 case 0x0106: return "WM_SYSCHAR";
4486 case 0x0107: return "WM_SYSDEADCHAR";
4487 case 0x0108: return "WM_KEYLAST";
4490 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4491 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4492 case 0x010F: return "WM_IME_COMPOSITION";
4495 case 0x0110: return "WM_INITDIALOG";
4496 case 0x0111: return "WM_COMMAND";
4497 case 0x0112: return "WM_SYSCOMMAND";
4498 case 0x0113: return "WM_TIMER";
4499 case 0x0114: return "WM_HSCROLL";
4500 case 0x0115: return "WM_VSCROLL";
4501 case 0x0116: return "WM_INITMENU";
4502 case 0x0117: return "WM_INITMENUPOPUP";
4503 case 0x011F: return "WM_MENUSELECT";
4504 case 0x0120: return "WM_MENUCHAR";
4505 case 0x0121: return "WM_ENTERIDLE";
4506 case 0x0200: return "WM_MOUSEMOVE";
4507 case 0x0201: return "WM_LBUTTONDOWN";
4508 case 0x0202: return "WM_LBUTTONUP";
4509 case 0x0203: return "WM_LBUTTONDBLCLK";
4510 case 0x0204: return "WM_RBUTTONDOWN";
4511 case 0x0205: return "WM_RBUTTONUP";
4512 case 0x0206: return "WM_RBUTTONDBLCLK";
4513 case 0x0207: return "WM_MBUTTONDOWN";
4514 case 0x0208: return "WM_MBUTTONUP";
4515 case 0x0209: return "WM_MBUTTONDBLCLK";
4516 case 0x020A: return "WM_MOUSEWHEEL";
4517 case 0x0210: return "WM_PARENTNOTIFY";
4518 case 0x0211: return "WM_ENTERMENULOOP";
4519 case 0x0212: return "WM_EXITMENULOOP";
4522 case 0x0213: return "WM_NEXTMENU";
4523 case 0x0214: return "WM_SIZING";
4524 case 0x0215: return "WM_CAPTURECHANGED";
4525 case 0x0216: return "WM_MOVING";
4526 case 0x0218: return "WM_POWERBROADCAST";
4527 case 0x0219: return "WM_DEVICECHANGE";
4530 case 0x0220: return "WM_MDICREATE";
4531 case 0x0221: return "WM_MDIDESTROY";
4532 case 0x0222: return "WM_MDIACTIVATE";
4533 case 0x0223: return "WM_MDIRESTORE";
4534 case 0x0224: return "WM_MDINEXT";
4535 case 0x0225: return "WM_MDIMAXIMIZE";
4536 case 0x0226: return "WM_MDITILE";
4537 case 0x0227: return "WM_MDICASCADE";
4538 case 0x0228: return "WM_MDIICONARRANGE";
4539 case 0x0229: return "WM_MDIGETACTIVE";
4540 case 0x0230: return "WM_MDISETMENU";
4541 case 0x0233: return "WM_DROPFILES";
4544 case 0x0281: return "WM_IME_SETCONTEXT";
4545 case 0x0282: return "WM_IME_NOTIFY";
4546 case 0x0283: return "WM_IME_CONTROL";
4547 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4548 case 0x0285: return "WM_IME_SELECT";
4549 case 0x0286: return "WM_IME_CHAR";
4550 case 0x0290: return "WM_IME_KEYDOWN";
4551 case 0x0291: return "WM_IME_KEYUP";
4554 case 0x0300: return "WM_CUT";
4555 case 0x0301: return "WM_COPY";
4556 case 0x0302: return "WM_PASTE";
4557 case 0x0303: return "WM_CLEAR";
4558 case 0x0304: return "WM_UNDO";
4559 case 0x0305: return "WM_RENDERFORMAT";
4560 case 0x0306: return "WM_RENDERALLFORMATS";
4561 case 0x0307: return "WM_DESTROYCLIPBOARD";
4562 case 0x0308: return "WM_DRAWCLIPBOARD";
4563 case 0x0309: return "WM_PAINTCLIPBOARD";
4564 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4565 case 0x030B: return "WM_SIZECLIPBOARD";
4566 case 0x030C: return "WM_ASKCBFORMATNAME";
4567 case 0x030D: return "WM_CHANGECBCHAIN";
4568 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4569 case 0x030F: return "WM_QUERYNEWPALETTE";
4570 case 0x0310: return "WM_PALETTEISCHANGING";
4571 case 0x0311: return "WM_PALETTECHANGED";
4574 // common controls messages - although they're not strictly speaking
4575 // standard, it's nice to decode them nevertheless
4578 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4579 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4580 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4581 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4582 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4583 case 0x1000 + 5: return "LVM_GETITEMA";
4584 case 0x1000 + 75: return "LVM_GETITEMW";
4585 case 0x1000 + 6: return "LVM_SETITEMA";
4586 case 0x1000 + 76: return "LVM_SETITEMW";
4587 case 0x1000 + 7: return "LVM_INSERTITEMA";
4588 case 0x1000 + 77: return "LVM_INSERTITEMW";
4589 case 0x1000 + 8: return "LVM_DELETEITEM";
4590 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4591 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4592 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4593 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4594 case 0x1000 + 13: return "LVM_FINDITEMA";
4595 case 0x1000 + 83: return "LVM_FINDITEMW";
4596 case 0x1000 + 14: return "LVM_GETITEMRECT";
4597 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4598 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4599 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4600 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4601 case 0x1000 + 18: return "LVM_HITTEST";
4602 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4603 case 0x1000 + 20: return "LVM_SCROLL";
4604 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4605 case 0x1000 + 22: return "LVM_ARRANGE";
4606 case 0x1000 + 23: return "LVM_EDITLABELA";
4607 case 0x1000 + 118: return "LVM_EDITLABELW";
4608 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4609 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4610 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4611 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4612 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4613 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4614 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4615 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4616 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4617 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4618 case 0x1000 + 31: return "LVM_GETHEADER";
4619 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4620 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4621 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4622 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4623 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4624 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4625 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4626 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4627 case 0x1000 + 41: return "LVM_GETORIGIN";
4628 case 0x1000 + 42: return "LVM_UPDATE";
4629 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4630 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4631 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4632 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4633 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4634 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4635 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4636 case 0x1000 + 48: return "LVM_SORTITEMS";
4637 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4638 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4639 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4640 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4641 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4642 case 0x1000 + 53: return "LVM_SETICONSPACING";
4643 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4644 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4645 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4646 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4647 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4648 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4649 case 0x1000 + 60: return "LVM_SETHOTITEM";
4650 case 0x1000 + 61: return "LVM_GETHOTITEM";
4651 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4652 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4653 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4654 case 0x1000 + 65: return "LVM_SETWORKAREA";
4657 case 0x1100 + 0: return "TVM_INSERTITEMA";
4658 case 0x1100 + 50: return "TVM_INSERTITEMW";
4659 case 0x1100 + 1: return "TVM_DELETEITEM";
4660 case 0x1100 + 2: return "TVM_EXPAND";
4661 case 0x1100 + 4: return "TVM_GETITEMRECT";
4662 case 0x1100 + 5: return "TVM_GETCOUNT";
4663 case 0x1100 + 6: return "TVM_GETINDENT";
4664 case 0x1100 + 7: return "TVM_SETINDENT";
4665 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4666 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4667 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4668 case 0x1100 + 11: return "TVM_SELECTITEM";
4669 case 0x1100 + 12: return "TVM_GETITEMA";
4670 case 0x1100 + 62: return "TVM_GETITEMW";
4671 case 0x1100 + 13: return "TVM_SETITEMA";
4672 case 0x1100 + 63: return "TVM_SETITEMW";
4673 case 0x1100 + 14: return "TVM_EDITLABELA";
4674 case 0x1100 + 65: return "TVM_EDITLABELW";
4675 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4676 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4677 case 0x1100 + 17: return "TVM_HITTEST";
4678 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4679 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4680 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4681 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4682 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4683 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4684 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4685 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4686 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4689 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4690 case 0x1200 + 1: return "HDM_INSERTITEMA";
4691 case 0x1200 + 10: return "HDM_INSERTITEMW";
4692 case 0x1200 + 2: return "HDM_DELETEITEM";
4693 case 0x1200 + 3: return "HDM_GETITEMA";
4694 case 0x1200 + 11: return "HDM_GETITEMW";
4695 case 0x1200 + 4: return "HDM_SETITEMA";
4696 case 0x1200 + 12: return "HDM_SETITEMW";
4697 case 0x1200 + 5: return "HDM_LAYOUT";
4698 case 0x1200 + 6: return "HDM_HITTEST";
4699 case 0x1200 + 7: return "HDM_GETITEMRECT";
4700 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4701 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4702 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4703 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4704 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4705 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4706 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4709 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4710 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4711 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4712 case 0x1300 + 5: return "TCM_GETITEMA";
4713 case 0x1300 + 60: return "TCM_GETITEMW";
4714 case 0x1300 + 6: return "TCM_SETITEMA";
4715 case 0x1300 + 61: return "TCM_SETITEMW";
4716 case 0x1300 + 7: return "TCM_INSERTITEMA";
4717 case 0x1300 + 62: return "TCM_INSERTITEMW";
4718 case 0x1300 + 8: return "TCM_DELETEITEM";
4719 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4720 case 0x1300 + 10: return "TCM_GETITEMRECT";
4721 case 0x1300 + 11: return "TCM_GETCURSEL";
4722 case 0x1300 + 12: return "TCM_SETCURSEL";
4723 case 0x1300 + 13: return "TCM_HITTEST";
4724 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4725 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4726 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4727 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4728 case 0x1300 + 43: return "TCM_SETPADDING";
4729 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4730 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4731 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4732 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4733 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4734 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4735 case 0x1300 + 50: return "TCM_DESELECTALL";
4738 case WM_USER
+1: return "TB_ENABLEBUTTON";
4739 case WM_USER
+2: return "TB_CHECKBUTTON";
4740 case WM_USER
+3: return "TB_PRESSBUTTON";
4741 case WM_USER
+4: return "TB_HIDEBUTTON";
4742 case WM_USER
+5: return "TB_INDETERMINATE";
4743 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4744 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4745 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4746 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4747 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4748 case WM_USER
+17: return "TB_SETSTATE";
4749 case WM_USER
+18: return "TB_GETSTATE";
4750 case WM_USER
+19: return "TB_ADDBITMAP";
4751 case WM_USER
+20: return "TB_ADDBUTTONS";
4752 case WM_USER
+21: return "TB_INSERTBUTTON";
4753 case WM_USER
+22: return "TB_DELETEBUTTON";
4754 case WM_USER
+23: return "TB_GETBUTTON";
4755 case WM_USER
+24: return "TB_BUTTONCOUNT";
4756 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4757 case WM_USER
+26: return "TB_SAVERESTOREA";
4758 case WM_USER
+76: return "TB_SAVERESTOREW";
4759 case WM_USER
+27: return "TB_CUSTOMIZE";
4760 case WM_USER
+28: return "TB_ADDSTRINGA";
4761 case WM_USER
+77: return "TB_ADDSTRINGW";
4762 case WM_USER
+29: return "TB_GETITEMRECT";
4763 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4764 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4765 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4766 case WM_USER
+33: return "TB_AUTOSIZE";
4767 case WM_USER
+35: return "TB_GETTOOLTIPS";
4768 case WM_USER
+36: return "TB_SETTOOLTIPS";
4769 case WM_USER
+37: return "TB_SETPARENT";
4770 case WM_USER
+39: return "TB_SETROWS";
4771 case WM_USER
+40: return "TB_GETROWS";
4772 case WM_USER
+42: return "TB_SETCMDID";
4773 case WM_USER
+43: return "TB_CHANGEBITMAP";
4774 case WM_USER
+44: return "TB_GETBITMAP";
4775 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4776 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4777 case WM_USER
+46: return "TB_REPLACEBITMAP";
4778 case WM_USER
+47: return "TB_SETINDENT";
4779 case WM_USER
+48: return "TB_SETIMAGELIST";
4780 case WM_USER
+49: return "TB_GETIMAGELIST";
4781 case WM_USER
+50: return "TB_LOADIMAGES";
4782 case WM_USER
+51: return "TB_GETRECT";
4783 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4784 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4785 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4786 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4787 case WM_USER
+56: return "TB_SETSTYLE";
4788 case WM_USER
+57: return "TB_GETSTYLE";
4789 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4790 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4791 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4792 case WM_USER
+61: return "TB_GETTEXTROWS";
4793 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4798 static char s_szBuf
[128];
4799 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4803 #endif //__WXDEBUG__
4805 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4806 int *x
, int *y
, WPARAM
*flags
)
4808 // construct the key mask
4809 WPARAM
& fwKeys
= *flags
;
4811 fwKeys
= MK_RBUTTON
;
4812 if ( wxIsCtrlDown() )
4813 fwKeys
|= MK_CONTROL
;
4814 if ( wxIsShiftDown() )
4817 // simulate right mouse button click
4818 DWORD dwPos
= ::GetMessagePos();
4819 *x
= GET_X_LPARAM(dwPos
);
4820 *y
= GET_Y_LPARAM(dwPos
);
4822 win
->ScreenToClient(x
, y
);
4825 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4829 HWND hwnd
= GetHwndOf(win
);
4830 HDC hdc
= ::GetDC(hwnd
);
4832 #if !wxDIALOG_UNIT_COMPATIBILITY
4833 // and select the current font into it
4834 HFONT hfont
= GetHfontOf(win
->GetFont());
4837 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4841 // finally retrieve the text metrics from it
4842 GetTextMetrics(hdc
, &tm
);
4844 #if !wxDIALOG_UNIT_COMPATIBILITY
4848 (void)::SelectObject(hdc
, hfont
);
4852 ::ReleaseDC(hwnd
, hdc
);
4857 // Find the wxWindow at the current mouse position, returning the mouse
4859 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4861 return wxFindWindowAtPoint(wxGetMousePosition());
4864 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4869 HWND hWndHit
= ::WindowFromPoint(pt2
);
4871 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4872 HWND hWnd
= hWndHit
;
4874 // Try to find a window with a wxWindow associated with it
4875 while (!win
&& (hWnd
!= 0))
4877 hWnd
= ::GetParent(hWnd
);
4878 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
4883 // Get the current mouse position.
4884 wxPoint
wxGetMousePosition()
4887 GetCursorPos( & pt
);
4888 return wxPoint(pt
.x
, pt
.y
);