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 HWND hWnd
= GetHwnd();
829 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
831 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
833 #if defined(__WIN95__)
835 info
.cbSize
= sizeof(SCROLLINFO
);
839 info
.fMask
= SIF_POS
;
841 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
843 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
844 #endif // __WIN95__/!__WIN95__
847 // New function that will replace some of the above.
848 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
849 int range
, bool refresh
)
851 #if defined(__WIN95__)
852 int oldRange
= range
- thumbVisible
;
854 int range1
= oldRange
;
856 // Try to adjust the range to cope with page size > 1
857 // - a Windows API quirk
858 int pageSize
= thumbVisible
;
859 if ( pageSize
> 1 && range
> 0)
861 range1
+= (pageSize
- 1);
867 if ( orient
== wxHORIZONTAL
) {
873 info
.cbSize
= sizeof(SCROLLINFO
);
874 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
878 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
880 HWND hWnd
= GetHwnd();
882 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
885 if ( orient
== wxHORIZONTAL
)
890 HWND hWnd
= GetHwnd();
893 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
894 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
897 if ( orient
== wxHORIZONTAL
) {
898 m_xThumbSize
= thumbVisible
;
900 m_yThumbSize
= thumbVisible
;
904 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
909 rect
.left
= prect
->x
;
911 rect
.right
= prect
->x
+ prect
->width
;
912 rect
.bottom
= prect
->y
+ prect
->height
;
915 ::ScrollWindow(GetHwnd(), dx
, dy
, prect
? &rect
: NULL
, NULL
);
918 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
920 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
923 for ( int n
= 0; n
< count
; n
++ )
925 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
927 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
930 // don't bother to continue, we're already at top/bottom
937 return pos
!= posStart
;
940 bool wxWindowMSW::ScrollLines(int lines
)
942 bool down
= lines
> 0;
944 return ScrollVertically(GetHwnd(),
945 down
? SB_LINEDOWN
: SB_LINEUP
,
946 down
? lines
: -lines
);
949 bool wxWindowMSW::ScrollPages(int pages
)
951 bool down
= pages
> 0;
953 return ScrollVertically(GetHwnd(),
954 down
? SB_PAGEDOWN
: SB_PAGEUP
,
955 down
? pages
: -pages
);
958 // ---------------------------------------------------------------------------
960 // ---------------------------------------------------------------------------
962 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
964 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
966 HWND hwnd
= (HWND
)hWnd
;
967 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
969 wxAssociateWinWithHandle(hwnd
, this);
971 m_oldWndProc
= (WXFARPROC
)::GetWindowLong(hwnd
, GWL_WNDPROC
);
973 // we don't need to subclass the window of our own class (in the Windows
974 // sense of the word)
975 if ( (WXFARPROC
) m_oldWndProc
!= (WXFARPROC
) wxWndProc
)
977 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
981 // don't bother restoring it neither
986 void wxWindowMSW::UnsubclassWin()
988 wxRemoveHandleAssociation(this);
990 // Restore old Window proc
991 HWND hwnd
= GetHwnd();
996 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
1000 FARPROC wndProc
= (FARPROC
)::GetWindowLong(hwnd
, GWL_WNDPROC
);
1001 if ( wndProc
!= (FARPROC
) m_oldWndProc
)
1003 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1006 m_oldWndProc
= NULL
;
1011 // Make a Windows extended style from the given wxWindows window style
1012 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1014 WXDWORD exStyle
= 0;
1015 if ( style
& wxTRANSPARENT_WINDOW
)
1016 exStyle
|= WS_EX_TRANSPARENT
;
1018 if ( !eliminateBorders
)
1020 if ( style
& wxSUNKEN_BORDER
)
1021 exStyle
|= WS_EX_CLIENTEDGE
;
1022 if ( style
& wxDOUBLE_BORDER
)
1023 exStyle
|= WS_EX_DLGMODALFRAME
;
1024 #if defined(__WIN95__)
1025 if ( style
& wxRAISED_BORDER
)
1026 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1027 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1028 if ( style
& wxSTATIC_BORDER
)
1029 exStyle
|= WS_EX_STATICEDGE
;
1036 // Determines whether native 3D effects or CTL3D should be used,
1037 // applying a default border style if required, and returning an extended
1038 // style to pass to CreateWindowEx.
1039 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1042 // If matches certain criteria, then assume no 3D effects
1043 // unless specifically requested (dealt with in MakeExtendedStyle)
1046 || !IsKindOf(CLASSINFO(wxControl
))
1047 #endif // wxUSE_CONTROLS
1048 || (m_windowStyle
& wxNO_BORDER
) )
1051 return MakeExtendedStyle(m_windowStyle
);
1054 // Determine whether we should be using 3D effects or not.
1055 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1057 // 1) App can specify global 3D effects
1058 *want3D
= wxTheApp
->GetAuto3D();
1060 // 2) If the parent is being drawn with user colours, or simple border specified,
1061 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1062 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1065 // 3) Control can override this global setting by defining
1066 // a border style, e.g. wxSUNKEN_BORDER
1067 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1070 // 4) If it's a special border, CTL3D can't cope so we want a native border
1071 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1072 (m_windowStyle
& wxSTATIC_BORDER
) )
1075 nativeBorder
= TRUE
;
1078 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1079 // effects from extended style
1082 nativeBorder
= FALSE
;
1085 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1087 // If we want 3D, but haven't specified a border here,
1088 // apply the default border style specified.
1089 // TODO what about non-Win95 WIN32? Does it have borders?
1090 #if defined(__WIN95__) && !wxUSE_CTL3D
1091 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1092 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1093 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1099 #if WXWIN_COMPATIBILITY
1100 // If nothing defined for this, try the parent.
1101 // E.g. we may be a button loaded from a resource, with no callback function
1103 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1105 if ( GetEventHandler()->ProcessEvent(event
) )
1108 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1110 #endif // WXWIN_COMPATIBILITY_2
1112 #if WXWIN_COMPATIBILITY
1113 wxObject
* wxWindowMSW::GetChild(int number
) const
1115 // Return a pointer to the Nth object in the Panel
1116 wxNode
*node
= GetChildren().First();
1119 node
= node
->Next();
1122 wxObject
*obj
= (wxObject
*)node
->Data();
1128 #endif // WXWIN_COMPATIBILITY
1130 // Setup background and foreground colours correctly
1131 void wxWindowMSW::SetupColours()
1134 SetBackgroundColour(GetParent()->GetBackgroundColour());
1137 bool wxWindowMSW::IsMouseInWindow() const
1139 // get the mouse position
1141 ::GetCursorPos(&pt
);
1143 // find the window which currently has the cursor and go up the window
1144 // chain until we find this window - or exhaust it
1145 HWND hwnd
= ::WindowFromPoint(pt
);
1146 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1147 hwnd
= ::GetParent(hwnd
);
1149 return hwnd
!= NULL
;
1152 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1154 // Check if we need to send a LEAVE event
1155 if ( m_mouseInWindow
)
1157 if ( !IsMouseInWindow() )
1159 // Generate a LEAVE event
1160 m_mouseInWindow
= FALSE
;
1162 // Unfortunately the mouse button and keyboard state may have
1163 // changed by the time the OnIdle function is called, so 'state'
1164 // may be meaningless.
1166 if ( wxIsShiftDown() )
1168 if ( wxIsCtrlDown() )
1169 state
|= MK_CONTROL
;
1170 if ( GetKeyState( VK_LBUTTON
) )
1171 state
|= MK_LBUTTON
;
1172 if ( GetKeyState( VK_MBUTTON
) )
1173 state
|= MK_MBUTTON
;
1174 if ( GetKeyState( VK_RBUTTON
) )
1175 state
|= MK_RBUTTON
;
1178 if ( !::GetCursorPos(&pt
) )
1180 wxLogLastError(_T("GetCursorPos"));
1183 // we need to have client coordinates here for symmetry with
1184 // wxEVT_ENTER_WINDOW
1185 RECT rect
= wxGetWindowRect(GetHwnd());
1189 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1190 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1192 (void)GetEventHandler()->ProcessEvent(event2
);
1199 // Set this window to be the child of 'parent'.
1200 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1202 if ( !wxWindowBase::Reparent(parent
) )
1205 HWND hWndChild
= GetHwnd();
1206 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1208 ::SetParent(hWndChild
, hWndParent
);
1213 void wxWindowMSW::Clear()
1215 wxClientDC
dc((wxWindow
*)this);
1216 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1217 dc
.SetBackground(brush
);
1221 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1223 #ifndef __WXMICROWIN__
1224 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1228 void wxWindowMSW::Freeze()
1230 SendSetRedraw(GetHwnd(), FALSE
);
1233 void wxWindowMSW::Thaw()
1235 SendSetRedraw(GetHwnd(), TRUE
);
1237 // we need to refresh everything or otherwise he invalidated area is not
1242 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1244 HWND hWnd
= GetHwnd();
1250 mswRect
.left
= rect
->x
;
1251 mswRect
.top
= rect
->y
;
1252 mswRect
.right
= rect
->x
+ rect
->width
;
1253 mswRect
.bottom
= rect
->y
+ rect
->height
;
1255 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1258 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1262 void wxWindowMSW::Update()
1264 if ( !::UpdateWindow(GetHwnd()) )
1266 wxLogLastError(_T("UpdateWindow"));
1269 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1270 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1271 // handler needs to be really drawn right now
1276 // ---------------------------------------------------------------------------
1278 // ---------------------------------------------------------------------------
1280 #if wxUSE_DRAG_AND_DROP
1282 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1284 if ( m_dropTarget
!= 0 ) {
1285 m_dropTarget
->Revoke(m_hWnd
);
1286 delete m_dropTarget
;
1289 m_dropTarget
= pDropTarget
;
1290 if ( m_dropTarget
!= 0 )
1291 m_dropTarget
->Register(m_hWnd
);
1294 #endif // wxUSE_DRAG_AND_DROP
1296 // old style file-manager drag&drop support: we retain the old-style
1297 // DragAcceptFiles in parallel with SetDropTarget.
1298 void wxWindowMSW::DragAcceptFiles(bool accept
)
1300 HWND hWnd
= GetHwnd();
1302 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1305 // ----------------------------------------------------------------------------
1307 // ----------------------------------------------------------------------------
1311 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1313 wxWindowBase::DoSetToolTip(tooltip
);
1316 m_tooltip
->SetWindow(this);
1319 #endif // wxUSE_TOOLTIPS
1321 // ---------------------------------------------------------------------------
1322 // moving and resizing
1323 // ---------------------------------------------------------------------------
1326 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1328 RECT rect
= wxGetWindowRect(GetHwnd());
1331 *x
= rect
.right
- rect
.left
;
1333 *y
= rect
.bottom
- rect
.top
;
1336 // Get size *available for subwindows* i.e. excluding menu bar etc.
1337 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1339 RECT rect
= wxGetClientRect(GetHwnd());
1347 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1349 RECT rect
= wxGetWindowRect(GetHwnd());
1352 point
.x
= rect
.left
;
1355 // we do the adjustments with respect to the parent only for the "real"
1356 // children, not for the dialogs/frames
1357 if ( !IsTopLevel() )
1359 HWND hParentWnd
= 0;
1360 wxWindow
*parent
= GetParent();
1362 hParentWnd
= GetWinHwnd(parent
);
1364 // Since we now have the absolute screen coords, if there's a parent we
1365 // must subtract its top left corner
1368 ::ScreenToClient(hParentWnd
, &point
);
1373 // We may be faking the client origin. So a window that's really at (0,
1374 // 30) may appear (to wxWin apps) to be at (0, 0).
1375 wxPoint
pt(parent
->GetClientAreaOrigin());
1387 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1395 ::ScreenToClient(GetHwnd(), &pt
);
1403 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1411 ::ClientToScreen(GetHwnd(), &pt
);
1419 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1421 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1423 wxLogLastError(wxT("MoveWindow"));
1427 // set the size of the window: if the dimensions are positive, just use them,
1428 // but if any of them is equal to -1, it means that we must find the value for
1429 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1430 // which case -1 is a valid value for x and y)
1432 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1433 // the width/height to best suit our contents, otherwise we reuse the current
1435 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1437 // get the current size and position...
1438 int currentX
, currentY
;
1439 GetPosition(¤tX
, ¤tY
);
1440 int currentW
,currentH
;
1441 GetSize(¤tW
, ¤tH
);
1443 // ... and don't do anything (avoiding flicker) if it's already ok
1444 if ( x
== currentX
&& y
== currentY
&&
1445 width
== currentW
&& height
== currentH
)
1450 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1452 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1455 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1457 wxSize
size(-1, -1);
1460 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1462 size
= DoGetBestSize();
1467 // just take the current one
1474 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1478 size
= DoGetBestSize();
1480 //else: already called DoGetBestSize() above
1486 // just take the current one
1491 DoMoveWindow(x
, y
, width
, height
);
1494 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1496 // setting the client size is less obvious than it it could have been
1497 // because in the result of changing the total size the window scrollbar
1498 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1499 // will not be correct as the difference between the total and client size
1500 // changes - so we keep changing it until we get it right
1502 // normally this loop shouldn't take more than 2 iterations (usually 1 but
1503 // if scrollbars [dis]appear as the result of the first call, then 2) but
1504 // just to be on the safe side we check for it instead of making it an
1505 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1506 for ( int i
= 0; i
< 3; i
++ )
1509 ::GetClientRect(GetHwnd(), &rectClient
);
1511 // if the size is already ok, stop here (rectClient.left = top = 0)
1512 if ( rectClient
.right
== width
&& rectClient
.bottom
== height
)
1519 // how did it happen? maybe OnSize() handler does something really
1520 // strange in this class?
1521 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1526 int widthClient
= width
,
1527 heightClient
= height
;
1529 // Find the difference between the entire window (title bar and all)
1530 // and the client area; add this to the new client size to move the
1533 ::GetWindowRect(GetHwnd(), &rectWin
);
1535 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1536 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1539 point
.x
= rectWin
.left
;
1540 point
.y
= rectWin
.top
;
1542 // MoveWindow positions the child windows relative to the parent, so
1543 // adjust if necessary
1544 if ( !IsTopLevel() )
1546 wxWindow
*parent
= GetParent();
1549 ::ScreenToClient(GetHwndOf(parent
), &point
);
1553 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1557 // For implementation purposes - sometimes decorations make the client area
1559 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1561 return wxPoint(0, 0);
1564 // ---------------------------------------------------------------------------
1566 // ---------------------------------------------------------------------------
1568 int wxWindowMSW::GetCharHeight() const
1570 return wxGetTextMetrics(this).tmHeight
;
1573 int wxWindowMSW::GetCharWidth() const
1575 // +1 is needed because Windows apparently adds it when calculating the
1576 // dialog units size in pixels
1577 #if wxDIALOG_UNIT_COMPATIBILITY
1578 return wxGetTextMetrics(this).tmAveCharWidth
;
1580 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1584 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1586 int *descent
, int *externalLeading
,
1587 const wxFont
*theFont
) const
1589 const wxFont
*fontToUse
= theFont
;
1591 fontToUse
= &m_font
;
1593 HWND hWnd
= GetHwnd();
1594 HDC dc
= ::GetDC(hWnd
);
1598 if ( fontToUse
&& fontToUse
->Ok() )
1600 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1602 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1607 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1608 GetTextMetrics(dc
, &tm
);
1610 if ( fontToUse
&& fnt
&& hfontOld
)
1611 SelectObject(dc
, hfontOld
);
1613 ReleaseDC(hWnd
, dc
);
1620 *descent
= tm
.tmDescent
;
1621 if ( externalLeading
)
1622 *externalLeading
= tm
.tmExternalLeading
;
1625 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1626 // ---------------------------------------------------------------------------
1627 // Caret manipulation
1628 // ---------------------------------------------------------------------------
1630 void wxWindowMSW::CreateCaret(int w
, int h
)
1632 SetCaret(new wxCaret(this, w
, h
));
1635 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1637 wxFAIL_MSG("not implemented");
1640 void wxWindowMSW::ShowCaret(bool show
)
1642 wxCHECK_RET( m_caret
, "no caret to show" );
1644 m_caret
->Show(show
);
1647 void wxWindowMSW::DestroyCaret()
1652 void wxWindowMSW::SetCaretPos(int x
, int y
)
1654 wxCHECK_RET( m_caret
, "no caret to move" );
1656 m_caret
->Move(x
, y
);
1659 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1661 wxCHECK_RET( m_caret
, "no caret to get position of" );
1663 m_caret
->GetPosition(x
, y
);
1665 #endif // wxUSE_CARET
1667 // ---------------------------------------------------------------------------
1669 // ---------------------------------------------------------------------------
1671 #if wxUSE_MENUS_NATIVE
1673 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1674 // immediately, without waiting for the next event loop iteration
1676 // NB: this function should probably be made public later as it can almost
1677 // surely replace wxYield() elsewhere as well
1678 static void wxYieldForCommandsOnly()
1680 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1681 // want to process it here)
1683 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1684 && msg
.message
!= WM_QUIT
)
1686 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1690 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1692 menu
->SetInvokingWindow(this);
1695 HWND hWnd
= GetHwnd();
1696 HMENU hMenu
= GetHmenuOf(menu
);
1700 ::ClientToScreen(hWnd
, &point
);
1701 wxCurrentPopupMenu
= menu
;
1702 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1704 // we need to do it righ now as otherwise the events are never going to be
1705 // sent to wxCurrentPopupMenu from HandleCommand()
1707 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1708 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1709 // destroyed as soon as we return (it can be a local variable in the caller
1710 // for example) and so we do need to process the event immediately
1711 wxYieldForCommandsOnly();
1713 wxCurrentPopupMenu
= NULL
;
1715 menu
->SetInvokingWindow(NULL
);
1720 #endif // wxUSE_MENUS_NATIVE
1722 // ===========================================================================
1723 // pre/post message processing
1724 // ===========================================================================
1726 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1729 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1731 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1734 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1736 // wxUniversal implements tab traversal itself
1737 #ifndef __WXUNIVERSAL__
1738 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1740 // intercept dialog navigation keys
1741 MSG
*msg
= (MSG
*)pMsg
;
1743 // here we try to do all the job which ::IsDialogMessage() usually does
1746 bool bProcess
= TRUE
;
1747 if ( msg
->message
!= WM_KEYDOWN
)
1750 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1755 bool bCtrlDown
= wxIsCtrlDown();
1756 bool bShiftDown
= wxIsShiftDown();
1758 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1759 // don't process it if it's the case (except for Ctrl-Tab/Enter
1760 // combinations which are always processed)
1764 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1767 bool bForward
= TRUE
,
1768 bWindowChange
= FALSE
;
1770 switch ( msg
->wParam
)
1773 // assume that nobody wants Shift-TAB for himself - if we
1774 // don't do it there is no easy way for a control to grab
1775 // TABs but still let Shift-TAB work as navugation key
1776 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1780 // Ctrl-Tab cycles thru notebook pages
1781 bWindowChange
= bCtrlDown
;
1782 bForward
= !bShiftDown
;
1788 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1796 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1802 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1804 // control wants to process Enter itself, don't
1805 // call IsDialogMessage() which would interpret
1809 else if ( lDlgCode
& DLGC_BUTTON
)
1811 // let IsDialogMessage() handle this for all
1812 // buttons except the owner-drawn ones which it
1813 // just seems to ignore
1814 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1815 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1817 // emulate the button click
1818 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1820 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1825 // FIXME: this should be handled by
1826 // wxNavigationKeyEvent handler and not here!!
1830 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1832 if ( btn
&& btn
->IsEnabled() )
1834 // if we do have a default button, do press it
1835 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1839 else // no default button
1840 #endif // wxUSE_BUTTON
1842 // no special function for enter and don't even
1843 // let IsDialogMessage() have it: it seems to
1844 // do something really strange with it
1857 wxNavigationKeyEvent event
;
1858 event
.SetDirection(bForward
);
1859 event
.SetWindowChange(bWindowChange
);
1860 event
.SetEventObject(this);
1862 if ( GetEventHandler()->ProcessEvent(event
) )
1869 // let ::IsDialogMessage() do almost everything and handle just the
1870 // things it doesn't here: Ctrl-TAB for switching notebook pages
1871 if ( msg
->message
== WM_KEYDOWN
)
1873 // don't process system keys here
1874 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1876 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1878 // find the first notebook parent and change its page
1879 wxWindow
*win
= this;
1880 wxNotebook
*nbook
= NULL
;
1881 while ( win
&& !nbook
)
1883 nbook
= wxDynamicCast(win
, wxNotebook
);
1884 win
= win
->GetParent();
1889 bool forward
= !wxIsShiftDown();
1891 nbook
->AdvanceSelection(forward
);
1898 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1900 // IsDialogMessage() did something...
1904 #endif // __WXUNIVERSAL__
1909 // relay mouse move events to the tooltip control
1910 MSG
*msg
= (MSG
*)pMsg
;
1911 if ( msg
->message
== WM_MOUSEMOVE
)
1912 m_tooltip
->RelayEvent(pMsg
);
1914 #endif // wxUSE_TOOLTIPS
1919 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1921 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1922 return m_acceleratorTable
.Translate(this, pMsg
);
1925 #endif // wxUSE_ACCEL
1928 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1930 // preprocess all messages by default
1934 // ---------------------------------------------------------------------------
1935 // message params unpackers (different for Win16 and Win32)
1936 // ---------------------------------------------------------------------------
1940 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1941 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1943 *id
= LOWORD(wParam
);
1944 *hwnd
= (WXHWND
)lParam
;
1945 *cmd
= HIWORD(wParam
);
1948 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1949 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1951 *state
= LOWORD(wParam
);
1952 *minimized
= HIWORD(wParam
);
1953 *hwnd
= (WXHWND
)lParam
;
1956 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1957 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1959 *code
= LOWORD(wParam
);
1960 *pos
= HIWORD(wParam
);
1961 *hwnd
= (WXHWND
)lParam
;
1964 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
1965 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
1967 #ifndef __WXMICROWIN__
1968 *nCtlColor
= CTLCOLOR_BTN
;
1969 *hwnd
= (WXHWND
)lParam
;
1970 *hdc
= (WXHDC
)wParam
;
1974 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
1975 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
1977 *item
= (WXWORD
)wParam
;
1978 *flags
= HIWORD(wParam
);
1979 *hmenu
= (WXHMENU
)lParam
;
1984 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1985 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
1987 *id
= (WXWORD
)wParam
;
1988 *hwnd
= (WXHWND
)LOWORD(lParam
);
1989 *cmd
= HIWORD(lParam
);
1992 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1993 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1995 *state
= (WXWORD
)wParam
;
1996 *minimized
= LOWORD(lParam
);
1997 *hwnd
= (WXHWND
)HIWORD(lParam
);
2000 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2001 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2003 *code
= (WXWORD
)wParam
;
2004 *pos
= LOWORD(lParam
);
2005 *hwnd
= (WXHWND
)HIWORD(lParam
);
2008 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2009 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2011 *hwnd
= (WXHWND
)LOWORD(lParam
);
2012 *nCtlColor
= (int)HIWORD(lParam
);
2013 *hdc
= (WXHDC
)wParam
;
2016 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2017 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2019 *item
= (WXWORD
)wParam
;
2020 *flags
= LOWORD(lParam
);
2021 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2026 // ---------------------------------------------------------------------------
2027 // Main wxWindows window proc and the window proc for wxWindow
2028 // ---------------------------------------------------------------------------
2030 // Hook for new window just as it's being created, when the window isn't yet
2031 // associated with the handle
2032 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2034 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2035 // window being created and insures that it's always unset back later
2036 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2038 gs_winBeingCreated
= winBeingCreated
;
2041 wxWindowCreationHook::~wxWindowCreationHook()
2043 gs_winBeingCreated
= NULL
;
2047 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2049 // trace all messages - useful for the debugging
2051 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2052 wxGetMessageName(message
), wParam
, lParam
);
2053 #endif // __WXDEBUG__
2055 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2057 // when we get the first message for the HWND we just created, we associate
2058 // it with wxWindow stored in gs_winBeingCreated
2059 if ( !wnd
&& gs_winBeingCreated
)
2061 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2062 wnd
= gs_winBeingCreated
;
2063 gs_winBeingCreated
= NULL
;
2064 wnd
->SetHWND((WXHWND
)hWnd
);
2070 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2072 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2077 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2079 // did we process the message?
2080 bool processed
= FALSE
;
2091 // for most messages we should return 0 when we do process the message
2099 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2102 // return 0 to allow window creation
2103 rc
.result
= mayCreate
? 0 : -1;
2109 // never set processed to TRUE and *always* pass WM_DESTROY to
2110 // DefWindowProc() as Windows may do some internal cleanup when
2111 // processing it and failing to pass the message along may cause
2112 // memory and resource leaks!
2113 (void)HandleDestroy();
2117 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2125 // we're not interested in these messages at all
2128 case SIZE_MINIMIZED
:
2129 // we shouldn't send sizev events for these messages as the
2130 // client size may be negative which breaks existing code
2132 // OTOH we might send another (wxMinimizedEvent?) one or
2133 // add an additional parameter to wxSizeEvent if this is
2134 // useful to anybody
2138 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2139 // fall through nevertheless
2141 case SIZE_MAXIMIZED
:
2143 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2148 #ifndef __WXMICROWIN__
2149 case WM_ACTIVATEAPP
:
2150 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2156 WXWORD state
, minimized
;
2158 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2160 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2165 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2169 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2173 processed
= HandlePaint();
2177 // don't let the DefWindowProc() destroy our window - we'll do it
2178 // ourselves in ~wxWindow
2184 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2188 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2189 GET_Y_LPARAM(lParam
),
2193 #if wxUSE_MOUSEWHEEL
2195 processed
= HandleMouseWheel(wParam
, lParam
);
2199 case WM_LBUTTONDOWN
:
2201 case WM_LBUTTONDBLCLK
:
2202 case WM_RBUTTONDOWN
:
2204 case WM_RBUTTONDBLCLK
:
2205 case WM_MBUTTONDOWN
:
2207 case WM_MBUTTONDBLCLK
:
2210 #ifdef __WXMICROWIN__
2211 // MicroWindows seems to ignore the fact that a window is
2212 // disabled. So catch mouse events and throw them away if
2214 wxWindowMSW
* win
= this;
2217 if (!win
->IsEnabled())
2222 win
= win
->GetParent();
2223 if (win
&& win
->IsTopLevel())
2226 #endif // __WXMICROWIN__
2229 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2231 processed
= HandleMouseEvent(message
,
2232 GET_X_LPARAM(lParam
),
2233 GET_Y_LPARAM(lParam
),
2239 #ifdef __WXMICROWIN__
2240 case WM_NCLBUTTONDOWN
:
2241 case WM_NCLBUTTONUP
:
2242 case WM_NCLBUTTONDBLCLK
:
2243 case WM_NCRBUTTONDOWN
:
2244 case WM_NCRBUTTONUP
:
2245 case WM_NCRBUTTONDBLCLK
:
2247 case WM_NCMBUTTONDOWN
:
2248 case WM_NCMBUTTONUP
:
2249 case WM_NCMBUTTONDBLCLK
:
2252 // MicroWindows seems to ignore the fact that a window
2253 // is disabled. So catch mouse events and throw them away if necessary.
2255 wxWindowMSW
* win
= this;
2258 if (!win
->IsEnabled())
2263 win
= win
->GetParent();
2264 if (win
&& win
->IsTopLevel())
2269 #endif // __WXMICROWIN__
2276 case MM_JOY1BUTTONDOWN
:
2277 case MM_JOY2BUTTONDOWN
:
2278 case MM_JOY1BUTTONUP
:
2279 case MM_JOY2BUTTONUP
:
2280 processed
= HandleJoystickEvent(message
,
2281 GET_X_LPARAM(lParam
),
2282 GET_Y_LPARAM(lParam
),
2285 #endif // __WXMICROWIN__
2288 processed
= HandleSysCommand(wParam
, lParam
);
2295 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2297 processed
= HandleCommand(id
, cmd
, hwnd
);
2303 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2307 // for these messages we must return TRUE if process the message
2310 case WM_MEASUREITEM
:
2312 int idCtrl
= (UINT
)wParam
;
2313 if ( message
== WM_DRAWITEM
)
2315 processed
= MSWOnDrawItem(idCtrl
,
2316 (WXDRAWITEMSTRUCT
*)lParam
);
2320 processed
= MSWOnMeasureItem(idCtrl
,
2321 (WXMEASUREITEMSTRUCT
*)lParam
);
2328 #endif // defined(WM_DRAWITEM)
2333 rc
.result
= m_lDlgCode
;
2336 //else: get the dlg code from the DefWindowProc()
2341 // If this has been processed by an event handler,
2342 // return 0 now (we've handled it).
2343 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2350 // we consider these message "not interesting" to OnChar
2351 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2360 // avoid duplicate messages to OnChar for these ASCII keys: they
2361 // will be translated by TranslateMessage() and received in WM_CHAR
2369 // but set processed to FALSE, not TRUE to still pass them to
2370 // the control's default window proc - otherwise built-in
2371 // keyboard handling won't work
2377 // special case of VK_APPS: treat it the same as right mouse
2378 // click because both usually pop up a context menu
2384 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2385 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2395 processed
= HandleChar((WORD
)wParam
, lParam
);
2402 // special case of VK_APPS: treat it the same as right mouse button
2403 if ( wParam
== VK_APPS
)
2408 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2409 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2414 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2419 case WM_CHAR
: // Always an ASCII character
2420 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2428 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2430 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2436 // CTLCOLOR messages are sent by children to query the parent for their
2437 // colors#ifndef __WXMICROWIN__
2438 #ifndef __WXMICROWIN__
2440 case WM_CTLCOLORMSGBOX
:
2441 case WM_CTLCOLOREDIT
:
2442 case WM_CTLCOLORLISTBOX
:
2443 case WM_CTLCOLORBTN
:
2444 case WM_CTLCOLORDLG
:
2445 case WM_CTLCOLORSCROLLBAR
:
2446 case WM_CTLCOLORSTATIC
:
2454 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2456 processed
= HandleCtlColor(&rc
.hBrush
,
2465 #endif // !__WXMICROWIN__
2467 // the return value for this message is ignored
2468 case WM_SYSCOLORCHANGE
:
2469 processed
= HandleSysColorChange();
2472 case WM_PALETTECHANGED
:
2473 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2476 case WM_QUERYNEWPALETTE
:
2477 processed
= HandleQueryNewPalette();
2481 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2484 // we processed the message, i.e. erased the background
2490 processed
= HandleDropFiles(wParam
);
2494 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2498 // we never set focus from here
2503 case WM_QUERYENDSESSION
:
2504 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2508 processed
= HandleEndSession(wParam
!= 0, lParam
);
2511 case WM_GETMINMAXINFO
:
2512 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2516 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2517 LOWORD(lParam
), // hit test
2518 HIWORD(lParam
)); // mouse msg
2522 // returning TRUE stops the DefWindowProc() from further
2523 // processing this message - exactly what we need because we've
2524 // just set the cursor.
2529 #if defined(__WIN32__) && defined(WM_HELP)
2532 HELPINFO
* info
= (HELPINFO
*) lParam
;
2533 // Don't yet process menu help events, just windows
2534 if (info
->iContextType
== HELPINFO_WINDOW
)
2536 wxWindowMSW
* subjectOfHelp
= this;
2537 bool eventProcessed
= FALSE
;
2538 while (subjectOfHelp
&& !eventProcessed
)
2540 wxHelpEvent
helpEvent(wxEVT_HELP
,
2541 subjectOfHelp
->GetId(),
2542 wxPoint(info
->MousePos
.x
,
2543 info
->MousePos
.y
) );
2544 helpEvent
.SetEventObject(this);
2546 GetEventHandler()->ProcessEvent(helpEvent
);
2548 // Go up the window hierarchy until the event is
2550 subjectOfHelp
= subjectOfHelp
->GetParent();
2553 processed
= eventProcessed
;
2555 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2557 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2558 helpEvent
.SetEventObject(this);
2559 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2562 //else: processed is already FALSE
2566 case WM_CONTEXTMENU
:
2568 // we don't convert from screen to client coordinates as
2569 // the event may be handled by a parent window
2570 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2572 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2573 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2578 // unfortunately this doesn't really work as then window which
2579 // doesn't accept focus doesn't get any mouse events neither which
2580 // means it can't get any input at all
2581 #if 0 //def __WXUNIVERSAL__
2583 // we shouldn't allow the windows which don't want to get focus to
2585 if ( !AcceptsFocus() )
2587 rc
.result
= HTTRANSPARENT
;
2591 #endif // __WXUNIVERSAL__
2597 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2598 wxGetMessageName(message
));
2599 #endif // __WXDEBUG__
2600 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2606 // ----------------------------------------------------------------------------
2607 // wxWindow <-> HWND map
2608 // ----------------------------------------------------------------------------
2610 wxWinHashTable
*wxWinHandleHash
= NULL
;
2612 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2614 return wxWinHandleHash
->Get((long)hWnd
);
2617 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2619 // adding NULL hWnd is (first) surely a result of an error and
2620 // (secondly) breaks menu command processing
2621 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2622 wxT("attempt to add a NULL hWnd to window list ignored") );
2624 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2626 if ( oldWin
&& (oldWin
!= win
) )
2628 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2629 hWnd
, win
->GetClassInfo()->GetClassName());
2632 #endif // __WXDEBUG__
2635 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2639 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2641 wxWinHandleHash
->Delete((long)win
->GetHWND());
2644 // ----------------------------------------------------------------------------
2645 // various MSW speciic class dependent functions
2646 // ----------------------------------------------------------------------------
2648 // Default destroyer - override if you destroy it in some other way
2649 // (e.g. with MDI child windows)
2650 void wxWindowMSW::MSWDestroyWindow()
2654 void wxWindowMSW::MSWDetachWindowMenu()
2656 #ifndef __WXUNIVERSAL__
2660 HMENU hMenu
= (HMENU
)m_hMenu
;
2662 int N
= ::GetMenuItemCount(hMenu
);
2663 for ( int i
= 0; i
< N
; i
++ )
2665 if ( !::GetMenuString(hMenu
, i
, buf
, WXSIZEOF(buf
), MF_BYPOSITION
) )
2667 wxLogLastError(wxT("GetMenuString"));
2672 if ( wxStrcmp(buf
, _("&Window")) == 0 )
2674 if ( !::RemoveMenu(hMenu
, i
, MF_BYPOSITION
) )
2676 wxLogLastError(wxT("RemoveMenu"));
2683 #endif // __WXUNIVERSAL__
2686 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2689 int& w
, int& h
) const
2691 bool nonDefault
= FALSE
;
2695 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2696 // just as well set it to CW_USEDEFAULT as well
2703 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2709 NB: there used to be some code here which set the initial size of the
2710 window to the client size of the parent if no explicit size was
2711 specified. This was wrong because wxWindows programs often assume
2712 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2713 it. To see why, you should understand that Windows sends WM_SIZE from
2714 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2715 from some base class ctor and so this WM_SIZE is not processed in the
2716 real class' OnSize() (because it's not fully constructed yet and the
2717 event goes to some base class OnSize() instead). So the WM_SIZE we
2718 rely on is the one sent when the parent frame resizes its children
2719 but here is the problem: if the child already has just the right
2720 size, nothing will happen as both wxWindows and Windows check for
2721 this and ignore any attempts to change the window size to the size it
2722 already has - so no WM_SIZE would be sent.
2726 // as abobe, h is not used at all in this case anyhow
2733 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2741 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2742 const wxChar
*title
,
2746 WXDWORD extendedStyle
)
2748 // choose the position/size for the new window
2750 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2752 // find the correct parent HWND
2753 wxWindow
*parent
= GetParent();
2754 bool isChild
= (style
& WS_CHILD
) != 0;
2756 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2758 // popup windows should have desktop as parent because they shouldn't
2759 // be limited to the parents client area as child windows usually are
2760 hParent
= ::GetDesktopWindow();
2764 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2766 // this is either a normal child window or a top level window with
2767 // wxFRAME_TOOL_WINDOW style (see below)
2768 hParent
= GetHwndOf(parent
);
2772 // this is either a window for which no parent was specified (not
2773 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2774 // style: we should use NULL parent HWND for it or it would be
2775 // always on top of its parent which is not what we usually want
2776 // (in fact, we only want it for frames with the special
2777 // wxFRAME_TOOL_WINDOW as above)
2783 // controlId is menu handle for the top level windows, so set it to 0
2784 // unless we're creating a child window
2788 controlId
= GetId();
2790 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2792 style
|= WS_CLIPSIBLINGS
;
2800 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2801 // which is the same but without CS_[HV]REDRAW class styles so using it
2802 // ensures that the window is not fully repainted on each resize
2803 wxString
className(wclass
);
2804 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2806 className
+= wxT("NR");
2809 // do create the window
2810 wxWindowCreationHook
hook(this);
2812 m_hWnd
= (WXHWND
)::CreateWindowEx
2816 title
? title
: wxT(""),
2822 NULL
// no extra data
2827 wxLogSysError(_("Can't create window of class %s"), wclass
);
2832 SubclassWin(m_hWnd
);
2834 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2839 // ===========================================================================
2840 // MSW message handlers
2841 // ===========================================================================
2843 // ---------------------------------------------------------------------------
2845 // ---------------------------------------------------------------------------
2848 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2849 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2851 #ifndef __WXMICROWIN__
2852 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2853 HWND hWnd
= hdr
->hwndFrom
;
2854 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2856 // is this one of our windows?
2859 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2862 // try all our children
2863 wxWindowList::Node
*node
= GetChildren().GetFirst();
2866 wxWindow
*child
= node
->GetData();
2867 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2872 node
= node
->GetNext();
2875 // finally try this window too (catches toolbar case)
2876 return MSWOnNotify(idCtrl
, lParam
, result
);
2877 #else // __WXMICROWIN__
2882 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2884 WXLPARAM
* WXUNUSED(result
))
2887 NMHDR
* hdr
= (NMHDR
*)lParam
;
2888 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2890 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2891 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2896 #endif // wxUSE_TOOLTIPS
2902 // ---------------------------------------------------------------------------
2903 // end session messages
2904 // ---------------------------------------------------------------------------
2906 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2908 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2909 event
.SetEventObject(wxTheApp
);
2910 event
.SetCanVeto(TRUE
);
2911 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2913 bool rc
= wxTheApp
->ProcessEvent(event
);
2917 // we may end only if the app didn't veto session closing (double
2919 *mayEnd
= !event
.GetVeto();
2925 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2927 // do nothing if the session isn't ending
2932 if ( (this != wxTheApp
->GetTopWindow()) )
2935 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2936 event
.SetEventObject(wxTheApp
);
2937 event
.SetCanVeto(FALSE
);
2938 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2940 return wxTheApp
->ProcessEvent(event
);
2943 // ---------------------------------------------------------------------------
2944 // window creation/destruction
2945 // ---------------------------------------------------------------------------
2947 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2949 // TODO: should generate this event from WM_NCCREATE
2950 wxWindowCreateEvent
event((wxWindow
*)this);
2951 (void)GetEventHandler()->ProcessEvent(event
);
2958 bool wxWindowMSW::HandleDestroy()
2960 wxWindowDestroyEvent
event((wxWindow
*)this);
2961 (void)GetEventHandler()->ProcessEvent(event
);
2963 // delete our drop target if we've got one
2964 #if wxUSE_DRAG_AND_DROP
2965 if ( m_dropTarget
!= NULL
)
2967 m_dropTarget
->Revoke(m_hWnd
);
2969 delete m_dropTarget
;
2970 m_dropTarget
= NULL
;
2972 #endif // wxUSE_DRAG_AND_DROP
2974 // WM_DESTROY handled
2978 // ---------------------------------------------------------------------------
2980 // ---------------------------------------------------------------------------
2982 bool wxWindowMSW::HandleActivate(int state
,
2983 bool WXUNUSED(minimized
),
2984 WXHWND
WXUNUSED(activate
))
2986 wxActivateEvent
event(wxEVT_ACTIVATE
,
2987 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
2989 event
.SetEventObject(this);
2991 return GetEventHandler()->ProcessEvent(event
);
2994 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
2996 // notify the parent keeping track of focus for the kbd navigation
2997 // purposes that we got it
2998 wxChildFocusEvent
eventFocus((wxWindow
*)this);
2999 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3005 m_caret
->OnSetFocus();
3007 #endif // wxUSE_CARET
3010 // If it's a wxTextCtrl don't send the event as it will be done
3011 // after the control gets to process it from EN_FOCUS handler
3012 if ( wxDynamicCastThis(wxTextCtrl
) )
3016 #endif // wxUSE_TEXTCTRL
3018 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3019 event
.SetEventObject(this);
3021 // wxFindWinFromHandle() may return NULL, it is ok
3022 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3024 return GetEventHandler()->ProcessEvent(event
);
3027 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3033 m_caret
->OnKillFocus();
3035 #endif // wxUSE_CARET
3038 // If it's a wxTextCtrl don't send the event as it will be done
3039 // after the control gets to process it.
3040 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3047 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3048 event
.SetEventObject(this);
3050 // wxFindWinFromHandle() may return NULL, it is ok
3051 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3053 return GetEventHandler()->ProcessEvent(event
);
3056 // ---------------------------------------------------------------------------
3058 // ---------------------------------------------------------------------------
3060 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3062 wxShowEvent
event(GetId(), show
);
3063 event
.m_eventObject
= this;
3065 return GetEventHandler()->ProcessEvent(event
);
3068 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3070 wxInitDialogEvent
event(GetId());
3071 event
.m_eventObject
= this;
3073 return GetEventHandler()->ProcessEvent(event
);
3076 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3078 #ifndef __WXMICROWIN__
3079 HDROP hFilesInfo
= (HDROP
) wParam
;
3081 // Get the total number of files dropped
3082 UINT gwFilesDropped
= ::DragQueryFile
3090 wxString
*files
= new wxString
[gwFilesDropped
];
3091 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3093 // first get the needed buffer length (+1 for terminating NUL)
3094 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3096 // and now get the file name
3097 ::DragQueryFile(hFilesInfo
, wIndex
,
3098 files
[wIndex
].GetWriteBuf(len
), len
);
3100 files
[wIndex
].UngetWriteBuf();
3102 DragFinish (hFilesInfo
);
3104 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3105 event
.m_eventObject
= this;
3108 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3109 event
.m_pos
.x
= dropPoint
.x
;
3110 event
.m_pos
.y
= dropPoint
.y
;
3112 return GetEventHandler()->ProcessEvent(event
);
3113 #else // __WXMICROWIN__
3118 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3120 int WXUNUSED(mouseMsg
))
3122 #ifndef __WXMICROWIN__
3123 // the logic is as follows:
3124 // -1. don't set cursor for non client area, including but not limited to
3125 // the title bar, scrollbars, &c
3126 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3127 // 1. if we have the cursor set it unless wxIsBusy()
3128 // 2. if we're a top level window, set some cursor anyhow
3129 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3131 if ( nHitTest
!= HTCLIENT
)
3136 HCURSOR hcursor
= 0;
3138 // first ask the user code - it may wish to set the cursor in some very
3139 // specific way (for example, depending on the current position)
3142 if ( !::GetCursorPos(&pt
) )
3144 wxLogLastError(wxT("GetCursorPos"));
3147 // In WIN16 it doesn't return a value.
3148 ::GetCursorPos(&pt
);
3153 ScreenToClient(&x
, &y
);
3154 wxSetCursorEvent
event(x
, y
);
3156 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3157 if ( processedEvtSetCursor
&& event
.HasCursor() )
3159 hcursor
= GetHcursorOf(event
.GetCursor());
3164 bool isBusy
= wxIsBusy();
3166 // the test for processedEvtSetCursor is here to prevent using m_cursor
3167 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3168 // it - this is a way to say that our cursor shouldn't be used for this
3170 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3172 hcursor
= GetHcursorOf(m_cursor
);
3179 hcursor
= wxGetCurrentBusyCursor();
3181 else if ( !hcursor
)
3183 const wxCursor
*cursor
= wxGetGlobalCursor();
3184 if ( cursor
&& cursor
->Ok() )
3186 hcursor
= GetHcursorOf(*cursor
);
3194 ::SetCursor(hcursor
);
3196 // cursor set, stop here
3199 #endif // __WXMICROWIN__
3201 // pass up the window chain
3205 // ---------------------------------------------------------------------------
3206 // owner drawn stuff
3207 // ---------------------------------------------------------------------------
3209 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3211 #if wxUSE_OWNER_DRAWN
3213 #if wxUSE_MENUS_NATIVE
3214 // is it a menu item?
3215 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3216 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3218 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3220 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3222 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3223 // the DC from being released
3224 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3225 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3226 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3227 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3229 return pMenuItem
->OnDrawItem
3233 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3234 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3237 #endif // wxUSE_MENUS_NATIVE
3240 wxWindow
*item
= FindItem(id
);
3241 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3243 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3245 #endif // wxUSE_CONTROLS
3247 #endif // USE_OWNER_DRAWN
3252 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3254 #if wxUSE_OWNER_DRAWN
3255 // is it a menu item?
3256 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3257 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3259 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3261 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3263 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3264 &pMeasureStruct
->itemHeight
);
3267 wxWindow
*item
= FindItem(id
);
3268 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3270 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3272 #endif // owner-drawn menus
3276 // ---------------------------------------------------------------------------
3277 // colours and palettes
3278 // ---------------------------------------------------------------------------
3280 bool wxWindowMSW::HandleSysColorChange()
3282 wxSysColourChangedEvent event
;
3283 event
.SetEventObject(this);
3285 (void)GetEventHandler()->ProcessEvent(event
);
3287 // always let the system carry on the default processing to allow the
3288 // native controls to react to the colours update
3292 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3300 #ifndef __WXMICROWIN__
3301 WXHBRUSH hBrush
= 0;
3303 if ( nCtlColor
== CTLCOLOR_DLG
)
3305 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3310 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3312 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3314 #endif // wxUSE_CONTROLS
3320 #else // __WXMICROWIN__
3325 // Define for each class of dialog and control
3326 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3327 WXHWND
WXUNUSED(hWnd
),
3328 WXUINT
WXUNUSED(nCtlColor
),
3329 WXUINT
WXUNUSED(message
),
3330 WXWPARAM
WXUNUSED(wParam
),
3331 WXLPARAM
WXUNUSED(lParam
))
3336 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3338 wxPaletteChangedEvent
event(GetId());
3339 event
.SetEventObject(this);
3340 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3342 return GetEventHandler()->ProcessEvent(event
);
3345 bool wxWindowMSW::HandleQueryNewPalette()
3347 wxQueryNewPaletteEvent
event(GetId());
3348 event
.SetEventObject(this);
3350 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3353 // Responds to colour changes: passes event on to children.
3354 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3356 wxWindowList::Node
*node
= GetChildren().GetFirst();
3359 // Only propagate to non-top-level windows because Windows already
3360 // sends this event to all top-level ones
3361 wxWindow
*win
= node
->GetData();
3362 if ( !win
->IsTopLevel() )
3364 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3365 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3366 // the standard controls
3367 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3370 node
= node
->GetNext();
3373 // update the colours we use if they were not set explicitly by the user:
3374 // this must be done or OnCtlColor() would continue to use the old colours
3377 m_foregroundColour
= wxSystemSettings::
3378 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3383 m_backgroundColour
= wxSystemSettings::
3384 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3388 // ---------------------------------------------------------------------------
3390 // ---------------------------------------------------------------------------
3392 bool wxWindowMSW::HandlePaint()
3395 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3397 wxLogLastError(wxT("CreateRectRgn"));
3398 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3399 wxLogLastError(wxT("GetUpdateRgn"));
3401 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3404 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3406 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3407 updateRect
.right
- updateRect
.left
,
3408 updateRect
.bottom
- updateRect
.top
);
3411 wxPaintEvent
event(m_windowId
);
3412 event
.SetEventObject(this);
3414 bool processed
= GetEventHandler()->ProcessEvent(event
);
3416 // note that we must generate NC event after the normal one as otherwise
3417 // BeginPaint() will happily overwrite our decorations with the background
3419 wxNcPaintEvent
eventNc(m_windowId
);
3420 eventNc
.SetEventObject(this);
3421 GetEventHandler()->ProcessEvent(eventNc
);
3426 // Can be called from an application's OnPaint handler
3427 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3429 #ifdef __WXUNIVERSAL__
3432 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3435 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3440 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3442 // Prevents flicker when dragging
3443 if ( ::IsIconic(GetHwnd()) )
3449 dc
.SetWindow((wxWindow
*)this);
3452 wxEraseEvent
event(m_windowId
, &dc
);
3453 event
.SetEventObject(this);
3454 bool rc
= GetEventHandler()->ProcessEvent(event
);
3458 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3459 dc
.SelectOldObjects(hdc
);
3464 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3467 ::GetClientRect(GetHwnd(), &rect
);
3469 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3470 m_backgroundColour
.Green(),
3471 m_backgroundColour
.Blue());
3472 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3474 wxLogLastError(wxT("CreateSolidBrush"));
3476 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3478 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3480 ::FillRect(hdc
, &rect
, hBrush
);
3481 ::DeleteObject(hBrush
);
3482 ::SetMapMode(hdc
, mode
);
3485 // ---------------------------------------------------------------------------
3486 // moving and resizing
3487 // ---------------------------------------------------------------------------
3489 bool wxWindowMSW::HandleMinimize()
3491 wxIconizeEvent
event(m_windowId
);
3492 event
.SetEventObject(this);
3494 return GetEventHandler()->ProcessEvent(event
);
3497 bool wxWindowMSW::HandleMaximize()
3499 wxMaximizeEvent
event(m_windowId
);
3500 event
.SetEventObject(this);
3502 return GetEventHandler()->ProcessEvent(event
);
3505 bool wxWindowMSW::HandleMove(int x
, int y
)
3507 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3508 event
.SetEventObject(this);
3510 return GetEventHandler()->ProcessEvent(event
);
3513 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3515 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3516 event
.SetEventObject(this);
3518 return GetEventHandler()->ProcessEvent(event
);
3521 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3523 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3527 if ( m_minWidth
!= -1 )
3529 info
->ptMinTrackSize
.x
= m_minWidth
;
3533 if ( m_minHeight
!= -1 )
3535 info
->ptMinTrackSize
.y
= m_minHeight
;
3539 if ( m_maxWidth
!= -1 )
3541 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3545 if ( m_maxHeight
!= -1 )
3547 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3554 // ---------------------------------------------------------------------------
3556 // ---------------------------------------------------------------------------
3558 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3560 #if wxUSE_MENUS_NATIVE
3561 if ( !cmd
&& wxCurrentPopupMenu
)
3563 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3564 wxCurrentPopupMenu
= NULL
;
3566 return popupMenu
->MSWCommand(cmd
, id
);
3568 #endif // wxUSE_MENUS_NATIVE
3570 wxWindow
*win
= NULL
;
3572 // first try to find it from HWND - this works even with the broken
3573 // programs using the same ids for different controls
3576 win
= wxFindWinFromHandle(control
);
3582 // must cast to a signed type before comparing with other ids!
3583 win
= FindItem((signed short)id
);
3588 return win
->MSWCommand(cmd
, id
);
3591 // the messages sent from the in-place edit control used by the treectrl
3592 // for label editing have id == 0, but they should _not_ be treated as menu
3593 // messages (they are EN_XXX ones, in fact) so don't translate anything
3594 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3597 // If no child window, it may be an accelerator, e.g. for a popup menu
3600 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3601 event
.SetEventObject(this);
3605 return GetEventHandler()->ProcessEvent(event
);
3607 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3610 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3611 // notifications to its parent which we want to reflect back to
3613 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3614 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3617 #endif // wxUSE_SPINCTRL
3622 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3624 // 4 bits are reserved
3625 switch ( wParam
& 0xFFFFFFF0 )
3628 return HandleMaximize();
3631 return HandleMinimize();
3637 // ---------------------------------------------------------------------------
3639 // ---------------------------------------------------------------------------
3641 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3645 // our client coords are not quite the same as Windows ones
3646 wxPoint pt
= GetClientAreaOrigin();
3647 event
.m_x
= x
- pt
.x
;
3648 event
.m_y
= y
- pt
.y
;
3650 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3651 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3652 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3653 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3654 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3655 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3657 event
.SetTimestamp(s_currentMsg
.time
);
3658 event
.m_eventObject
= this;
3660 #if wxUSE_MOUSEEVENT_HACK
3663 m_lastMouseEvent
= event
.GetEventType();
3664 #endif // wxUSE_MOUSEEVENT_HACK
3667 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3669 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3670 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3671 // from the message id and take the value in the table to get wxWin event
3673 static const wxEventType eventsMouse
[] =
3687 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3688 InitMouseEvent(event
, x
, y
, flags
);
3690 return GetEventHandler()->ProcessEvent(event
);
3693 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3695 if ( !m_mouseInWindow
)
3697 // it would be wrong to assume that just because we get a mouse move
3698 // event that the mouse is inside the window: although this is usually
3699 // true, it is not if we had captured the mouse, so we need to check
3700 // the mouse coordinates here
3701 if ( !HasCapture() || IsMouseInWindow() )
3703 // Generate an ENTER event
3704 m_mouseInWindow
= TRUE
;
3706 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3707 InitMouseEvent(event
, x
, y
, flags
);
3709 (void)GetEventHandler()->ProcessEvent(event
);
3713 #if wxUSE_MOUSEEVENT_HACK
3714 // Window gets a click down message followed by a mouse move message even
3715 // if position isn't changed! We want to discard the trailing move event
3716 // if x and y are the same.
3717 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3718 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3719 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3720 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3722 m_lastMouseEvent
= wxEVT_MOTION
;
3726 #endif // wxUSE_MOUSEEVENT_HACK
3728 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3732 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3734 #if wxUSE_MOUSEWHEEL
3735 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3736 InitMouseEvent(event
,
3737 GET_X_LPARAM(lParam
),
3738 GET_Y_LPARAM(lParam
),
3740 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3741 event
.m_wheelDelta
= WHEEL_DELTA
;
3744 static int s_linesPerRotation
= -1;
3745 if ( s_linesPerRotation
== -1 )
3747 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3748 &s_linesPerRotation
, 0))
3750 // this is not supposed to happen
3751 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3753 // the default is 3, so use it if SystemParametersInfo() failed
3754 s_linesPerRotation
= 3;
3758 // no SystemParametersInfo() under Win16
3759 static const int s_linesPerRotation
= 3;
3762 event
.m_linesPerAction
= s_linesPerRotation
;
3763 return GetEventHandler()->ProcessEvent(event
);
3774 // ---------------------------------------------------------------------------
3775 // keyboard handling
3776 // ---------------------------------------------------------------------------
3778 // create the key event of the given type for the given key - used by
3779 // HandleChar and HandleKeyDown/Up
3780 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3782 WXLPARAM lParam
) const
3784 wxKeyEvent
event(evType
);
3785 event
.SetId(GetId());
3786 event
.m_shiftDown
= wxIsShiftDown();
3787 event
.m_controlDown
= wxIsCtrlDown();
3788 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3790 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3791 event
.m_keyCode
= id
;
3792 event
.SetTimestamp(s_currentMsg
.time
);
3794 // translate the position to client coords
3798 GetWindowRect(GetHwnd(),&rect
);
3808 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3810 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3812 bool ctrlDown
= FALSE
;
3817 // If 1 -> 26, translate to CTRL plus a letter.
3819 if ( (id
> 0) && (id
< 27) )
3841 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3843 // it's ASCII and will be processed here only when called from
3844 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3850 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3853 event
.m_controlDown
= TRUE
;
3856 if ( GetEventHandler()->ProcessEvent(event
) )
3863 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3865 int id
= wxCharCodeMSWToWX(wParam
);
3869 // normal ASCII char
3873 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3875 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3876 if ( GetEventHandler()->ProcessEvent(event
) )
3885 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3887 int id
= wxCharCodeMSWToWX(wParam
);
3891 // normal ASCII char
3895 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3897 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3898 if ( GetEventHandler()->ProcessEvent(event
) )
3905 // ---------------------------------------------------------------------------
3907 // ---------------------------------------------------------------------------
3909 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3913 if ( flags
& JOY_BUTTON1CHG
)
3914 change
= wxJOY_BUTTON1
;
3915 if ( flags
& JOY_BUTTON2CHG
)
3916 change
= wxJOY_BUTTON2
;
3917 if ( flags
& JOY_BUTTON3CHG
)
3918 change
= wxJOY_BUTTON3
;
3919 if ( flags
& JOY_BUTTON4CHG
)
3920 change
= wxJOY_BUTTON4
;
3923 if ( flags
& JOY_BUTTON1
)
3924 buttons
|= wxJOY_BUTTON1
;
3925 if ( flags
& JOY_BUTTON2
)
3926 buttons
|= wxJOY_BUTTON2
;
3927 if ( flags
& JOY_BUTTON3
)
3928 buttons
|= wxJOY_BUTTON3
;
3929 if ( flags
& JOY_BUTTON4
)
3930 buttons
|= wxJOY_BUTTON4
;
3932 // the event ids aren't consecutive so we can't use table based lookup
3934 wxEventType eventType
;
3939 eventType
= wxEVT_JOY_MOVE
;
3944 eventType
= wxEVT_JOY_MOVE
;
3949 eventType
= wxEVT_JOY_ZMOVE
;
3954 eventType
= wxEVT_JOY_ZMOVE
;
3957 case MM_JOY1BUTTONDOWN
:
3959 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3962 case MM_JOY2BUTTONDOWN
:
3964 eventType
= wxEVT_JOY_BUTTON_DOWN
;
3967 case MM_JOY1BUTTONUP
:
3969 eventType
= wxEVT_JOY_BUTTON_UP
;
3972 case MM_JOY2BUTTONUP
:
3974 eventType
= wxEVT_JOY_BUTTON_UP
;
3978 wxFAIL_MSG(wxT("no such joystick event"));
3983 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
3984 event
.SetPosition(wxPoint(x
, y
));
3985 event
.SetEventObject(this);
3987 return GetEventHandler()->ProcessEvent(event
);
3993 // ---------------------------------------------------------------------------
3995 // ---------------------------------------------------------------------------
3997 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
3998 WXWORD pos
, WXHWND control
)
4002 wxWindow
*child
= wxFindWinFromHandle(control
);
4004 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4007 wxScrollWinEvent event
;
4008 event
.SetPosition(pos
);
4009 event
.SetOrientation(orientation
);
4010 event
.m_eventObject
= this;
4015 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4019 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4023 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4027 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4031 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4035 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4038 case SB_THUMBPOSITION
:
4041 // under Win32, the scrollbar range and position are 32 bit integers,
4042 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4043 // explicitly query the scrollbar for the correct position (this must
4044 // be done only for these two SB_ events as they are the only one
4045 // carrying the scrollbar position)
4047 SCROLLINFO scrollInfo
;
4048 wxZeroMemory(scrollInfo
);
4049 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4050 scrollInfo
.fMask
= SIF_TRACKPOS
;
4052 if ( !::GetScrollInfo(GetHwnd(),
4053 orientation
== wxHORIZONTAL
? SB_HORZ
4057 wxLogLastError(_T("GetScrollInfo"));
4060 event
.SetPosition(scrollInfo
.nTrackPos
);
4064 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4065 ? wxEVT_SCROLLWIN_THUMBRELEASE
4066 : wxEVT_SCROLLWIN_THUMBTRACK
;
4073 return GetEventHandler()->ProcessEvent(event
);
4076 // ===========================================================================
4078 // ===========================================================================
4080 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4083 HDC dc
= ::GetDC((HWND
) wnd
);
4088 // the_font->UseResource();
4089 // the_font->RealizeResource();
4090 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4092 was
= (HFONT
) SelectObject(dc
,fnt
);
4094 GetTextMetrics(dc
, &tm
);
4095 if ( the_font
&& fnt
&& was
)
4097 SelectObject(dc
,was
);
4099 ReleaseDC((HWND
)wnd
, dc
);
4102 *x
= tm
.tmAveCharWidth
;
4104 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4107 // the_font->ReleaseResource();
4110 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4111 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4112 int wxCharCodeMSWToWX(int keySym
)
4117 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4118 case VK_BACK
: id
= WXK_BACK
; break;
4119 case VK_TAB
: id
= WXK_TAB
; break;
4120 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4121 case VK_RETURN
: id
= WXK_RETURN
; break;
4122 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4123 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4124 case VK_MENU
: id
= WXK_MENU
; break;
4125 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4126 case VK_SPACE
: id
= WXK_SPACE
; break;
4127 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4128 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4129 case VK_NEXT
: id
= WXK_NEXT
; break;
4130 case VK_END
: id
= WXK_END
; break;
4131 case VK_HOME
: id
= WXK_HOME
; break;
4132 case VK_LEFT
: id
= WXK_LEFT
; break;
4133 case VK_UP
: id
= WXK_UP
; break;
4134 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4135 case VK_DOWN
: id
= WXK_DOWN
; break;
4136 case VK_SELECT
: id
= WXK_SELECT
; break;
4137 case VK_PRINT
: id
= WXK_PRINT
; break;
4138 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4139 case VK_INSERT
: id
= WXK_INSERT
; break;
4140 case VK_DELETE
: id
= WXK_DELETE
; break;
4141 case VK_HELP
: id
= WXK_HELP
; break;
4142 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4143 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4144 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4145 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4146 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4147 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4148 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4149 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4150 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4151 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4152 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4153 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4154 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4155 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4156 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4157 case VK_F1
: id
= WXK_F1
; break;
4158 case VK_F2
: id
= WXK_F2
; break;
4159 case VK_F3
: id
= WXK_F3
; break;
4160 case VK_F4
: id
= WXK_F4
; break;
4161 case VK_F5
: id
= WXK_F5
; break;
4162 case VK_F6
: id
= WXK_F6
; break;
4163 case VK_F7
: id
= WXK_F7
; break;
4164 case VK_F8
: id
= WXK_F8
; break;
4165 case VK_F9
: id
= WXK_F9
; break;
4166 case VK_F10
: id
= WXK_F10
; break;
4167 case VK_F11
: id
= WXK_F11
; break;
4168 case VK_F12
: id
= WXK_F12
; break;
4169 case VK_F13
: id
= WXK_F13
; break;
4170 case VK_F14
: id
= WXK_F14
; break;
4171 case VK_F15
: id
= WXK_F15
; break;
4172 case VK_F16
: id
= WXK_F16
; break;
4173 case VK_F17
: id
= WXK_F17
; break;
4174 case VK_F18
: id
= WXK_F18
; break;
4175 case VK_F19
: id
= WXK_F19
; break;
4176 case VK_F20
: id
= WXK_F20
; break;
4177 case VK_F21
: id
= WXK_F21
; break;
4178 case VK_F22
: id
= WXK_F22
; break;
4179 case VK_F23
: id
= WXK_F23
; break;
4180 case VK_F24
: id
= WXK_F24
; break;
4181 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4182 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4190 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4196 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4197 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4198 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4199 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4200 case WXK_MENU
: keySym
= VK_MENU
; break;
4201 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4202 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4203 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4204 case WXK_END
: keySym
= VK_END
; break;
4205 case WXK_HOME
: keySym
= VK_HOME
; break;
4206 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4207 case WXK_UP
: keySym
= VK_UP
; break;
4208 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4209 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4210 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4211 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4212 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4213 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4214 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4215 case WXK_HELP
: keySym
= VK_HELP
; break;
4216 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4217 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4218 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4219 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4220 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4221 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4222 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4223 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4224 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4225 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4226 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4227 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4228 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4229 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4230 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4231 case WXK_F1
: keySym
= VK_F1
; break;
4232 case WXK_F2
: keySym
= VK_F2
; break;
4233 case WXK_F3
: keySym
= VK_F3
; break;
4234 case WXK_F4
: keySym
= VK_F4
; break;
4235 case WXK_F5
: keySym
= VK_F5
; break;
4236 case WXK_F6
: keySym
= VK_F6
; break;
4237 case WXK_F7
: keySym
= VK_F7
; break;
4238 case WXK_F8
: keySym
= VK_F8
; break;
4239 case WXK_F9
: keySym
= VK_F9
; break;
4240 case WXK_F10
: keySym
= VK_F10
; break;
4241 case WXK_F11
: keySym
= VK_F11
; break;
4242 case WXK_F12
: keySym
= VK_F12
; break;
4243 case WXK_F13
: keySym
= VK_F13
; break;
4244 case WXK_F14
: keySym
= VK_F14
; break;
4245 case WXK_F15
: keySym
= VK_F15
; break;
4246 case WXK_F16
: keySym
= VK_F16
; break;
4247 case WXK_F17
: keySym
= VK_F17
; break;
4248 case WXK_F18
: keySym
= VK_F18
; break;
4249 case WXK_F19
: keySym
= VK_F19
; break;
4250 case WXK_F20
: keySym
= VK_F20
; break;
4251 case WXK_F21
: keySym
= VK_F21
; break;
4252 case WXK_F22
: keySym
= VK_F22
; break;
4253 case WXK_F23
: keySym
= VK_F23
; break;
4254 case WXK_F24
: keySym
= VK_F24
; break;
4255 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4256 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4267 wxWindow
*wxGetActiveWindow()
4269 HWND hWnd
= GetActiveWindow();
4272 return wxFindWinFromHandle((WXHWND
) hWnd
);
4277 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4279 HWND hwnd
= (HWND
)hWnd
;
4281 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4282 // by code in msw/radiobox.cpp), for all the others we just search up the
4284 wxWindow
*win
= (wxWindow
*)NULL
;
4287 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4290 // all these hacks only work under Win32 anyhow
4294 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4295 // wxWindow class which overrides WM_GETDLGCODE processing to
4296 // do it as well, win would be already non NULL
4297 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4299 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4301 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4302 #endif // wxUSE_RADIOBOX
4304 // spin control text buddy window should be mapped to spin ctrl
4305 // itself so try it too
4306 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4309 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4311 #endif // wxUSE_SPINCTRL
4317 while ( hwnd
&& !win
)
4319 // this is a really ugly hack needed to avoid mistakenly returning the
4320 // parent frame wxWindow for the find/replace modeless dialog HWND -
4321 // this, in turn, is needed to call IsDialogMessage() from
4322 // wxApp::ProcessMessage() as for this we must return NULL from here
4324 // FIXME: this is clearly not the best way to do it but I think we'll
4325 // need to change HWND <-> wxWindow code more heavily than I can
4326 // do it now to fix it
4327 #ifndef __WXMICROWIN__
4328 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4330 // it's a dialog box, don't go upwards
4335 hwnd
= ::GetParent(hwnd
);
4336 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4342 #ifndef __WXMICROWIN__
4344 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4345 // in active frames and dialogs, regardless of where the focus is.
4346 static HHOOK wxTheKeyboardHook
= 0;
4347 static FARPROC wxTheKeyboardHookProc
= 0;
4348 int APIENTRY _EXPORT
4349 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4351 void wxSetKeyboardHook(bool doIt
)
4355 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4356 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4358 #if defined(__WIN32__) && !defined(__TWIN32__)
4359 GetCurrentThreadId()
4360 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4368 UnhookWindowsHookEx(wxTheKeyboardHook
);
4370 // avoids warning about statement with no effect (FreeProcInstance
4371 // doesn't do anything under Win32)
4372 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4373 FreeProcInstance(wxTheKeyboardHookProc
);
4378 int APIENTRY _EXPORT
4379 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4381 DWORD hiWord
= HIWORD(lParam
);
4382 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4384 int id
= wxCharCodeMSWToWX(wParam
);
4387 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4388 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4389 event
.m_altDown
= TRUE
;
4391 event
.m_eventObject
= NULL
;
4392 event
.m_keyCode
= id
;
4393 event
.m_shiftDown
= wxIsShiftDown();
4394 event
.m_controlDown
= wxIsCtrlDown();
4395 event
.SetTimestamp(s_currentMsg
.time
);
4397 wxWindow
*win
= wxGetActiveWindow();
4398 wxEvtHandler
*handler
;
4401 handler
= win
->GetEventHandler();
4402 event
.SetId(win
->GetId());
4410 if ( handler
&& handler
->ProcessEvent(event
) )
4418 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4421 #endif // !__WXMICROWIN__
4424 const char *wxGetMessageName(int message
)
4428 case 0x0000: return "WM_NULL";
4429 case 0x0001: return "WM_CREATE";
4430 case 0x0002: return "WM_DESTROY";
4431 case 0x0003: return "WM_MOVE";
4432 case 0x0005: return "WM_SIZE";
4433 case 0x0006: return "WM_ACTIVATE";
4434 case 0x0007: return "WM_SETFOCUS";
4435 case 0x0008: return "WM_KILLFOCUS";
4436 case 0x000A: return "WM_ENABLE";
4437 case 0x000B: return "WM_SETREDRAW";
4438 case 0x000C: return "WM_SETTEXT";
4439 case 0x000D: return "WM_GETTEXT";
4440 case 0x000E: return "WM_GETTEXTLENGTH";
4441 case 0x000F: return "WM_PAINT";
4442 case 0x0010: return "WM_CLOSE";
4443 case 0x0011: return "WM_QUERYENDSESSION";
4444 case 0x0012: return "WM_QUIT";
4445 case 0x0013: return "WM_QUERYOPEN";
4446 case 0x0014: return "WM_ERASEBKGND";
4447 case 0x0015: return "WM_SYSCOLORCHANGE";
4448 case 0x0016: return "WM_ENDSESSION";
4449 case 0x0017: return "WM_SYSTEMERROR";
4450 case 0x0018: return "WM_SHOWWINDOW";
4451 case 0x0019: return "WM_CTLCOLOR";
4452 case 0x001A: return "WM_WININICHANGE";
4453 case 0x001B: return "WM_DEVMODECHANGE";
4454 case 0x001C: return "WM_ACTIVATEAPP";
4455 case 0x001D: return "WM_FONTCHANGE";
4456 case 0x001E: return "WM_TIMECHANGE";
4457 case 0x001F: return "WM_CANCELMODE";
4458 case 0x0020: return "WM_SETCURSOR";
4459 case 0x0021: return "WM_MOUSEACTIVATE";
4460 case 0x0022: return "WM_CHILDACTIVATE";
4461 case 0x0023: return "WM_QUEUESYNC";
4462 case 0x0024: return "WM_GETMINMAXINFO";
4463 case 0x0026: return "WM_PAINTICON";
4464 case 0x0027: return "WM_ICONERASEBKGND";
4465 case 0x0028: return "WM_NEXTDLGCTL";
4466 case 0x002A: return "WM_SPOOLERSTATUS";
4467 case 0x002B: return "WM_DRAWITEM";
4468 case 0x002C: return "WM_MEASUREITEM";
4469 case 0x002D: return "WM_DELETEITEM";
4470 case 0x002E: return "WM_VKEYTOITEM";
4471 case 0x002F: return "WM_CHARTOITEM";
4472 case 0x0030: return "WM_SETFONT";
4473 case 0x0031: return "WM_GETFONT";
4474 case 0x0037: return "WM_QUERYDRAGICON";
4475 case 0x0039: return "WM_COMPAREITEM";
4476 case 0x0041: return "WM_COMPACTING";
4477 case 0x0044: return "WM_COMMNOTIFY";
4478 case 0x0046: return "WM_WINDOWPOSCHANGING";
4479 case 0x0047: return "WM_WINDOWPOSCHANGED";
4480 case 0x0048: return "WM_POWER";
4483 case 0x004A: return "WM_COPYDATA";
4484 case 0x004B: return "WM_CANCELJOURNAL";
4485 case 0x004E: return "WM_NOTIFY";
4486 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4487 case 0x0051: return "WM_INPUTLANGCHANGE";
4488 case 0x0052: return "WM_TCARD";
4489 case 0x0053: return "WM_HELP";
4490 case 0x0054: return "WM_USERCHANGED";
4491 case 0x0055: return "WM_NOTIFYFORMAT";
4492 case 0x007B: return "WM_CONTEXTMENU";
4493 case 0x007C: return "WM_STYLECHANGING";
4494 case 0x007D: return "WM_STYLECHANGED";
4495 case 0x007E: return "WM_DISPLAYCHANGE";
4496 case 0x007F: return "WM_GETICON";
4497 case 0x0080: return "WM_SETICON";
4500 case 0x0081: return "WM_NCCREATE";
4501 case 0x0082: return "WM_NCDESTROY";
4502 case 0x0083: return "WM_NCCALCSIZE";
4503 case 0x0084: return "WM_NCHITTEST";
4504 case 0x0085: return "WM_NCPAINT";
4505 case 0x0086: return "WM_NCACTIVATE";
4506 case 0x0087: return "WM_GETDLGCODE";
4507 case 0x00A0: return "WM_NCMOUSEMOVE";
4508 case 0x00A1: return "WM_NCLBUTTONDOWN";
4509 case 0x00A2: return "WM_NCLBUTTONUP";
4510 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4511 case 0x00A4: return "WM_NCRBUTTONDOWN";
4512 case 0x00A5: return "WM_NCRBUTTONUP";
4513 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4514 case 0x00A7: return "WM_NCMBUTTONDOWN";
4515 case 0x00A8: return "WM_NCMBUTTONUP";
4516 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4517 case 0x0100: return "WM_KEYDOWN";
4518 case 0x0101: return "WM_KEYUP";
4519 case 0x0102: return "WM_CHAR";
4520 case 0x0103: return "WM_DEADCHAR";
4521 case 0x0104: return "WM_SYSKEYDOWN";
4522 case 0x0105: return "WM_SYSKEYUP";
4523 case 0x0106: return "WM_SYSCHAR";
4524 case 0x0107: return "WM_SYSDEADCHAR";
4525 case 0x0108: return "WM_KEYLAST";
4528 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4529 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4530 case 0x010F: return "WM_IME_COMPOSITION";
4533 case 0x0110: return "WM_INITDIALOG";
4534 case 0x0111: return "WM_COMMAND";
4535 case 0x0112: return "WM_SYSCOMMAND";
4536 case 0x0113: return "WM_TIMER";
4537 case 0x0114: return "WM_HSCROLL";
4538 case 0x0115: return "WM_VSCROLL";
4539 case 0x0116: return "WM_INITMENU";
4540 case 0x0117: return "WM_INITMENUPOPUP";
4541 case 0x011F: return "WM_MENUSELECT";
4542 case 0x0120: return "WM_MENUCHAR";
4543 case 0x0121: return "WM_ENTERIDLE";
4544 case 0x0200: return "WM_MOUSEMOVE";
4545 case 0x0201: return "WM_LBUTTONDOWN";
4546 case 0x0202: return "WM_LBUTTONUP";
4547 case 0x0203: return "WM_LBUTTONDBLCLK";
4548 case 0x0204: return "WM_RBUTTONDOWN";
4549 case 0x0205: return "WM_RBUTTONUP";
4550 case 0x0206: return "WM_RBUTTONDBLCLK";
4551 case 0x0207: return "WM_MBUTTONDOWN";
4552 case 0x0208: return "WM_MBUTTONUP";
4553 case 0x0209: return "WM_MBUTTONDBLCLK";
4554 case 0x020A: return "WM_MOUSEWHEEL";
4555 case 0x0210: return "WM_PARENTNOTIFY";
4556 case 0x0211: return "WM_ENTERMENULOOP";
4557 case 0x0212: return "WM_EXITMENULOOP";
4560 case 0x0213: return "WM_NEXTMENU";
4561 case 0x0214: return "WM_SIZING";
4562 case 0x0215: return "WM_CAPTURECHANGED";
4563 case 0x0216: return "WM_MOVING";
4564 case 0x0218: return "WM_POWERBROADCAST";
4565 case 0x0219: return "WM_DEVICECHANGE";
4568 case 0x0220: return "WM_MDICREATE";
4569 case 0x0221: return "WM_MDIDESTROY";
4570 case 0x0222: return "WM_MDIACTIVATE";
4571 case 0x0223: return "WM_MDIRESTORE";
4572 case 0x0224: return "WM_MDINEXT";
4573 case 0x0225: return "WM_MDIMAXIMIZE";
4574 case 0x0226: return "WM_MDITILE";
4575 case 0x0227: return "WM_MDICASCADE";
4576 case 0x0228: return "WM_MDIICONARRANGE";
4577 case 0x0229: return "WM_MDIGETACTIVE";
4578 case 0x0230: return "WM_MDISETMENU";
4579 case 0x0233: return "WM_DROPFILES";
4582 case 0x0281: return "WM_IME_SETCONTEXT";
4583 case 0x0282: return "WM_IME_NOTIFY";
4584 case 0x0283: return "WM_IME_CONTROL";
4585 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4586 case 0x0285: return "WM_IME_SELECT";
4587 case 0x0286: return "WM_IME_CHAR";
4588 case 0x0290: return "WM_IME_KEYDOWN";
4589 case 0x0291: return "WM_IME_KEYUP";
4592 case 0x0300: return "WM_CUT";
4593 case 0x0301: return "WM_COPY";
4594 case 0x0302: return "WM_PASTE";
4595 case 0x0303: return "WM_CLEAR";
4596 case 0x0304: return "WM_UNDO";
4597 case 0x0305: return "WM_RENDERFORMAT";
4598 case 0x0306: return "WM_RENDERALLFORMATS";
4599 case 0x0307: return "WM_DESTROYCLIPBOARD";
4600 case 0x0308: return "WM_DRAWCLIPBOARD";
4601 case 0x0309: return "WM_PAINTCLIPBOARD";
4602 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4603 case 0x030B: return "WM_SIZECLIPBOARD";
4604 case 0x030C: return "WM_ASKCBFORMATNAME";
4605 case 0x030D: return "WM_CHANGECBCHAIN";
4606 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4607 case 0x030F: return "WM_QUERYNEWPALETTE";
4608 case 0x0310: return "WM_PALETTEISCHANGING";
4609 case 0x0311: return "WM_PALETTECHANGED";
4612 // common controls messages - although they're not strictly speaking
4613 // standard, it's nice to decode them nevertheless
4616 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4617 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4618 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4619 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4620 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4621 case 0x1000 + 5: return "LVM_GETITEMA";
4622 case 0x1000 + 75: return "LVM_GETITEMW";
4623 case 0x1000 + 6: return "LVM_SETITEMA";
4624 case 0x1000 + 76: return "LVM_SETITEMW";
4625 case 0x1000 + 7: return "LVM_INSERTITEMA";
4626 case 0x1000 + 77: return "LVM_INSERTITEMW";
4627 case 0x1000 + 8: return "LVM_DELETEITEM";
4628 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4629 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4630 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4631 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4632 case 0x1000 + 13: return "LVM_FINDITEMA";
4633 case 0x1000 + 83: return "LVM_FINDITEMW";
4634 case 0x1000 + 14: return "LVM_GETITEMRECT";
4635 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4636 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4637 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4638 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4639 case 0x1000 + 18: return "LVM_HITTEST";
4640 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4641 case 0x1000 + 20: return "LVM_SCROLL";
4642 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4643 case 0x1000 + 22: return "LVM_ARRANGE";
4644 case 0x1000 + 23: return "LVM_EDITLABELA";
4645 case 0x1000 + 118: return "LVM_EDITLABELW";
4646 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4647 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4648 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4649 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4650 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4651 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4652 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4653 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4654 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4655 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4656 case 0x1000 + 31: return "LVM_GETHEADER";
4657 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4658 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4659 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4660 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4661 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4662 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4663 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4664 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4665 case 0x1000 + 41: return "LVM_GETORIGIN";
4666 case 0x1000 + 42: return "LVM_UPDATE";
4667 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4668 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4669 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4670 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4671 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4672 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4673 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4674 case 0x1000 + 48: return "LVM_SORTITEMS";
4675 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4676 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4677 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4678 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4679 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4680 case 0x1000 + 53: return "LVM_SETICONSPACING";
4681 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4682 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4683 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4684 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4685 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4686 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4687 case 0x1000 + 60: return "LVM_SETHOTITEM";
4688 case 0x1000 + 61: return "LVM_GETHOTITEM";
4689 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4690 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4691 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4692 case 0x1000 + 65: return "LVM_SETWORKAREA";
4695 case 0x1100 + 0: return "TVM_INSERTITEMA";
4696 case 0x1100 + 50: return "TVM_INSERTITEMW";
4697 case 0x1100 + 1: return "TVM_DELETEITEM";
4698 case 0x1100 + 2: return "TVM_EXPAND";
4699 case 0x1100 + 4: return "TVM_GETITEMRECT";
4700 case 0x1100 + 5: return "TVM_GETCOUNT";
4701 case 0x1100 + 6: return "TVM_GETINDENT";
4702 case 0x1100 + 7: return "TVM_SETINDENT";
4703 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4704 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4705 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4706 case 0x1100 + 11: return "TVM_SELECTITEM";
4707 case 0x1100 + 12: return "TVM_GETITEMA";
4708 case 0x1100 + 62: return "TVM_GETITEMW";
4709 case 0x1100 + 13: return "TVM_SETITEMA";
4710 case 0x1100 + 63: return "TVM_SETITEMW";
4711 case 0x1100 + 14: return "TVM_EDITLABELA";
4712 case 0x1100 + 65: return "TVM_EDITLABELW";
4713 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4714 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4715 case 0x1100 + 17: return "TVM_HITTEST";
4716 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4717 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4718 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4719 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4720 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4721 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4722 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4723 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4724 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4727 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4728 case 0x1200 + 1: return "HDM_INSERTITEMA";
4729 case 0x1200 + 10: return "HDM_INSERTITEMW";
4730 case 0x1200 + 2: return "HDM_DELETEITEM";
4731 case 0x1200 + 3: return "HDM_GETITEMA";
4732 case 0x1200 + 11: return "HDM_GETITEMW";
4733 case 0x1200 + 4: return "HDM_SETITEMA";
4734 case 0x1200 + 12: return "HDM_SETITEMW";
4735 case 0x1200 + 5: return "HDM_LAYOUT";
4736 case 0x1200 + 6: return "HDM_HITTEST";
4737 case 0x1200 + 7: return "HDM_GETITEMRECT";
4738 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4739 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4740 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4741 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4742 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4743 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4744 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4747 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4748 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4749 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4750 case 0x1300 + 5: return "TCM_GETITEMA";
4751 case 0x1300 + 60: return "TCM_GETITEMW";
4752 case 0x1300 + 6: return "TCM_SETITEMA";
4753 case 0x1300 + 61: return "TCM_SETITEMW";
4754 case 0x1300 + 7: return "TCM_INSERTITEMA";
4755 case 0x1300 + 62: return "TCM_INSERTITEMW";
4756 case 0x1300 + 8: return "TCM_DELETEITEM";
4757 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4758 case 0x1300 + 10: return "TCM_GETITEMRECT";
4759 case 0x1300 + 11: return "TCM_GETCURSEL";
4760 case 0x1300 + 12: return "TCM_SETCURSEL";
4761 case 0x1300 + 13: return "TCM_HITTEST";
4762 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4763 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4764 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4765 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4766 case 0x1300 + 43: return "TCM_SETPADDING";
4767 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4768 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4769 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4770 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4771 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4772 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4773 case 0x1300 + 50: return "TCM_DESELECTALL";
4776 case WM_USER
+1: return "TB_ENABLEBUTTON";
4777 case WM_USER
+2: return "TB_CHECKBUTTON";
4778 case WM_USER
+3: return "TB_PRESSBUTTON";
4779 case WM_USER
+4: return "TB_HIDEBUTTON";
4780 case WM_USER
+5: return "TB_INDETERMINATE";
4781 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4782 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4783 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4784 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4785 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4786 case WM_USER
+17: return "TB_SETSTATE";
4787 case WM_USER
+18: return "TB_GETSTATE";
4788 case WM_USER
+19: return "TB_ADDBITMAP";
4789 case WM_USER
+20: return "TB_ADDBUTTONS";
4790 case WM_USER
+21: return "TB_INSERTBUTTON";
4791 case WM_USER
+22: return "TB_DELETEBUTTON";
4792 case WM_USER
+23: return "TB_GETBUTTON";
4793 case WM_USER
+24: return "TB_BUTTONCOUNT";
4794 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4795 case WM_USER
+26: return "TB_SAVERESTOREA";
4796 case WM_USER
+76: return "TB_SAVERESTOREW";
4797 case WM_USER
+27: return "TB_CUSTOMIZE";
4798 case WM_USER
+28: return "TB_ADDSTRINGA";
4799 case WM_USER
+77: return "TB_ADDSTRINGW";
4800 case WM_USER
+29: return "TB_GETITEMRECT";
4801 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4802 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4803 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4804 case WM_USER
+33: return "TB_AUTOSIZE";
4805 case WM_USER
+35: return "TB_GETTOOLTIPS";
4806 case WM_USER
+36: return "TB_SETTOOLTIPS";
4807 case WM_USER
+37: return "TB_SETPARENT";
4808 case WM_USER
+39: return "TB_SETROWS";
4809 case WM_USER
+40: return "TB_GETROWS";
4810 case WM_USER
+42: return "TB_SETCMDID";
4811 case WM_USER
+43: return "TB_CHANGEBITMAP";
4812 case WM_USER
+44: return "TB_GETBITMAP";
4813 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4814 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4815 case WM_USER
+46: return "TB_REPLACEBITMAP";
4816 case WM_USER
+47: return "TB_SETINDENT";
4817 case WM_USER
+48: return "TB_SETIMAGELIST";
4818 case WM_USER
+49: return "TB_GETIMAGELIST";
4819 case WM_USER
+50: return "TB_LOADIMAGES";
4820 case WM_USER
+51: return "TB_GETRECT";
4821 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4822 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4823 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4824 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4825 case WM_USER
+56: return "TB_SETSTYLE";
4826 case WM_USER
+57: return "TB_GETSTYLE";
4827 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4828 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4829 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4830 case WM_USER
+61: return "TB_GETTEXTROWS";
4831 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4836 static char s_szBuf
[128];
4837 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4841 #endif //__WXDEBUG__
4843 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4844 int *x
, int *y
, WPARAM
*flags
)
4846 // construct the key mask
4847 WPARAM
& fwKeys
= *flags
;
4849 fwKeys
= MK_RBUTTON
;
4850 if ( wxIsCtrlDown() )
4851 fwKeys
|= MK_CONTROL
;
4852 if ( wxIsShiftDown() )
4855 // simulate right mouse button click
4856 DWORD dwPos
= ::GetMessagePos();
4857 *x
= GET_X_LPARAM(dwPos
);
4858 *y
= GET_Y_LPARAM(dwPos
);
4860 win
->ScreenToClient(x
, y
);
4863 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4867 HWND hwnd
= GetHwndOf(win
);
4868 HDC hdc
= ::GetDC(hwnd
);
4870 #if !wxDIALOG_UNIT_COMPATIBILITY
4871 // and select the current font into it
4872 HFONT hfont
= GetHfontOf(win
->GetFont());
4875 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4879 // finally retrieve the text metrics from it
4880 GetTextMetrics(hdc
, &tm
);
4882 #if !wxDIALOG_UNIT_COMPATIBILITY
4886 (void)::SelectObject(hdc
, hfont
);
4890 ::ReleaseDC(hwnd
, hdc
);
4895 // Find the wxWindow at the current mouse position, returning the mouse
4897 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4899 return wxFindWindowAtPoint(wxGetMousePosition());
4902 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4907 HWND hWndHit
= ::WindowFromPoint(pt2
);
4909 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4910 HWND hWnd
= hWndHit
;
4912 // Try to find a window with a wxWindow associated with it
4913 while (!win
&& (hWnd
!= 0))
4915 hWnd
= ::GetParent(hWnd
);
4916 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
4921 // Get the current mouse position.
4922 wxPoint
wxGetMousePosition()
4925 GetCursorPos( & pt
);
4926 return wxPoint(pt
.x
, pt
.y
);