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
;
306 // pass WM_GETDLGCODE to DefWindowProc()
311 m_backgroundTransparent
= FALSE
;
313 // as all windows are created with WS_VISIBLE style...
316 #if wxUSE_MOUSEEVENT_HACK
319 m_lastMouseEvent
= -1;
320 #endif // wxUSE_MOUSEEVENT_HACK
324 wxWindowMSW::~wxWindowMSW()
326 m_isBeingDeleted
= TRUE
;
328 #ifndef __WXUNIVERSAL__
329 // VS: make sure there's no wxFrame with last focus set to us:
330 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
332 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
335 if ( frame
->GetLastFocus() == this )
337 frame
->SetLastFocus((wxWindow
*)NULL
);
342 #endif // __WXUNIVERSAL__
344 // VS: destroy children first and _then_ detach *this from its parent.
345 // If we'd do it the other way around, children wouldn't be able
346 // find their parent frame (see above).
350 m_parent
->RemoveChild(this);
354 // VZ: test temp removed to understand what really happens here
355 //if (::IsWindow(GetHwnd()))
357 if ( !::DestroyWindow(GetHwnd()) )
358 wxLogLastError(wxT("DestroyWindow"));
361 // remove hWnd <-> wxWindow association
362 wxRemoveHandleAssociation(this);
366 // real construction (Init() must have been called before!)
367 bool wxWindowMSW::Create(wxWindow
*parent
,
372 const wxString
& name
)
374 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
377 // wxGTK doesn't allow to create controls with static box as the parent so
378 // this will result in a crash when the program is ported to wxGTK - warn
381 // the correct solution is to create the controls as siblings of the
383 wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
),
384 _T("wxStaticBox can't be used as a window parent!") );
385 #endif // wxUSE_STATBOX
387 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
390 parent
->AddChild(this);
392 // all windows are created visible
393 DWORD msflags
= WS_CHILD
| WS_VISIBLE
;
395 #ifdef __WXUNIVERSAL__
396 // no 3d effects, we draw them ourselves
398 #else // !wxUniversal
399 if ( style
& wxCLIP_CHILDREN
)
400 msflags
|= WS_CLIPCHILDREN
;
401 if ( style
& wxCLIP_SIBLINGS
)
402 msflags
|= WS_CLIPSIBLINGS
;
405 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
);
407 // Even with extended styles, need to combine with WS_BORDER
408 // for them to look right.
410 (m_windowStyle
& (wxBORDER
|
416 msflags
|= WS_BORDER
;
419 // calculate the value to return from WM_GETDLGCODE handler
420 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
422 // want everything: i.e. all keys and WM_CHAR message
423 m_lDlgCode
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
424 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
426 #endif // wxUniversal/!wxUniversal
428 if ( style
& wxPOPUP_WINDOW
)
430 // a popup window floats on top of everything
431 exStyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
433 // it is also created hidden as other top level windows
434 msflags
&= ~WS_VISIBLE
;
438 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
);
441 // ---------------------------------------------------------------------------
443 // ---------------------------------------------------------------------------
445 void wxWindowMSW::SetFocus()
447 HWND hWnd
= GetHwnd();
448 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
450 #ifndef __WXMICROWIN__
454 if ( !::SetFocus(hWnd
) )
456 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
457 // was there really an error?
458 DWORD dwRes
= ::GetLastError();
461 HWND hwndFocus
= ::GetFocus();
462 if ( hwndFocus
!= hWnd
)
464 wxLogApiError(_T("SetFocus"), dwRes
);
471 // Get the window with the focus
472 wxWindow
*wxWindowBase::FindFocus()
474 HWND hWnd
= ::GetFocus();
477 return wxGetWindowFromHWND((WXHWND
)hWnd
);
483 bool wxWindowMSW::Enable(bool enable
)
485 if ( !wxWindowBase::Enable(enable
) )
488 HWND hWnd
= GetHwnd();
490 ::EnableWindow(hWnd
, (BOOL
)enable
);
492 // VZ: no, this is a bad idea: imagine that you have a dialog with some
493 // disabled controls and disable it - you really wouldn't like the
494 // disabled controls be reenabled too when you reenable the dialog!
496 wxWindowList::Node
*node
= GetChildren().GetFirst();
499 wxWindow
*child
= node
->GetData();
500 child
->Enable(enable
);
502 node
= node
->GetNext();
509 bool wxWindowMSW::Show(bool show
)
511 if ( !wxWindowBase::Show(show
) )
514 HWND hWnd
= GetHwnd();
515 int cshow
= show
? SW_SHOW
: SW_HIDE
;
516 ::ShowWindow(hWnd
, cshow
);
520 wxBringWindowToTop(hWnd
);
526 // Raise the window to the top of the Z order
527 void wxWindowMSW::Raise()
529 wxBringWindowToTop(GetHwnd());
532 // Lower the window to the bottom of the Z order
533 void wxWindowMSW::Lower()
535 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
536 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
539 void wxWindowMSW::SetTitle( const wxString
& title
)
541 SetWindowText(GetHwnd(), title
.c_str());
544 wxString
wxWindowMSW::GetTitle() const
546 return wxGetWindowText(GetHWND());
549 void wxWindowMSW::DoCaptureMouse()
551 HWND hWnd
= GetHwnd();
558 void wxWindowMSW::DoReleaseMouse()
560 if ( !::ReleaseCapture() )
562 wxLogLastError(_T("ReleaseCapture"));
566 /* static */ wxWindow
*wxWindowBase::GetCapture()
568 HWND hwnd
= ::GetCapture();
569 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
572 bool wxWindowMSW::SetFont(const wxFont
& font
)
574 if ( !wxWindowBase::SetFont(font
) )
580 HWND hWnd
= GetHwnd();
583 WXHANDLE hFont
= m_font
.GetResourceHandle();
585 wxASSERT_MSG( hFont
, wxT("should have valid font") );
587 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
592 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
594 if ( !wxWindowBase::SetCursor(cursor
) )
602 HWND hWnd
= GetHwnd();
604 // Change the cursor NOW if we're within the correct window
606 ::GetCursorPos(&point
);
608 RECT rect
= wxGetWindowRect(hWnd
);
610 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
611 ::SetCursor(GetHcursorOf(m_cursor
));
617 void wxWindowMSW::WarpPointer (int x
, int y
)
619 ClientToScreen(&x
, &y
);
621 if ( !::SetCursorPos(x
, y
) )
623 wxLogLastError(_T("SetCursorPos"));
627 #if WXWIN_COMPATIBILITY
628 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
631 #endif // WXWIN_COMPATIBILITY
633 // ---------------------------------------------------------------------------
635 // ---------------------------------------------------------------------------
637 #if WXWIN_COMPATIBILITY
638 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
640 #if defined(__WIN95__)
644 // Try to adjust the range to cope with page size > 1
645 // - a Windows API quirk
646 int pageSize
= GetScrollPage(orient
);
647 if ( pageSize
> 1 && range
> 0)
649 range1
+= (pageSize
- 1);
655 if ( orient
== wxHORIZONTAL
) {
661 info
.cbSize
= sizeof(SCROLLINFO
);
662 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
666 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
668 HWND hWnd
= GetHwnd();
670 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
673 if ( orient
== wxHORIZONTAL
)
678 HWND hWnd
= GetHwnd();
680 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
684 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
686 #if defined(__WIN95__)
690 if ( orient
== wxHORIZONTAL
) {
698 info
.cbSize
= sizeof(SCROLLINFO
);
701 info
.fMask
= SIF_PAGE
;
703 HWND hWnd
= GetHwnd();
705 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
707 if ( orient
== wxHORIZONTAL
)
714 int wxWindowMSW::OldGetScrollRange(int orient
) const
717 if ( orient
== wxHORIZONTAL
)
722 #if __WATCOMC__ && defined(__WINDOWS_386__)
723 short minPos
, maxPos
;
727 HWND hWnd
= GetHwnd();
730 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
731 #if defined(__WIN95__)
732 // Try to adjust the range to cope with page size > 1
733 // - a Windows API quirk
734 int pageSize
= GetScrollPage(orient
);
737 maxPos
-= (pageSize
- 1);
746 int wxWindowMSW::GetScrollPage(int orient
) const
748 if ( orient
== wxHORIZONTAL
)
754 #endif // WXWIN_COMPATIBILITY
756 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
758 #ifdef __WXMICROWIN__
759 return ::GetScrollPosWX(hWnd
, wOrient
);
761 return ::GetScrollPos(hWnd
, wOrient
);
765 int wxWindowMSW::GetScrollPos(int orient
) const
768 if ( orient
== wxHORIZONTAL
)
773 HWND hWnd
= GetHwnd();
774 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
776 return GetScrollPosition(hWnd
, wOrient
);
779 // This now returns the whole range, not just the number
780 // of positions that we can scroll.
781 int wxWindowMSW::GetScrollRange(int orient
) const
784 if ( orient
== wxHORIZONTAL
)
789 #if __WATCOMC__ && defined(__WINDOWS_386__)
790 short minPos
, maxPos
;
794 HWND hWnd
= GetHwnd();
797 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
798 #if defined(__WIN95__)
799 // Try to adjust the range to cope with page size > 1
800 // - a Windows API quirk
801 int pageSize
= GetScrollThumb(orient
);
804 maxPos
-= (pageSize
- 1);
806 // October 10th: new range concept.
816 int wxWindowMSW::GetScrollThumb(int orient
) const
818 if ( orient
== wxHORIZONTAL
)
824 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
826 HWND hWnd
= GetHwnd();
827 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
829 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
831 #if defined(__WIN95__)
833 info
.cbSize
= sizeof(SCROLLINFO
);
837 info
.fMask
= SIF_POS
;
839 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
841 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
842 #endif // __WIN95__/!__WIN95__
845 // New function that will replace some of the above.
846 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
847 int range
, bool refresh
)
849 #if defined(__WIN95__)
850 int oldRange
= range
- thumbVisible
;
852 int range1
= oldRange
;
854 // Try to adjust the range to cope with page size > 1
855 // - a Windows API quirk
856 int pageSize
= thumbVisible
;
857 if ( pageSize
> 1 && range
> 0)
859 range1
+= (pageSize
- 1);
865 if ( orient
== wxHORIZONTAL
) {
871 info
.cbSize
= sizeof(SCROLLINFO
);
872 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
876 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
878 HWND hWnd
= GetHwnd();
880 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
883 if ( orient
== wxHORIZONTAL
)
888 HWND hWnd
= GetHwnd();
891 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
892 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
895 if ( orient
== wxHORIZONTAL
) {
896 m_xThumbSize
= thumbVisible
;
898 m_yThumbSize
= thumbVisible
;
902 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
907 rect
.left
= prect
->x
;
909 rect
.right
= prect
->x
+ prect
->width
;
910 rect
.bottom
= prect
->y
+ prect
->height
;
919 ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
);
922 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
924 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
927 for ( int n
= 0; n
< count
; n
++ )
929 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
931 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
934 // don't bother to continue, we're already at top/bottom
941 return pos
!= posStart
;
944 bool wxWindowMSW::ScrollLines(int lines
)
946 bool down
= lines
> 0;
948 return ScrollVertically(GetHwnd(),
949 down
? SB_LINEDOWN
: SB_LINEUP
,
950 down
? lines
: -lines
);
953 bool wxWindowMSW::ScrollPages(int pages
)
955 bool down
= pages
> 0;
957 return ScrollVertically(GetHwnd(),
958 down
? SB_PAGEDOWN
: SB_PAGEUP
,
959 down
? pages
: -pages
);
962 // ---------------------------------------------------------------------------
964 // ---------------------------------------------------------------------------
966 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
968 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
970 HWND hwnd
= (HWND
)hWnd
;
971 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
973 wxAssociateWinWithHandle(hwnd
, this);
975 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
977 // we don't need to subclass the window of our own class (in the Windows
978 // sense of the word)
979 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
981 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
985 // don't bother restoring it neither
990 void wxWindowMSW::UnsubclassWin()
992 wxRemoveHandleAssociation(this);
994 // Restore old Window proc
995 HWND hwnd
= GetHwnd();
1000 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
1004 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
1006 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1009 m_oldWndProc
= NULL
;
1014 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
1016 #if wxUSE_UNICODE_MSLU
1017 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
1018 // because it doesn't return pointer to the real wnd proc but rather a handle
1019 // of a fake proc that does Unicode<->ANSI translation.
1021 // The hack bellow works, because WNDCLASS contains original window handler
1022 // rather that the unicows fake one. This may not be on purpose, though; if
1023 // it stops working with future versions of unicows.dll, we can override
1024 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
1025 // Unicows_RegisterClass to our own versions that keep track of
1026 // fake<->real wnd proc mapping.
1028 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
1029 // with RegisterClass!!
1031 static wxChar buffer
[512];
1034 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1035 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1036 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1038 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1043 // Make a Windows extended style from the given wxWindows window style
1044 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1046 WXDWORD exStyle
= 0;
1047 if ( style
& wxTRANSPARENT_WINDOW
)
1048 exStyle
|= WS_EX_TRANSPARENT
;
1050 if ( !eliminateBorders
)
1052 if ( style
& wxSUNKEN_BORDER
)
1053 exStyle
|= WS_EX_CLIENTEDGE
;
1054 if ( style
& wxDOUBLE_BORDER
)
1055 exStyle
|= WS_EX_DLGMODALFRAME
;
1056 #if defined(__WIN95__)
1057 if ( style
& wxRAISED_BORDER
)
1058 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1059 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1060 if ( style
& wxSTATIC_BORDER
)
1061 exStyle
|= WS_EX_STATICEDGE
;
1068 // Determines whether native 3D effects or CTL3D should be used,
1069 // applying a default border style if required, and returning an extended
1070 // style to pass to CreateWindowEx.
1071 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1074 // If matches certain criteria, then assume no 3D effects
1075 // unless specifically requested (dealt with in MakeExtendedStyle)
1078 || !IsKindOf(CLASSINFO(wxControl
))
1079 #endif // wxUSE_CONTROLS
1080 || (m_windowStyle
& wxNO_BORDER
) )
1083 return MakeExtendedStyle(m_windowStyle
);
1086 // Determine whether we should be using 3D effects or not.
1087 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1089 // 1) App can specify global 3D effects
1090 *want3D
= wxTheApp
->GetAuto3D();
1092 // 2) If the parent is being drawn with user colours, or simple border specified,
1093 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1094 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1097 // 3) Control can override this global setting by defining
1098 // a border style, e.g. wxSUNKEN_BORDER
1099 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1102 // 4) If it's a special border, CTL3D can't cope so we want a native border
1103 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1104 (m_windowStyle
& wxSTATIC_BORDER
) )
1107 nativeBorder
= TRUE
;
1110 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1111 // effects from extended style
1114 nativeBorder
= FALSE
;
1117 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1119 // If we want 3D, but haven't specified a border here,
1120 // apply the default border style specified.
1121 // TODO what about non-Win95 WIN32? Does it have borders?
1122 #if defined(__WIN95__) && !wxUSE_CTL3D
1123 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1124 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1125 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1131 #if WXWIN_COMPATIBILITY
1132 // If nothing defined for this, try the parent.
1133 // E.g. we may be a button loaded from a resource, with no callback function
1135 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1137 if ( GetEventHandler()->ProcessEvent(event
) )
1140 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1142 #endif // WXWIN_COMPATIBILITY_2
1144 #if WXWIN_COMPATIBILITY
1145 wxObject
* wxWindowMSW::GetChild(int number
) const
1147 // Return a pointer to the Nth object in the Panel
1148 wxNode
*node
= GetChildren().First();
1151 node
= node
->Next();
1154 wxObject
*obj
= (wxObject
*)node
->Data();
1160 #endif // WXWIN_COMPATIBILITY
1162 // Setup background and foreground colours correctly
1163 void wxWindowMSW::SetupColours()
1166 SetBackgroundColour(GetParent()->GetBackgroundColour());
1169 bool wxWindowMSW::IsMouseInWindow() const
1171 // get the mouse position
1173 ::GetCursorPos(&pt
);
1175 // find the window which currently has the cursor and go up the window
1176 // chain until we find this window - or exhaust it
1177 HWND hwnd
= ::WindowFromPoint(pt
);
1178 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1179 hwnd
= ::GetParent(hwnd
);
1181 return hwnd
!= NULL
;
1184 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1186 // Check if we need to send a LEAVE event
1187 if ( m_mouseInWindow
)
1189 if ( !IsMouseInWindow() && !HasCapture())
1191 // Generate a LEAVE event
1192 m_mouseInWindow
= FALSE
;
1194 // Unfortunately the mouse button and keyboard state may have
1195 // changed by the time the OnIdle function is called, so 'state'
1196 // may be meaningless.
1198 if ( wxIsShiftDown() )
1200 if ( wxIsCtrlDown() )
1201 state
|= MK_CONTROL
;
1202 if ( GetKeyState( VK_LBUTTON
) )
1203 state
|= MK_LBUTTON
;
1204 if ( GetKeyState( VK_MBUTTON
) )
1205 state
|= MK_MBUTTON
;
1206 if ( GetKeyState( VK_RBUTTON
) )
1207 state
|= MK_RBUTTON
;
1210 if ( !::GetCursorPos(&pt
) )
1212 wxLogLastError(_T("GetCursorPos"));
1215 // we need to have client coordinates here for symmetry with
1216 // wxEVT_ENTER_WINDOW
1217 RECT rect
= wxGetWindowRect(GetHwnd());
1221 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1222 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1224 (void)GetEventHandler()->ProcessEvent(event2
);
1231 // Set this window to be the child of 'parent'.
1232 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1234 if ( !wxWindowBase::Reparent(parent
) )
1237 HWND hWndChild
= GetHwnd();
1238 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1240 ::SetParent(hWndChild
, hWndParent
);
1245 void wxWindowMSW::Clear()
1247 wxClientDC
dc((wxWindow
*)this);
1248 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1249 dc
.SetBackground(brush
);
1253 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1255 #ifndef __WXMICROWIN__
1256 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1260 void wxWindowMSW::Freeze()
1262 SendSetRedraw(GetHwnd(), FALSE
);
1265 void wxWindowMSW::Thaw()
1267 SendSetRedraw(GetHwnd(), TRUE
);
1269 // we need to refresh everything or otherwise he invalidated area is not
1274 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1276 HWND hWnd
= GetHwnd();
1282 mswRect
.left
= rect
->x
;
1283 mswRect
.top
= rect
->y
;
1284 mswRect
.right
= rect
->x
+ rect
->width
;
1285 mswRect
.bottom
= rect
->y
+ rect
->height
;
1287 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1290 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1294 void wxWindowMSW::Update()
1296 if ( !::UpdateWindow(GetHwnd()) )
1298 wxLogLastError(_T("UpdateWindow"));
1301 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1302 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1303 // handler needs to be really drawn right now
1308 // ---------------------------------------------------------------------------
1310 // ---------------------------------------------------------------------------
1312 #if wxUSE_DRAG_AND_DROP
1314 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1316 if ( m_dropTarget
!= 0 ) {
1317 m_dropTarget
->Revoke(m_hWnd
);
1318 delete m_dropTarget
;
1321 m_dropTarget
= pDropTarget
;
1322 if ( m_dropTarget
!= 0 )
1323 m_dropTarget
->Register(m_hWnd
);
1326 #endif // wxUSE_DRAG_AND_DROP
1328 // old style file-manager drag&drop support: we retain the old-style
1329 // DragAcceptFiles in parallel with SetDropTarget.
1330 void wxWindowMSW::DragAcceptFiles(bool accept
)
1332 HWND hWnd
= GetHwnd();
1334 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1337 // ----------------------------------------------------------------------------
1339 // ----------------------------------------------------------------------------
1343 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1345 wxWindowBase::DoSetToolTip(tooltip
);
1348 m_tooltip
->SetWindow(this);
1351 #endif // wxUSE_TOOLTIPS
1353 // ---------------------------------------------------------------------------
1354 // moving and resizing
1355 // ---------------------------------------------------------------------------
1358 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1360 RECT rect
= wxGetWindowRect(GetHwnd());
1363 *x
= rect
.right
- rect
.left
;
1365 *y
= rect
.bottom
- rect
.top
;
1368 // Get size *available for subwindows* i.e. excluding menu bar etc.
1369 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1371 RECT rect
= wxGetClientRect(GetHwnd());
1379 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1381 RECT rect
= wxGetWindowRect(GetHwnd());
1384 point
.x
= rect
.left
;
1387 // we do the adjustments with respect to the parent only for the "real"
1388 // children, not for the dialogs/frames
1389 if ( !IsTopLevel() )
1391 HWND hParentWnd
= 0;
1392 wxWindow
*parent
= GetParent();
1394 hParentWnd
= GetWinHwnd(parent
);
1396 // Since we now have the absolute screen coords, if there's a parent we
1397 // must subtract its top left corner
1400 ::ScreenToClient(hParentWnd
, &point
);
1405 // We may be faking the client origin. So a window that's really at (0,
1406 // 30) may appear (to wxWin apps) to be at (0, 0).
1407 wxPoint
pt(parent
->GetClientAreaOrigin());
1419 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1427 ::ScreenToClient(GetHwnd(), &pt
);
1435 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1443 ::ClientToScreen(GetHwnd(), &pt
);
1451 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1453 // TODO: is this consistent with other platforms?
1454 // Still, negative width or height shouldn't be allowed
1459 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1461 wxLogLastError(wxT("MoveWindow"));
1465 // set the size of the window: if the dimensions are positive, just use them,
1466 // but if any of them is equal to -1, it means that we must find the value for
1467 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1468 // which case -1 is a valid value for x and y)
1470 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1471 // the width/height to best suit our contents, otherwise we reuse the current
1473 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1475 // get the current size and position...
1476 int currentX
, currentY
;
1477 GetPosition(¤tX
, ¤tY
);
1478 int currentW
,currentH
;
1479 GetSize(¤tW
, ¤tH
);
1481 // ... and don't do anything (avoiding flicker) if it's already ok
1482 if ( x
== currentX
&& y
== currentY
&&
1483 width
== currentW
&& height
== currentH
)
1488 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1490 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1493 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1495 wxSize
size(-1, -1);
1498 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1500 size
= DoGetBestSize();
1505 // just take the current one
1512 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1516 size
= DoGetBestSize();
1518 //else: already called DoGetBestSize() above
1524 // just take the current one
1529 DoMoveWindow(x
, y
, width
, height
);
1532 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1534 // setting the client size is less obvious than it it could have been
1535 // because in the result of changing the total size the window scrollbar
1536 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1537 // will not be correct as the difference between the total and client size
1538 // changes - so we keep changing it until we get it right
1540 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1541 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1542 // may become 3 if the window had 0 size originally and so we didn't
1543 // calculate the scrollbar correction correctly during the first iteration)
1544 // but just to be on the safe side we check for it instead of making it an
1545 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1546 for ( int i
= 0; i
< 4; i
++ )
1549 ::GetClientRect(GetHwnd(), &rectClient
);
1551 // if the size is already ok, stop here (rectClient.left = top = 0)
1552 if ( (rectClient
.right
== width
|| width
== -1) &&
1553 (rectClient
.bottom
== height
|| height
== -1) )
1560 // how did it happen? maybe OnSize() handler does something really
1561 // strange in this class?
1562 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1567 int widthClient
= width
,
1568 heightClient
= height
;
1570 // Find the difference between the entire window (title bar and all)
1571 // and the client area; add this to the new client size to move the
1574 ::GetWindowRect(GetHwnd(), &rectWin
);
1576 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1577 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1580 point
.x
= rectWin
.left
;
1581 point
.y
= rectWin
.top
;
1583 // MoveWindow positions the child windows relative to the parent, so
1584 // adjust if necessary
1585 if ( !IsTopLevel() )
1587 wxWindow
*parent
= GetParent();
1590 ::ScreenToClient(GetHwndOf(parent
), &point
);
1594 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1598 // For implementation purposes - sometimes decorations make the client area
1600 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1602 return wxPoint(0, 0);
1605 // ---------------------------------------------------------------------------
1607 // ---------------------------------------------------------------------------
1609 int wxWindowMSW::GetCharHeight() const
1611 return wxGetTextMetrics(this).tmHeight
;
1614 int wxWindowMSW::GetCharWidth() const
1616 // +1 is needed because Windows apparently adds it when calculating the
1617 // dialog units size in pixels
1618 #if wxDIALOG_UNIT_COMPATIBILITY
1619 return wxGetTextMetrics(this).tmAveCharWidth
;
1621 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1625 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1627 int *descent
, int *externalLeading
,
1628 const wxFont
*theFont
) const
1630 const wxFont
*fontToUse
= theFont
;
1632 fontToUse
= &m_font
;
1634 HWND hWnd
= GetHwnd();
1635 HDC dc
= ::GetDC(hWnd
);
1639 if ( fontToUse
&& fontToUse
->Ok() )
1641 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1643 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1648 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1649 GetTextMetrics(dc
, &tm
);
1651 if ( fontToUse
&& fnt
&& hfontOld
)
1652 SelectObject(dc
, hfontOld
);
1654 ReleaseDC(hWnd
, dc
);
1661 *descent
= tm
.tmDescent
;
1662 if ( externalLeading
)
1663 *externalLeading
= tm
.tmExternalLeading
;
1666 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1667 // ---------------------------------------------------------------------------
1668 // Caret manipulation
1669 // ---------------------------------------------------------------------------
1671 void wxWindowMSW::CreateCaret(int w
, int h
)
1673 SetCaret(new wxCaret(this, w
, h
));
1676 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1678 wxFAIL_MSG("not implemented");
1681 void wxWindowMSW::ShowCaret(bool show
)
1683 wxCHECK_RET( m_caret
, "no caret to show" );
1685 m_caret
->Show(show
);
1688 void wxWindowMSW::DestroyCaret()
1693 void wxWindowMSW::SetCaretPos(int x
, int y
)
1695 wxCHECK_RET( m_caret
, "no caret to move" );
1697 m_caret
->Move(x
, y
);
1700 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1702 wxCHECK_RET( m_caret
, "no caret to get position of" );
1704 m_caret
->GetPosition(x
, y
);
1706 #endif // wxUSE_CARET
1708 // ---------------------------------------------------------------------------
1710 // ---------------------------------------------------------------------------
1712 #if wxUSE_MENUS_NATIVE
1714 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1715 // immediately, without waiting for the next event loop iteration
1717 // NB: this function should probably be made public later as it can almost
1718 // surely replace wxYield() elsewhere as well
1719 static void wxYieldForCommandsOnly()
1721 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1722 // want to process it here)
1724 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1725 && msg
.message
!= WM_QUIT
)
1727 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1731 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1733 menu
->SetInvokingWindow(this);
1736 HWND hWnd
= GetHwnd();
1737 HMENU hMenu
= GetHmenuOf(menu
);
1741 ::ClientToScreen(hWnd
, &point
);
1742 wxCurrentPopupMenu
= menu
;
1743 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1745 // we need to do it righ now as otherwise the events are never going to be
1746 // sent to wxCurrentPopupMenu from HandleCommand()
1748 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1749 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1750 // destroyed as soon as we return (it can be a local variable in the caller
1751 // for example) and so we do need to process the event immediately
1752 wxYieldForCommandsOnly();
1754 wxCurrentPopupMenu
= NULL
;
1756 menu
->SetInvokingWindow(NULL
);
1761 #endif // wxUSE_MENUS_NATIVE
1763 // ===========================================================================
1764 // pre/post message processing
1765 // ===========================================================================
1767 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1770 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1772 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1775 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1777 // wxUniversal implements tab traversal itself
1778 #ifndef __WXUNIVERSAL__
1779 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1781 // intercept dialog navigation keys
1782 MSG
*msg
= (MSG
*)pMsg
;
1784 // here we try to do all the job which ::IsDialogMessage() usually does
1787 bool bProcess
= TRUE
;
1788 if ( msg
->message
!= WM_KEYDOWN
)
1791 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1796 bool bCtrlDown
= wxIsCtrlDown();
1797 bool bShiftDown
= wxIsShiftDown();
1799 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1800 // don't process it if it's the case (except for Ctrl-Tab/Enter
1801 // combinations which are always processed)
1805 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1808 bool bForward
= TRUE
,
1809 bWindowChange
= FALSE
;
1811 switch ( msg
->wParam
)
1814 // assume that nobody wants Shift-TAB for himself - if we
1815 // don't do it there is no easy way for a control to grab
1816 // TABs but still let Shift-TAB work as navugation key
1817 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1821 // Ctrl-Tab cycles thru notebook pages
1822 bWindowChange
= bCtrlDown
;
1823 bForward
= !bShiftDown
;
1829 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1837 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1843 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1845 // control wants to process Enter itself, don't
1846 // call IsDialogMessage() which would interpret
1850 else if ( lDlgCode
& DLGC_BUTTON
)
1852 // let IsDialogMessage() handle this for all
1853 // buttons except the owner-drawn ones which it
1854 // just seems to ignore
1855 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1856 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1858 // emulate the button click
1859 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1861 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1866 // FIXME: this should be handled by
1867 // wxNavigationKeyEvent handler and not here!!
1871 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1873 if ( btn
&& btn
->IsEnabled() )
1875 // if we do have a default button, do press it
1876 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1880 else // no default button
1881 #endif // wxUSE_BUTTON
1883 // no special function for enter and don't even
1884 // let IsDialogMessage() have it: it seems to
1885 // do something really strange with it
1898 wxNavigationKeyEvent event
;
1899 event
.SetDirection(bForward
);
1900 event
.SetWindowChange(bWindowChange
);
1901 event
.SetEventObject(this);
1903 if ( GetEventHandler()->ProcessEvent(event
) )
1910 // let ::IsDialogMessage() do almost everything and handle just the
1911 // things it doesn't here: Ctrl-TAB for switching notebook pages
1912 if ( msg
->message
== WM_KEYDOWN
)
1914 // don't process system keys here
1915 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1917 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1919 // find the first notebook parent and change its page
1920 wxWindow
*win
= this;
1921 wxNotebook
*nbook
= NULL
;
1922 while ( win
&& !nbook
)
1924 nbook
= wxDynamicCast(win
, wxNotebook
);
1925 win
= win
->GetParent();
1930 bool forward
= !wxIsShiftDown();
1932 nbook
->AdvanceSelection(forward
);
1939 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1941 // IsDialogMessage() did something...
1945 #endif // __WXUNIVERSAL__
1950 // relay mouse move events to the tooltip control
1951 MSG
*msg
= (MSG
*)pMsg
;
1952 if ( msg
->message
== WM_MOUSEMOVE
)
1953 m_tooltip
->RelayEvent(pMsg
);
1955 #endif // wxUSE_TOOLTIPS
1960 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1962 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1963 return m_acceleratorTable
.Translate(this, pMsg
);
1966 #endif // wxUSE_ACCEL
1969 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1971 // preprocess all messages by default
1975 // ---------------------------------------------------------------------------
1976 // message params unpackers (different for Win16 and Win32)
1977 // ---------------------------------------------------------------------------
1981 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1982 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1984 *id
= LOWORD(wParam
);
1985 *hwnd
= (WXHWND
)lParam
;
1986 *cmd
= HIWORD(wParam
);
1989 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1990 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1992 *state
= LOWORD(wParam
);
1993 *minimized
= HIWORD(wParam
);
1994 *hwnd
= (WXHWND
)lParam
;
1997 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1998 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2000 *code
= LOWORD(wParam
);
2001 *pos
= HIWORD(wParam
);
2002 *hwnd
= (WXHWND
)lParam
;
2005 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2006 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2008 #ifndef __WXMICROWIN__
2009 *nCtlColor
= CTLCOLOR_BTN
;
2010 *hwnd
= (WXHWND
)lParam
;
2011 *hdc
= (WXHDC
)wParam
;
2015 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2016 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2018 *item
= (WXWORD
)wParam
;
2019 *flags
= HIWORD(wParam
);
2020 *hmenu
= (WXHMENU
)lParam
;
2025 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2026 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2028 *id
= (WXWORD
)wParam
;
2029 *hwnd
= (WXHWND
)LOWORD(lParam
);
2030 *cmd
= HIWORD(lParam
);
2033 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2034 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2036 *state
= (WXWORD
)wParam
;
2037 *minimized
= LOWORD(lParam
);
2038 *hwnd
= (WXHWND
)HIWORD(lParam
);
2041 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2042 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2044 *code
= (WXWORD
)wParam
;
2045 *pos
= LOWORD(lParam
);
2046 *hwnd
= (WXHWND
)HIWORD(lParam
);
2049 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2050 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2052 *hwnd
= (WXHWND
)LOWORD(lParam
);
2053 *nCtlColor
= (int)HIWORD(lParam
);
2054 *hdc
= (WXHDC
)wParam
;
2057 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2058 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2060 *item
= (WXWORD
)wParam
;
2061 *flags
= LOWORD(lParam
);
2062 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2067 // ---------------------------------------------------------------------------
2068 // Main wxWindows window proc and the window proc for wxWindow
2069 // ---------------------------------------------------------------------------
2071 // Hook for new window just as it's being created, when the window isn't yet
2072 // associated with the handle
2073 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2075 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2076 // window being created and insures that it's always unset back later
2077 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2079 gs_winBeingCreated
= winBeingCreated
;
2082 wxWindowCreationHook::~wxWindowCreationHook()
2084 gs_winBeingCreated
= NULL
;
2088 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2090 // trace all messages - useful for the debugging
2092 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2093 wxGetMessageName(message
), wParam
, lParam
);
2094 #endif // __WXDEBUG__
2096 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2098 // when we get the first message for the HWND we just created, we associate
2099 // it with wxWindow stored in gs_winBeingCreated
2100 if ( !wnd
&& gs_winBeingCreated
)
2102 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2103 wnd
= gs_winBeingCreated
;
2104 gs_winBeingCreated
= NULL
;
2105 wnd
->SetHWND((WXHWND
)hWnd
);
2111 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2113 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2118 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2120 // did we process the message?
2121 bool processed
= FALSE
;
2132 // for most messages we should return 0 when we do process the message
2140 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2143 // return 0 to allow window creation
2144 rc
.result
= mayCreate
? 0 : -1;
2150 // never set processed to TRUE and *always* pass WM_DESTROY to
2151 // DefWindowProc() as Windows may do some internal cleanup when
2152 // processing it and failing to pass the message along may cause
2153 // memory and resource leaks!
2154 (void)HandleDestroy();
2158 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2166 // we're not interested in these messages at all
2169 case SIZE_MINIMIZED
:
2170 // we shouldn't send sizev events for these messages as the
2171 // client size may be negative which breaks existing code
2173 // OTOH we might send another (wxMinimizedEvent?) one or
2174 // add an additional parameter to wxSizeEvent if this is
2175 // useful to anybody
2179 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2180 // fall through nevertheless
2182 case SIZE_MAXIMIZED
:
2184 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2189 #ifndef __WXMICROWIN__
2190 case WM_ACTIVATEAPP
:
2191 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2197 WXWORD state
, minimized
;
2199 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2201 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2206 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2210 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2214 processed
= HandlePaint();
2218 // don't let the DefWindowProc() destroy our window - we'll do it
2219 // ourselves in ~wxWindow
2225 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2229 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2230 GET_Y_LPARAM(lParam
),
2234 #if wxUSE_MOUSEWHEEL
2236 processed
= HandleMouseWheel(wParam
, lParam
);
2240 case WM_LBUTTONDOWN
:
2242 case WM_LBUTTONDBLCLK
:
2243 case WM_RBUTTONDOWN
:
2245 case WM_RBUTTONDBLCLK
:
2246 case WM_MBUTTONDOWN
:
2248 case WM_MBUTTONDBLCLK
:
2251 #ifdef __WXMICROWIN__
2252 // MicroWindows seems to ignore the fact that a window is
2253 // disabled. So catch mouse events and throw them away if
2255 wxWindowMSW
* win
= this;
2258 if (!win
->IsEnabled())
2263 win
= win
->GetParent();
2264 if (win
&& win
->IsTopLevel())
2267 #endif // __WXMICROWIN__
2270 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2272 processed
= HandleMouseEvent(message
,
2273 GET_X_LPARAM(lParam
),
2274 GET_Y_LPARAM(lParam
),
2280 #ifdef __WXMICROWIN__
2281 case WM_NCLBUTTONDOWN
:
2282 case WM_NCLBUTTONUP
:
2283 case WM_NCLBUTTONDBLCLK
:
2284 case WM_NCRBUTTONDOWN
:
2285 case WM_NCRBUTTONUP
:
2286 case WM_NCRBUTTONDBLCLK
:
2288 case WM_NCMBUTTONDOWN
:
2289 case WM_NCMBUTTONUP
:
2290 case WM_NCMBUTTONDBLCLK
:
2293 // MicroWindows seems to ignore the fact that a window
2294 // is disabled. So catch mouse events and throw them away if necessary.
2296 wxWindowMSW
* win
= this;
2299 if (!win
->IsEnabled())
2304 win
= win
->GetParent();
2305 if (win
&& win
->IsTopLevel())
2310 #endif // __WXMICROWIN__
2317 case MM_JOY1BUTTONDOWN
:
2318 case MM_JOY2BUTTONDOWN
:
2319 case MM_JOY1BUTTONUP
:
2320 case MM_JOY2BUTTONUP
:
2321 processed
= HandleJoystickEvent(message
,
2322 GET_X_LPARAM(lParam
),
2323 GET_Y_LPARAM(lParam
),
2326 #endif // __WXMICROWIN__
2329 processed
= HandleSysCommand(wParam
, lParam
);
2336 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2338 processed
= HandleCommand(id
, cmd
, hwnd
);
2344 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2348 // for these messages we must return TRUE if process the message
2351 case WM_MEASUREITEM
:
2353 int idCtrl
= (UINT
)wParam
;
2354 if ( message
== WM_DRAWITEM
)
2356 processed
= MSWOnDrawItem(idCtrl
,
2357 (WXDRAWITEMSTRUCT
*)lParam
);
2361 processed
= MSWOnMeasureItem(idCtrl
,
2362 (WXMEASUREITEMSTRUCT
*)lParam
);
2369 #endif // defined(WM_DRAWITEM)
2374 rc
.result
= m_lDlgCode
;
2377 //else: get the dlg code from the DefWindowProc()
2382 // If this has been processed by an event handler,
2383 // return 0 now (we've handled it).
2384 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2391 // we consider these message "not interesting" to OnChar
2392 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2401 // avoid duplicate messages to OnChar for these ASCII keys: they
2402 // will be translated by TranslateMessage() and received in WM_CHAR
2410 // but set processed to FALSE, not TRUE to still pass them to
2411 // the control's default window proc - otherwise built-in
2412 // keyboard handling won't work
2418 // special case of VK_APPS: treat it the same as right mouse
2419 // click because both usually pop up a context menu
2425 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2426 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2436 processed
= HandleChar((WORD
)wParam
, lParam
);
2443 // special case of VK_APPS: treat it the same as right mouse button
2444 if ( wParam
== VK_APPS
)
2449 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2450 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2455 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2460 case WM_CHAR
: // Always an ASCII character
2461 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2469 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2471 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2477 // CTLCOLOR messages are sent by children to query the parent for their
2478 // colors#ifndef __WXMICROWIN__
2479 #ifndef __WXMICROWIN__
2481 case WM_CTLCOLORMSGBOX
:
2482 case WM_CTLCOLOREDIT
:
2483 case WM_CTLCOLORLISTBOX
:
2484 case WM_CTLCOLORBTN
:
2485 case WM_CTLCOLORDLG
:
2486 case WM_CTLCOLORSCROLLBAR
:
2487 case WM_CTLCOLORSTATIC
:
2495 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2497 processed
= HandleCtlColor(&rc
.hBrush
,
2506 #endif // !__WXMICROWIN__
2508 case WM_SYSCOLORCHANGE
:
2509 // the return value for this message is ignored
2510 processed
= HandleSysColorChange();
2513 case WM_PALETTECHANGED
:
2514 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2517 case WM_QUERYNEWPALETTE
:
2518 processed
= HandleQueryNewPalette();
2522 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2525 // we processed the message, i.e. erased the background
2531 processed
= HandleDropFiles(wParam
);
2535 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2539 // we never set focus from here
2544 case WM_QUERYENDSESSION
:
2545 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2549 processed
= HandleEndSession(wParam
!= 0, lParam
);
2552 case WM_GETMINMAXINFO
:
2553 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2557 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2558 LOWORD(lParam
), // hit test
2559 HIWORD(lParam
)); // mouse msg
2563 // returning TRUE stops the DefWindowProc() from further
2564 // processing this message - exactly what we need because we've
2565 // just set the cursor.
2570 #if defined(__WIN32__) && defined(WM_HELP)
2573 HELPINFO
* info
= (HELPINFO
*) lParam
;
2574 // Don't yet process menu help events, just windows
2575 if (info
->iContextType
== HELPINFO_WINDOW
)
2577 wxWindowMSW
* subjectOfHelp
= this;
2578 bool eventProcessed
= FALSE
;
2579 while (subjectOfHelp
&& !eventProcessed
)
2581 wxHelpEvent
helpEvent(wxEVT_HELP
,
2582 subjectOfHelp
->GetId(),
2583 wxPoint(info
->MousePos
.x
,
2584 info
->MousePos
.y
) );
2585 helpEvent
.SetEventObject(this);
2587 GetEventHandler()->ProcessEvent(helpEvent
);
2589 // Go up the window hierarchy until the event is
2591 subjectOfHelp
= subjectOfHelp
->GetParent();
2594 processed
= eventProcessed
;
2596 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2598 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2599 helpEvent
.SetEventObject(this);
2600 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2603 //else: processed is already FALSE
2607 case WM_CONTEXTMENU
:
2609 // we don't convert from screen to client coordinates as
2610 // the event may be handled by a parent window
2611 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2613 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2614 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2619 // unfortunately this doesn't really work as then window which
2620 // doesn't accept focus doesn't get any mouse events neither which
2621 // means it can't get any input at all
2622 #if 0 //def __WXUNIVERSAL__
2624 // we shouldn't allow the windows which don't want to get focus to
2626 if ( !AcceptsFocus() )
2628 rc
.result
= HTTRANSPARENT
;
2632 #endif // __WXUNIVERSAL__
2638 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2639 wxGetMessageName(message
));
2640 #endif // __WXDEBUG__
2641 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2647 // ----------------------------------------------------------------------------
2648 // wxWindow <-> HWND map
2649 // ----------------------------------------------------------------------------
2651 wxWinHashTable
*wxWinHandleHash
= NULL
;
2653 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2655 return wxWinHandleHash
->Get((long)hWnd
);
2658 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2660 // adding NULL hWnd is (first) surely a result of an error and
2661 // (secondly) breaks menu command processing
2662 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2663 wxT("attempt to add a NULL hWnd to window list ignored") );
2665 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2667 if ( oldWin
&& (oldWin
!= win
) )
2669 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2670 hWnd
, win
->GetClassInfo()->GetClassName());
2673 #endif // __WXDEBUG__
2676 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2680 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2682 wxWinHandleHash
->Delete((long)win
->GetHWND());
2685 // ----------------------------------------------------------------------------
2686 // various MSW speciic class dependent functions
2687 // ----------------------------------------------------------------------------
2689 // Default destroyer - override if you destroy it in some other way
2690 // (e.g. with MDI child windows)
2691 void wxWindowMSW::MSWDestroyWindow()
2695 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2698 int& w
, int& h
) const
2700 bool nonDefault
= FALSE
;
2704 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2705 // just as well set it to CW_USEDEFAULT as well
2712 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2718 NB: there used to be some code here which set the initial size of the
2719 window to the client size of the parent if no explicit size was
2720 specified. This was wrong because wxWindows programs often assume
2721 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2722 it. To see why, you should understand that Windows sends WM_SIZE from
2723 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2724 from some base class ctor and so this WM_SIZE is not processed in the
2725 real class' OnSize() (because it's not fully constructed yet and the
2726 event goes to some base class OnSize() instead). So the WM_SIZE we
2727 rely on is the one sent when the parent frame resizes its children
2728 but here is the problem: if the child already has just the right
2729 size, nothing will happen as both wxWindows and Windows check for
2730 this and ignore any attempts to change the window size to the size it
2731 already has - so no WM_SIZE would be sent.
2735 // as abobe, h is not used at all in this case anyhow
2742 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2750 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2751 const wxChar
*title
,
2755 WXDWORD extendedStyle
)
2757 // choose the position/size for the new window
2759 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2761 // find the correct parent HWND
2762 wxWindow
*parent
= GetParent();
2763 bool isChild
= (style
& WS_CHILD
) != 0;
2765 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2767 // popup windows should have desktop as parent because they shouldn't
2768 // be limited to the parents client area as child windows usually are
2769 hParent
= ::GetDesktopWindow();
2773 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2775 // this is either a normal child window or a top level window with
2776 // wxFRAME_TOOL_WINDOW style (see below)
2777 hParent
= GetHwndOf(parent
);
2781 // this is either a window for which no parent was specified (not
2782 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2783 // style: we should use NULL parent HWND for it or it would be
2784 // always on top of its parent which is not what we usually want
2785 // (in fact, we only want it for frames with the special
2786 // wxFRAME_TOOL_WINDOW as above)
2792 // controlId is menu handle for the top level windows, so set it to 0
2793 // unless we're creating a child window
2797 controlId
= GetId();
2799 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2801 style
|= WS_CLIPSIBLINGS
;
2809 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2810 // which is the same but without CS_[HV]REDRAW class styles so using it
2811 // ensures that the window is not fully repainted on each resize
2812 wxString
className(wclass
);
2813 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2815 className
+= wxT("NR");
2818 // do create the window
2819 wxWindowCreationHook
hook(this);
2821 m_hWnd
= (WXHWND
)::CreateWindowEx
2825 title
? title
: wxT(""),
2831 NULL
// no extra data
2836 wxLogSysError(_("Can't create window of class %s"), wclass
);
2841 SubclassWin(m_hWnd
);
2843 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2848 // ===========================================================================
2849 // MSW message handlers
2850 // ===========================================================================
2852 // ---------------------------------------------------------------------------
2854 // ---------------------------------------------------------------------------
2857 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2858 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2860 #ifndef __WXMICROWIN__
2861 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2862 HWND hWnd
= hdr
->hwndFrom
;
2863 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2865 // is this one of our windows?
2868 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2871 // try all our children
2872 wxWindowList::Node
*node
= GetChildren().GetFirst();
2875 wxWindow
*child
= node
->GetData();
2876 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2881 node
= node
->GetNext();
2884 // finally try this window too (catches toolbar case)
2885 return MSWOnNotify(idCtrl
, lParam
, result
);
2886 #else // __WXMICROWIN__
2891 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2893 WXLPARAM
* WXUNUSED(result
))
2896 NMHDR
* hdr
= (NMHDR
*)lParam
;
2897 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2899 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2900 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2905 #endif // wxUSE_TOOLTIPS
2911 // ---------------------------------------------------------------------------
2912 // end session messages
2913 // ---------------------------------------------------------------------------
2915 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2917 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2918 event
.SetEventObject(wxTheApp
);
2919 event
.SetCanVeto(TRUE
);
2920 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2922 bool rc
= wxTheApp
->ProcessEvent(event
);
2926 // we may end only if the app didn't veto session closing (double
2928 *mayEnd
= !event
.GetVeto();
2934 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2936 // do nothing if the session isn't ending
2941 if ( (this != wxTheApp
->GetTopWindow()) )
2944 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2945 event
.SetEventObject(wxTheApp
);
2946 event
.SetCanVeto(FALSE
);
2947 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2949 return wxTheApp
->ProcessEvent(event
);
2952 // ---------------------------------------------------------------------------
2953 // window creation/destruction
2954 // ---------------------------------------------------------------------------
2956 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2958 // TODO: should generate this event from WM_NCCREATE
2959 wxWindowCreateEvent
event((wxWindow
*)this);
2960 (void)GetEventHandler()->ProcessEvent(event
);
2967 bool wxWindowMSW::HandleDestroy()
2969 wxWindowDestroyEvent
event((wxWindow
*)this);
2970 (void)GetEventHandler()->ProcessEvent(event
);
2972 // delete our drop target if we've got one
2973 #if wxUSE_DRAG_AND_DROP
2974 if ( m_dropTarget
!= NULL
)
2976 m_dropTarget
->Revoke(m_hWnd
);
2978 delete m_dropTarget
;
2979 m_dropTarget
= NULL
;
2981 #endif // wxUSE_DRAG_AND_DROP
2983 // WM_DESTROY handled
2987 // ---------------------------------------------------------------------------
2989 // ---------------------------------------------------------------------------
2991 bool wxWindowMSW::HandleActivate(int state
,
2992 bool WXUNUSED(minimized
),
2993 WXHWND
WXUNUSED(activate
))
2995 wxActivateEvent
event(wxEVT_ACTIVATE
,
2996 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
2998 event
.SetEventObject(this);
3000 return GetEventHandler()->ProcessEvent(event
);
3003 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3005 // notify the parent keeping track of focus for the kbd navigation
3006 // purposes that we got it
3007 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3008 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3014 m_caret
->OnSetFocus();
3016 #endif // wxUSE_CARET
3019 // If it's a wxTextCtrl don't send the event as it will be done
3020 // after the control gets to process it from EN_FOCUS handler
3021 if ( wxDynamicCastThis(wxTextCtrl
) )
3025 #endif // wxUSE_TEXTCTRL
3027 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3028 event
.SetEventObject(this);
3030 // wxFindWinFromHandle() may return NULL, it is ok
3031 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3033 return GetEventHandler()->ProcessEvent(event
);
3036 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3042 m_caret
->OnKillFocus();
3044 #endif // wxUSE_CARET
3047 // If it's a wxTextCtrl don't send the event as it will be done
3048 // after the control gets to process it.
3049 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3056 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3057 event
.SetEventObject(this);
3059 // wxFindWinFromHandle() may return NULL, it is ok
3060 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3062 return GetEventHandler()->ProcessEvent(event
);
3065 // ---------------------------------------------------------------------------
3067 // ---------------------------------------------------------------------------
3069 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3071 wxShowEvent
event(GetId(), show
);
3072 event
.m_eventObject
= this;
3074 return GetEventHandler()->ProcessEvent(event
);
3077 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3079 wxInitDialogEvent
event(GetId());
3080 event
.m_eventObject
= this;
3082 return GetEventHandler()->ProcessEvent(event
);
3085 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3087 #ifndef __WXMICROWIN__
3088 HDROP hFilesInfo
= (HDROP
) wParam
;
3090 // Get the total number of files dropped
3091 UINT gwFilesDropped
= ::DragQueryFile
3099 wxString
*files
= new wxString
[gwFilesDropped
];
3100 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3102 // first get the needed buffer length (+1 for terminating NUL)
3103 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3105 // and now get the file name
3106 ::DragQueryFile(hFilesInfo
, wIndex
,
3107 files
[wIndex
].GetWriteBuf(len
), len
);
3109 files
[wIndex
].UngetWriteBuf();
3111 DragFinish (hFilesInfo
);
3113 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3114 event
.m_eventObject
= this;
3117 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3118 event
.m_pos
.x
= dropPoint
.x
;
3119 event
.m_pos
.y
= dropPoint
.y
;
3121 return GetEventHandler()->ProcessEvent(event
);
3122 #else // __WXMICROWIN__
3127 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3129 int WXUNUSED(mouseMsg
))
3131 #ifndef __WXMICROWIN__
3132 // the logic is as follows:
3133 // -1. don't set cursor for non client area, including but not limited to
3134 // the title bar, scrollbars, &c
3135 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3136 // 1. if we have the cursor set it unless wxIsBusy()
3137 // 2. if we're a top level window, set some cursor anyhow
3138 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3140 if ( nHitTest
!= HTCLIENT
)
3145 HCURSOR hcursor
= 0;
3147 // first ask the user code - it may wish to set the cursor in some very
3148 // specific way (for example, depending on the current position)
3151 if ( !::GetCursorPos(&pt
) )
3153 wxLogLastError(wxT("GetCursorPos"));
3156 // In WIN16 it doesn't return a value.
3157 ::GetCursorPos(&pt
);
3162 ScreenToClient(&x
, &y
);
3163 wxSetCursorEvent
event(x
, y
);
3165 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3166 if ( processedEvtSetCursor
&& event
.HasCursor() )
3168 hcursor
= GetHcursorOf(event
.GetCursor());
3173 bool isBusy
= wxIsBusy();
3175 // the test for processedEvtSetCursor is here to prevent using m_cursor
3176 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3177 // it - this is a way to say that our cursor shouldn't be used for this
3179 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3181 hcursor
= GetHcursorOf(m_cursor
);
3188 hcursor
= wxGetCurrentBusyCursor();
3190 else if ( !hcursor
)
3192 const wxCursor
*cursor
= wxGetGlobalCursor();
3193 if ( cursor
&& cursor
->Ok() )
3195 hcursor
= GetHcursorOf(*cursor
);
3203 ::SetCursor(hcursor
);
3205 // cursor set, stop here
3208 #endif // __WXMICROWIN__
3210 // pass up the window chain
3214 // ---------------------------------------------------------------------------
3215 // owner drawn stuff
3216 // ---------------------------------------------------------------------------
3218 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3220 #if wxUSE_OWNER_DRAWN
3222 #if wxUSE_MENUS_NATIVE
3223 // is it a menu item?
3224 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3225 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3227 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3229 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3231 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3232 // the DC from being released
3233 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3234 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3235 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3236 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3238 return pMenuItem
->OnDrawItem
3242 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3243 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3246 #endif // wxUSE_MENUS_NATIVE
3249 wxWindow
*item
= FindItem(id
);
3250 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3252 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3254 #endif // wxUSE_CONTROLS
3256 #endif // USE_OWNER_DRAWN
3261 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3263 #if wxUSE_OWNER_DRAWN
3264 // is it a menu item?
3265 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3266 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3268 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3270 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3272 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3273 &pMeasureStruct
->itemHeight
);
3276 wxWindow
*item
= FindItem(id
);
3277 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3279 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3281 #endif // owner-drawn menus
3285 // ---------------------------------------------------------------------------
3286 // colours and palettes
3287 // ---------------------------------------------------------------------------
3289 bool wxWindowMSW::HandleSysColorChange()
3291 wxSysColourChangedEvent event
;
3292 event
.SetEventObject(this);
3294 (void)GetEventHandler()->ProcessEvent(event
);
3296 // always let the system carry on the default processing to allow the
3297 // native controls to react to the colours update
3301 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3309 #ifndef __WXMICROWIN__
3310 WXHBRUSH hBrush
= 0;
3312 if ( nCtlColor
== CTLCOLOR_DLG
)
3314 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3319 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3321 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3323 #endif // wxUSE_CONTROLS
3329 #else // __WXMICROWIN__
3334 // Define for each class of dialog and control
3335 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3336 WXHWND
WXUNUSED(hWnd
),
3337 WXUINT
WXUNUSED(nCtlColor
),
3338 WXUINT
WXUNUSED(message
),
3339 WXWPARAM
WXUNUSED(wParam
),
3340 WXLPARAM
WXUNUSED(lParam
))
3345 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3347 wxPaletteChangedEvent
event(GetId());
3348 event
.SetEventObject(this);
3349 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3351 return GetEventHandler()->ProcessEvent(event
);
3354 bool wxWindowMSW::HandleQueryNewPalette()
3356 wxQueryNewPaletteEvent
event(GetId());
3357 event
.SetEventObject(this);
3359 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3362 // Responds to colour changes: passes event on to children.
3363 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3365 // the top level window also reset the standard colour map as it might have
3366 // changed (there is no need to do it for the non top level windows as we
3367 // only have to do it once)
3371 gs_hasStdCmap
= FALSE
;
3373 wxWindowList::Node
*node
= GetChildren().GetFirst();
3376 // Only propagate to non-top-level windows because Windows already
3377 // sends this event to all top-level ones
3378 wxWindow
*win
= node
->GetData();
3379 if ( !win
->IsTopLevel() )
3381 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3382 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3383 // the standard controls
3384 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3387 node
= node
->GetNext();
3390 // update the colours we use if they were not set explicitly by the user:
3391 // this must be done or OnCtlColor() would continue to use the old colours
3394 m_foregroundColour
= wxSystemSettings::
3395 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3400 m_backgroundColour
= wxSystemSettings::
3401 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3405 extern wxCOLORMAP
*wxGetStdColourMap()
3407 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3408 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3410 if ( !gs_hasStdCmap
)
3412 static bool s_coloursInit
= FALSE
;
3414 if ( !s_coloursInit
)
3416 // When a bitmap is loaded, the RGB values can change (apparently
3417 // because Windows adjusts them to care for the old programs always
3418 // using 0xc0c0c0 while the transparent colour for the new Windows
3419 // versions is different). But we do this adjustment ourselves so
3420 // we want to avoid Windows' "help" and for this we need to have a
3421 // reference bitmap which can tell us what the RGB values change
3423 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3424 if ( stdColourBitmap
.Ok() )
3426 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3427 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3428 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3431 memDC
.SelectObject(stdColourBitmap
);
3434 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3436 memDC
.GetPixel(i
, 0, &colour
);
3437 s_stdColours
[i
] = wxColourToRGB(colour
);
3440 else // wxBITMAP_STD_COLOURS couldn't be loaded
3442 s_stdColours
[0] = RGB(000,000,000); // black
3443 s_stdColours
[1] = RGB(128,128,128); // dark grey
3444 s_stdColours
[2] = RGB(192,192,192); // light grey
3445 s_stdColours
[3] = RGB(255,255,255); // white
3446 //s_stdColours[4] = RGB(000,000,255); // blue
3447 //s_stdColours[5] = RGB(255,000,255); // magenta
3450 s_coloursInit
= TRUE
;
3453 gs_hasStdCmap
= TRUE
;
3455 // create the colour map
3456 #define INIT_CMAP_ENTRY(col) \
3457 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3458 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3460 INIT_CMAP_ENTRY(BTNTEXT
);
3461 INIT_CMAP_ENTRY(BTNSHADOW
);
3462 INIT_CMAP_ENTRY(BTNFACE
);
3463 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3465 #undef INIT_CMAP_ENTRY
3471 // ---------------------------------------------------------------------------
3473 // ---------------------------------------------------------------------------
3475 bool wxWindowMSW::HandlePaint()
3478 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3480 wxLogLastError(wxT("CreateRectRgn"));
3481 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3482 wxLogLastError(wxT("GetUpdateRgn"));
3484 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3487 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3489 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3490 updateRect
.right
- updateRect
.left
,
3491 updateRect
.bottom
- updateRect
.top
);
3494 wxPaintEvent
event(m_windowId
);
3495 event
.SetEventObject(this);
3497 bool processed
= GetEventHandler()->ProcessEvent(event
);
3499 // note that we must generate NC event after the normal one as otherwise
3500 // BeginPaint() will happily overwrite our decorations with the background
3502 wxNcPaintEvent
eventNc(m_windowId
);
3503 eventNc
.SetEventObject(this);
3504 GetEventHandler()->ProcessEvent(eventNc
);
3509 // Can be called from an application's OnPaint handler
3510 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3512 #ifdef __WXUNIVERSAL__
3515 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3518 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3523 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3525 // Prevents flicker when dragging
3526 if ( ::IsIconic(GetHwnd()) )
3532 dc
.SetWindow((wxWindow
*)this);
3535 wxEraseEvent
event(m_windowId
, &dc
);
3536 event
.SetEventObject(this);
3537 bool rc
= GetEventHandler()->ProcessEvent(event
);
3541 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3542 dc
.SelectOldObjects(hdc
);
3547 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3550 ::GetClientRect(GetHwnd(), &rect
);
3552 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3553 m_backgroundColour
.Green(),
3554 m_backgroundColour
.Blue());
3555 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3557 wxLogLastError(wxT("CreateSolidBrush"));
3559 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3561 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3563 ::FillRect(hdc
, &rect
, hBrush
);
3564 ::DeleteObject(hBrush
);
3565 ::SetMapMode(hdc
, mode
);
3568 // ---------------------------------------------------------------------------
3569 // moving and resizing
3570 // ---------------------------------------------------------------------------
3572 bool wxWindowMSW::HandleMinimize()
3574 wxIconizeEvent
event(m_windowId
);
3575 event
.SetEventObject(this);
3577 return GetEventHandler()->ProcessEvent(event
);
3580 bool wxWindowMSW::HandleMaximize()
3582 wxMaximizeEvent
event(m_windowId
);
3583 event
.SetEventObject(this);
3585 return GetEventHandler()->ProcessEvent(event
);
3588 bool wxWindowMSW::HandleMove(int x
, int y
)
3590 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3591 event
.SetEventObject(this);
3593 return GetEventHandler()->ProcessEvent(event
);
3596 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3598 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3599 event
.SetEventObject(this);
3601 return GetEventHandler()->ProcessEvent(event
);
3604 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3606 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3610 if ( m_minWidth
!= -1 )
3612 info
->ptMinTrackSize
.x
= m_minWidth
;
3616 if ( m_minHeight
!= -1 )
3618 info
->ptMinTrackSize
.y
= m_minHeight
;
3622 if ( m_maxWidth
!= -1 )
3624 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3628 if ( m_maxHeight
!= -1 )
3630 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3637 // ---------------------------------------------------------------------------
3639 // ---------------------------------------------------------------------------
3641 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3643 #if wxUSE_MENUS_NATIVE
3644 if ( !cmd
&& wxCurrentPopupMenu
)
3646 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3647 wxCurrentPopupMenu
= NULL
;
3649 return popupMenu
->MSWCommand(cmd
, id
);
3651 #endif // wxUSE_MENUS_NATIVE
3653 wxWindow
*win
= NULL
;
3655 // first try to find it from HWND - this works even with the broken
3656 // programs using the same ids for different controls
3659 win
= wxFindWinFromHandle(control
);
3665 // must cast to a signed type before comparing with other ids!
3666 win
= FindItem((signed short)id
);
3671 return win
->MSWCommand(cmd
, id
);
3674 // the messages sent from the in-place edit control used by the treectrl
3675 // for label editing have id == 0, but they should _not_ be treated as menu
3676 // messages (they are EN_XXX ones, in fact) so don't translate anything
3677 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3680 // If no child window, it may be an accelerator, e.g. for a popup menu
3683 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3684 event
.SetEventObject(this);
3688 return GetEventHandler()->ProcessEvent(event
);
3690 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3693 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3694 // notifications to its parent which we want to reflect back to
3696 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3697 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3700 #endif // wxUSE_SPINCTRL
3705 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3707 // 4 bits are reserved
3708 switch ( wParam
& 0xFFFFFFF0 )
3711 return HandleMaximize();
3714 return HandleMinimize();
3720 // ---------------------------------------------------------------------------
3722 // ---------------------------------------------------------------------------
3724 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3728 // our client coords are not quite the same as Windows ones
3729 wxPoint pt
= GetClientAreaOrigin();
3730 event
.m_x
= x
- pt
.x
;
3731 event
.m_y
= y
- pt
.y
;
3733 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3734 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3735 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3736 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3737 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3738 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3740 event
.SetTimestamp(s_currentMsg
.time
);
3741 event
.m_eventObject
= this;
3743 #if wxUSE_MOUSEEVENT_HACK
3746 m_lastMouseEvent
= event
.GetEventType();
3747 #endif // wxUSE_MOUSEEVENT_HACK
3750 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3752 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3753 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3754 // from the message id and take the value in the table to get wxWin event
3756 static const wxEventType eventsMouse
[] =
3770 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3771 InitMouseEvent(event
, x
, y
, flags
);
3773 return GetEventHandler()->ProcessEvent(event
);
3776 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3778 if ( !m_mouseInWindow
)
3780 // it would be wrong to assume that just because we get a mouse move
3781 // event that the mouse is inside the window: although this is usually
3782 // true, it is not if we had captured the mouse, so we need to check
3783 // the mouse coordinates here
3784 if ( !HasCapture() || IsMouseInWindow() )
3786 // Generate an ENTER event
3787 m_mouseInWindow
= TRUE
;
3789 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3790 InitMouseEvent(event
, x
, y
, flags
);
3792 (void)GetEventHandler()->ProcessEvent(event
);
3796 #if wxUSE_MOUSEEVENT_HACK
3797 // Window gets a click down message followed by a mouse move message even
3798 // if position isn't changed! We want to discard the trailing move event
3799 // if x and y are the same.
3800 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3801 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3802 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3803 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3805 m_lastMouseEvent
= wxEVT_MOTION
;
3809 #endif // wxUSE_MOUSEEVENT_HACK
3811 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3815 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3817 #if wxUSE_MOUSEWHEEL
3818 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3819 InitMouseEvent(event
,
3820 GET_X_LPARAM(lParam
),
3821 GET_Y_LPARAM(lParam
),
3823 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3824 event
.m_wheelDelta
= WHEEL_DELTA
;
3827 static int s_linesPerRotation
= -1;
3828 if ( s_linesPerRotation
== -1 )
3830 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3831 &s_linesPerRotation
, 0))
3833 // this is not supposed to happen
3834 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3836 // the default is 3, so use it if SystemParametersInfo() failed
3837 s_linesPerRotation
= 3;
3841 // no SystemParametersInfo() under Win16
3842 static const int s_linesPerRotation
= 3;
3845 event
.m_linesPerAction
= s_linesPerRotation
;
3846 return GetEventHandler()->ProcessEvent(event
);
3857 // ---------------------------------------------------------------------------
3858 // keyboard handling
3859 // ---------------------------------------------------------------------------
3861 // create the key event of the given type for the given key - used by
3862 // HandleChar and HandleKeyDown/Up
3863 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3865 WXLPARAM lParam
) const
3867 wxKeyEvent
event(evType
);
3868 event
.SetId(GetId());
3869 event
.m_shiftDown
= wxIsShiftDown();
3870 event
.m_controlDown
= wxIsCtrlDown();
3871 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3873 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3874 event
.m_keyCode
= id
;
3875 event
.SetTimestamp(s_currentMsg
.time
);
3877 // translate the position to client coords
3881 GetWindowRect(GetHwnd(),&rect
);
3891 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3893 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3895 bool ctrlDown
= FALSE
;
3900 // If 1 -> 26, translate to CTRL plus a letter.
3902 if ( (id
> 0) && (id
< 27) )
3924 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3926 // it's ASCII and will be processed here only when called from
3927 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3933 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3936 event
.m_controlDown
= TRUE
;
3939 if ( GetEventHandler()->ProcessEvent(event
) )
3946 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3948 int id
= wxCharCodeMSWToWX(wParam
);
3952 // normal ASCII char
3956 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3958 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3959 if ( GetEventHandler()->ProcessEvent(event
) )
3968 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3970 int id
= wxCharCodeMSWToWX(wParam
);
3974 // normal ASCII char
3978 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3980 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3981 if ( GetEventHandler()->ProcessEvent(event
) )
3988 // ---------------------------------------------------------------------------
3990 // ---------------------------------------------------------------------------
3992 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3996 if ( flags
& JOY_BUTTON1CHG
)
3997 change
= wxJOY_BUTTON1
;
3998 if ( flags
& JOY_BUTTON2CHG
)
3999 change
= wxJOY_BUTTON2
;
4000 if ( flags
& JOY_BUTTON3CHG
)
4001 change
= wxJOY_BUTTON3
;
4002 if ( flags
& JOY_BUTTON4CHG
)
4003 change
= wxJOY_BUTTON4
;
4006 if ( flags
& JOY_BUTTON1
)
4007 buttons
|= wxJOY_BUTTON1
;
4008 if ( flags
& JOY_BUTTON2
)
4009 buttons
|= wxJOY_BUTTON2
;
4010 if ( flags
& JOY_BUTTON3
)
4011 buttons
|= wxJOY_BUTTON3
;
4012 if ( flags
& JOY_BUTTON4
)
4013 buttons
|= wxJOY_BUTTON4
;
4015 // the event ids aren't consecutive so we can't use table based lookup
4017 wxEventType eventType
;
4022 eventType
= wxEVT_JOY_MOVE
;
4027 eventType
= wxEVT_JOY_MOVE
;
4032 eventType
= wxEVT_JOY_ZMOVE
;
4037 eventType
= wxEVT_JOY_ZMOVE
;
4040 case MM_JOY1BUTTONDOWN
:
4042 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4045 case MM_JOY2BUTTONDOWN
:
4047 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4050 case MM_JOY1BUTTONUP
:
4052 eventType
= wxEVT_JOY_BUTTON_UP
;
4055 case MM_JOY2BUTTONUP
:
4057 eventType
= wxEVT_JOY_BUTTON_UP
;
4061 wxFAIL_MSG(wxT("no such joystick event"));
4066 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4067 event
.SetPosition(wxPoint(x
, y
));
4068 event
.SetEventObject(this);
4070 return GetEventHandler()->ProcessEvent(event
);
4076 // ---------------------------------------------------------------------------
4078 // ---------------------------------------------------------------------------
4080 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4081 WXWORD pos
, WXHWND control
)
4085 wxWindow
*child
= wxFindWinFromHandle(control
);
4087 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4090 wxScrollWinEvent event
;
4091 event
.SetPosition(pos
);
4092 event
.SetOrientation(orientation
);
4093 event
.m_eventObject
= this;
4098 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4102 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4106 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4110 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4114 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4118 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4121 case SB_THUMBPOSITION
:
4124 // under Win32, the scrollbar range and position are 32 bit integers,
4125 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4126 // explicitly query the scrollbar for the correct position (this must
4127 // be done only for these two SB_ events as they are the only one
4128 // carrying the scrollbar position)
4130 SCROLLINFO scrollInfo
;
4131 wxZeroMemory(scrollInfo
);
4132 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4133 scrollInfo
.fMask
= SIF_TRACKPOS
;
4135 if ( !::GetScrollInfo(GetHwnd(),
4136 orientation
== wxHORIZONTAL
? SB_HORZ
4140 wxLogLastError(_T("GetScrollInfo"));
4143 event
.SetPosition(scrollInfo
.nTrackPos
);
4147 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4148 ? wxEVT_SCROLLWIN_THUMBRELEASE
4149 : wxEVT_SCROLLWIN_THUMBTRACK
;
4156 return GetEventHandler()->ProcessEvent(event
);
4159 // ===========================================================================
4161 // ===========================================================================
4163 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4166 HDC dc
= ::GetDC((HWND
) wnd
);
4171 // the_font->UseResource();
4172 // the_font->RealizeResource();
4173 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4175 was
= (HFONT
) SelectObject(dc
,fnt
);
4177 GetTextMetrics(dc
, &tm
);
4178 if ( the_font
&& fnt
&& was
)
4180 SelectObject(dc
,was
);
4182 ReleaseDC((HWND
)wnd
, dc
);
4185 *x
= tm
.tmAveCharWidth
;
4187 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4190 // the_font->ReleaseResource();
4193 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4194 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4195 int wxCharCodeMSWToWX(int keySym
)
4200 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4201 case VK_BACK
: id
= WXK_BACK
; break;
4202 case VK_TAB
: id
= WXK_TAB
; break;
4203 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4204 case VK_RETURN
: id
= WXK_RETURN
; break;
4205 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4206 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4207 case VK_MENU
: id
= WXK_MENU
; break;
4208 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4209 case VK_SPACE
: id
= WXK_SPACE
; break;
4210 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4211 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4212 case VK_NEXT
: id
= WXK_NEXT
; break;
4213 case VK_END
: id
= WXK_END
; break;
4214 case VK_HOME
: id
= WXK_HOME
; break;
4215 case VK_LEFT
: id
= WXK_LEFT
; break;
4216 case VK_UP
: id
= WXK_UP
; break;
4217 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4218 case VK_DOWN
: id
= WXK_DOWN
; break;
4219 case VK_SELECT
: id
= WXK_SELECT
; break;
4220 case VK_PRINT
: id
= WXK_PRINT
; break;
4221 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4222 case VK_INSERT
: id
= WXK_INSERT
; break;
4223 case VK_DELETE
: id
= WXK_DELETE
; break;
4224 case VK_HELP
: id
= WXK_HELP
; break;
4225 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4226 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4227 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4228 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4229 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4230 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4231 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4232 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4233 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4234 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4235 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4236 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4237 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4238 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4239 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4240 case VK_F1
: id
= WXK_F1
; break;
4241 case VK_F2
: id
= WXK_F2
; break;
4242 case VK_F3
: id
= WXK_F3
; break;
4243 case VK_F4
: id
= WXK_F4
; break;
4244 case VK_F5
: id
= WXK_F5
; break;
4245 case VK_F6
: id
= WXK_F6
; break;
4246 case VK_F7
: id
= WXK_F7
; break;
4247 case VK_F8
: id
= WXK_F8
; break;
4248 case VK_F9
: id
= WXK_F9
; break;
4249 case VK_F10
: id
= WXK_F10
; break;
4250 case VK_F11
: id
= WXK_F11
; break;
4251 case VK_F12
: id
= WXK_F12
; break;
4252 case VK_F13
: id
= WXK_F13
; break;
4253 case VK_F14
: id
= WXK_F14
; break;
4254 case VK_F15
: id
= WXK_F15
; break;
4255 case VK_F16
: id
= WXK_F16
; break;
4256 case VK_F17
: id
= WXK_F17
; break;
4257 case VK_F18
: id
= WXK_F18
; break;
4258 case VK_F19
: id
= WXK_F19
; break;
4259 case VK_F20
: id
= WXK_F20
; break;
4260 case VK_F21
: id
= WXK_F21
; break;
4261 case VK_F22
: id
= WXK_F22
; break;
4262 case VK_F23
: id
= WXK_F23
; break;
4263 case VK_F24
: id
= WXK_F24
; break;
4264 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4265 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4273 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4279 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4280 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4281 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4282 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4283 case WXK_MENU
: keySym
= VK_MENU
; break;
4284 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4285 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4286 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4287 case WXK_END
: keySym
= VK_END
; break;
4288 case WXK_HOME
: keySym
= VK_HOME
; break;
4289 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4290 case WXK_UP
: keySym
= VK_UP
; break;
4291 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4292 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4293 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4294 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4295 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4296 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4297 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4298 case WXK_HELP
: keySym
= VK_HELP
; break;
4299 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4300 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4301 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4302 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4303 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4304 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4305 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4306 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4307 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4308 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4309 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4310 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4311 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4312 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4313 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4314 case WXK_F1
: keySym
= VK_F1
; break;
4315 case WXK_F2
: keySym
= VK_F2
; break;
4316 case WXK_F3
: keySym
= VK_F3
; break;
4317 case WXK_F4
: keySym
= VK_F4
; break;
4318 case WXK_F5
: keySym
= VK_F5
; break;
4319 case WXK_F6
: keySym
= VK_F6
; break;
4320 case WXK_F7
: keySym
= VK_F7
; break;
4321 case WXK_F8
: keySym
= VK_F8
; break;
4322 case WXK_F9
: keySym
= VK_F9
; break;
4323 case WXK_F10
: keySym
= VK_F10
; break;
4324 case WXK_F11
: keySym
= VK_F11
; break;
4325 case WXK_F12
: keySym
= VK_F12
; break;
4326 case WXK_F13
: keySym
= VK_F13
; break;
4327 case WXK_F14
: keySym
= VK_F14
; break;
4328 case WXK_F15
: keySym
= VK_F15
; break;
4329 case WXK_F16
: keySym
= VK_F16
; break;
4330 case WXK_F17
: keySym
= VK_F17
; break;
4331 case WXK_F18
: keySym
= VK_F18
; break;
4332 case WXK_F19
: keySym
= VK_F19
; break;
4333 case WXK_F20
: keySym
= VK_F20
; break;
4334 case WXK_F21
: keySym
= VK_F21
; break;
4335 case WXK_F22
: keySym
= VK_F22
; break;
4336 case WXK_F23
: keySym
= VK_F23
; break;
4337 case WXK_F24
: keySym
= VK_F24
; break;
4338 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4339 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4350 wxWindow
*wxGetActiveWindow()
4352 HWND hWnd
= GetActiveWindow();
4355 return wxFindWinFromHandle((WXHWND
) hWnd
);
4360 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4362 HWND hwnd
= (HWND
)hWnd
;
4364 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4365 // by code in msw/radiobox.cpp), for all the others we just search up the
4367 wxWindow
*win
= (wxWindow
*)NULL
;
4370 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4373 // all these hacks only work under Win32 anyhow
4377 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4378 // wxWindow class which overrides WM_GETDLGCODE processing to
4379 // do it as well, win would be already non NULL
4380 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4382 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4384 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4385 #endif // wxUSE_RADIOBOX
4387 // spin control text buddy window should be mapped to spin ctrl
4388 // itself so try it too
4389 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4392 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4394 #endif // wxUSE_SPINCTRL
4400 while ( hwnd
&& !win
)
4402 // this is a really ugly hack needed to avoid mistakenly returning the
4403 // parent frame wxWindow for the find/replace modeless dialog HWND -
4404 // this, in turn, is needed to call IsDialogMessage() from
4405 // wxApp::ProcessMessage() as for this we must return NULL from here
4407 // FIXME: this is clearly not the best way to do it but I think we'll
4408 // need to change HWND <-> wxWindow code more heavily than I can
4409 // do it now to fix it
4410 #ifndef __WXMICROWIN__
4411 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4413 // it's a dialog box, don't go upwards
4418 hwnd
= ::GetParent(hwnd
);
4419 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4425 #ifndef __WXMICROWIN__
4427 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4428 // in active frames and dialogs, regardless of where the focus is.
4429 static HHOOK wxTheKeyboardHook
= 0;
4430 static FARPROC wxTheKeyboardHookProc
= 0;
4431 int APIENTRY _EXPORT
4432 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4434 void wxSetKeyboardHook(bool doIt
)
4438 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4439 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4441 #if defined(__WIN32__) && !defined(__TWIN32__)
4442 GetCurrentThreadId()
4443 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4451 UnhookWindowsHookEx(wxTheKeyboardHook
);
4453 // avoids warning about statement with no effect (FreeProcInstance
4454 // doesn't do anything under Win32)
4455 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4456 FreeProcInstance(wxTheKeyboardHookProc
);
4461 int APIENTRY _EXPORT
4462 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4464 DWORD hiWord
= HIWORD(lParam
);
4465 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4467 int id
= wxCharCodeMSWToWX(wParam
);
4470 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4471 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4472 event
.m_altDown
= TRUE
;
4474 event
.m_eventObject
= NULL
;
4475 event
.m_keyCode
= id
;
4476 event
.m_shiftDown
= wxIsShiftDown();
4477 event
.m_controlDown
= wxIsCtrlDown();
4478 event
.SetTimestamp(s_currentMsg
.time
);
4480 wxWindow
*win
= wxGetActiveWindow();
4481 wxEvtHandler
*handler
;
4484 handler
= win
->GetEventHandler();
4485 event
.SetId(win
->GetId());
4493 if ( handler
&& handler
->ProcessEvent(event
) )
4501 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4504 #endif // !__WXMICROWIN__
4507 const char *wxGetMessageName(int message
)
4511 case 0x0000: return "WM_NULL";
4512 case 0x0001: return "WM_CREATE";
4513 case 0x0002: return "WM_DESTROY";
4514 case 0x0003: return "WM_MOVE";
4515 case 0x0005: return "WM_SIZE";
4516 case 0x0006: return "WM_ACTIVATE";
4517 case 0x0007: return "WM_SETFOCUS";
4518 case 0x0008: return "WM_KILLFOCUS";
4519 case 0x000A: return "WM_ENABLE";
4520 case 0x000B: return "WM_SETREDRAW";
4521 case 0x000C: return "WM_SETTEXT";
4522 case 0x000D: return "WM_GETTEXT";
4523 case 0x000E: return "WM_GETTEXTLENGTH";
4524 case 0x000F: return "WM_PAINT";
4525 case 0x0010: return "WM_CLOSE";
4526 case 0x0011: return "WM_QUERYENDSESSION";
4527 case 0x0012: return "WM_QUIT";
4528 case 0x0013: return "WM_QUERYOPEN";
4529 case 0x0014: return "WM_ERASEBKGND";
4530 case 0x0015: return "WM_SYSCOLORCHANGE";
4531 case 0x0016: return "WM_ENDSESSION";
4532 case 0x0017: return "WM_SYSTEMERROR";
4533 case 0x0018: return "WM_SHOWWINDOW";
4534 case 0x0019: return "WM_CTLCOLOR";
4535 case 0x001A: return "WM_WININICHANGE";
4536 case 0x001B: return "WM_DEVMODECHANGE";
4537 case 0x001C: return "WM_ACTIVATEAPP";
4538 case 0x001D: return "WM_FONTCHANGE";
4539 case 0x001E: return "WM_TIMECHANGE";
4540 case 0x001F: return "WM_CANCELMODE";
4541 case 0x0020: return "WM_SETCURSOR";
4542 case 0x0021: return "WM_MOUSEACTIVATE";
4543 case 0x0022: return "WM_CHILDACTIVATE";
4544 case 0x0023: return "WM_QUEUESYNC";
4545 case 0x0024: return "WM_GETMINMAXINFO";
4546 case 0x0026: return "WM_PAINTICON";
4547 case 0x0027: return "WM_ICONERASEBKGND";
4548 case 0x0028: return "WM_NEXTDLGCTL";
4549 case 0x002A: return "WM_SPOOLERSTATUS";
4550 case 0x002B: return "WM_DRAWITEM";
4551 case 0x002C: return "WM_MEASUREITEM";
4552 case 0x002D: return "WM_DELETEITEM";
4553 case 0x002E: return "WM_VKEYTOITEM";
4554 case 0x002F: return "WM_CHARTOITEM";
4555 case 0x0030: return "WM_SETFONT";
4556 case 0x0031: return "WM_GETFONT";
4557 case 0x0037: return "WM_QUERYDRAGICON";
4558 case 0x0039: return "WM_COMPAREITEM";
4559 case 0x0041: return "WM_COMPACTING";
4560 case 0x0044: return "WM_COMMNOTIFY";
4561 case 0x0046: return "WM_WINDOWPOSCHANGING";
4562 case 0x0047: return "WM_WINDOWPOSCHANGED";
4563 case 0x0048: return "WM_POWER";
4566 case 0x004A: return "WM_COPYDATA";
4567 case 0x004B: return "WM_CANCELJOURNAL";
4568 case 0x004E: return "WM_NOTIFY";
4569 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4570 case 0x0051: return "WM_INPUTLANGCHANGE";
4571 case 0x0052: return "WM_TCARD";
4572 case 0x0053: return "WM_HELP";
4573 case 0x0054: return "WM_USERCHANGED";
4574 case 0x0055: return "WM_NOTIFYFORMAT";
4575 case 0x007B: return "WM_CONTEXTMENU";
4576 case 0x007C: return "WM_STYLECHANGING";
4577 case 0x007D: return "WM_STYLECHANGED";
4578 case 0x007E: return "WM_DISPLAYCHANGE";
4579 case 0x007F: return "WM_GETICON";
4580 case 0x0080: return "WM_SETICON";
4583 case 0x0081: return "WM_NCCREATE";
4584 case 0x0082: return "WM_NCDESTROY";
4585 case 0x0083: return "WM_NCCALCSIZE";
4586 case 0x0084: return "WM_NCHITTEST";
4587 case 0x0085: return "WM_NCPAINT";
4588 case 0x0086: return "WM_NCACTIVATE";
4589 case 0x0087: return "WM_GETDLGCODE";
4590 case 0x00A0: return "WM_NCMOUSEMOVE";
4591 case 0x00A1: return "WM_NCLBUTTONDOWN";
4592 case 0x00A2: return "WM_NCLBUTTONUP";
4593 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4594 case 0x00A4: return "WM_NCRBUTTONDOWN";
4595 case 0x00A5: return "WM_NCRBUTTONUP";
4596 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4597 case 0x00A7: return "WM_NCMBUTTONDOWN";
4598 case 0x00A8: return "WM_NCMBUTTONUP";
4599 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4600 case 0x0100: return "WM_KEYDOWN";
4601 case 0x0101: return "WM_KEYUP";
4602 case 0x0102: return "WM_CHAR";
4603 case 0x0103: return "WM_DEADCHAR";
4604 case 0x0104: return "WM_SYSKEYDOWN";
4605 case 0x0105: return "WM_SYSKEYUP";
4606 case 0x0106: return "WM_SYSCHAR";
4607 case 0x0107: return "WM_SYSDEADCHAR";
4608 case 0x0108: return "WM_KEYLAST";
4611 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4612 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4613 case 0x010F: return "WM_IME_COMPOSITION";
4616 case 0x0110: return "WM_INITDIALOG";
4617 case 0x0111: return "WM_COMMAND";
4618 case 0x0112: return "WM_SYSCOMMAND";
4619 case 0x0113: return "WM_TIMER";
4620 case 0x0114: return "WM_HSCROLL";
4621 case 0x0115: return "WM_VSCROLL";
4622 case 0x0116: return "WM_INITMENU";
4623 case 0x0117: return "WM_INITMENUPOPUP";
4624 case 0x011F: return "WM_MENUSELECT";
4625 case 0x0120: return "WM_MENUCHAR";
4626 case 0x0121: return "WM_ENTERIDLE";
4627 case 0x0200: return "WM_MOUSEMOVE";
4628 case 0x0201: return "WM_LBUTTONDOWN";
4629 case 0x0202: return "WM_LBUTTONUP";
4630 case 0x0203: return "WM_LBUTTONDBLCLK";
4631 case 0x0204: return "WM_RBUTTONDOWN";
4632 case 0x0205: return "WM_RBUTTONUP";
4633 case 0x0206: return "WM_RBUTTONDBLCLK";
4634 case 0x0207: return "WM_MBUTTONDOWN";
4635 case 0x0208: return "WM_MBUTTONUP";
4636 case 0x0209: return "WM_MBUTTONDBLCLK";
4637 case 0x020A: return "WM_MOUSEWHEEL";
4638 case 0x0210: return "WM_PARENTNOTIFY";
4639 case 0x0211: return "WM_ENTERMENULOOP";
4640 case 0x0212: return "WM_EXITMENULOOP";
4643 case 0x0213: return "WM_NEXTMENU";
4644 case 0x0214: return "WM_SIZING";
4645 case 0x0215: return "WM_CAPTURECHANGED";
4646 case 0x0216: return "WM_MOVING";
4647 case 0x0218: return "WM_POWERBROADCAST";
4648 case 0x0219: return "WM_DEVICECHANGE";
4651 case 0x0220: return "WM_MDICREATE";
4652 case 0x0221: return "WM_MDIDESTROY";
4653 case 0x0222: return "WM_MDIACTIVATE";
4654 case 0x0223: return "WM_MDIRESTORE";
4655 case 0x0224: return "WM_MDINEXT";
4656 case 0x0225: return "WM_MDIMAXIMIZE";
4657 case 0x0226: return "WM_MDITILE";
4658 case 0x0227: return "WM_MDICASCADE";
4659 case 0x0228: return "WM_MDIICONARRANGE";
4660 case 0x0229: return "WM_MDIGETACTIVE";
4661 case 0x0230: return "WM_MDISETMENU";
4662 case 0x0233: return "WM_DROPFILES";
4665 case 0x0281: return "WM_IME_SETCONTEXT";
4666 case 0x0282: return "WM_IME_NOTIFY";
4667 case 0x0283: return "WM_IME_CONTROL";
4668 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4669 case 0x0285: return "WM_IME_SELECT";
4670 case 0x0286: return "WM_IME_CHAR";
4671 case 0x0290: return "WM_IME_KEYDOWN";
4672 case 0x0291: return "WM_IME_KEYUP";
4675 case 0x0300: return "WM_CUT";
4676 case 0x0301: return "WM_COPY";
4677 case 0x0302: return "WM_PASTE";
4678 case 0x0303: return "WM_CLEAR";
4679 case 0x0304: return "WM_UNDO";
4680 case 0x0305: return "WM_RENDERFORMAT";
4681 case 0x0306: return "WM_RENDERALLFORMATS";
4682 case 0x0307: return "WM_DESTROYCLIPBOARD";
4683 case 0x0308: return "WM_DRAWCLIPBOARD";
4684 case 0x0309: return "WM_PAINTCLIPBOARD";
4685 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4686 case 0x030B: return "WM_SIZECLIPBOARD";
4687 case 0x030C: return "WM_ASKCBFORMATNAME";
4688 case 0x030D: return "WM_CHANGECBCHAIN";
4689 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4690 case 0x030F: return "WM_QUERYNEWPALETTE";
4691 case 0x0310: return "WM_PALETTEISCHANGING";
4692 case 0x0311: return "WM_PALETTECHANGED";
4695 // common controls messages - although they're not strictly speaking
4696 // standard, it's nice to decode them nevertheless
4699 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4700 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4701 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4702 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4703 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4704 case 0x1000 + 5: return "LVM_GETITEMA";
4705 case 0x1000 + 75: return "LVM_GETITEMW";
4706 case 0x1000 + 6: return "LVM_SETITEMA";
4707 case 0x1000 + 76: return "LVM_SETITEMW";
4708 case 0x1000 + 7: return "LVM_INSERTITEMA";
4709 case 0x1000 + 77: return "LVM_INSERTITEMW";
4710 case 0x1000 + 8: return "LVM_DELETEITEM";
4711 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4712 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4713 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4714 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4715 case 0x1000 + 13: return "LVM_FINDITEMA";
4716 case 0x1000 + 83: return "LVM_FINDITEMW";
4717 case 0x1000 + 14: return "LVM_GETITEMRECT";
4718 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4719 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4720 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4721 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4722 case 0x1000 + 18: return "LVM_HITTEST";
4723 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4724 case 0x1000 + 20: return "LVM_SCROLL";
4725 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4726 case 0x1000 + 22: return "LVM_ARRANGE";
4727 case 0x1000 + 23: return "LVM_EDITLABELA";
4728 case 0x1000 + 118: return "LVM_EDITLABELW";
4729 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4730 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4731 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4732 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4733 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4734 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4735 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4736 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4737 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4738 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4739 case 0x1000 + 31: return "LVM_GETHEADER";
4740 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4741 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4742 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4743 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4744 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4745 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4746 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4747 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4748 case 0x1000 + 41: return "LVM_GETORIGIN";
4749 case 0x1000 + 42: return "LVM_UPDATE";
4750 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4751 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4752 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4753 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4754 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4755 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4756 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4757 case 0x1000 + 48: return "LVM_SORTITEMS";
4758 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4759 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4760 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4761 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4762 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4763 case 0x1000 + 53: return "LVM_SETICONSPACING";
4764 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4765 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4766 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4767 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4768 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4769 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4770 case 0x1000 + 60: return "LVM_SETHOTITEM";
4771 case 0x1000 + 61: return "LVM_GETHOTITEM";
4772 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4773 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4774 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4775 case 0x1000 + 65: return "LVM_SETWORKAREA";
4778 case 0x1100 + 0: return "TVM_INSERTITEMA";
4779 case 0x1100 + 50: return "TVM_INSERTITEMW";
4780 case 0x1100 + 1: return "TVM_DELETEITEM";
4781 case 0x1100 + 2: return "TVM_EXPAND";
4782 case 0x1100 + 4: return "TVM_GETITEMRECT";
4783 case 0x1100 + 5: return "TVM_GETCOUNT";
4784 case 0x1100 + 6: return "TVM_GETINDENT";
4785 case 0x1100 + 7: return "TVM_SETINDENT";
4786 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4787 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4788 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4789 case 0x1100 + 11: return "TVM_SELECTITEM";
4790 case 0x1100 + 12: return "TVM_GETITEMA";
4791 case 0x1100 + 62: return "TVM_GETITEMW";
4792 case 0x1100 + 13: return "TVM_SETITEMA";
4793 case 0x1100 + 63: return "TVM_SETITEMW";
4794 case 0x1100 + 14: return "TVM_EDITLABELA";
4795 case 0x1100 + 65: return "TVM_EDITLABELW";
4796 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4797 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4798 case 0x1100 + 17: return "TVM_HITTEST";
4799 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4800 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4801 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4802 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4803 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4804 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4805 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4806 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4807 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4810 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4811 case 0x1200 + 1: return "HDM_INSERTITEMA";
4812 case 0x1200 + 10: return "HDM_INSERTITEMW";
4813 case 0x1200 + 2: return "HDM_DELETEITEM";
4814 case 0x1200 + 3: return "HDM_GETITEMA";
4815 case 0x1200 + 11: return "HDM_GETITEMW";
4816 case 0x1200 + 4: return "HDM_SETITEMA";
4817 case 0x1200 + 12: return "HDM_SETITEMW";
4818 case 0x1200 + 5: return "HDM_LAYOUT";
4819 case 0x1200 + 6: return "HDM_HITTEST";
4820 case 0x1200 + 7: return "HDM_GETITEMRECT";
4821 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4822 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4823 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4824 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4825 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4826 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4827 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4830 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4831 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4832 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4833 case 0x1300 + 5: return "TCM_GETITEMA";
4834 case 0x1300 + 60: return "TCM_GETITEMW";
4835 case 0x1300 + 6: return "TCM_SETITEMA";
4836 case 0x1300 + 61: return "TCM_SETITEMW";
4837 case 0x1300 + 7: return "TCM_INSERTITEMA";
4838 case 0x1300 + 62: return "TCM_INSERTITEMW";
4839 case 0x1300 + 8: return "TCM_DELETEITEM";
4840 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4841 case 0x1300 + 10: return "TCM_GETITEMRECT";
4842 case 0x1300 + 11: return "TCM_GETCURSEL";
4843 case 0x1300 + 12: return "TCM_SETCURSEL";
4844 case 0x1300 + 13: return "TCM_HITTEST";
4845 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4846 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4847 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4848 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4849 case 0x1300 + 43: return "TCM_SETPADDING";
4850 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4851 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4852 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4853 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4854 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4855 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4856 case 0x1300 + 50: return "TCM_DESELECTALL";
4859 case WM_USER
+1: return "TB_ENABLEBUTTON";
4860 case WM_USER
+2: return "TB_CHECKBUTTON";
4861 case WM_USER
+3: return "TB_PRESSBUTTON";
4862 case WM_USER
+4: return "TB_HIDEBUTTON";
4863 case WM_USER
+5: return "TB_INDETERMINATE";
4864 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4865 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4866 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4867 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4868 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4869 case WM_USER
+17: return "TB_SETSTATE";
4870 case WM_USER
+18: return "TB_GETSTATE";
4871 case WM_USER
+19: return "TB_ADDBITMAP";
4872 case WM_USER
+20: return "TB_ADDBUTTONS";
4873 case WM_USER
+21: return "TB_INSERTBUTTON";
4874 case WM_USER
+22: return "TB_DELETEBUTTON";
4875 case WM_USER
+23: return "TB_GETBUTTON";
4876 case WM_USER
+24: return "TB_BUTTONCOUNT";
4877 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4878 case WM_USER
+26: return "TB_SAVERESTOREA";
4879 case WM_USER
+76: return "TB_SAVERESTOREW";
4880 case WM_USER
+27: return "TB_CUSTOMIZE";
4881 case WM_USER
+28: return "TB_ADDSTRINGA";
4882 case WM_USER
+77: return "TB_ADDSTRINGW";
4883 case WM_USER
+29: return "TB_GETITEMRECT";
4884 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4885 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4886 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4887 case WM_USER
+33: return "TB_AUTOSIZE";
4888 case WM_USER
+35: return "TB_GETTOOLTIPS";
4889 case WM_USER
+36: return "TB_SETTOOLTIPS";
4890 case WM_USER
+37: return "TB_SETPARENT";
4891 case WM_USER
+39: return "TB_SETROWS";
4892 case WM_USER
+40: return "TB_GETROWS";
4893 case WM_USER
+42: return "TB_SETCMDID";
4894 case WM_USER
+43: return "TB_CHANGEBITMAP";
4895 case WM_USER
+44: return "TB_GETBITMAP";
4896 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4897 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4898 case WM_USER
+46: return "TB_REPLACEBITMAP";
4899 case WM_USER
+47: return "TB_SETINDENT";
4900 case WM_USER
+48: return "TB_SETIMAGELIST";
4901 case WM_USER
+49: return "TB_GETIMAGELIST";
4902 case WM_USER
+50: return "TB_LOADIMAGES";
4903 case WM_USER
+51: return "TB_GETRECT";
4904 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4905 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4906 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4907 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4908 case WM_USER
+56: return "TB_SETSTYLE";
4909 case WM_USER
+57: return "TB_GETSTYLE";
4910 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4911 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4912 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4913 case WM_USER
+61: return "TB_GETTEXTROWS";
4914 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4919 static char s_szBuf
[128];
4920 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4924 #endif //__WXDEBUG__
4926 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4927 int *x
, int *y
, WPARAM
*flags
)
4929 // construct the key mask
4930 WPARAM
& fwKeys
= *flags
;
4932 fwKeys
= MK_RBUTTON
;
4933 if ( wxIsCtrlDown() )
4934 fwKeys
|= MK_CONTROL
;
4935 if ( wxIsShiftDown() )
4938 // simulate right mouse button click
4939 DWORD dwPos
= ::GetMessagePos();
4940 *x
= GET_X_LPARAM(dwPos
);
4941 *y
= GET_Y_LPARAM(dwPos
);
4943 win
->ScreenToClient(x
, y
);
4946 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4950 HWND hwnd
= GetHwndOf(win
);
4951 HDC hdc
= ::GetDC(hwnd
);
4953 #if !wxDIALOG_UNIT_COMPATIBILITY
4954 // and select the current font into it
4955 HFONT hfont
= GetHfontOf(win
->GetFont());
4958 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4962 // finally retrieve the text metrics from it
4963 GetTextMetrics(hdc
, &tm
);
4965 #if !wxDIALOG_UNIT_COMPATIBILITY
4969 (void)::SelectObject(hdc
, hfont
);
4973 ::ReleaseDC(hwnd
, hdc
);
4978 // Find the wxWindow at the current mouse position, returning the mouse
4980 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4982 return wxFindWindowAtPoint(wxGetMousePosition());
4985 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4990 HWND hWndHit
= ::WindowFromPoint(pt2
);
4992 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4993 HWND hWnd
= hWndHit
;
4995 // Try to find a window with a wxWindow associated with it
4996 while (!win
&& (hWnd
!= 0))
4998 hWnd
= ::GetParent(hWnd
);
4999 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
5004 // Get the current mouse position.
5005 wxPoint
wxGetMousePosition()
5008 GetCursorPos( & pt
);
5009 return wxPoint(pt
.x
, pt
.y
);