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"
40 #include "wx/dcmemory.h"
43 #include "wx/layout.h"
44 #include "wx/dialog.h"
46 #include "wx/listbox.h"
47 #include "wx/button.h"
48 #include "wx/msgdlg.h"
49 #include "wx/settings.h"
50 #include "wx/statbox.h"
54 #include "wx/ownerdrw.h"
57 #if wxUSE_DRAG_AND_DROP
61 #include "wx/menuitem.h"
64 #include "wx/msw/private.h"
67 #include "wx/tooltip.h"
75 #include "wx/spinctrl.h"
76 #endif // wxUSE_SPINCTRL
81 #include "wx/textctrl.h"
82 #include "wx/notebook.h"
86 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
95 #if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
99 #elif !defined(__WXMICROWIN__) // broken compiler
101 #include "wx/msw/gnuwin32/extra.h"
105 // This didn't appear in mingw until 2.95.2
107 #define SIF_TRACKPOS 16
111 #ifndef WM_MOUSEWHEEL
112 #define WM_MOUSEWHEEL 0x020A
115 #define WHEEL_DELTA 120
117 #ifndef SPI_GETWHEELSCROLLLINES
118 #define SPI_GETWHEELSCROLLLINES 104
122 // ---------------------------------------------------------------------------
124 // ---------------------------------------------------------------------------
126 // the last Windows message we got (FIXME-MT)
127 extern MSG s_currentMsg
;
129 #if wxUSE_MENUS_NATIVE
130 wxMenu
*wxCurrentPopupMenu
= NULL
;
131 #endif // wxUSE_MENUS_NATIVE
133 extern const wxChar
*wxCanvasClassName
;
135 // true if we had already created the std colour map, used by
136 // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
137 static bool gs_hasStdCmap
= FALSE
;
139 // ---------------------------------------------------------------------------
141 // ---------------------------------------------------------------------------
143 // the window proc for all our windows
144 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
145 WPARAM wParam
, LPARAM lParam
);
148 const char *wxGetMessageName(int message
);
151 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
152 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
153 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
155 // this magical function is used to translate VK_APPS key presses to right
157 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
158 int *x
, int *y
, WPARAM
*flags
);
160 // get the text metrics for the current font
161 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
163 // wrapper around BringWindowToTop() API
164 static inline void wxBringWindowToTop(HWND hwnd
)
166 #ifdef __WXMICROWIN__
167 // It seems that MicroWindows brings the _parent_ of the window to the top,
168 // which can be the wrong one.
170 // activate (set focus to) specified window
173 // raise top level parent to top of z order
174 ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
175 #else // !__WXMICROWIN__
176 if ( !::BringWindowToTop(hwnd
) )
178 wxLogLastError(_T("BringWindowToTop"));
180 #endif // __WXMICROWIN__/!__WXMICROWIN__
183 // ---------------------------------------------------------------------------
185 // ---------------------------------------------------------------------------
187 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
189 #ifdef __WXUNIVERSAL__
190 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
192 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
193 #endif // __WXUNIVERSAL__/__WXMSW__
195 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
196 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
197 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
198 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
199 EVT_IDLE(wxWindowMSW::OnIdle
)
202 // ===========================================================================
204 // ===========================================================================
206 // ---------------------------------------------------------------------------
207 // wxWindow utility functions
208 // ---------------------------------------------------------------------------
210 // Find an item given the MS Windows id
211 wxWindow
*wxWindowMSW::FindItem(long id
) const
214 wxControl
*item
= wxDynamicCastThis(wxControl
);
217 // is it we or one of our "internal" children?
218 if ( item
->GetId() == id
219 #ifndef __WXUNIVERSAL__
220 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
221 #endif // __WXUNIVERSAL__
227 #endif // wxUSE_CONTROLS
229 wxWindowList::Node
*current
= GetChildren().GetFirst();
232 wxWindow
*childWin
= current
->GetData();
234 wxWindow
*wnd
= childWin
->FindItem(id
);
238 current
= current
->GetNext();
244 // Find an item given the MS Windows handle
245 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
247 wxWindowList::Node
*current
= GetChildren().GetFirst();
250 wxWindow
*parent
= current
->GetData();
252 // Do a recursive search.
253 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
259 || parent
->IsKindOf(CLASSINFO(wxControl
))
260 #endif // wxUSE_CONTROLS
263 wxWindow
*item
= current
->GetData();
264 if ( item
->GetHWND() == hWnd
)
268 if ( item
->ContainsHWND(hWnd
) )
273 current
= current
->GetNext();
278 // Default command handler
279 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
284 // ----------------------------------------------------------------------------
285 // constructors and such
286 // ----------------------------------------------------------------------------
288 void wxWindowMSW::Init()
294 m_doubleClickAllowed
= 0;
296 m_isBeingDeleted
= FALSE
;
299 m_mouseInWindow
= FALSE
;
308 m_backgroundTransparent
= FALSE
;
310 // as all windows are created with WS_VISIBLE style...
313 #if wxUSE_MOUSEEVENT_HACK
316 m_lastMouseEvent
= -1;
317 #endif // wxUSE_MOUSEEVENT_HACK
321 wxWindowMSW::~wxWindowMSW()
323 m_isBeingDeleted
= TRUE
;
325 #ifndef __WXUNIVERSAL__
326 // VS: make sure there's no wxFrame with last focus set to us:
327 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
329 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
332 if ( frame
->GetLastFocus() == this )
334 frame
->SetLastFocus((wxWindow
*)NULL
);
339 #endif // __WXUNIVERSAL__
341 // VS: destroy children first and _then_ detach *this from its parent.
342 // If we'd do it the other way around, children wouldn't be able
343 // find their parent frame (see above).
347 m_parent
->RemoveChild(this);
351 // VZ: test temp removed to understand what really happens here
352 //if (::IsWindow(GetHwnd()))
354 if ( !::DestroyWindow(GetHwnd()) )
355 wxLogLastError(wxT("DestroyWindow"));
358 // remove hWnd <-> wxWindow association
359 wxRemoveHandleAssociation(this);
363 // real construction (Init() must have been called before!)
364 bool wxWindowMSW::Create(wxWindow
*parent
,
369 const wxString
& name
)
371 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
374 // wxGTK doesn't allow to create controls with static box as the parent so
375 // this will result in a crash when the program is ported to wxGTK - warn
378 // the correct solution is to create the controls as siblings of the
380 wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
),
381 _T("wxStaticBox can't be used as a window parent!") );
382 #endif // wxUSE_STATBOX
384 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
387 parent
->AddChild(this);
389 // all windows are created visible
390 DWORD msflags
= WS_CHILD
| WS_VISIBLE
;
392 #ifdef __WXUNIVERSAL__
393 // no 3d effects, we draw them ourselves
395 #else // !wxUniversal
396 if ( style
& wxCLIP_CHILDREN
)
397 msflags
|= WS_CLIPCHILDREN
;
398 if ( style
& wxCLIP_SIBLINGS
)
399 msflags
|= WS_CLIPSIBLINGS
;
402 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
);
404 // Even with extended styles, need to combine with WS_BORDER
405 // for them to look right.
407 (m_windowStyle
& (wxBORDER
|
413 msflags
|= WS_BORDER
;
415 #endif // wxUniversal/!wxUniversal
417 if ( style
& wxPOPUP_WINDOW
)
419 // a popup window floats on top of everything
420 exStyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
422 // it is also created hidden as other top level windows
423 msflags
&= ~WS_VISIBLE
;
427 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
);
430 // ---------------------------------------------------------------------------
432 // ---------------------------------------------------------------------------
434 void wxWindowMSW::SetFocus()
436 HWND hWnd
= GetHwnd();
437 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
439 #ifndef __WXMICROWIN__
443 if ( !::SetFocus(hWnd
) )
445 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
446 // was there really an error?
447 DWORD dwRes
= ::GetLastError();
450 HWND hwndFocus
= ::GetFocus();
451 if ( hwndFocus
!= hWnd
)
453 wxLogApiError(_T("SetFocus"), dwRes
);
460 // Get the window with the focus
461 wxWindow
*wxWindowBase::FindFocus()
463 HWND hWnd
= ::GetFocus();
466 return wxGetWindowFromHWND((WXHWND
)hWnd
);
472 bool wxWindowMSW::Enable(bool enable
)
474 if ( !wxWindowBase::Enable(enable
) )
477 HWND hWnd
= GetHwnd();
479 ::EnableWindow(hWnd
, (BOOL
)enable
);
481 // VZ: no, this is a bad idea: imagine that you have a dialog with some
482 // disabled controls and disable it - you really wouldn't like the
483 // disabled controls be reenabled too when you reenable the dialog!
485 wxWindowList::Node
*node
= GetChildren().GetFirst();
488 wxWindow
*child
= node
->GetData();
489 child
->Enable(enable
);
491 node
= node
->GetNext();
498 bool wxWindowMSW::Show(bool show
)
500 if ( !wxWindowBase::Show(show
) )
503 HWND hWnd
= GetHwnd();
504 int cshow
= show
? SW_SHOW
: SW_HIDE
;
505 ::ShowWindow(hWnd
, cshow
);
509 wxBringWindowToTop(hWnd
);
515 // Raise the window to the top of the Z order
516 void wxWindowMSW::Raise()
518 wxBringWindowToTop(GetHwnd());
521 // Lower the window to the bottom of the Z order
522 void wxWindowMSW::Lower()
524 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
525 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
528 void wxWindowMSW::SetTitle( const wxString
& title
)
530 SetWindowText(GetHwnd(), title
.c_str());
533 wxString
wxWindowMSW::GetTitle() const
535 return wxGetWindowText(GetHWND());
538 void wxWindowMSW::DoCaptureMouse()
540 HWND hWnd
= GetHwnd();
547 void wxWindowMSW::DoReleaseMouse()
549 if ( !::ReleaseCapture() )
551 wxLogLastError(_T("ReleaseCapture"));
555 /* static */ wxWindow
*wxWindowBase::GetCapture()
557 HWND hwnd
= ::GetCapture();
558 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
561 bool wxWindowMSW::SetFont(const wxFont
& font
)
563 if ( !wxWindowBase::SetFont(font
) )
569 HWND hWnd
= GetHwnd();
572 WXHANDLE hFont
= m_font
.GetResourceHandle();
574 wxASSERT_MSG( hFont
, wxT("should have valid font") );
576 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
581 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
583 if ( !wxWindowBase::SetCursor(cursor
) )
591 HWND hWnd
= GetHwnd();
593 // Change the cursor NOW if we're within the correct window
595 ::GetCursorPos(&point
);
597 RECT rect
= wxGetWindowRect(hWnd
);
599 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
600 ::SetCursor(GetHcursorOf(m_cursor
));
606 void wxWindowMSW::WarpPointer (int x
, int y
)
608 ClientToScreen(&x
, &y
);
610 if ( !::SetCursorPos(x
, y
) )
612 wxLogLastError(_T("SetCursorPos"));
616 #if WXWIN_COMPATIBILITY
617 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
620 #endif // WXWIN_COMPATIBILITY
622 // ---------------------------------------------------------------------------
624 // ---------------------------------------------------------------------------
626 #if WXWIN_COMPATIBILITY
627 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
629 #if defined(__WIN95__)
633 // Try to adjust the range to cope with page size > 1
634 // - a Windows API quirk
635 int pageSize
= GetScrollPage(orient
);
636 if ( pageSize
> 1 && range
> 0)
638 range1
+= (pageSize
- 1);
644 if ( orient
== wxHORIZONTAL
) {
650 info
.cbSize
= sizeof(SCROLLINFO
);
651 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
655 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
657 HWND hWnd
= GetHwnd();
659 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
662 if ( orient
== wxHORIZONTAL
)
667 HWND hWnd
= GetHwnd();
669 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
673 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
675 #if defined(__WIN95__)
679 if ( orient
== wxHORIZONTAL
) {
687 info
.cbSize
= sizeof(SCROLLINFO
);
690 info
.fMask
= SIF_PAGE
;
692 HWND hWnd
= GetHwnd();
694 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
696 if ( orient
== wxHORIZONTAL
)
703 int wxWindowMSW::OldGetScrollRange(int orient
) const
706 if ( orient
== wxHORIZONTAL
)
711 #if __WATCOMC__ && defined(__WINDOWS_386__)
712 short minPos
, maxPos
;
716 HWND hWnd
= GetHwnd();
719 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
720 #if defined(__WIN95__)
721 // Try to adjust the range to cope with page size > 1
722 // - a Windows API quirk
723 int pageSize
= GetScrollPage(orient
);
726 maxPos
-= (pageSize
- 1);
735 int wxWindowMSW::GetScrollPage(int orient
) const
737 if ( orient
== wxHORIZONTAL
)
743 #endif // WXWIN_COMPATIBILITY
745 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
747 #ifdef __WXMICROWIN__
748 return ::GetScrollPosWX(hWnd
, wOrient
);
750 return ::GetScrollPos(hWnd
, wOrient
);
754 int wxWindowMSW::GetScrollPos(int orient
) const
757 if ( orient
== wxHORIZONTAL
)
762 HWND hWnd
= GetHwnd();
763 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
765 return GetScrollPosition(hWnd
, wOrient
);
768 // This now returns the whole range, not just the number
769 // of positions that we can scroll.
770 int wxWindowMSW::GetScrollRange(int orient
) const
773 if ( orient
== wxHORIZONTAL
)
778 #if __WATCOMC__ && defined(__WINDOWS_386__)
779 short minPos
, maxPos
;
783 HWND hWnd
= GetHwnd();
786 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
787 #if defined(__WIN95__)
788 // Try to adjust the range to cope with page size > 1
789 // - a Windows API quirk
790 int pageSize
= GetScrollThumb(orient
);
793 maxPos
-= (pageSize
- 1);
795 // October 10th: new range concept.
805 int wxWindowMSW::GetScrollThumb(int orient
) const
807 if ( orient
== wxHORIZONTAL
)
813 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
815 HWND hWnd
= GetHwnd();
816 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
818 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
820 #if defined(__WIN95__)
822 info
.cbSize
= sizeof(SCROLLINFO
);
826 info
.fMask
= SIF_POS
;
828 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
830 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
831 #endif // __WIN95__/!__WIN95__
834 // New function that will replace some of the above.
835 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
836 int range
, bool refresh
)
838 #if defined(__WIN95__)
839 int oldRange
= range
- thumbVisible
;
841 int range1
= oldRange
;
843 // Try to adjust the range to cope with page size > 1
844 // - a Windows API quirk
845 int pageSize
= thumbVisible
;
846 if ( pageSize
> 1 && range
> 0)
848 range1
+= (pageSize
- 1);
854 if ( orient
== wxHORIZONTAL
) {
860 info
.cbSize
= sizeof(SCROLLINFO
);
861 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
865 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
867 HWND hWnd
= GetHwnd();
869 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
872 if ( orient
== wxHORIZONTAL
)
877 HWND hWnd
= GetHwnd();
880 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
881 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
884 if ( orient
== wxHORIZONTAL
) {
885 m_xThumbSize
= thumbVisible
;
887 m_yThumbSize
= thumbVisible
;
891 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
897 rect
.left
= prect
->x
;
899 rect
.right
= prect
->x
+ prect
->width
;
900 rect
.bottom
= prect
->y
+ prect
->height
;
908 ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
);
911 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
913 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
916 for ( int n
= 0; n
< count
; n
++ )
918 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
920 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
923 // don't bother to continue, we're already at top/bottom
930 return pos
!= posStart
;
933 bool wxWindowMSW::ScrollLines(int lines
)
935 bool down
= lines
> 0;
937 return ScrollVertically(GetHwnd(),
938 down
? SB_LINEDOWN
: SB_LINEUP
,
939 down
? lines
: -lines
);
942 bool wxWindowMSW::ScrollPages(int pages
)
944 bool down
= pages
> 0;
946 return ScrollVertically(GetHwnd(),
947 down
? SB_PAGEDOWN
: SB_PAGEUP
,
948 down
? pages
: -pages
);
951 // ---------------------------------------------------------------------------
953 // ---------------------------------------------------------------------------
955 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
957 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
959 HWND hwnd
= (HWND
)hWnd
;
960 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
962 wxAssociateWinWithHandle(hwnd
, this);
964 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
966 // we don't need to subclass the window of our own class (in the Windows
967 // sense of the word)
968 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
970 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
974 // don't bother restoring it neither
979 void wxWindowMSW::UnsubclassWin()
981 wxRemoveHandleAssociation(this);
983 // Restore old Window proc
984 HWND hwnd
= GetHwnd();
989 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
993 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
995 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1003 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
1005 #if wxUSE_UNICODE_MSLU
1006 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
1007 // because it doesn't return pointer to the real wnd proc but rather a handle
1008 // of a fake proc that does Unicode<->ANSI translation.
1010 // The hack bellow works, because WNDCLASS contains original window handler
1011 // rather that the unicows fake one. This may not be on purpose, though; if
1012 // it stops working with future versions of unicows.dll, we can override
1013 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
1014 // Unicows_RegisterClass to our own versions that keep track of
1015 // fake<->real wnd proc mapping.
1017 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
1018 // with RegisterClass!!
1020 static wxChar buffer
[512];
1023 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1024 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1025 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1027 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1032 // Make a Windows extended style from the given wxWindows window style
1033 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1035 WXDWORD exStyle
= 0;
1036 if ( style
& wxTRANSPARENT_WINDOW
)
1037 exStyle
|= WS_EX_TRANSPARENT
;
1039 if ( !eliminateBorders
)
1041 if ( style
& wxSUNKEN_BORDER
)
1042 exStyle
|= WS_EX_CLIENTEDGE
;
1043 if ( style
& wxDOUBLE_BORDER
)
1044 exStyle
|= WS_EX_DLGMODALFRAME
;
1045 #if defined(__WIN95__)
1046 if ( style
& wxRAISED_BORDER
)
1047 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1048 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1049 if ( style
& wxSTATIC_BORDER
)
1050 exStyle
|= WS_EX_STATICEDGE
;
1057 // Determines whether native 3D effects or CTL3D should be used,
1058 // applying a default border style if required, and returning an extended
1059 // style to pass to CreateWindowEx.
1060 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1063 // If matches certain criteria, then assume no 3D effects
1064 // unless specifically requested (dealt with in MakeExtendedStyle)
1067 || !IsKindOf(CLASSINFO(wxControl
))
1068 #endif // wxUSE_CONTROLS
1069 || (m_windowStyle
& wxNO_BORDER
) )
1072 return MakeExtendedStyle(m_windowStyle
);
1075 // Determine whether we should be using 3D effects or not.
1076 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1078 // 1) App can specify global 3D effects
1079 *want3D
= wxTheApp
->GetAuto3D();
1081 // 2) If the parent is being drawn with user colours, or simple border specified,
1082 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1083 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1086 // 3) Control can override this global setting by defining
1087 // a border style, e.g. wxSUNKEN_BORDER
1088 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1091 // 4) If it's a special border, CTL3D can't cope so we want a native border
1092 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1093 (m_windowStyle
& wxSTATIC_BORDER
) )
1096 nativeBorder
= TRUE
;
1099 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1100 // effects from extended style
1103 nativeBorder
= FALSE
;
1106 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1108 // If we want 3D, but haven't specified a border here,
1109 // apply the default border style specified.
1110 // TODO what about non-Win95 WIN32? Does it have borders?
1111 #if defined(__WIN95__) && !wxUSE_CTL3D
1112 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1113 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1114 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1120 #if WXWIN_COMPATIBILITY
1121 // If nothing defined for this, try the parent.
1122 // E.g. we may be a button loaded from a resource, with no callback function
1124 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1126 if ( GetEventHandler()->ProcessEvent(event
) )
1129 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1131 #endif // WXWIN_COMPATIBILITY_2
1133 #if WXWIN_COMPATIBILITY
1134 wxObject
* wxWindowMSW::GetChild(int number
) const
1136 // Return a pointer to the Nth object in the Panel
1137 wxNode
*node
= GetChildren().First();
1140 node
= node
->Next();
1143 wxObject
*obj
= (wxObject
*)node
->Data();
1149 #endif // WXWIN_COMPATIBILITY
1151 // Setup background and foreground colours correctly
1152 void wxWindowMSW::SetupColours()
1155 SetBackgroundColour(GetParent()->GetBackgroundColour());
1158 bool wxWindowMSW::IsMouseInWindow() const
1160 // get the mouse position
1162 ::GetCursorPos(&pt
);
1164 // find the window which currently has the cursor and go up the window
1165 // chain until we find this window - or exhaust it
1166 HWND hwnd
= ::WindowFromPoint(pt
);
1167 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1168 hwnd
= ::GetParent(hwnd
);
1170 return hwnd
!= NULL
;
1173 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1175 // Check if we need to send a LEAVE event
1176 if ( m_mouseInWindow
)
1178 if ( !IsMouseInWindow() && !HasCapture())
1180 // Generate a LEAVE event
1181 m_mouseInWindow
= FALSE
;
1183 // Unfortunately the mouse button and keyboard state may have
1184 // changed by the time the OnIdle function is called, so 'state'
1185 // may be meaningless.
1187 if ( wxIsShiftDown() )
1189 if ( wxIsCtrlDown() )
1190 state
|= MK_CONTROL
;
1191 if ( GetKeyState( VK_LBUTTON
) )
1192 state
|= MK_LBUTTON
;
1193 if ( GetKeyState( VK_MBUTTON
) )
1194 state
|= MK_MBUTTON
;
1195 if ( GetKeyState( VK_RBUTTON
) )
1196 state
|= MK_RBUTTON
;
1199 if ( !::GetCursorPos(&pt
) )
1201 wxLogLastError(_T("GetCursorPos"));
1204 // we need to have client coordinates here for symmetry with
1205 // wxEVT_ENTER_WINDOW
1206 RECT rect
= wxGetWindowRect(GetHwnd());
1210 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1211 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1213 (void)GetEventHandler()->ProcessEvent(event2
);
1220 // Set this window to be the child of 'parent'.
1221 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1223 if ( !wxWindowBase::Reparent(parent
) )
1226 HWND hWndChild
= GetHwnd();
1227 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1229 ::SetParent(hWndChild
, hWndParent
);
1234 void wxWindowMSW::Clear()
1236 wxClientDC
dc((wxWindow
*)this);
1237 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1238 dc
.SetBackground(brush
);
1242 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1244 #ifndef __WXMICROWIN__
1245 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1249 void wxWindowMSW::Freeze()
1251 SendSetRedraw(GetHwnd(), FALSE
);
1254 void wxWindowMSW::Thaw()
1256 SendSetRedraw(GetHwnd(), TRUE
);
1258 // we need to refresh everything or otherwise he invalidated area is not
1263 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1265 HWND hWnd
= GetHwnd();
1271 mswRect
.left
= rect
->x
;
1272 mswRect
.top
= rect
->y
;
1273 mswRect
.right
= rect
->x
+ rect
->width
;
1274 mswRect
.bottom
= rect
->y
+ rect
->height
;
1276 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1279 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1283 void wxWindowMSW::Update()
1285 if ( !::UpdateWindow(GetHwnd()) )
1287 wxLogLastError(_T("UpdateWindow"));
1290 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1291 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1292 // handler needs to be really drawn right now
1297 // ---------------------------------------------------------------------------
1299 // ---------------------------------------------------------------------------
1301 #if wxUSE_DRAG_AND_DROP
1303 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1305 if ( m_dropTarget
!= 0 ) {
1306 m_dropTarget
->Revoke(m_hWnd
);
1307 delete m_dropTarget
;
1310 m_dropTarget
= pDropTarget
;
1311 if ( m_dropTarget
!= 0 )
1312 m_dropTarget
->Register(m_hWnd
);
1315 #endif // wxUSE_DRAG_AND_DROP
1317 // old style file-manager drag&drop support: we retain the old-style
1318 // DragAcceptFiles in parallel with SetDropTarget.
1319 void wxWindowMSW::DragAcceptFiles(bool accept
)
1321 HWND hWnd
= GetHwnd();
1323 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1326 // ----------------------------------------------------------------------------
1328 // ----------------------------------------------------------------------------
1332 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1334 wxWindowBase::DoSetToolTip(tooltip
);
1337 m_tooltip
->SetWindow(this);
1340 #endif // wxUSE_TOOLTIPS
1342 // ---------------------------------------------------------------------------
1343 // moving and resizing
1344 // ---------------------------------------------------------------------------
1347 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1349 RECT rect
= wxGetWindowRect(GetHwnd());
1352 *x
= rect
.right
- rect
.left
;
1354 *y
= rect
.bottom
- rect
.top
;
1357 // Get size *available for subwindows* i.e. excluding menu bar etc.
1358 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1360 RECT rect
= wxGetClientRect(GetHwnd());
1368 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1370 RECT rect
= wxGetWindowRect(GetHwnd());
1373 point
.x
= rect
.left
;
1376 // we do the adjustments with respect to the parent only for the "real"
1377 // children, not for the dialogs/frames
1378 if ( !IsTopLevel() )
1380 HWND hParentWnd
= 0;
1381 wxWindow
*parent
= GetParent();
1383 hParentWnd
= GetWinHwnd(parent
);
1385 // Since we now have the absolute screen coords, if there's a parent we
1386 // must subtract its top left corner
1389 ::ScreenToClient(hParentWnd
, &point
);
1394 // We may be faking the client origin. So a window that's really at (0,
1395 // 30) may appear (to wxWin apps) to be at (0, 0).
1396 wxPoint
pt(parent
->GetClientAreaOrigin());
1408 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1416 ::ScreenToClient(GetHwnd(), &pt
);
1424 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1432 ::ClientToScreen(GetHwnd(), &pt
);
1440 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1442 // TODO: is this consistent with other platforms?
1443 // Still, negative width or height shouldn't be allowed
1448 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1450 wxLogLastError(wxT("MoveWindow"));
1454 // set the size of the window: if the dimensions are positive, just use them,
1455 // but if any of them is equal to -1, it means that we must find the value for
1456 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1457 // which case -1 is a valid value for x and y)
1459 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1460 // the width/height to best suit our contents, otherwise we reuse the current
1462 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1464 // get the current size and position...
1465 int currentX
, currentY
;
1466 GetPosition(¤tX
, ¤tY
);
1467 int currentW
,currentH
;
1468 GetSize(¤tW
, ¤tH
);
1470 // ... and don't do anything (avoiding flicker) if it's already ok
1471 if ( x
== currentX
&& y
== currentY
&&
1472 width
== currentW
&& height
== currentH
)
1477 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1479 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1482 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1484 wxSize
size(-1, -1);
1487 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1489 size
= DoGetBestSize();
1494 // just take the current one
1501 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1505 size
= DoGetBestSize();
1507 //else: already called DoGetBestSize() above
1513 // just take the current one
1518 DoMoveWindow(x
, y
, width
, height
);
1521 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1523 // setting the client size is less obvious than it it could have been
1524 // because in the result of changing the total size the window scrollbar
1525 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1526 // will not be correct as the difference between the total and client size
1527 // changes - so we keep changing it until we get it right
1529 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1530 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1531 // may become 3 if the window had 0 size originally and so we didn't
1532 // calculate the scrollbar correction correctly during the first iteration)
1533 // but just to be on the safe side we check for it instead of making it an
1534 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1535 for ( int i
= 0; i
< 4; i
++ )
1538 ::GetClientRect(GetHwnd(), &rectClient
);
1540 // if the size is already ok, stop here (rectClient.left = top = 0)
1541 if ( (rectClient
.right
== width
|| width
== -1) &&
1542 (rectClient
.bottom
== height
|| height
== -1) )
1549 // how did it happen? maybe OnSize() handler does something really
1550 // strange in this class?
1551 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1556 int widthClient
= width
,
1557 heightClient
= height
;
1559 // Find the difference between the entire window (title bar and all)
1560 // and the client area; add this to the new client size to move the
1563 ::GetWindowRect(GetHwnd(), &rectWin
);
1565 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1566 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1569 point
.x
= rectWin
.left
;
1570 point
.y
= rectWin
.top
;
1572 // MoveWindow positions the child windows relative to the parent, so
1573 // adjust if necessary
1574 if ( !IsTopLevel() )
1576 wxWindow
*parent
= GetParent();
1579 ::ScreenToClient(GetHwndOf(parent
), &point
);
1583 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1587 // For implementation purposes - sometimes decorations make the client area
1589 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1591 return wxPoint(0, 0);
1594 // ---------------------------------------------------------------------------
1596 // ---------------------------------------------------------------------------
1598 int wxWindowMSW::GetCharHeight() const
1600 return wxGetTextMetrics(this).tmHeight
;
1603 int wxWindowMSW::GetCharWidth() const
1605 // +1 is needed because Windows apparently adds it when calculating the
1606 // dialog units size in pixels
1607 #if wxDIALOG_UNIT_COMPATIBILITY
1608 return wxGetTextMetrics(this).tmAveCharWidth
;
1610 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1614 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1616 int *descent
, int *externalLeading
,
1617 const wxFont
*theFont
) const
1619 const wxFont
*fontToUse
= theFont
;
1621 fontToUse
= &m_font
;
1623 HWND hWnd
= GetHwnd();
1624 HDC dc
= ::GetDC(hWnd
);
1628 if ( fontToUse
&& fontToUse
->Ok() )
1630 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1632 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1637 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1638 GetTextMetrics(dc
, &tm
);
1640 if ( fontToUse
&& fnt
&& hfontOld
)
1641 SelectObject(dc
, hfontOld
);
1643 ReleaseDC(hWnd
, dc
);
1650 *descent
= tm
.tmDescent
;
1651 if ( externalLeading
)
1652 *externalLeading
= tm
.tmExternalLeading
;
1655 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1656 // ---------------------------------------------------------------------------
1657 // Caret manipulation
1658 // ---------------------------------------------------------------------------
1660 void wxWindowMSW::CreateCaret(int w
, int h
)
1662 SetCaret(new wxCaret(this, w
, h
));
1665 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1667 wxFAIL_MSG("not implemented");
1670 void wxWindowMSW::ShowCaret(bool show
)
1672 wxCHECK_RET( m_caret
, "no caret to show" );
1674 m_caret
->Show(show
);
1677 void wxWindowMSW::DestroyCaret()
1682 void wxWindowMSW::SetCaretPos(int x
, int y
)
1684 wxCHECK_RET( m_caret
, "no caret to move" );
1686 m_caret
->Move(x
, y
);
1689 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1691 wxCHECK_RET( m_caret
, "no caret to get position of" );
1693 m_caret
->GetPosition(x
, y
);
1695 #endif // wxUSE_CARET
1697 // ---------------------------------------------------------------------------
1699 // ---------------------------------------------------------------------------
1701 #if wxUSE_MENUS_NATIVE
1703 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1704 // immediately, without waiting for the next event loop iteration
1706 // NB: this function should probably be made public later as it can almost
1707 // surely replace wxYield() elsewhere as well
1708 static void wxYieldForCommandsOnly()
1710 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1711 // want to process it here)
1713 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1714 && msg
.message
!= WM_QUIT
)
1716 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1720 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1722 menu
->SetInvokingWindow(this);
1725 HWND hWnd
= GetHwnd();
1726 HMENU hMenu
= GetHmenuOf(menu
);
1730 ::ClientToScreen(hWnd
, &point
);
1731 wxCurrentPopupMenu
= menu
;
1732 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1734 // we need to do it righ now as otherwise the events are never going to be
1735 // sent to wxCurrentPopupMenu from HandleCommand()
1737 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1738 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1739 // destroyed as soon as we return (it can be a local variable in the caller
1740 // for example) and so we do need to process the event immediately
1741 wxYieldForCommandsOnly();
1743 wxCurrentPopupMenu
= NULL
;
1745 menu
->SetInvokingWindow(NULL
);
1750 #endif // wxUSE_MENUS_NATIVE
1752 // ===========================================================================
1753 // pre/post message processing
1754 // ===========================================================================
1756 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1759 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1761 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1764 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1766 // wxUniversal implements tab traversal itself
1767 #ifndef __WXUNIVERSAL__
1768 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1770 // intercept dialog navigation keys
1771 MSG
*msg
= (MSG
*)pMsg
;
1773 // here we try to do all the job which ::IsDialogMessage() usually does
1776 bool bProcess
= TRUE
;
1777 if ( msg
->message
!= WM_KEYDOWN
)
1780 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1785 bool bCtrlDown
= wxIsCtrlDown();
1786 bool bShiftDown
= wxIsShiftDown();
1788 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1789 // don't process it if it's the case (except for Ctrl-Tab/Enter
1790 // combinations which are always processed)
1794 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1797 bool bForward
= TRUE
,
1798 bWindowChange
= FALSE
;
1800 switch ( msg
->wParam
)
1803 // assume that nobody wants Shift-TAB for himself - if we
1804 // don't do it there is no easy way for a control to grab
1805 // TABs but still let Shift-TAB work as navugation key
1806 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1810 // Ctrl-Tab cycles thru notebook pages
1811 bWindowChange
= bCtrlDown
;
1812 bForward
= !bShiftDown
;
1818 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1826 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1832 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1834 // control wants to process Enter itself, don't
1835 // call IsDialogMessage() which would interpret
1839 else if ( lDlgCode
& DLGC_BUTTON
)
1841 // let IsDialogMessage() handle this for all
1842 // buttons except the owner-drawn ones which it
1843 // just seems to ignore
1844 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1845 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1847 // emulate the button click
1848 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1850 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1855 // FIXME: this should be handled by
1856 // wxNavigationKeyEvent handler and not here!!
1860 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1862 if ( btn
&& btn
->IsEnabled() )
1864 // if we do have a default button, do press it
1865 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1869 else // no default button
1870 #endif // wxUSE_BUTTON
1872 // no special function for enter and don't even
1873 // let IsDialogMessage() have it: it seems to
1874 // do something really strange with it
1887 wxNavigationKeyEvent event
;
1888 event
.SetDirection(bForward
);
1889 event
.SetWindowChange(bWindowChange
);
1890 event
.SetEventObject(this);
1892 if ( GetEventHandler()->ProcessEvent(event
) )
1899 // let ::IsDialogMessage() do almost everything and handle just the
1900 // things it doesn't here: Ctrl-TAB for switching notebook pages
1901 if ( msg
->message
== WM_KEYDOWN
)
1903 // don't process system keys here
1904 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1906 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1908 // find the first notebook parent and change its page
1909 wxWindow
*win
= this;
1910 wxNotebook
*nbook
= NULL
;
1911 while ( win
&& !nbook
)
1913 nbook
= wxDynamicCast(win
, wxNotebook
);
1914 win
= win
->GetParent();
1919 bool forward
= !wxIsShiftDown();
1921 nbook
->AdvanceSelection(forward
);
1928 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1930 // IsDialogMessage() did something...
1934 #endif // __WXUNIVERSAL__
1939 // relay mouse move events to the tooltip control
1940 MSG
*msg
= (MSG
*)pMsg
;
1941 if ( msg
->message
== WM_MOUSEMOVE
)
1942 m_tooltip
->RelayEvent(pMsg
);
1944 #endif // wxUSE_TOOLTIPS
1949 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1951 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1952 return m_acceleratorTable
.Translate(this, pMsg
);
1956 #endif // wxUSE_ACCEL
1959 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
))
1961 // preprocess all messages by default
1965 // ---------------------------------------------------------------------------
1966 // message params unpackers (different for Win16 and Win32)
1967 // ---------------------------------------------------------------------------
1971 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1972 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1974 *id
= LOWORD(wParam
);
1975 *hwnd
= (WXHWND
)lParam
;
1976 *cmd
= HIWORD(wParam
);
1979 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1980 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1982 *state
= LOWORD(wParam
);
1983 *minimized
= HIWORD(wParam
);
1984 *hwnd
= (WXHWND
)lParam
;
1987 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1988 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1990 *code
= LOWORD(wParam
);
1991 *pos
= HIWORD(wParam
);
1992 *hwnd
= (WXHWND
)lParam
;
1995 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
1996 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
1998 #ifndef __WXMICROWIN__
1999 *nCtlColor
= CTLCOLOR_BTN
;
2000 *hwnd
= (WXHWND
)lParam
;
2001 *hdc
= (WXHDC
)wParam
;
2005 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2006 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2008 *item
= (WXWORD
)wParam
;
2009 *flags
= HIWORD(wParam
);
2010 *hmenu
= (WXHMENU
)lParam
;
2015 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2016 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2018 *id
= (WXWORD
)wParam
;
2019 *hwnd
= (WXHWND
)LOWORD(lParam
);
2020 *cmd
= HIWORD(lParam
);
2023 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2024 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2026 *state
= (WXWORD
)wParam
;
2027 *minimized
= LOWORD(lParam
);
2028 *hwnd
= (WXHWND
)HIWORD(lParam
);
2031 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2032 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2034 *code
= (WXWORD
)wParam
;
2035 *pos
= LOWORD(lParam
);
2036 *hwnd
= (WXHWND
)HIWORD(lParam
);
2039 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2040 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2042 *hwnd
= (WXHWND
)LOWORD(lParam
);
2043 *nCtlColor
= (int)HIWORD(lParam
);
2044 *hdc
= (WXHDC
)wParam
;
2047 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2048 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2050 *item
= (WXWORD
)wParam
;
2051 *flags
= LOWORD(lParam
);
2052 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2057 // ---------------------------------------------------------------------------
2058 // Main wxWindows window proc and the window proc for wxWindow
2059 // ---------------------------------------------------------------------------
2061 // Hook for new window just as it's being created, when the window isn't yet
2062 // associated with the handle
2063 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2065 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2066 // window being created and insures that it's always unset back later
2067 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2069 gs_winBeingCreated
= winBeingCreated
;
2072 wxWindowCreationHook::~wxWindowCreationHook()
2074 gs_winBeingCreated
= NULL
;
2078 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2080 // trace all messages - useful for the debugging
2082 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2083 wxGetMessageName(message
), wParam
, lParam
);
2084 #endif // __WXDEBUG__
2086 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2088 // when we get the first message for the HWND we just created, we associate
2089 // it with wxWindow stored in gs_winBeingCreated
2090 if ( !wnd
&& gs_winBeingCreated
)
2092 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2093 wnd
= gs_winBeingCreated
;
2094 gs_winBeingCreated
= NULL
;
2095 wnd
->SetHWND((WXHWND
)hWnd
);
2101 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2103 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2108 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2110 // did we process the message?
2111 bool processed
= FALSE
;
2122 // for most messages we should return 0 when we do process the message
2130 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2133 // return 0 to allow window creation
2134 rc
.result
= mayCreate
? 0 : -1;
2140 // never set processed to TRUE and *always* pass WM_DESTROY to
2141 // DefWindowProc() as Windows may do some internal cleanup when
2142 // processing it and failing to pass the message along may cause
2143 // memory and resource leaks!
2144 (void)HandleDestroy();
2148 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2156 // we're not interested in these messages at all
2159 case SIZE_MINIMIZED
:
2160 // we shouldn't send sizev events for these messages as the
2161 // client size may be negative which breaks existing code
2163 // OTOH we might send another (wxMinimizedEvent?) one or
2164 // add an additional parameter to wxSizeEvent if this is
2165 // useful to anybody
2169 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2170 // fall through nevertheless
2172 case SIZE_MAXIMIZED
:
2174 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2179 #ifndef __WXMICROWIN__
2180 case WM_ACTIVATEAPP
:
2181 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2187 WXWORD state
, minimized
;
2189 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2191 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2196 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2200 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2204 processed
= HandlePaint();
2208 // don't let the DefWindowProc() destroy our window - we'll do it
2209 // ourselves in ~wxWindow
2215 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2219 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2220 GET_Y_LPARAM(lParam
),
2224 #if wxUSE_MOUSEWHEEL
2226 processed
= HandleMouseWheel(wParam
, lParam
);
2230 case WM_LBUTTONDOWN
:
2232 case WM_LBUTTONDBLCLK
:
2233 case WM_RBUTTONDOWN
:
2235 case WM_RBUTTONDBLCLK
:
2236 case WM_MBUTTONDOWN
:
2238 case WM_MBUTTONDBLCLK
:
2241 #ifdef __WXMICROWIN__
2242 // MicroWindows seems to ignore the fact that a window is
2243 // disabled. So catch mouse events and throw them away if
2245 wxWindowMSW
* win
= this;
2248 if (!win
->IsEnabled())
2253 win
= win
->GetParent();
2254 if (win
&& win
->IsTopLevel())
2257 #endif // __WXMICROWIN__
2260 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2262 processed
= HandleMouseEvent(message
,
2263 GET_X_LPARAM(lParam
),
2264 GET_Y_LPARAM(lParam
),
2270 #ifdef __WXMICROWIN__
2271 case WM_NCLBUTTONDOWN
:
2272 case WM_NCLBUTTONUP
:
2273 case WM_NCLBUTTONDBLCLK
:
2274 case WM_NCRBUTTONDOWN
:
2275 case WM_NCRBUTTONUP
:
2276 case WM_NCRBUTTONDBLCLK
:
2278 case WM_NCMBUTTONDOWN
:
2279 case WM_NCMBUTTONUP
:
2280 case WM_NCMBUTTONDBLCLK
:
2283 // MicroWindows seems to ignore the fact that a window
2284 // is disabled. So catch mouse events and throw them away if necessary.
2286 wxWindowMSW
* win
= this;
2289 if (!win
->IsEnabled())
2294 win
= win
->GetParent();
2295 if (win
&& win
->IsTopLevel())
2300 #endif // __WXMICROWIN__
2307 case MM_JOY1BUTTONDOWN
:
2308 case MM_JOY2BUTTONDOWN
:
2309 case MM_JOY1BUTTONUP
:
2310 case MM_JOY2BUTTONUP
:
2311 processed
= HandleJoystickEvent(message
,
2312 GET_X_LPARAM(lParam
),
2313 GET_Y_LPARAM(lParam
),
2316 #endif // __WXMICROWIN__
2319 processed
= HandleSysCommand(wParam
, lParam
);
2326 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2328 processed
= HandleCommand(id
, cmd
, hwnd
);
2334 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2338 // for these messages we must return TRUE if process the message
2341 case WM_MEASUREITEM
:
2343 int idCtrl
= (UINT
)wParam
;
2344 if ( message
== WM_DRAWITEM
)
2346 processed
= MSWOnDrawItem(idCtrl
,
2347 (WXDRAWITEMSTRUCT
*)lParam
);
2351 processed
= MSWOnMeasureItem(idCtrl
,
2352 (WXMEASUREITEMSTRUCT
*)lParam
);
2359 #endif // defined(WM_DRAWITEM)
2362 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
2364 // want everything: i.e. all keys and WM_CHAR message
2365 rc
.result
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
2366 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
2369 //else: get the dlg code from the DefWindowProc()
2374 // If this has been processed by an event handler,
2375 // return 0 now (we've handled it).
2376 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2383 // we consider these message "not interesting" to OnChar
2384 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2393 // avoid duplicate messages to OnChar for these ASCII keys: they
2394 // will be translated by TranslateMessage() and received in WM_CHAR
2402 // but set processed to FALSE, not TRUE to still pass them to
2403 // the control's default window proc - otherwise built-in
2404 // keyboard handling won't work
2410 // special case of VK_APPS: treat it the same as right mouse
2411 // click because both usually pop up a context menu
2417 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2418 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2428 processed
= HandleChar((WORD
)wParam
, lParam
);
2435 // special case of VK_APPS: treat it the same as right mouse button
2436 if ( wParam
== VK_APPS
)
2441 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2442 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2447 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2452 case WM_CHAR
: // Always an ASCII character
2453 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2461 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2463 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2469 // CTLCOLOR messages are sent by children to query the parent for their
2470 // colors#ifndef __WXMICROWIN__
2471 #ifndef __WXMICROWIN__
2473 case WM_CTLCOLORMSGBOX
:
2474 case WM_CTLCOLOREDIT
:
2475 case WM_CTLCOLORLISTBOX
:
2476 case WM_CTLCOLORBTN
:
2477 case WM_CTLCOLORDLG
:
2478 case WM_CTLCOLORSCROLLBAR
:
2479 case WM_CTLCOLORSTATIC
:
2487 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2489 processed
= HandleCtlColor(&rc
.hBrush
,
2498 #endif // !__WXMICROWIN__
2500 case WM_SYSCOLORCHANGE
:
2501 // the return value for this message is ignored
2502 processed
= HandleSysColorChange();
2505 case WM_DISPLAYCHANGE
:
2506 processed
= HandleDisplayChange();
2509 case WM_PALETTECHANGED
:
2510 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2513 case WM_QUERYNEWPALETTE
:
2514 processed
= HandleQueryNewPalette();
2518 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2521 // we processed the message, i.e. erased the background
2527 processed
= HandleDropFiles(wParam
);
2531 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2535 // we never set focus from here
2540 case WM_QUERYENDSESSION
:
2541 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2545 processed
= HandleEndSession(wParam
!= 0, lParam
);
2548 case WM_GETMINMAXINFO
:
2549 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2553 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2554 LOWORD(lParam
), // hit test
2555 HIWORD(lParam
)); // mouse msg
2559 // returning TRUE stops the DefWindowProc() from further
2560 // processing this message - exactly what we need because we've
2561 // just set the cursor.
2566 #if defined(__WIN32__) && defined(WM_HELP)
2569 HELPINFO
* info
= (HELPINFO
*) lParam
;
2570 // Don't yet process menu help events, just windows
2571 if (info
->iContextType
== HELPINFO_WINDOW
)
2573 wxWindowMSW
* subjectOfHelp
= this;
2574 bool eventProcessed
= FALSE
;
2575 while (subjectOfHelp
&& !eventProcessed
)
2577 wxHelpEvent
helpEvent(wxEVT_HELP
,
2578 subjectOfHelp
->GetId(),
2579 wxPoint(info
->MousePos
.x
,
2580 info
->MousePos
.y
) );
2581 helpEvent
.SetEventObject(this);
2583 GetEventHandler()->ProcessEvent(helpEvent
);
2585 // Go up the window hierarchy until the event is
2587 subjectOfHelp
= subjectOfHelp
->GetParent();
2590 processed
= eventProcessed
;
2592 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2594 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2595 helpEvent
.SetEventObject(this);
2596 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2599 //else: processed is already FALSE
2603 case WM_CONTEXTMENU
:
2605 // we don't convert from screen to client coordinates as
2606 // the event may be handled by a parent window
2607 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2609 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2610 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2615 // unfortunately this doesn't really work as then window which
2616 // doesn't accept focus doesn't get any mouse events neither which
2617 // means it can't get any input at all
2618 #if 0 //def __WXUNIVERSAL__
2620 // we shouldn't allow the windows which don't want to get focus to
2622 if ( !AcceptsFocus() )
2624 rc
.result
= HTTRANSPARENT
;
2628 #endif // __WXUNIVERSAL__
2634 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2635 wxGetMessageName(message
));
2636 #endif // __WXDEBUG__
2637 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2643 // ----------------------------------------------------------------------------
2644 // wxWindow <-> HWND map
2645 // ----------------------------------------------------------------------------
2647 wxWinHashTable
*wxWinHandleHash
= NULL
;
2649 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2651 return wxWinHandleHash
->Get((long)hWnd
);
2654 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2656 // adding NULL hWnd is (first) surely a result of an error and
2657 // (secondly) breaks menu command processing
2658 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2659 wxT("attempt to add a NULL hWnd to window list ignored") );
2661 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2663 if ( oldWin
&& (oldWin
!= win
) )
2665 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2666 hWnd
, win
->GetClassInfo()->GetClassName());
2669 #endif // __WXDEBUG__
2672 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2676 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2678 wxWinHandleHash
->Delete((long)win
->GetHWND());
2681 // ----------------------------------------------------------------------------
2682 // various MSW speciic class dependent functions
2683 // ----------------------------------------------------------------------------
2685 // Default destroyer - override if you destroy it in some other way
2686 // (e.g. with MDI child windows)
2687 void wxWindowMSW::MSWDestroyWindow()
2691 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2694 int& w
, int& h
) const
2696 bool nonDefault
= FALSE
;
2700 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2701 // just as well set it to CW_USEDEFAULT as well
2708 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2714 NB: there used to be some code here which set the initial size of the
2715 window to the client size of the parent if no explicit size was
2716 specified. This was wrong because wxWindows programs often assume
2717 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2718 it. To see why, you should understand that Windows sends WM_SIZE from
2719 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2720 from some base class ctor and so this WM_SIZE is not processed in the
2721 real class' OnSize() (because it's not fully constructed yet and the
2722 event goes to some base class OnSize() instead). So the WM_SIZE we
2723 rely on is the one sent when the parent frame resizes its children
2724 but here is the problem: if the child already has just the right
2725 size, nothing will happen as both wxWindows and Windows check for
2726 this and ignore any attempts to change the window size to the size it
2727 already has - so no WM_SIZE would be sent.
2731 // as abobe, h is not used at all in this case anyhow
2738 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2746 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2747 const wxChar
*title
,
2751 WXDWORD extendedStyle
)
2753 // choose the position/size for the new window
2755 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2757 // find the correct parent HWND
2758 wxWindow
*parent
= GetParent();
2759 bool isChild
= (style
& WS_CHILD
) != 0;
2761 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2763 // popup windows should have desktop as parent because they shouldn't
2764 // be limited to the parents client area as child windows usually are
2765 hParent
= ::GetDesktopWindow();
2769 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2771 // this is either a normal child window or a top level window with
2772 // wxFRAME_TOOL_WINDOW style (see below)
2773 hParent
= GetHwndOf(parent
);
2777 // this is either a window for which no parent was specified (not
2778 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2779 // style: we should use NULL parent HWND for it or it would be
2780 // always on top of its parent which is not what we usually want
2781 // (in fact, we only want it for frames with the special
2782 // wxFRAME_TOOL_WINDOW as above)
2788 // controlId is menu handle for the top level windows, so set it to 0
2789 // unless we're creating a child window
2793 controlId
= GetId();
2795 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2797 style
|= WS_CLIPSIBLINGS
;
2805 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2806 // which is the same but without CS_[HV]REDRAW class styles so using it
2807 // ensures that the window is not fully repainted on each resize
2808 wxString
className(wclass
);
2809 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2811 className
+= wxT("NR");
2814 // do create the window
2815 wxWindowCreationHook
hook(this);
2817 m_hWnd
= (WXHWND
)::CreateWindowEx
2821 title
? title
: wxT(""),
2827 NULL
// no extra data
2832 wxLogSysError(_("Can't create window of class %s"), wclass
);
2837 SubclassWin(m_hWnd
);
2839 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2844 // ===========================================================================
2845 // MSW message handlers
2846 // ===========================================================================
2848 // ---------------------------------------------------------------------------
2850 // ---------------------------------------------------------------------------
2853 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2854 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2856 #ifndef __WXMICROWIN__
2857 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2858 HWND hWnd
= hdr
->hwndFrom
;
2859 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2861 // is this one of our windows?
2864 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2867 // try all our children
2868 wxWindowList::Node
*node
= GetChildren().GetFirst();
2871 wxWindow
*child
= node
->GetData();
2872 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2877 node
= node
->GetNext();
2880 // finally try this window too (catches toolbar case)
2881 return MSWOnNotify(idCtrl
, lParam
, result
);
2882 #else // __WXMICROWIN__
2887 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2889 WXLPARAM
* WXUNUSED(result
))
2892 NMHDR
* hdr
= (NMHDR
*)lParam
;
2893 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2895 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2896 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2901 #endif // wxUSE_TOOLTIPS
2907 // ---------------------------------------------------------------------------
2908 // end session messages
2909 // ---------------------------------------------------------------------------
2911 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2913 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2914 event
.SetEventObject(wxTheApp
);
2915 event
.SetCanVeto(TRUE
);
2916 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2918 bool rc
= wxTheApp
->ProcessEvent(event
);
2922 // we may end only if the app didn't veto session closing (double
2924 *mayEnd
= !event
.GetVeto();
2930 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2932 // do nothing if the session isn't ending
2937 if ( (this != wxTheApp
->GetTopWindow()) )
2940 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2941 event
.SetEventObject(wxTheApp
);
2942 event
.SetCanVeto(FALSE
);
2943 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2945 return wxTheApp
->ProcessEvent(event
);
2948 // ---------------------------------------------------------------------------
2949 // window creation/destruction
2950 // ---------------------------------------------------------------------------
2952 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2954 // TODO: should generate this event from WM_NCCREATE
2955 wxWindowCreateEvent
event((wxWindow
*)this);
2956 (void)GetEventHandler()->ProcessEvent(event
);
2963 bool wxWindowMSW::HandleDestroy()
2965 wxWindowDestroyEvent
event((wxWindow
*)this);
2966 (void)GetEventHandler()->ProcessEvent(event
);
2968 // delete our drop target if we've got one
2969 #if wxUSE_DRAG_AND_DROP
2970 if ( m_dropTarget
!= NULL
)
2972 m_dropTarget
->Revoke(m_hWnd
);
2974 delete m_dropTarget
;
2975 m_dropTarget
= NULL
;
2977 #endif // wxUSE_DRAG_AND_DROP
2979 // WM_DESTROY handled
2983 // ---------------------------------------------------------------------------
2985 // ---------------------------------------------------------------------------
2987 bool wxWindowMSW::HandleActivate(int state
,
2988 bool WXUNUSED(minimized
),
2989 WXHWND
WXUNUSED(activate
))
2991 wxActivateEvent
event(wxEVT_ACTIVATE
,
2992 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
2994 event
.SetEventObject(this);
2996 return GetEventHandler()->ProcessEvent(event
);
2999 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3001 // notify the parent keeping track of focus for the kbd navigation
3002 // purposes that we got it
3003 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3004 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3010 m_caret
->OnSetFocus();
3012 #endif // wxUSE_CARET
3015 // If it's a wxTextCtrl don't send the event as it will be done
3016 // after the control gets to process it from EN_FOCUS handler
3017 if ( wxDynamicCastThis(wxTextCtrl
) )
3021 #endif // wxUSE_TEXTCTRL
3023 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3024 event
.SetEventObject(this);
3026 // wxFindWinFromHandle() may return NULL, it is ok
3027 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3029 return GetEventHandler()->ProcessEvent(event
);
3032 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3038 m_caret
->OnKillFocus();
3040 #endif // wxUSE_CARET
3043 // If it's a wxTextCtrl don't send the event as it will be done
3044 // after the control gets to process it.
3045 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3052 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3053 event
.SetEventObject(this);
3055 // wxFindWinFromHandle() may return NULL, it is ok
3056 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3058 return GetEventHandler()->ProcessEvent(event
);
3061 // ---------------------------------------------------------------------------
3063 // ---------------------------------------------------------------------------
3065 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3067 wxShowEvent
event(GetId(), show
);
3068 event
.m_eventObject
= this;
3070 return GetEventHandler()->ProcessEvent(event
);
3073 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3075 wxInitDialogEvent
event(GetId());
3076 event
.m_eventObject
= this;
3078 return GetEventHandler()->ProcessEvent(event
);
3081 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3083 #ifndef __WXMICROWIN__
3084 HDROP hFilesInfo
= (HDROP
) wParam
;
3086 // Get the total number of files dropped
3087 UINT gwFilesDropped
= ::DragQueryFile
3095 wxString
*files
= new wxString
[gwFilesDropped
];
3096 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3098 // first get the needed buffer length (+1 for terminating NUL)
3099 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3101 // and now get the file name
3102 ::DragQueryFile(hFilesInfo
, wIndex
,
3103 files
[wIndex
].GetWriteBuf(len
), len
);
3105 files
[wIndex
].UngetWriteBuf();
3107 DragFinish (hFilesInfo
);
3109 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3110 event
.m_eventObject
= this;
3113 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3114 event
.m_pos
.x
= dropPoint
.x
;
3115 event
.m_pos
.y
= dropPoint
.y
;
3117 return GetEventHandler()->ProcessEvent(event
);
3118 #else // __WXMICROWIN__
3123 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3125 int WXUNUSED(mouseMsg
))
3127 #ifndef __WXMICROWIN__
3128 // the logic is as follows:
3129 // -1. don't set cursor for non client area, including but not limited to
3130 // the title bar, scrollbars, &c
3131 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3132 // 1. if we have the cursor set it unless wxIsBusy()
3133 // 2. if we're a top level window, set some cursor anyhow
3134 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3136 if ( nHitTest
!= HTCLIENT
)
3141 HCURSOR hcursor
= 0;
3143 // first ask the user code - it may wish to set the cursor in some very
3144 // specific way (for example, depending on the current position)
3147 if ( !::GetCursorPos(&pt
) )
3149 wxLogLastError(wxT("GetCursorPos"));
3152 // In WIN16 it doesn't return a value.
3153 ::GetCursorPos(&pt
);
3158 ScreenToClient(&x
, &y
);
3159 wxSetCursorEvent
event(x
, y
);
3161 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3162 if ( processedEvtSetCursor
&& event
.HasCursor() )
3164 hcursor
= GetHcursorOf(event
.GetCursor());
3169 bool isBusy
= wxIsBusy();
3171 // the test for processedEvtSetCursor is here to prevent using m_cursor
3172 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3173 // it - this is a way to say that our cursor shouldn't be used for this
3175 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3177 hcursor
= GetHcursorOf(m_cursor
);
3184 hcursor
= wxGetCurrentBusyCursor();
3186 else if ( !hcursor
)
3188 const wxCursor
*cursor
= wxGetGlobalCursor();
3189 if ( cursor
&& cursor
->Ok() )
3191 hcursor
= GetHcursorOf(*cursor
);
3199 ::SetCursor(hcursor
);
3201 // cursor set, stop here
3204 #endif // __WXMICROWIN__
3206 // pass up the window chain
3210 // ---------------------------------------------------------------------------
3211 // owner drawn stuff
3212 // ---------------------------------------------------------------------------
3214 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3216 #if wxUSE_OWNER_DRAWN
3218 #if wxUSE_MENUS_NATIVE
3219 // is it a menu item?
3220 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3221 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3223 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3225 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3227 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3228 // the DC from being released
3229 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3230 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3231 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3232 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3234 return pMenuItem
->OnDrawItem
3238 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3239 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3242 #endif // wxUSE_MENUS_NATIVE
3245 wxWindow
*item
= FindItem(id
);
3246 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3248 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3250 #endif // wxUSE_CONTROLS
3252 #endif // USE_OWNER_DRAWN
3257 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3259 #if wxUSE_OWNER_DRAWN
3260 // is it a menu item?
3261 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3262 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3264 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3266 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3268 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3269 &pMeasureStruct
->itemHeight
);
3272 wxWindow
*item
= FindItem(id
);
3273 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3275 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3277 #endif // owner-drawn menus
3281 // ---------------------------------------------------------------------------
3282 // colours and palettes
3283 // ---------------------------------------------------------------------------
3285 bool wxWindowMSW::HandleSysColorChange()
3287 wxSysColourChangedEvent event
;
3288 event
.SetEventObject(this);
3290 (void)GetEventHandler()->ProcessEvent(event
);
3292 // always let the system carry on the default processing to allow the
3293 // native controls to react to the colours update
3297 bool wxWindowMSW::HandleDisplayChange()
3299 wxDisplayChangedEvent event
;
3300 event
.SetEventObject(this);
3302 return GetEventHandler()->ProcessEvent(event
);
3305 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3313 #ifndef __WXMICROWIN__
3314 WXHBRUSH hBrush
= 0;
3316 if ( nCtlColor
== CTLCOLOR_DLG
)
3318 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3323 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3325 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3327 #endif // wxUSE_CONTROLS
3333 #else // __WXMICROWIN__
3338 // Define for each class of dialog and control
3339 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3340 WXHWND
WXUNUSED(hWnd
),
3341 WXUINT
WXUNUSED(nCtlColor
),
3342 WXUINT
WXUNUSED(message
),
3343 WXWPARAM
WXUNUSED(wParam
),
3344 WXLPARAM
WXUNUSED(lParam
))
3349 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3352 // same as below except we don't respond to our own messages
3353 if ( hWndPalChange
!= GetHWND() )
3355 // check to see if we our our parents have a custom palette
3356 wxWindow
*win
= this;
3357 while ( win
&& !win
->HasCustomPalette() )
3359 win
= win
->GetParent();
3362 if ( win
&& win
->HasCustomPalette() )
3364 // realize the palette to see whether redrawing is needed
3365 HDC hdc
= ::GetDC((HWND
) hWndPalChange
);
3366 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3367 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3369 int result
= ::RealizePalette(hdc
);
3371 // restore the palette (before releasing the DC)
3372 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3373 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3374 ::RealizePalette(hdc
);
3375 ::ReleaseDC((HWND
) hWndPalChange
, hdc
);
3377 // now check for the need to redraw
3379 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
);
3383 #endif // wxUSE_PALETTE
3385 wxPaletteChangedEvent
event(GetId());
3386 event
.SetEventObject(this);
3387 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3389 return GetEventHandler()->ProcessEvent(event
);
3392 bool wxWindowMSW::HandleQueryNewPalette()
3396 // check to see if we our our parents have a custom palette
3397 wxWindow
*win
= this;
3398 while (!win
->HasCustomPalette() && win
->GetParent()) win
= win
->GetParent();
3399 if (win
->HasCustomPalette()) {
3400 /* realize the palette to see whether redrawing is needed */
3401 HDC hdc
= GetDC((HWND
) GetHWND());
3402 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3403 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) );
3405 int result
= ::RealizePalette(hdc
);
3406 /* restore the palette (before releasing the DC) */
3407 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3408 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) );
3409 ::RealizePalette(hdc
);
3410 ::ReleaseDC((HWND
) GetHWND(), hdc
);
3411 /* now check for the need to redraw */
3413 ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
);
3415 #endif // wxUSE_PALETTE
3417 wxQueryNewPaletteEvent
event(GetId());
3418 event
.SetEventObject(this);
3420 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3423 // Responds to colour changes: passes event on to children.
3424 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
))
3426 // the top level window also reset the standard colour map as it might have
3427 // changed (there is no need to do it for the non top level windows as we
3428 // only have to do it once)
3432 gs_hasStdCmap
= FALSE
;
3434 wxWindowList::Node
*node
= GetChildren().GetFirst();
3437 // Only propagate to non-top-level windows because Windows already
3438 // sends this event to all top-level ones
3439 wxWindow
*win
= node
->GetData();
3440 if ( !win
->IsTopLevel() )
3442 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3443 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3444 // the standard controls
3445 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3448 node
= node
->GetNext();
3451 // update the colours we use if they were not set explicitly by the user:
3452 // this must be done or OnCtlColor() would continue to use the old colours
3455 m_foregroundColour
= wxSystemSettings::
3456 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3461 m_backgroundColour
= wxSystemSettings::
3462 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3466 extern wxCOLORMAP
*wxGetStdColourMap()
3468 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3469 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3471 if ( !gs_hasStdCmap
)
3473 static bool s_coloursInit
= FALSE
;
3475 if ( !s_coloursInit
)
3477 // When a bitmap is loaded, the RGB values can change (apparently
3478 // because Windows adjusts them to care for the old programs always
3479 // using 0xc0c0c0 while the transparent colour for the new Windows
3480 // versions is different). But we do this adjustment ourselves so
3481 // we want to avoid Windows' "help" and for this we need to have a
3482 // reference bitmap which can tell us what the RGB values change
3484 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3485 if ( stdColourBitmap
.Ok() )
3487 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3488 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3489 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3492 memDC
.SelectObject(stdColourBitmap
);
3495 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3497 memDC
.GetPixel(i
, 0, &colour
);
3498 s_stdColours
[i
] = wxColourToRGB(colour
);
3501 else // wxBITMAP_STD_COLOURS couldn't be loaded
3503 s_stdColours
[0] = RGB(000,000,000); // black
3504 s_stdColours
[1] = RGB(128,128,128); // dark grey
3505 s_stdColours
[2] = RGB(192,192,192); // light grey
3506 s_stdColours
[3] = RGB(255,255,255); // white
3507 //s_stdColours[4] = RGB(000,000,255); // blue
3508 //s_stdColours[5] = RGB(255,000,255); // magenta
3511 s_coloursInit
= TRUE
;
3514 gs_hasStdCmap
= TRUE
;
3516 // create the colour map
3517 #define INIT_CMAP_ENTRY(col) \
3518 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3519 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3521 INIT_CMAP_ENTRY(BTNTEXT
);
3522 INIT_CMAP_ENTRY(BTNSHADOW
);
3523 INIT_CMAP_ENTRY(BTNFACE
);
3524 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3526 #undef INIT_CMAP_ENTRY
3532 // ---------------------------------------------------------------------------
3534 // ---------------------------------------------------------------------------
3536 bool wxWindowMSW::HandlePaint()
3539 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3541 wxLogLastError(wxT("CreateRectRgn"));
3542 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3543 wxLogLastError(wxT("GetUpdateRgn"));
3545 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3548 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3550 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3551 updateRect
.right
- updateRect
.left
,
3552 updateRect
.bottom
- updateRect
.top
);
3555 wxPaintEvent
event(m_windowId
);
3556 event
.SetEventObject(this);
3558 bool processed
= GetEventHandler()->ProcessEvent(event
);
3560 // note that we must generate NC event after the normal one as otherwise
3561 // BeginPaint() will happily overwrite our decorations with the background
3563 wxNcPaintEvent
eventNc(m_windowId
);
3564 eventNc
.SetEventObject(this);
3565 GetEventHandler()->ProcessEvent(eventNc
);
3570 // Can be called from an application's OnPaint handler
3571 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3573 #ifdef __WXUNIVERSAL__
3576 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3579 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3584 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3586 // Prevents flicker when dragging
3587 if ( ::IsIconic(GetHwnd()) )
3593 dc
.SetWindow((wxWindow
*)this);
3596 wxEraseEvent
event(m_windowId
, &dc
);
3597 event
.SetEventObject(this);
3598 bool rc
= GetEventHandler()->ProcessEvent(event
);
3602 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3603 dc
.SelectOldObjects(hdc
);
3608 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3611 ::GetClientRect(GetHwnd(), &rect
);
3613 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3614 m_backgroundColour
.Green(),
3615 m_backgroundColour
.Blue());
3616 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3618 wxLogLastError(wxT("CreateSolidBrush"));
3620 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3622 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3624 ::FillRect(hdc
, &rect
, hBrush
);
3625 ::DeleteObject(hBrush
);
3626 ::SetMapMode(hdc
, mode
);
3629 // ---------------------------------------------------------------------------
3630 // moving and resizing
3631 // ---------------------------------------------------------------------------
3633 bool wxWindowMSW::HandleMinimize()
3635 wxIconizeEvent
event(m_windowId
);
3636 event
.SetEventObject(this);
3638 return GetEventHandler()->ProcessEvent(event
);
3641 bool wxWindowMSW::HandleMaximize()
3643 wxMaximizeEvent
event(m_windowId
);
3644 event
.SetEventObject(this);
3646 return GetEventHandler()->ProcessEvent(event
);
3649 bool wxWindowMSW::HandleMove(int x
, int y
)
3651 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3652 event
.SetEventObject(this);
3654 return GetEventHandler()->ProcessEvent(event
);
3657 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3659 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3660 event
.SetEventObject(this);
3662 return GetEventHandler()->ProcessEvent(event
);
3665 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3667 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3671 int minWidth
= GetMinWidth(),
3672 minHeight
= GetMinHeight(),
3673 maxWidth
= GetMaxWidth(),
3674 maxHeight
= GetMaxHeight();
3676 if ( minWidth
!= -1 )
3678 info
->ptMinTrackSize
.x
= minWidth
;
3682 if ( minHeight
!= -1 )
3684 info
->ptMinTrackSize
.y
= minHeight
;
3688 if ( maxWidth
!= -1 )
3690 info
->ptMaxTrackSize
.x
= maxWidth
;
3694 if ( maxHeight
!= -1 )
3696 info
->ptMaxTrackSize
.y
= maxHeight
;
3703 // ---------------------------------------------------------------------------
3705 // ---------------------------------------------------------------------------
3707 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3709 #if wxUSE_MENUS_NATIVE
3710 if ( !cmd
&& wxCurrentPopupMenu
)
3712 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3713 wxCurrentPopupMenu
= NULL
;
3715 return popupMenu
->MSWCommand(cmd
, id
);
3717 #endif // wxUSE_MENUS_NATIVE
3719 wxWindow
*win
= NULL
;
3721 // first try to find it from HWND - this works even with the broken
3722 // programs using the same ids for different controls
3725 win
= wxFindWinFromHandle(control
);
3731 // must cast to a signed type before comparing with other ids!
3732 win
= FindItem((signed short)id
);
3737 return win
->MSWCommand(cmd
, id
);
3740 // the messages sent from the in-place edit control used by the treectrl
3741 // for label editing have id == 0, but they should _not_ be treated as menu
3742 // messages (they are EN_XXX ones, in fact) so don't translate anything
3743 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3746 // If no child window, it may be an accelerator, e.g. for a popup menu
3749 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3750 event
.SetEventObject(this);
3754 return GetEventHandler()->ProcessEvent(event
);
3756 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3759 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3760 // notifications to its parent which we want to reflect back to
3762 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3763 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3766 #endif // wxUSE_SPINCTRL
3771 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3773 // 4 bits are reserved
3774 switch ( wParam
& 0xFFFFFFF0 )
3777 return HandleMaximize();
3780 return HandleMinimize();
3786 // ---------------------------------------------------------------------------
3788 // ---------------------------------------------------------------------------
3790 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3794 // our client coords are not quite the same as Windows ones
3795 wxPoint pt
= GetClientAreaOrigin();
3796 event
.m_x
= x
- pt
.x
;
3797 event
.m_y
= y
- pt
.y
;
3799 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3800 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3801 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3802 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3803 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3804 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3806 event
.SetTimestamp(s_currentMsg
.time
);
3807 event
.m_eventObject
= this;
3809 #if wxUSE_MOUSEEVENT_HACK
3812 m_lastMouseEvent
= event
.GetEventType();
3813 #endif // wxUSE_MOUSEEVENT_HACK
3816 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3818 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3819 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3820 // from the message id and take the value in the table to get wxWin event
3822 static const wxEventType eventsMouse
[] =
3836 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3837 InitMouseEvent(event
, x
, y
, flags
);
3839 return GetEventHandler()->ProcessEvent(event
);
3842 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3844 if ( !m_mouseInWindow
)
3846 // it would be wrong to assume that just because we get a mouse move
3847 // event that the mouse is inside the window: although this is usually
3848 // true, it is not if we had captured the mouse, so we need to check
3849 // the mouse coordinates here
3850 if ( !HasCapture() || IsMouseInWindow() )
3852 // Generate an ENTER event
3853 m_mouseInWindow
= TRUE
;
3855 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3856 InitMouseEvent(event
, x
, y
, flags
);
3858 (void)GetEventHandler()->ProcessEvent(event
);
3862 #if wxUSE_MOUSEEVENT_HACK
3863 // Window gets a click down message followed by a mouse move message even
3864 // if position isn't changed! We want to discard the trailing move event
3865 // if x and y are the same.
3866 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3867 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3868 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3869 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3871 m_lastMouseEvent
= wxEVT_MOTION
;
3875 #endif // wxUSE_MOUSEEVENT_HACK
3877 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3881 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3883 #if wxUSE_MOUSEWHEEL
3884 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3885 InitMouseEvent(event
,
3886 GET_X_LPARAM(lParam
),
3887 GET_Y_LPARAM(lParam
),
3889 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3890 event
.m_wheelDelta
= WHEEL_DELTA
;
3893 static int s_linesPerRotation
= -1;
3894 if ( s_linesPerRotation
== -1 )
3896 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3897 &s_linesPerRotation
, 0))
3899 // this is not supposed to happen
3900 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3902 // the default is 3, so use it if SystemParametersInfo() failed
3903 s_linesPerRotation
= 3;
3907 // no SystemParametersInfo() under Win16
3908 static const int s_linesPerRotation
= 3;
3911 event
.m_linesPerAction
= s_linesPerRotation
;
3912 return GetEventHandler()->ProcessEvent(event
);
3923 // ---------------------------------------------------------------------------
3924 // keyboard handling
3925 // ---------------------------------------------------------------------------
3927 // create the key event of the given type for the given key - used by
3928 // HandleChar and HandleKeyDown/Up
3929 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3931 WXLPARAM lParam
) const
3933 wxKeyEvent
event(evType
);
3934 event
.SetId(GetId());
3935 event
.m_shiftDown
= wxIsShiftDown();
3936 event
.m_controlDown
= wxIsCtrlDown();
3937 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3939 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3940 event
.m_keyCode
= id
;
3941 event
.SetTimestamp(s_currentMsg
.time
);
3943 // translate the position to client coords
3947 GetWindowRect(GetHwnd(),&rect
);
3957 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3959 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3961 bool ctrlDown
= FALSE
;
3966 // If 1 -> 26, translate to CTRL plus a letter.
3968 if ( (id
> 0) && (id
< 27) )
3990 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3992 // it's ASCII and will be processed here only when called from
3993 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3999 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
4002 event
.m_controlDown
= TRUE
;
4005 if ( GetEventHandler()->ProcessEvent(event
) )
4012 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
4014 int id
= wxCharCodeMSWToWX(wParam
);
4018 // normal ASCII char
4022 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4024 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
4025 if ( GetEventHandler()->ProcessEvent(event
) )
4034 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
4036 int id
= wxCharCodeMSWToWX(wParam
);
4040 // normal ASCII char
4044 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4046 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
4047 if ( GetEventHandler()->ProcessEvent(event
) )
4054 // ---------------------------------------------------------------------------
4056 // ---------------------------------------------------------------------------
4058 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4062 if ( flags
& JOY_BUTTON1CHG
)
4063 change
= wxJOY_BUTTON1
;
4064 if ( flags
& JOY_BUTTON2CHG
)
4065 change
= wxJOY_BUTTON2
;
4066 if ( flags
& JOY_BUTTON3CHG
)
4067 change
= wxJOY_BUTTON3
;
4068 if ( flags
& JOY_BUTTON4CHG
)
4069 change
= wxJOY_BUTTON4
;
4072 if ( flags
& JOY_BUTTON1
)
4073 buttons
|= wxJOY_BUTTON1
;
4074 if ( flags
& JOY_BUTTON2
)
4075 buttons
|= wxJOY_BUTTON2
;
4076 if ( flags
& JOY_BUTTON3
)
4077 buttons
|= wxJOY_BUTTON3
;
4078 if ( flags
& JOY_BUTTON4
)
4079 buttons
|= wxJOY_BUTTON4
;
4081 // the event ids aren't consecutive so we can't use table based lookup
4083 wxEventType eventType
;
4088 eventType
= wxEVT_JOY_MOVE
;
4093 eventType
= wxEVT_JOY_MOVE
;
4098 eventType
= wxEVT_JOY_ZMOVE
;
4103 eventType
= wxEVT_JOY_ZMOVE
;
4106 case MM_JOY1BUTTONDOWN
:
4108 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4111 case MM_JOY2BUTTONDOWN
:
4113 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4116 case MM_JOY1BUTTONUP
:
4118 eventType
= wxEVT_JOY_BUTTON_UP
;
4121 case MM_JOY2BUTTONUP
:
4123 eventType
= wxEVT_JOY_BUTTON_UP
;
4127 wxFAIL_MSG(wxT("no such joystick event"));
4132 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4133 event
.SetPosition(wxPoint(x
, y
));
4134 event
.SetEventObject(this);
4136 return GetEventHandler()->ProcessEvent(event
);
4142 // ---------------------------------------------------------------------------
4144 // ---------------------------------------------------------------------------
4146 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4147 WXWORD pos
, WXHWND control
)
4151 wxWindow
*child
= wxFindWinFromHandle(control
);
4153 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4156 wxScrollWinEvent event
;
4157 event
.SetPosition(pos
);
4158 event
.SetOrientation(orientation
);
4159 event
.m_eventObject
= this;
4164 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4168 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4172 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4176 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4180 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4184 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4187 case SB_THUMBPOSITION
:
4190 // under Win32, the scrollbar range and position are 32 bit integers,
4191 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4192 // explicitly query the scrollbar for the correct position (this must
4193 // be done only for these two SB_ events as they are the only one
4194 // carrying the scrollbar position)
4196 SCROLLINFO scrollInfo
;
4197 wxZeroMemory(scrollInfo
);
4198 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4199 scrollInfo
.fMask
= SIF_TRACKPOS
;
4201 if ( !::GetScrollInfo(GetHwnd(),
4202 orientation
== wxHORIZONTAL
? SB_HORZ
4206 wxLogLastError(_T("GetScrollInfo"));
4209 event
.SetPosition(scrollInfo
.nTrackPos
);
4213 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4214 ? wxEVT_SCROLLWIN_THUMBRELEASE
4215 : wxEVT_SCROLLWIN_THUMBTRACK
;
4222 return GetEventHandler()->ProcessEvent(event
);
4225 // ===========================================================================
4227 // ===========================================================================
4229 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4232 HDC dc
= ::GetDC((HWND
) wnd
);
4237 // the_font->UseResource();
4238 // the_font->RealizeResource();
4239 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4241 was
= (HFONT
) SelectObject(dc
,fnt
);
4243 GetTextMetrics(dc
, &tm
);
4244 if ( the_font
&& fnt
&& was
)
4246 SelectObject(dc
,was
);
4248 ReleaseDC((HWND
)wnd
, dc
);
4251 *x
= tm
.tmAveCharWidth
;
4253 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4256 // the_font->ReleaseResource();
4259 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4260 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4261 int wxCharCodeMSWToWX(int keySym
)
4266 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4267 case VK_BACK
: id
= WXK_BACK
; break;
4268 case VK_TAB
: id
= WXK_TAB
; break;
4269 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4270 case VK_RETURN
: id
= WXK_RETURN
; break;
4271 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4272 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4273 case VK_MENU
: id
= WXK_MENU
; break;
4274 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4275 case VK_SPACE
: id
= WXK_SPACE
; break;
4276 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4277 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4278 case VK_NEXT
: id
= WXK_NEXT
; break;
4279 case VK_END
: id
= WXK_END
; break;
4280 case VK_HOME
: id
= WXK_HOME
; break;
4281 case VK_LEFT
: id
= WXK_LEFT
; break;
4282 case VK_UP
: id
= WXK_UP
; break;
4283 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4284 case VK_DOWN
: id
= WXK_DOWN
; break;
4285 case VK_SELECT
: id
= WXK_SELECT
; break;
4286 case VK_PRINT
: id
= WXK_PRINT
; break;
4287 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4288 case VK_INSERT
: id
= WXK_INSERT
; break;
4289 case VK_DELETE
: id
= WXK_DELETE
; break;
4290 case VK_HELP
: id
= WXK_HELP
; break;
4291 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4292 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4293 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4294 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4295 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4296 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4297 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4298 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4299 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4300 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4301 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4302 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4303 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4304 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4305 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4306 case VK_F1
: id
= WXK_F1
; break;
4307 case VK_F2
: id
= WXK_F2
; break;
4308 case VK_F3
: id
= WXK_F3
; break;
4309 case VK_F4
: id
= WXK_F4
; break;
4310 case VK_F5
: id
= WXK_F5
; break;
4311 case VK_F6
: id
= WXK_F6
; break;
4312 case VK_F7
: id
= WXK_F7
; break;
4313 case VK_F8
: id
= WXK_F8
; break;
4314 case VK_F9
: id
= WXK_F9
; break;
4315 case VK_F10
: id
= WXK_F10
; break;
4316 case VK_F11
: id
= WXK_F11
; break;
4317 case VK_F12
: id
= WXK_F12
; break;
4318 case VK_F13
: id
= WXK_F13
; break;
4319 case VK_F14
: id
= WXK_F14
; break;
4320 case VK_F15
: id
= WXK_F15
; break;
4321 case VK_F16
: id
= WXK_F16
; break;
4322 case VK_F17
: id
= WXK_F17
; break;
4323 case VK_F18
: id
= WXK_F18
; break;
4324 case VK_F19
: id
= WXK_F19
; break;
4325 case VK_F20
: id
= WXK_F20
; break;
4326 case VK_F21
: id
= WXK_F21
; break;
4327 case VK_F22
: id
= WXK_F22
; break;
4328 case VK_F23
: id
= WXK_F23
; break;
4329 case VK_F24
: id
= WXK_F24
; break;
4330 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4331 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4339 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4345 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4346 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4347 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4348 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4349 case WXK_MENU
: keySym
= VK_MENU
; break;
4350 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4351 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4352 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4353 case WXK_END
: keySym
= VK_END
; break;
4354 case WXK_HOME
: keySym
= VK_HOME
; break;
4355 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4356 case WXK_UP
: keySym
= VK_UP
; break;
4357 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4358 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4359 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4360 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4361 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4362 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4363 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4364 case WXK_HELP
: keySym
= VK_HELP
; break;
4365 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4366 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4367 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4368 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4369 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4370 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4371 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4372 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4373 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4374 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4375 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4376 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4377 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4378 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4379 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4380 case WXK_F1
: keySym
= VK_F1
; break;
4381 case WXK_F2
: keySym
= VK_F2
; break;
4382 case WXK_F3
: keySym
= VK_F3
; break;
4383 case WXK_F4
: keySym
= VK_F4
; break;
4384 case WXK_F5
: keySym
= VK_F5
; break;
4385 case WXK_F6
: keySym
= VK_F6
; break;
4386 case WXK_F7
: keySym
= VK_F7
; break;
4387 case WXK_F8
: keySym
= VK_F8
; break;
4388 case WXK_F9
: keySym
= VK_F9
; break;
4389 case WXK_F10
: keySym
= VK_F10
; break;
4390 case WXK_F11
: keySym
= VK_F11
; break;
4391 case WXK_F12
: keySym
= VK_F12
; break;
4392 case WXK_F13
: keySym
= VK_F13
; break;
4393 case WXK_F14
: keySym
= VK_F14
; break;
4394 case WXK_F15
: keySym
= VK_F15
; break;
4395 case WXK_F16
: keySym
= VK_F16
; break;
4396 case WXK_F17
: keySym
= VK_F17
; break;
4397 case WXK_F18
: keySym
= VK_F18
; break;
4398 case WXK_F19
: keySym
= VK_F19
; break;
4399 case WXK_F20
: keySym
= VK_F20
; break;
4400 case WXK_F21
: keySym
= VK_F21
; break;
4401 case WXK_F22
: keySym
= VK_F22
; break;
4402 case WXK_F23
: keySym
= VK_F23
; break;
4403 case WXK_F24
: keySym
= VK_F24
; break;
4404 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4405 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4416 wxWindow
*wxGetActiveWindow()
4418 HWND hWnd
= GetActiveWindow();
4421 return wxFindWinFromHandle((WXHWND
) hWnd
);
4426 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4428 HWND hwnd
= (HWND
)hWnd
;
4430 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4431 // by code in msw/radiobox.cpp), for all the others we just search up the
4433 wxWindow
*win
= (wxWindow
*)NULL
;
4436 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4439 // all these hacks only work under Win32 anyhow
4443 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4444 // wxWindow class which overrides WM_GETDLGCODE processing to
4445 // do it as well, win would be already non NULL
4446 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4448 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4450 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4451 #endif // wxUSE_RADIOBOX
4453 // spin control text buddy window should be mapped to spin ctrl
4454 // itself so try it too
4455 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4458 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4460 #endif // wxUSE_SPINCTRL
4466 while ( hwnd
&& !win
)
4468 // this is a really ugly hack needed to avoid mistakenly returning the
4469 // parent frame wxWindow for the find/replace modeless dialog HWND -
4470 // this, in turn, is needed to call IsDialogMessage() from
4471 // wxApp::ProcessMessage() as for this we must return NULL from here
4473 // FIXME: this is clearly not the best way to do it but I think we'll
4474 // need to change HWND <-> wxWindow code more heavily than I can
4475 // do it now to fix it
4476 #ifndef __WXMICROWIN__
4477 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4479 // it's a dialog box, don't go upwards
4484 hwnd
= ::GetParent(hwnd
);
4485 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4491 #ifndef __WXMICROWIN__
4493 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4494 // in active frames and dialogs, regardless of where the focus is.
4495 static HHOOK wxTheKeyboardHook
= 0;
4496 static FARPROC wxTheKeyboardHookProc
= 0;
4497 int APIENTRY _EXPORT
4498 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4500 void wxSetKeyboardHook(bool doIt
)
4504 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4505 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4507 #if defined(__WIN32__) && !defined(__TWIN32__)
4508 GetCurrentThreadId()
4509 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4517 UnhookWindowsHookEx(wxTheKeyboardHook
);
4519 // avoids warning about statement with no effect (FreeProcInstance
4520 // doesn't do anything under Win32)
4521 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4522 FreeProcInstance(wxTheKeyboardHookProc
);
4527 int APIENTRY _EXPORT
4528 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4530 DWORD hiWord
= HIWORD(lParam
);
4531 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4533 int id
= wxCharCodeMSWToWX(wParam
);
4536 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4537 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4538 event
.m_altDown
= TRUE
;
4540 event
.m_eventObject
= NULL
;
4541 event
.m_keyCode
= id
;
4542 event
.m_shiftDown
= wxIsShiftDown();
4543 event
.m_controlDown
= wxIsCtrlDown();
4544 event
.SetTimestamp(s_currentMsg
.time
);
4546 wxWindow
*win
= wxGetActiveWindow();
4547 wxEvtHandler
*handler
;
4550 handler
= win
->GetEventHandler();
4551 event
.SetId(win
->GetId());
4559 if ( handler
&& handler
->ProcessEvent(event
) )
4567 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4570 #endif // !__WXMICROWIN__
4573 const char *wxGetMessageName(int message
)
4577 case 0x0000: return "WM_NULL";
4578 case 0x0001: return "WM_CREATE";
4579 case 0x0002: return "WM_DESTROY";
4580 case 0x0003: return "WM_MOVE";
4581 case 0x0005: return "WM_SIZE";
4582 case 0x0006: return "WM_ACTIVATE";
4583 case 0x0007: return "WM_SETFOCUS";
4584 case 0x0008: return "WM_KILLFOCUS";
4585 case 0x000A: return "WM_ENABLE";
4586 case 0x000B: return "WM_SETREDRAW";
4587 case 0x000C: return "WM_SETTEXT";
4588 case 0x000D: return "WM_GETTEXT";
4589 case 0x000E: return "WM_GETTEXTLENGTH";
4590 case 0x000F: return "WM_PAINT";
4591 case 0x0010: return "WM_CLOSE";
4592 case 0x0011: return "WM_QUERYENDSESSION";
4593 case 0x0012: return "WM_QUIT";
4594 case 0x0013: return "WM_QUERYOPEN";
4595 case 0x0014: return "WM_ERASEBKGND";
4596 case 0x0015: return "WM_SYSCOLORCHANGE";
4597 case 0x0016: return "WM_ENDSESSION";
4598 case 0x0017: return "WM_SYSTEMERROR";
4599 case 0x0018: return "WM_SHOWWINDOW";
4600 case 0x0019: return "WM_CTLCOLOR";
4601 case 0x001A: return "WM_WININICHANGE";
4602 case 0x001B: return "WM_DEVMODECHANGE";
4603 case 0x001C: return "WM_ACTIVATEAPP";
4604 case 0x001D: return "WM_FONTCHANGE";
4605 case 0x001E: return "WM_TIMECHANGE";
4606 case 0x001F: return "WM_CANCELMODE";
4607 case 0x0020: return "WM_SETCURSOR";
4608 case 0x0021: return "WM_MOUSEACTIVATE";
4609 case 0x0022: return "WM_CHILDACTIVATE";
4610 case 0x0023: return "WM_QUEUESYNC";
4611 case 0x0024: return "WM_GETMINMAXINFO";
4612 case 0x0026: return "WM_PAINTICON";
4613 case 0x0027: return "WM_ICONERASEBKGND";
4614 case 0x0028: return "WM_NEXTDLGCTL";
4615 case 0x002A: return "WM_SPOOLERSTATUS";
4616 case 0x002B: return "WM_DRAWITEM";
4617 case 0x002C: return "WM_MEASUREITEM";
4618 case 0x002D: return "WM_DELETEITEM";
4619 case 0x002E: return "WM_VKEYTOITEM";
4620 case 0x002F: return "WM_CHARTOITEM";
4621 case 0x0030: return "WM_SETFONT";
4622 case 0x0031: return "WM_GETFONT";
4623 case 0x0037: return "WM_QUERYDRAGICON";
4624 case 0x0039: return "WM_COMPAREITEM";
4625 case 0x0041: return "WM_COMPACTING";
4626 case 0x0044: return "WM_COMMNOTIFY";
4627 case 0x0046: return "WM_WINDOWPOSCHANGING";
4628 case 0x0047: return "WM_WINDOWPOSCHANGED";
4629 case 0x0048: return "WM_POWER";
4632 case 0x004A: return "WM_COPYDATA";
4633 case 0x004B: return "WM_CANCELJOURNAL";
4634 case 0x004E: return "WM_NOTIFY";
4635 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4636 case 0x0051: return "WM_INPUTLANGCHANGE";
4637 case 0x0052: return "WM_TCARD";
4638 case 0x0053: return "WM_HELP";
4639 case 0x0054: return "WM_USERCHANGED";
4640 case 0x0055: return "WM_NOTIFYFORMAT";
4641 case 0x007B: return "WM_CONTEXTMENU";
4642 case 0x007C: return "WM_STYLECHANGING";
4643 case 0x007D: return "WM_STYLECHANGED";
4644 case 0x007E: return "WM_DISPLAYCHANGE";
4645 case 0x007F: return "WM_GETICON";
4646 case 0x0080: return "WM_SETICON";
4649 case 0x0081: return "WM_NCCREATE";
4650 case 0x0082: return "WM_NCDESTROY";
4651 case 0x0083: return "WM_NCCALCSIZE";
4652 case 0x0084: return "WM_NCHITTEST";
4653 case 0x0085: return "WM_NCPAINT";
4654 case 0x0086: return "WM_NCACTIVATE";
4655 case 0x0087: return "WM_GETDLGCODE";
4656 case 0x00A0: return "WM_NCMOUSEMOVE";
4657 case 0x00A1: return "WM_NCLBUTTONDOWN";
4658 case 0x00A2: return "WM_NCLBUTTONUP";
4659 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4660 case 0x00A4: return "WM_NCRBUTTONDOWN";
4661 case 0x00A5: return "WM_NCRBUTTONUP";
4662 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4663 case 0x00A7: return "WM_NCMBUTTONDOWN";
4664 case 0x00A8: return "WM_NCMBUTTONUP";
4665 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4666 case 0x0100: return "WM_KEYDOWN";
4667 case 0x0101: return "WM_KEYUP";
4668 case 0x0102: return "WM_CHAR";
4669 case 0x0103: return "WM_DEADCHAR";
4670 case 0x0104: return "WM_SYSKEYDOWN";
4671 case 0x0105: return "WM_SYSKEYUP";
4672 case 0x0106: return "WM_SYSCHAR";
4673 case 0x0107: return "WM_SYSDEADCHAR";
4674 case 0x0108: return "WM_KEYLAST";
4677 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4678 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4679 case 0x010F: return "WM_IME_COMPOSITION";
4682 case 0x0110: return "WM_INITDIALOG";
4683 case 0x0111: return "WM_COMMAND";
4684 case 0x0112: return "WM_SYSCOMMAND";
4685 case 0x0113: return "WM_TIMER";
4686 case 0x0114: return "WM_HSCROLL";
4687 case 0x0115: return "WM_VSCROLL";
4688 case 0x0116: return "WM_INITMENU";
4689 case 0x0117: return "WM_INITMENUPOPUP";
4690 case 0x011F: return "WM_MENUSELECT";
4691 case 0x0120: return "WM_MENUCHAR";
4692 case 0x0121: return "WM_ENTERIDLE";
4693 case 0x0200: return "WM_MOUSEMOVE";
4694 case 0x0201: return "WM_LBUTTONDOWN";
4695 case 0x0202: return "WM_LBUTTONUP";
4696 case 0x0203: return "WM_LBUTTONDBLCLK";
4697 case 0x0204: return "WM_RBUTTONDOWN";
4698 case 0x0205: return "WM_RBUTTONUP";
4699 case 0x0206: return "WM_RBUTTONDBLCLK";
4700 case 0x0207: return "WM_MBUTTONDOWN";
4701 case 0x0208: return "WM_MBUTTONUP";
4702 case 0x0209: return "WM_MBUTTONDBLCLK";
4703 case 0x020A: return "WM_MOUSEWHEEL";
4704 case 0x0210: return "WM_PARENTNOTIFY";
4705 case 0x0211: return "WM_ENTERMENULOOP";
4706 case 0x0212: return "WM_EXITMENULOOP";
4709 case 0x0213: return "WM_NEXTMENU";
4710 case 0x0214: return "WM_SIZING";
4711 case 0x0215: return "WM_CAPTURECHANGED";
4712 case 0x0216: return "WM_MOVING";
4713 case 0x0218: return "WM_POWERBROADCAST";
4714 case 0x0219: return "WM_DEVICECHANGE";
4717 case 0x0220: return "WM_MDICREATE";
4718 case 0x0221: return "WM_MDIDESTROY";
4719 case 0x0222: return "WM_MDIACTIVATE";
4720 case 0x0223: return "WM_MDIRESTORE";
4721 case 0x0224: return "WM_MDINEXT";
4722 case 0x0225: return "WM_MDIMAXIMIZE";
4723 case 0x0226: return "WM_MDITILE";
4724 case 0x0227: return "WM_MDICASCADE";
4725 case 0x0228: return "WM_MDIICONARRANGE";
4726 case 0x0229: return "WM_MDIGETACTIVE";
4727 case 0x0230: return "WM_MDISETMENU";
4728 case 0x0233: return "WM_DROPFILES";
4731 case 0x0281: return "WM_IME_SETCONTEXT";
4732 case 0x0282: return "WM_IME_NOTIFY";
4733 case 0x0283: return "WM_IME_CONTROL";
4734 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4735 case 0x0285: return "WM_IME_SELECT";
4736 case 0x0286: return "WM_IME_CHAR";
4737 case 0x0290: return "WM_IME_KEYDOWN";
4738 case 0x0291: return "WM_IME_KEYUP";
4741 case 0x0300: return "WM_CUT";
4742 case 0x0301: return "WM_COPY";
4743 case 0x0302: return "WM_PASTE";
4744 case 0x0303: return "WM_CLEAR";
4745 case 0x0304: return "WM_UNDO";
4746 case 0x0305: return "WM_RENDERFORMAT";
4747 case 0x0306: return "WM_RENDERALLFORMATS";
4748 case 0x0307: return "WM_DESTROYCLIPBOARD";
4749 case 0x0308: return "WM_DRAWCLIPBOARD";
4750 case 0x0309: return "WM_PAINTCLIPBOARD";
4751 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4752 case 0x030B: return "WM_SIZECLIPBOARD";
4753 case 0x030C: return "WM_ASKCBFORMATNAME";
4754 case 0x030D: return "WM_CHANGECBCHAIN";
4755 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4756 case 0x030F: return "WM_QUERYNEWPALETTE";
4757 case 0x0310: return "WM_PALETTEISCHANGING";
4758 case 0x0311: return "WM_PALETTECHANGED";
4761 // common controls messages - although they're not strictly speaking
4762 // standard, it's nice to decode them nevertheless
4765 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4766 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4767 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4768 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4769 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4770 case 0x1000 + 5: return "LVM_GETITEMA";
4771 case 0x1000 + 75: return "LVM_GETITEMW";
4772 case 0x1000 + 6: return "LVM_SETITEMA";
4773 case 0x1000 + 76: return "LVM_SETITEMW";
4774 case 0x1000 + 7: return "LVM_INSERTITEMA";
4775 case 0x1000 + 77: return "LVM_INSERTITEMW";
4776 case 0x1000 + 8: return "LVM_DELETEITEM";
4777 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4778 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4779 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4780 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4781 case 0x1000 + 13: return "LVM_FINDITEMA";
4782 case 0x1000 + 83: return "LVM_FINDITEMW";
4783 case 0x1000 + 14: return "LVM_GETITEMRECT";
4784 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4785 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4786 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4787 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4788 case 0x1000 + 18: return "LVM_HITTEST";
4789 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4790 case 0x1000 + 20: return "LVM_SCROLL";
4791 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4792 case 0x1000 + 22: return "LVM_ARRANGE";
4793 case 0x1000 + 23: return "LVM_EDITLABELA";
4794 case 0x1000 + 118: return "LVM_EDITLABELW";
4795 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4796 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4797 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4798 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4799 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4800 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4801 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4802 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4803 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4804 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4805 case 0x1000 + 31: return "LVM_GETHEADER";
4806 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4807 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4808 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4809 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4810 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4811 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4812 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4813 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4814 case 0x1000 + 41: return "LVM_GETORIGIN";
4815 case 0x1000 + 42: return "LVM_UPDATE";
4816 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4817 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4818 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4819 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4820 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4821 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4822 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4823 case 0x1000 + 48: return "LVM_SORTITEMS";
4824 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4825 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4826 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4827 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4828 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4829 case 0x1000 + 53: return "LVM_SETICONSPACING";
4830 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4831 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4832 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4833 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4834 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4835 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4836 case 0x1000 + 60: return "LVM_SETHOTITEM";
4837 case 0x1000 + 61: return "LVM_GETHOTITEM";
4838 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4839 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4840 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4841 case 0x1000 + 65: return "LVM_SETWORKAREA";
4844 case 0x1100 + 0: return "TVM_INSERTITEMA";
4845 case 0x1100 + 50: return "TVM_INSERTITEMW";
4846 case 0x1100 + 1: return "TVM_DELETEITEM";
4847 case 0x1100 + 2: return "TVM_EXPAND";
4848 case 0x1100 + 4: return "TVM_GETITEMRECT";
4849 case 0x1100 + 5: return "TVM_GETCOUNT";
4850 case 0x1100 + 6: return "TVM_GETINDENT";
4851 case 0x1100 + 7: return "TVM_SETINDENT";
4852 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4853 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4854 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4855 case 0x1100 + 11: return "TVM_SELECTITEM";
4856 case 0x1100 + 12: return "TVM_GETITEMA";
4857 case 0x1100 + 62: return "TVM_GETITEMW";
4858 case 0x1100 + 13: return "TVM_SETITEMA";
4859 case 0x1100 + 63: return "TVM_SETITEMW";
4860 case 0x1100 + 14: return "TVM_EDITLABELA";
4861 case 0x1100 + 65: return "TVM_EDITLABELW";
4862 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4863 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4864 case 0x1100 + 17: return "TVM_HITTEST";
4865 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4866 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4867 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4868 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4869 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4870 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4871 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4872 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4873 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4876 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4877 case 0x1200 + 1: return "HDM_INSERTITEMA";
4878 case 0x1200 + 10: return "HDM_INSERTITEMW";
4879 case 0x1200 + 2: return "HDM_DELETEITEM";
4880 case 0x1200 + 3: return "HDM_GETITEMA";
4881 case 0x1200 + 11: return "HDM_GETITEMW";
4882 case 0x1200 + 4: return "HDM_SETITEMA";
4883 case 0x1200 + 12: return "HDM_SETITEMW";
4884 case 0x1200 + 5: return "HDM_LAYOUT";
4885 case 0x1200 + 6: return "HDM_HITTEST";
4886 case 0x1200 + 7: return "HDM_GETITEMRECT";
4887 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4888 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4889 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4890 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4891 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4892 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4893 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4896 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4897 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4898 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4899 case 0x1300 + 5: return "TCM_GETITEMA";
4900 case 0x1300 + 60: return "TCM_GETITEMW";
4901 case 0x1300 + 6: return "TCM_SETITEMA";
4902 case 0x1300 + 61: return "TCM_SETITEMW";
4903 case 0x1300 + 7: return "TCM_INSERTITEMA";
4904 case 0x1300 + 62: return "TCM_INSERTITEMW";
4905 case 0x1300 + 8: return "TCM_DELETEITEM";
4906 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4907 case 0x1300 + 10: return "TCM_GETITEMRECT";
4908 case 0x1300 + 11: return "TCM_GETCURSEL";
4909 case 0x1300 + 12: return "TCM_SETCURSEL";
4910 case 0x1300 + 13: return "TCM_HITTEST";
4911 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4912 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4913 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4914 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4915 case 0x1300 + 43: return "TCM_SETPADDING";
4916 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4917 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4918 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4919 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4920 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4921 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4922 case 0x1300 + 50: return "TCM_DESELECTALL";
4925 case WM_USER
+1: return "TB_ENABLEBUTTON";
4926 case WM_USER
+2: return "TB_CHECKBUTTON";
4927 case WM_USER
+3: return "TB_PRESSBUTTON";
4928 case WM_USER
+4: return "TB_HIDEBUTTON";
4929 case WM_USER
+5: return "TB_INDETERMINATE";
4930 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4931 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4932 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4933 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4934 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4935 case WM_USER
+17: return "TB_SETSTATE";
4936 case WM_USER
+18: return "TB_GETSTATE";
4937 case WM_USER
+19: return "TB_ADDBITMAP";
4938 case WM_USER
+20: return "TB_ADDBUTTONS";
4939 case WM_USER
+21: return "TB_INSERTBUTTON";
4940 case WM_USER
+22: return "TB_DELETEBUTTON";
4941 case WM_USER
+23: return "TB_GETBUTTON";
4942 case WM_USER
+24: return "TB_BUTTONCOUNT";
4943 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4944 case WM_USER
+26: return "TB_SAVERESTOREA";
4945 case WM_USER
+76: return "TB_SAVERESTOREW";
4946 case WM_USER
+27: return "TB_CUSTOMIZE";
4947 case WM_USER
+28: return "TB_ADDSTRINGA";
4948 case WM_USER
+77: return "TB_ADDSTRINGW";
4949 case WM_USER
+29: return "TB_GETITEMRECT";
4950 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4951 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4952 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4953 case WM_USER
+33: return "TB_AUTOSIZE";
4954 case WM_USER
+35: return "TB_GETTOOLTIPS";
4955 case WM_USER
+36: return "TB_SETTOOLTIPS";
4956 case WM_USER
+37: return "TB_SETPARENT";
4957 case WM_USER
+39: return "TB_SETROWS";
4958 case WM_USER
+40: return "TB_GETROWS";
4959 case WM_USER
+42: return "TB_SETCMDID";
4960 case WM_USER
+43: return "TB_CHANGEBITMAP";
4961 case WM_USER
+44: return "TB_GETBITMAP";
4962 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4963 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4964 case WM_USER
+46: return "TB_REPLACEBITMAP";
4965 case WM_USER
+47: return "TB_SETINDENT";
4966 case WM_USER
+48: return "TB_SETIMAGELIST";
4967 case WM_USER
+49: return "TB_GETIMAGELIST";
4968 case WM_USER
+50: return "TB_LOADIMAGES";
4969 case WM_USER
+51: return "TB_GETRECT";
4970 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4971 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4972 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4973 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4974 case WM_USER
+56: return "TB_SETSTYLE";
4975 case WM_USER
+57: return "TB_GETSTYLE";
4976 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4977 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4978 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4979 case WM_USER
+61: return "TB_GETTEXTROWS";
4980 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4985 static char s_szBuf
[128];
4986 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4990 #endif //__WXDEBUG__
4992 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4993 int *x
, int *y
, WPARAM
*flags
)
4995 // construct the key mask
4996 WPARAM
& fwKeys
= *flags
;
4998 fwKeys
= MK_RBUTTON
;
4999 if ( wxIsCtrlDown() )
5000 fwKeys
|= MK_CONTROL
;
5001 if ( wxIsShiftDown() )
5004 // simulate right mouse button click
5005 DWORD dwPos
= ::GetMessagePos();
5006 *x
= GET_X_LPARAM(dwPos
);
5007 *y
= GET_Y_LPARAM(dwPos
);
5009 win
->ScreenToClient(x
, y
);
5012 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
5016 HWND hwnd
= GetHwndOf(win
);
5017 HDC hdc
= ::GetDC(hwnd
);
5019 #if !wxDIALOG_UNIT_COMPATIBILITY
5020 // and select the current font into it
5021 HFONT hfont
= GetHfontOf(win
->GetFont());
5024 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
5028 // finally retrieve the text metrics from it
5029 GetTextMetrics(hdc
, &tm
);
5031 #if !wxDIALOG_UNIT_COMPATIBILITY
5035 (void)::SelectObject(hdc
, hfont
);
5039 ::ReleaseDC(hwnd
, hdc
);
5044 // Find the wxWindow at the current mouse position, returning the mouse
5046 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
5048 return wxFindWindowAtPoint(wxGetMousePosition());
5051 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
5056 HWND hWndHit
= ::WindowFromPoint(pt2
);
5058 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
5059 HWND hWnd
= hWndHit
;
5061 // Try to find a window with a wxWindow associated with it
5062 while (!win
&& (hWnd
!= 0))
5064 hWnd
= ::GetParent(hWnd
);
5065 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
5070 // Get the current mouse position.
5071 wxPoint
wxGetMousePosition()
5074 GetCursorPos( & pt
);
5075 return wxPoint(pt
.x
, pt
.y
);