1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/windows.cpp
4 // Author: Julian Smart
5 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
21 #pragma implementation "window.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
33 #include "wx/msw/winundef.h"
34 #include "wx/window.h"
39 #include "wx/dcclient.h"
42 #include "wx/layout.h"
43 #include "wx/dialog.h"
45 #include "wx/listbox.h"
46 #include "wx/button.h"
47 #include "wx/msgdlg.h"
48 #include "wx/settings.h"
49 #include "wx/statbox.h"
53 #include "wx/ownerdrw.h"
56 #if wxUSE_DRAG_AND_DROP
60 #include "wx/menuitem.h"
63 #include "wx/msw/private.h"
66 #include "wx/tooltip.h"
74 #include "wx/spinctrl.h"
75 #endif // wxUSE_SPINCTRL
80 #include "wx/textctrl.h"
81 #include "wx/notebook.h"
85 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
94 #if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
98 #elif !defined(__WXMICROWIN__) // broken compiler
100 #include "wx/msw/gnuwin32/extra.h"
104 // This didn't appear in mingw until 2.95.2
106 #define SIF_TRACKPOS 16
110 #ifndef WM_MOUSEWHEEL
111 #define WM_MOUSEWHEEL 0x020A
114 #define WHEEL_DELTA 120
116 #ifndef SPI_GETWHEELSCROLLLINES
117 #define SPI_GETWHEELSCROLLLINES 104
121 // ---------------------------------------------------------------------------
123 // ---------------------------------------------------------------------------
125 // the last Windows message we got (FIXME-MT)
126 extern MSG s_currentMsg
;
128 #if wxUSE_MENUS_NATIVE
129 wxMenu
*wxCurrentPopupMenu
= NULL
;
130 #endif // wxUSE_MENUS_NATIVE
132 extern const wxChar
*wxCanvasClassName
;
134 // true if we had already created the std colour map, used by
135 // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
136 static bool gs_hasStdCmap
= FALSE
;
138 // ---------------------------------------------------------------------------
140 // ---------------------------------------------------------------------------
142 // the window proc for all our windows
143 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
144 WPARAM wParam
, LPARAM lParam
);
147 const char *wxGetMessageName(int message
);
150 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
151 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
152 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
154 // this magical function is used to translate VK_APPS key presses to right
156 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
157 int *x
, int *y
, WPARAM
*flags
);
159 // get the text metrics for the current font
160 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
162 // wrapper around BringWindowToTop() API
163 static inline void wxBringWindowToTop(HWND hwnd
)
165 #ifdef __WXMICROWIN__
166 // It seems that MicroWindows brings the _parent_ of the window to the top,
167 // which can be the wrong one.
169 // activate (set focus to) specified window
172 // raise top level parent to top of z order
173 ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
174 #else // !__WXMICROWIN__
175 if ( !::BringWindowToTop(hwnd
) )
177 wxLogLastError(_T("BringWindowToTop"));
179 #endif // __WXMICROWIN__/!__WXMICROWIN__
182 // ---------------------------------------------------------------------------
184 // ---------------------------------------------------------------------------
186 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
188 #ifdef __WXUNIVERSAL__
189 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
191 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
192 #endif // __WXUNIVERSAL__/__WXMSW__
194 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
195 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
196 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
197 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
198 EVT_IDLE(wxWindowMSW::OnIdle
)
201 // ===========================================================================
203 // ===========================================================================
205 // ---------------------------------------------------------------------------
206 // wxWindow utility functions
207 // ---------------------------------------------------------------------------
209 // Find an item given the MS Windows id
210 wxWindow
*wxWindowMSW::FindItem(long id
) const
213 wxControl
*item
= wxDynamicCastThis(wxControl
);
216 // is it we or one of our "internal" children?
217 if ( item
->GetId() == id
218 #ifndef __WXUNIVERSAL__
219 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
220 #endif // __WXUNIVERSAL__
226 #endif // wxUSE_CONTROLS
228 wxWindowList::Node
*current
= GetChildren().GetFirst();
231 wxWindow
*childWin
= current
->GetData();
233 wxWindow
*wnd
= childWin
->FindItem(id
);
237 current
= current
->GetNext();
243 // Find an item given the MS Windows handle
244 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
246 wxWindowList::Node
*current
= GetChildren().GetFirst();
249 wxWindow
*parent
= current
->GetData();
251 // Do a recursive search.
252 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
258 || parent
->IsKindOf(CLASSINFO(wxControl
))
259 #endif // wxUSE_CONTROLS
262 wxWindow
*item
= current
->GetData();
263 if ( item
->GetHWND() == hWnd
)
267 if ( item
->ContainsHWND(hWnd
) )
272 current
= current
->GetNext();
277 // Default command handler
278 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
283 // ----------------------------------------------------------------------------
284 // constructors and such
285 // ----------------------------------------------------------------------------
287 void wxWindowMSW::Init()
293 m_doubleClickAllowed
= 0;
295 m_isBeingDeleted
= FALSE
;
298 m_mouseInWindow
= FALSE
;
305 // pass WM_GETDLGCODE to DefWindowProc()
310 m_backgroundTransparent
= FALSE
;
312 // as all windows are created with WS_VISIBLE style...
315 #if wxUSE_MOUSEEVENT_HACK
318 m_lastMouseEvent
= -1;
319 #endif // wxUSE_MOUSEEVENT_HACK
323 wxWindowMSW::~wxWindowMSW()
325 m_isBeingDeleted
= TRUE
;
327 #ifndef __WXUNIVERSAL__
328 // VS: make sure there's no wxFrame with last focus set to us:
329 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
331 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
334 if ( frame
->GetLastFocus() == this )
336 frame
->SetLastFocus((wxWindow
*)NULL
);
341 #endif // __WXUNIVERSAL__
343 // VS: destroy children first and _then_ detach *this from its parent.
344 // If we'd do it the other way around, children wouldn't be able
345 // find their parent frame (see above).
349 m_parent
->RemoveChild(this);
353 // VZ: test temp removed to understand what really happens here
354 //if (::IsWindow(GetHwnd()))
356 if ( !::DestroyWindow(GetHwnd()) )
357 wxLogLastError(wxT("DestroyWindow"));
360 // remove hWnd <-> wxWindow association
361 wxRemoveHandleAssociation(this);
365 // real construction (Init() must have been called before!)
366 bool wxWindowMSW::Create(wxWindow
*parent
,
371 const wxString
& name
)
373 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
376 // wxGTK doesn't allow to create controls with static box as the parent so
377 // this will result in a crash when the program is ported to wxGTK - warn
380 // the correct solution is to create the controls as siblings of the
382 wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
),
383 _T("wxStaticBox can't be used as a window parent!") );
384 #endif // wxUSE_STATBOX
386 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
389 parent
->AddChild(this);
391 // all windows are created visible
392 DWORD msflags
= WS_CHILD
| WS_VISIBLE
;
394 #ifdef __WXUNIVERSAL__
395 // no 3d effects, we draw them ourselves
397 #else // !wxUniversal
398 if ( style
& wxCLIP_CHILDREN
)
399 msflags
|= WS_CLIPCHILDREN
;
400 if ( style
& wxCLIP_SIBLINGS
)
401 msflags
|= WS_CLIPSIBLINGS
;
404 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
);
406 // Even with extended styles, need to combine with WS_BORDER
407 // for them to look right.
409 (m_windowStyle
& (wxBORDER
|
415 msflags
|= WS_BORDER
;
418 // calculate the value to return from WM_GETDLGCODE handler
419 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
421 // want everything: i.e. all keys and WM_CHAR message
422 m_lDlgCode
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
423 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
425 #endif // wxUniversal/!wxUniversal
427 if ( style
& wxPOPUP_WINDOW
)
429 // a popup window floats on top of everything
430 exStyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
432 // it is also created hidden as other top level windows
433 msflags
&= ~WS_VISIBLE
;
437 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
);
440 // ---------------------------------------------------------------------------
442 // ---------------------------------------------------------------------------
444 void wxWindowMSW::SetFocus()
446 HWND hWnd
= GetHwnd();
447 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
449 #ifndef __WXMICROWIN__
453 if ( !::SetFocus(hWnd
) )
455 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
456 // was there really an error?
457 DWORD dwRes
= ::GetLastError();
460 HWND hwndFocus
= ::GetFocus();
461 if ( hwndFocus
!= hWnd
)
463 wxLogApiError(_T("SetFocus"), dwRes
);
470 // Get the window with the focus
471 wxWindow
*wxWindowBase::FindFocus()
473 HWND hWnd
= ::GetFocus();
476 return wxGetWindowFromHWND((WXHWND
)hWnd
);
482 bool wxWindowMSW::Enable(bool enable
)
484 if ( !wxWindowBase::Enable(enable
) )
487 HWND hWnd
= GetHwnd();
489 ::EnableWindow(hWnd
, (BOOL
)enable
);
491 // VZ: no, this is a bad idea: imagine that you have a dialog with some
492 // disabled controls and disable it - you really wouldn't like the
493 // disabled controls be reenabled too when you reenable the dialog!
495 wxWindowList::Node
*node
= GetChildren().GetFirst();
498 wxWindow
*child
= node
->GetData();
499 child
->Enable(enable
);
501 node
= node
->GetNext();
508 bool wxWindowMSW::Show(bool show
)
510 if ( !wxWindowBase::Show(show
) )
513 HWND hWnd
= GetHwnd();
514 int cshow
= show
? SW_SHOW
: SW_HIDE
;
515 ::ShowWindow(hWnd
, cshow
);
519 wxBringWindowToTop(hWnd
);
525 // Raise the window to the top of the Z order
526 void wxWindowMSW::Raise()
528 wxBringWindowToTop(GetHwnd());
531 // Lower the window to the bottom of the Z order
532 void wxWindowMSW::Lower()
534 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
535 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
538 void wxWindowMSW::SetTitle( const wxString
& title
)
540 SetWindowText(GetHwnd(), title
.c_str());
543 wxString
wxWindowMSW::GetTitle() const
545 return wxGetWindowText(GetHWND());
548 void wxWindowMSW::CaptureMouse()
550 HWND hWnd
= GetHwnd();
557 void wxWindowMSW::ReleaseMouse()
559 if ( !::ReleaseCapture() )
561 wxLogLastError(_T("ReleaseCapture"));
565 /* static */ wxWindow
*wxWindowBase::GetCapture()
567 HWND hwnd
= ::GetCapture();
568 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
571 bool wxWindowMSW::SetFont(const wxFont
& font
)
573 if ( !wxWindowBase::SetFont(font
) )
579 HWND hWnd
= GetHwnd();
582 WXHANDLE hFont
= m_font
.GetResourceHandle();
584 wxASSERT_MSG( hFont
, wxT("should have valid font") );
586 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
591 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
593 if ( !wxWindowBase::SetCursor(cursor
) )
601 HWND hWnd
= GetHwnd();
603 // Change the cursor NOW if we're within the correct window
605 ::GetCursorPos(&point
);
607 RECT rect
= wxGetWindowRect(hWnd
);
609 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
610 ::SetCursor(GetHcursorOf(m_cursor
));
616 void wxWindowMSW::WarpPointer (int x
, int y
)
618 ClientToScreen(&x
, &y
);
620 if ( !::SetCursorPos(x
, y
) )
622 wxLogLastError(_T("SetCursorPos"));
626 #if WXWIN_COMPATIBILITY
627 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
630 #endif // WXWIN_COMPATIBILITY
632 // ---------------------------------------------------------------------------
634 // ---------------------------------------------------------------------------
636 #if WXWIN_COMPATIBILITY
637 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
639 #if defined(__WIN95__)
643 // Try to adjust the range to cope with page size > 1
644 // - a Windows API quirk
645 int pageSize
= GetScrollPage(orient
);
646 if ( pageSize
> 1 && range
> 0)
648 range1
+= (pageSize
- 1);
654 if ( orient
== wxHORIZONTAL
) {
660 info
.cbSize
= sizeof(SCROLLINFO
);
661 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
665 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
667 HWND hWnd
= GetHwnd();
669 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
672 if ( orient
== wxHORIZONTAL
)
677 HWND hWnd
= GetHwnd();
679 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
683 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
685 #if defined(__WIN95__)
689 if ( orient
== wxHORIZONTAL
) {
697 info
.cbSize
= sizeof(SCROLLINFO
);
700 info
.fMask
= SIF_PAGE
;
702 HWND hWnd
= GetHwnd();
704 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
706 if ( orient
== wxHORIZONTAL
)
713 int wxWindowMSW::OldGetScrollRange(int orient
) const
716 if ( orient
== wxHORIZONTAL
)
721 #if __WATCOMC__ && defined(__WINDOWS_386__)
722 short minPos
, maxPos
;
726 HWND hWnd
= GetHwnd();
729 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
730 #if defined(__WIN95__)
731 // Try to adjust the range to cope with page size > 1
732 // - a Windows API quirk
733 int pageSize
= GetScrollPage(orient
);
736 maxPos
-= (pageSize
- 1);
745 int wxWindowMSW::GetScrollPage(int orient
) const
747 if ( orient
== wxHORIZONTAL
)
753 #endif // WXWIN_COMPATIBILITY
755 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
757 #ifdef __WXMICROWIN__
758 return ::GetScrollPosWX(hWnd
, wOrient
);
760 return ::GetScrollPos(hWnd
, wOrient
);
764 int wxWindowMSW::GetScrollPos(int orient
) const
767 if ( orient
== wxHORIZONTAL
)
772 HWND hWnd
= GetHwnd();
773 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
775 return GetScrollPosition(hWnd
, wOrient
);
778 // This now returns the whole range, not just the number
779 // of positions that we can scroll.
780 int wxWindowMSW::GetScrollRange(int orient
) const
783 if ( orient
== wxHORIZONTAL
)
788 #if __WATCOMC__ && defined(__WINDOWS_386__)
789 short minPos
, maxPos
;
793 HWND hWnd
= GetHwnd();
796 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
797 #if defined(__WIN95__)
798 // Try to adjust the range to cope with page size > 1
799 // - a Windows API quirk
800 int pageSize
= GetScrollThumb(orient
);
803 maxPos
-= (pageSize
- 1);
805 // October 10th: new range concept.
815 int wxWindowMSW::GetScrollThumb(int orient
) const
817 if ( orient
== wxHORIZONTAL
)
823 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
825 HWND hWnd
= GetHwnd();
826 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
828 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
830 #if defined(__WIN95__)
832 info
.cbSize
= sizeof(SCROLLINFO
);
836 info
.fMask
= SIF_POS
;
838 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
840 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
841 #endif // __WIN95__/!__WIN95__
844 // New function that will replace some of the above.
845 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
846 int range
, bool refresh
)
848 #if defined(__WIN95__)
849 int oldRange
= range
- thumbVisible
;
851 int range1
= oldRange
;
853 // Try to adjust the range to cope with page size > 1
854 // - a Windows API quirk
855 int pageSize
= thumbVisible
;
856 if ( pageSize
> 1 && range
> 0)
858 range1
+= (pageSize
- 1);
864 if ( orient
== wxHORIZONTAL
) {
870 info
.cbSize
= sizeof(SCROLLINFO
);
871 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
875 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
877 HWND hWnd
= GetHwnd();
879 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
882 if ( orient
== wxHORIZONTAL
)
887 HWND hWnd
= GetHwnd();
890 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
891 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
894 if ( orient
== wxHORIZONTAL
) {
895 m_xThumbSize
= thumbVisible
;
897 m_yThumbSize
= thumbVisible
;
901 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
906 rect
.left
= prect
->x
;
908 rect
.right
= prect
->x
+ prect
->width
;
909 rect
.bottom
= prect
->y
+ prect
->height
;
912 ::ScrollWindow(GetHwnd(), dx
, dy
, prect
? &rect
: NULL
, NULL
);
915 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
917 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
920 for ( int n
= 0; n
< count
; n
++ )
922 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
924 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
927 // don't bother to continue, we're already at top/bottom
934 return pos
!= posStart
;
937 bool wxWindowMSW::ScrollLines(int lines
)
939 bool down
= lines
> 0;
941 return ScrollVertically(GetHwnd(),
942 down
? SB_LINEDOWN
: SB_LINEUP
,
943 down
? lines
: -lines
);
946 bool wxWindowMSW::ScrollPages(int pages
)
948 bool down
= pages
> 0;
950 return ScrollVertically(GetHwnd(),
951 down
? SB_PAGEDOWN
: SB_PAGEUP
,
952 down
? pages
: -pages
);
955 // ---------------------------------------------------------------------------
957 // ---------------------------------------------------------------------------
959 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
961 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
963 HWND hwnd
= (HWND
)hWnd
;
964 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
966 wxAssociateWinWithHandle(hwnd
, this);
968 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
970 // we don't need to subclass the window of our own class (in the Windows
971 // sense of the word)
972 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
974 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
978 // don't bother restoring it neither
983 void wxWindowMSW::UnsubclassWin()
985 wxRemoveHandleAssociation(this);
987 // Restore old Window proc
988 HWND hwnd
= GetHwnd();
993 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
997 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
999 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1002 m_oldWndProc
= NULL
;
1007 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
1009 #if wxUSE_UNICODE_MSLU
1010 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
1011 // because it doesn't return pointer to the real wnd proc but rather a handle
1012 // of a fake proc that does Unicode<->ANSI translation.
1014 // The hack bellow works, because WNDCLASS contains original window handler
1015 // rather that the unicows fake one. This may not be on purpose, though; if
1016 // it stops working with future versions of unicows.dll, we can override
1017 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
1018 // Unicows_RegisterClass to our own versions that keep track of
1019 // fake<->real wnd proc mapping.
1021 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
1022 // with RegisterClass!!
1024 static wxChar buffer
[512];
1027 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1028 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1029 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1031 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1036 // Make a Windows extended style from the given wxWindows window style
1037 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1039 WXDWORD exStyle
= 0;
1040 if ( style
& wxTRANSPARENT_WINDOW
)
1041 exStyle
|= WS_EX_TRANSPARENT
;
1043 if ( !eliminateBorders
)
1045 if ( style
& wxSUNKEN_BORDER
)
1046 exStyle
|= WS_EX_CLIENTEDGE
;
1047 if ( style
& wxDOUBLE_BORDER
)
1048 exStyle
|= WS_EX_DLGMODALFRAME
;
1049 #if defined(__WIN95__)
1050 if ( style
& wxRAISED_BORDER
)
1051 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1052 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1053 if ( style
& wxSTATIC_BORDER
)
1054 exStyle
|= WS_EX_STATICEDGE
;
1061 // Determines whether native 3D effects or CTL3D should be used,
1062 // applying a default border style if required, and returning an extended
1063 // style to pass to CreateWindowEx.
1064 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1067 // If matches certain criteria, then assume no 3D effects
1068 // unless specifically requested (dealt with in MakeExtendedStyle)
1071 || !IsKindOf(CLASSINFO(wxControl
))
1072 #endif // wxUSE_CONTROLS
1073 || (m_windowStyle
& wxNO_BORDER
) )
1076 return MakeExtendedStyle(m_windowStyle
);
1079 // Determine whether we should be using 3D effects or not.
1080 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1082 // 1) App can specify global 3D effects
1083 *want3D
= wxTheApp
->GetAuto3D();
1085 // 2) If the parent is being drawn with user colours, or simple border specified,
1086 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1087 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1090 // 3) Control can override this global setting by defining
1091 // a border style, e.g. wxSUNKEN_BORDER
1092 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1095 // 4) If it's a special border, CTL3D can't cope so we want a native border
1096 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1097 (m_windowStyle
& wxSTATIC_BORDER
) )
1100 nativeBorder
= TRUE
;
1103 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1104 // effects from extended style
1107 nativeBorder
= FALSE
;
1110 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1112 // If we want 3D, but haven't specified a border here,
1113 // apply the default border style specified.
1114 // TODO what about non-Win95 WIN32? Does it have borders?
1115 #if defined(__WIN95__) && !wxUSE_CTL3D
1116 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1117 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1118 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1124 #if WXWIN_COMPATIBILITY
1125 // If nothing defined for this, try the parent.
1126 // E.g. we may be a button loaded from a resource, with no callback function
1128 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1130 if ( GetEventHandler()->ProcessEvent(event
) )
1133 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1135 #endif // WXWIN_COMPATIBILITY_2
1137 #if WXWIN_COMPATIBILITY
1138 wxObject
* wxWindowMSW::GetChild(int number
) const
1140 // Return a pointer to the Nth object in the Panel
1141 wxNode
*node
= GetChildren().First();
1144 node
= node
->Next();
1147 wxObject
*obj
= (wxObject
*)node
->Data();
1153 #endif // WXWIN_COMPATIBILITY
1155 // Setup background and foreground colours correctly
1156 void wxWindowMSW::SetupColours()
1159 SetBackgroundColour(GetParent()->GetBackgroundColour());
1162 bool wxWindowMSW::IsMouseInWindow() const
1164 // get the mouse position
1166 ::GetCursorPos(&pt
);
1168 // find the window which currently has the cursor and go up the window
1169 // chain until we find this window - or exhaust it
1170 HWND hwnd
= ::WindowFromPoint(pt
);
1171 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1172 hwnd
= ::GetParent(hwnd
);
1174 return hwnd
!= NULL
;
1177 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1179 // Check if we need to send a LEAVE event
1180 if ( m_mouseInWindow
)
1182 if ( !IsMouseInWindow() )
1184 // Generate a LEAVE event
1185 m_mouseInWindow
= FALSE
;
1187 // Unfortunately the mouse button and keyboard state may have
1188 // changed by the time the OnIdle function is called, so 'state'
1189 // may be meaningless.
1191 if ( wxIsShiftDown() )
1193 if ( wxIsCtrlDown() )
1194 state
|= MK_CONTROL
;
1195 if ( GetKeyState( VK_LBUTTON
) )
1196 state
|= MK_LBUTTON
;
1197 if ( GetKeyState( VK_MBUTTON
) )
1198 state
|= MK_MBUTTON
;
1199 if ( GetKeyState( VK_RBUTTON
) )
1200 state
|= MK_RBUTTON
;
1203 if ( !::GetCursorPos(&pt
) )
1205 wxLogLastError(_T("GetCursorPos"));
1208 // we need to have client coordinates here for symmetry with
1209 // wxEVT_ENTER_WINDOW
1210 RECT rect
= wxGetWindowRect(GetHwnd());
1214 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1215 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1217 (void)GetEventHandler()->ProcessEvent(event2
);
1224 // Set this window to be the child of 'parent'.
1225 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1227 if ( !wxWindowBase::Reparent(parent
) )
1230 HWND hWndChild
= GetHwnd();
1231 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1233 ::SetParent(hWndChild
, hWndParent
);
1238 void wxWindowMSW::Clear()
1240 wxClientDC
dc((wxWindow
*)this);
1241 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1242 dc
.SetBackground(brush
);
1246 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1248 #ifndef __WXMICROWIN__
1249 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1253 void wxWindowMSW::Freeze()
1255 SendSetRedraw(GetHwnd(), FALSE
);
1258 void wxWindowMSW::Thaw()
1260 SendSetRedraw(GetHwnd(), TRUE
);
1262 // we need to refresh everything or otherwise he invalidated area is not
1267 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1269 HWND hWnd
= GetHwnd();
1275 mswRect
.left
= rect
->x
;
1276 mswRect
.top
= rect
->y
;
1277 mswRect
.right
= rect
->x
+ rect
->width
;
1278 mswRect
.bottom
= rect
->y
+ rect
->height
;
1280 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1283 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1287 void wxWindowMSW::Update()
1289 if ( !::UpdateWindow(GetHwnd()) )
1291 wxLogLastError(_T("UpdateWindow"));
1294 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1295 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1296 // handler needs to be really drawn right now
1301 // ---------------------------------------------------------------------------
1303 // ---------------------------------------------------------------------------
1305 #if wxUSE_DRAG_AND_DROP
1307 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1309 if ( m_dropTarget
!= 0 ) {
1310 m_dropTarget
->Revoke(m_hWnd
);
1311 delete m_dropTarget
;
1314 m_dropTarget
= pDropTarget
;
1315 if ( m_dropTarget
!= 0 )
1316 m_dropTarget
->Register(m_hWnd
);
1319 #endif // wxUSE_DRAG_AND_DROP
1321 // old style file-manager drag&drop support: we retain the old-style
1322 // DragAcceptFiles in parallel with SetDropTarget.
1323 void wxWindowMSW::DragAcceptFiles(bool accept
)
1325 HWND hWnd
= GetHwnd();
1327 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1330 // ----------------------------------------------------------------------------
1332 // ----------------------------------------------------------------------------
1336 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1338 wxWindowBase::DoSetToolTip(tooltip
);
1341 m_tooltip
->SetWindow(this);
1344 #endif // wxUSE_TOOLTIPS
1346 // ---------------------------------------------------------------------------
1347 // moving and resizing
1348 // ---------------------------------------------------------------------------
1351 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1353 RECT rect
= wxGetWindowRect(GetHwnd());
1356 *x
= rect
.right
- rect
.left
;
1358 *y
= rect
.bottom
- rect
.top
;
1361 // Get size *available for subwindows* i.e. excluding menu bar etc.
1362 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1364 RECT rect
= wxGetClientRect(GetHwnd());
1372 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1374 RECT rect
= wxGetWindowRect(GetHwnd());
1377 point
.x
= rect
.left
;
1380 // we do the adjustments with respect to the parent only for the "real"
1381 // children, not for the dialogs/frames
1382 if ( !IsTopLevel() )
1384 HWND hParentWnd
= 0;
1385 wxWindow
*parent
= GetParent();
1387 hParentWnd
= GetWinHwnd(parent
);
1389 // Since we now have the absolute screen coords, if there's a parent we
1390 // must subtract its top left corner
1393 ::ScreenToClient(hParentWnd
, &point
);
1398 // We may be faking the client origin. So a window that's really at (0,
1399 // 30) may appear (to wxWin apps) to be at (0, 0).
1400 wxPoint
pt(parent
->GetClientAreaOrigin());
1412 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1420 ::ScreenToClient(GetHwnd(), &pt
);
1428 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1436 ::ClientToScreen(GetHwnd(), &pt
);
1444 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1446 // TODO: is this consistent with other platforms?
1447 // Still, negative width or height shouldn't be allowed
1452 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1454 wxLogLastError(wxT("MoveWindow"));
1458 // set the size of the window: if the dimensions are positive, just use them,
1459 // but if any of them is equal to -1, it means that we must find the value for
1460 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1461 // which case -1 is a valid value for x and y)
1463 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1464 // the width/height to best suit our contents, otherwise we reuse the current
1466 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1468 // get the current size and position...
1469 int currentX
, currentY
;
1470 GetPosition(¤tX
, ¤tY
);
1471 int currentW
,currentH
;
1472 GetSize(¤tW
, ¤tH
);
1474 // ... and don't do anything (avoiding flicker) if it's already ok
1475 if ( x
== currentX
&& y
== currentY
&&
1476 width
== currentW
&& height
== currentH
)
1481 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1483 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1486 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1488 wxSize
size(-1, -1);
1491 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1493 size
= DoGetBestSize();
1498 // just take the current one
1505 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1509 size
= DoGetBestSize();
1511 //else: already called DoGetBestSize() above
1517 // just take the current one
1522 DoMoveWindow(x
, y
, width
, height
);
1525 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1527 // setting the client size is less obvious than it it could have been
1528 // because in the result of changing the total size the window scrollbar
1529 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1530 // will not be correct as the difference between the total and client size
1531 // changes - so we keep changing it until we get it right
1533 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1534 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1535 // may become 3 if the window had 0 size originally and so we didn't
1536 // calculate the scrollbar correction correctly during the first iteration)
1537 // but just to be on the safe side we check for it instead of making it an
1538 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1539 for ( int i
= 0; i
< 4; i
++ )
1542 ::GetClientRect(GetHwnd(), &rectClient
);
1544 // if the size is already ok, stop here (rectClient.left = top = 0)
1545 if ( rectClient
.right
== width
&& rectClient
.bottom
== height
)
1552 // how did it happen? maybe OnSize() handler does something really
1553 // strange in this class?
1554 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1559 int widthClient
= width
,
1560 heightClient
= height
;
1562 // Find the difference between the entire window (title bar and all)
1563 // and the client area; add this to the new client size to move the
1566 ::GetWindowRect(GetHwnd(), &rectWin
);
1568 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1569 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1572 point
.x
= rectWin
.left
;
1573 point
.y
= rectWin
.top
;
1575 // MoveWindow positions the child windows relative to the parent, so
1576 // adjust if necessary
1577 if ( !IsTopLevel() )
1579 wxWindow
*parent
= GetParent();
1582 ::ScreenToClient(GetHwndOf(parent
), &point
);
1586 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1590 // For implementation purposes - sometimes decorations make the client area
1592 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1594 return wxPoint(0, 0);
1597 // ---------------------------------------------------------------------------
1599 // ---------------------------------------------------------------------------
1601 int wxWindowMSW::GetCharHeight() const
1603 return wxGetTextMetrics(this).tmHeight
;
1606 int wxWindowMSW::GetCharWidth() const
1608 // +1 is needed because Windows apparently adds it when calculating the
1609 // dialog units size in pixels
1610 #if wxDIALOG_UNIT_COMPATIBILITY
1611 return wxGetTextMetrics(this).tmAveCharWidth
;
1613 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1617 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1619 int *descent
, int *externalLeading
,
1620 const wxFont
*theFont
) const
1622 const wxFont
*fontToUse
= theFont
;
1624 fontToUse
= &m_font
;
1626 HWND hWnd
= GetHwnd();
1627 HDC dc
= ::GetDC(hWnd
);
1631 if ( fontToUse
&& fontToUse
->Ok() )
1633 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1635 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1640 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1641 GetTextMetrics(dc
, &tm
);
1643 if ( fontToUse
&& fnt
&& hfontOld
)
1644 SelectObject(dc
, hfontOld
);
1646 ReleaseDC(hWnd
, dc
);
1653 *descent
= tm
.tmDescent
;
1654 if ( externalLeading
)
1655 *externalLeading
= tm
.tmExternalLeading
;
1658 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1659 // ---------------------------------------------------------------------------
1660 // Caret manipulation
1661 // ---------------------------------------------------------------------------
1663 void wxWindowMSW::CreateCaret(int w
, int h
)
1665 SetCaret(new wxCaret(this, w
, h
));
1668 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1670 wxFAIL_MSG("not implemented");
1673 void wxWindowMSW::ShowCaret(bool show
)
1675 wxCHECK_RET( m_caret
, "no caret to show" );
1677 m_caret
->Show(show
);
1680 void wxWindowMSW::DestroyCaret()
1685 void wxWindowMSW::SetCaretPos(int x
, int y
)
1687 wxCHECK_RET( m_caret
, "no caret to move" );
1689 m_caret
->Move(x
, y
);
1692 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1694 wxCHECK_RET( m_caret
, "no caret to get position of" );
1696 m_caret
->GetPosition(x
, y
);
1698 #endif // wxUSE_CARET
1700 // ---------------------------------------------------------------------------
1702 // ---------------------------------------------------------------------------
1704 #if wxUSE_MENUS_NATIVE
1706 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1707 // immediately, without waiting for the next event loop iteration
1709 // NB: this function should probably be made public later as it can almost
1710 // surely replace wxYield() elsewhere as well
1711 static void wxYieldForCommandsOnly()
1713 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1714 // want to process it here)
1716 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1717 && msg
.message
!= WM_QUIT
)
1719 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1723 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1725 menu
->SetInvokingWindow(this);
1728 HWND hWnd
= GetHwnd();
1729 HMENU hMenu
= GetHmenuOf(menu
);
1733 ::ClientToScreen(hWnd
, &point
);
1734 wxCurrentPopupMenu
= menu
;
1735 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1737 // we need to do it righ now as otherwise the events are never going to be
1738 // sent to wxCurrentPopupMenu from HandleCommand()
1740 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1741 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1742 // destroyed as soon as we return (it can be a local variable in the caller
1743 // for example) and so we do need to process the event immediately
1744 wxYieldForCommandsOnly();
1746 wxCurrentPopupMenu
= NULL
;
1748 menu
->SetInvokingWindow(NULL
);
1753 #endif // wxUSE_MENUS_NATIVE
1755 // ===========================================================================
1756 // pre/post message processing
1757 // ===========================================================================
1759 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1762 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1764 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1767 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1769 // wxUniversal implements tab traversal itself
1770 #ifndef __WXUNIVERSAL__
1771 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1773 // intercept dialog navigation keys
1774 MSG
*msg
= (MSG
*)pMsg
;
1776 // here we try to do all the job which ::IsDialogMessage() usually does
1779 bool bProcess
= TRUE
;
1780 if ( msg
->message
!= WM_KEYDOWN
)
1783 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1788 bool bCtrlDown
= wxIsCtrlDown();
1789 bool bShiftDown
= wxIsShiftDown();
1791 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1792 // don't process it if it's the case (except for Ctrl-Tab/Enter
1793 // combinations which are always processed)
1797 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1800 bool bForward
= TRUE
,
1801 bWindowChange
= FALSE
;
1803 switch ( msg
->wParam
)
1806 // assume that nobody wants Shift-TAB for himself - if we
1807 // don't do it there is no easy way for a control to grab
1808 // TABs but still let Shift-TAB work as navugation key
1809 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1813 // Ctrl-Tab cycles thru notebook pages
1814 bWindowChange
= bCtrlDown
;
1815 bForward
= !bShiftDown
;
1821 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1829 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1835 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1837 // control wants to process Enter itself, don't
1838 // call IsDialogMessage() which would interpret
1842 else if ( lDlgCode
& DLGC_BUTTON
)
1844 // let IsDialogMessage() handle this for all
1845 // buttons except the owner-drawn ones which it
1846 // just seems to ignore
1847 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1848 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1850 // emulate the button click
1851 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1853 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1858 // FIXME: this should be handled by
1859 // wxNavigationKeyEvent handler and not here!!
1863 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1865 if ( btn
&& btn
->IsEnabled() )
1867 // if we do have a default button, do press it
1868 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1872 else // no default button
1873 #endif // wxUSE_BUTTON
1875 // no special function for enter and don't even
1876 // let IsDialogMessage() have it: it seems to
1877 // do something really strange with it
1890 wxNavigationKeyEvent event
;
1891 event
.SetDirection(bForward
);
1892 event
.SetWindowChange(bWindowChange
);
1893 event
.SetEventObject(this);
1895 if ( GetEventHandler()->ProcessEvent(event
) )
1902 // let ::IsDialogMessage() do almost everything and handle just the
1903 // things it doesn't here: Ctrl-TAB for switching notebook pages
1904 if ( msg
->message
== WM_KEYDOWN
)
1906 // don't process system keys here
1907 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1909 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1911 // find the first notebook parent and change its page
1912 wxWindow
*win
= this;
1913 wxNotebook
*nbook
= NULL
;
1914 while ( win
&& !nbook
)
1916 nbook
= wxDynamicCast(win
, wxNotebook
);
1917 win
= win
->GetParent();
1922 bool forward
= !wxIsShiftDown();
1924 nbook
->AdvanceSelection(forward
);
1931 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1933 // IsDialogMessage() did something...
1937 #endif // __WXUNIVERSAL__
1942 // relay mouse move events to the tooltip control
1943 MSG
*msg
= (MSG
*)pMsg
;
1944 if ( msg
->message
== WM_MOUSEMOVE
)
1945 m_tooltip
->RelayEvent(pMsg
);
1947 #endif // wxUSE_TOOLTIPS
1952 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1954 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1955 return m_acceleratorTable
.Translate(this, pMsg
);
1958 #endif // wxUSE_ACCEL
1961 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1963 // preprocess all messages by default
1967 // ---------------------------------------------------------------------------
1968 // message params unpackers (different for Win16 and Win32)
1969 // ---------------------------------------------------------------------------
1973 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1974 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1976 *id
= LOWORD(wParam
);
1977 *hwnd
= (WXHWND
)lParam
;
1978 *cmd
= HIWORD(wParam
);
1981 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1982 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1984 *state
= LOWORD(wParam
);
1985 *minimized
= HIWORD(wParam
);
1986 *hwnd
= (WXHWND
)lParam
;
1989 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1990 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1992 *code
= LOWORD(wParam
);
1993 *pos
= HIWORD(wParam
);
1994 *hwnd
= (WXHWND
)lParam
;
1997 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
1998 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2000 #ifndef __WXMICROWIN__
2001 *nCtlColor
= CTLCOLOR_BTN
;
2002 *hwnd
= (WXHWND
)lParam
;
2003 *hdc
= (WXHDC
)wParam
;
2007 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2008 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2010 *item
= (WXWORD
)wParam
;
2011 *flags
= HIWORD(wParam
);
2012 *hmenu
= (WXHMENU
)lParam
;
2017 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2018 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2020 *id
= (WXWORD
)wParam
;
2021 *hwnd
= (WXHWND
)LOWORD(lParam
);
2022 *cmd
= HIWORD(lParam
);
2025 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2026 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2028 *state
= (WXWORD
)wParam
;
2029 *minimized
= LOWORD(lParam
);
2030 *hwnd
= (WXHWND
)HIWORD(lParam
);
2033 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2034 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2036 *code
= (WXWORD
)wParam
;
2037 *pos
= LOWORD(lParam
);
2038 *hwnd
= (WXHWND
)HIWORD(lParam
);
2041 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2042 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2044 *hwnd
= (WXHWND
)LOWORD(lParam
);
2045 *nCtlColor
= (int)HIWORD(lParam
);
2046 *hdc
= (WXHDC
)wParam
;
2049 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2050 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2052 *item
= (WXWORD
)wParam
;
2053 *flags
= LOWORD(lParam
);
2054 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2059 // ---------------------------------------------------------------------------
2060 // Main wxWindows window proc and the window proc for wxWindow
2061 // ---------------------------------------------------------------------------
2063 // Hook for new window just as it's being created, when the window isn't yet
2064 // associated with the handle
2065 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2067 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2068 // window being created and insures that it's always unset back later
2069 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2071 gs_winBeingCreated
= winBeingCreated
;
2074 wxWindowCreationHook::~wxWindowCreationHook()
2076 gs_winBeingCreated
= NULL
;
2080 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2082 // trace all messages - useful for the debugging
2084 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2085 wxGetMessageName(message
), wParam
, lParam
);
2086 #endif // __WXDEBUG__
2088 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2090 // when we get the first message for the HWND we just created, we associate
2091 // it with wxWindow stored in gs_winBeingCreated
2092 if ( !wnd
&& gs_winBeingCreated
)
2094 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2095 wnd
= gs_winBeingCreated
;
2096 gs_winBeingCreated
= NULL
;
2097 wnd
->SetHWND((WXHWND
)hWnd
);
2103 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2105 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2110 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2112 // did we process the message?
2113 bool processed
= FALSE
;
2124 // for most messages we should return 0 when we do process the message
2132 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2135 // return 0 to allow window creation
2136 rc
.result
= mayCreate
? 0 : -1;
2142 // never set processed to TRUE and *always* pass WM_DESTROY to
2143 // DefWindowProc() as Windows may do some internal cleanup when
2144 // processing it and failing to pass the message along may cause
2145 // memory and resource leaks!
2146 (void)HandleDestroy();
2150 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2158 // we're not interested in these messages at all
2161 case SIZE_MINIMIZED
:
2162 // we shouldn't send sizev events for these messages as the
2163 // client size may be negative which breaks existing code
2165 // OTOH we might send another (wxMinimizedEvent?) one or
2166 // add an additional parameter to wxSizeEvent if this is
2167 // useful to anybody
2171 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2172 // fall through nevertheless
2174 case SIZE_MAXIMIZED
:
2176 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2181 #ifndef __WXMICROWIN__
2182 case WM_ACTIVATEAPP
:
2183 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2189 WXWORD state
, minimized
;
2191 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2193 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2198 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2202 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2206 processed
= HandlePaint();
2210 // don't let the DefWindowProc() destroy our window - we'll do it
2211 // ourselves in ~wxWindow
2217 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2221 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2222 GET_Y_LPARAM(lParam
),
2226 #if wxUSE_MOUSEWHEEL
2228 processed
= HandleMouseWheel(wParam
, lParam
);
2232 case WM_LBUTTONDOWN
:
2234 case WM_LBUTTONDBLCLK
:
2235 case WM_RBUTTONDOWN
:
2237 case WM_RBUTTONDBLCLK
:
2238 case WM_MBUTTONDOWN
:
2240 case WM_MBUTTONDBLCLK
:
2243 #ifdef __WXMICROWIN__
2244 // MicroWindows seems to ignore the fact that a window is
2245 // disabled. So catch mouse events and throw them away if
2247 wxWindowMSW
* win
= this;
2250 if (!win
->IsEnabled())
2255 win
= win
->GetParent();
2256 if (win
&& win
->IsTopLevel())
2259 #endif // __WXMICROWIN__
2262 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2264 processed
= HandleMouseEvent(message
,
2265 GET_X_LPARAM(lParam
),
2266 GET_Y_LPARAM(lParam
),
2272 #ifdef __WXMICROWIN__
2273 case WM_NCLBUTTONDOWN
:
2274 case WM_NCLBUTTONUP
:
2275 case WM_NCLBUTTONDBLCLK
:
2276 case WM_NCRBUTTONDOWN
:
2277 case WM_NCRBUTTONUP
:
2278 case WM_NCRBUTTONDBLCLK
:
2280 case WM_NCMBUTTONDOWN
:
2281 case WM_NCMBUTTONUP
:
2282 case WM_NCMBUTTONDBLCLK
:
2285 // MicroWindows seems to ignore the fact that a window
2286 // is disabled. So catch mouse events and throw them away if necessary.
2288 wxWindowMSW
* win
= this;
2291 if (!win
->IsEnabled())
2296 win
= win
->GetParent();
2297 if (win
&& win
->IsTopLevel())
2302 #endif // __WXMICROWIN__
2309 case MM_JOY1BUTTONDOWN
:
2310 case MM_JOY2BUTTONDOWN
:
2311 case MM_JOY1BUTTONUP
:
2312 case MM_JOY2BUTTONUP
:
2313 processed
= HandleJoystickEvent(message
,
2314 GET_X_LPARAM(lParam
),
2315 GET_Y_LPARAM(lParam
),
2318 #endif // __WXMICROWIN__
2321 processed
= HandleSysCommand(wParam
, lParam
);
2328 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2330 processed
= HandleCommand(id
, cmd
, hwnd
);
2336 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2340 // for these messages we must return TRUE if process the message
2343 case WM_MEASUREITEM
:
2345 int idCtrl
= (UINT
)wParam
;
2346 if ( message
== WM_DRAWITEM
)
2348 processed
= MSWOnDrawItem(idCtrl
,
2349 (WXDRAWITEMSTRUCT
*)lParam
);
2353 processed
= MSWOnMeasureItem(idCtrl
,
2354 (WXMEASUREITEMSTRUCT
*)lParam
);
2361 #endif // defined(WM_DRAWITEM)
2366 rc
.result
= m_lDlgCode
;
2369 //else: get the dlg code from the DefWindowProc()
2374 // If this has been processed by an event handler,
2375 // return 0 now (we've handled it).
2376 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2383 // we consider these message "not interesting" to OnChar
2384 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2393 // avoid duplicate messages to OnChar for these ASCII keys: they
2394 // will be translated by TranslateMessage() and received in WM_CHAR
2402 // but set processed to FALSE, not TRUE to still pass them to
2403 // the control's default window proc - otherwise built-in
2404 // keyboard handling won't work
2410 // special case of VK_APPS: treat it the same as right mouse
2411 // click because both usually pop up a context menu
2417 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2418 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2428 processed
= HandleChar((WORD
)wParam
, lParam
);
2435 // special case of VK_APPS: treat it the same as right mouse button
2436 if ( wParam
== VK_APPS
)
2441 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2442 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2447 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2452 case WM_CHAR
: // Always an ASCII character
2453 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2461 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2463 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2469 // CTLCOLOR messages are sent by children to query the parent for their
2470 // colors#ifndef __WXMICROWIN__
2471 #ifndef __WXMICROWIN__
2473 case WM_CTLCOLORMSGBOX
:
2474 case WM_CTLCOLOREDIT
:
2475 case WM_CTLCOLORLISTBOX
:
2476 case WM_CTLCOLORBTN
:
2477 case WM_CTLCOLORDLG
:
2478 case WM_CTLCOLORSCROLLBAR
:
2479 case WM_CTLCOLORSTATIC
:
2487 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2489 processed
= HandleCtlColor(&rc
.hBrush
,
2498 #endif // !__WXMICROWIN__
2500 case WM_SYSCOLORCHANGE
:
2501 // the return value for this message is ignored
2502 processed
= HandleSysColorChange();
2505 case WM_PALETTECHANGED
:
2506 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2509 case WM_QUERYNEWPALETTE
:
2510 processed
= HandleQueryNewPalette();
2514 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2517 // we processed the message, i.e. erased the background
2523 processed
= HandleDropFiles(wParam
);
2527 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2531 // we never set focus from here
2536 case WM_QUERYENDSESSION
:
2537 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2541 processed
= HandleEndSession(wParam
!= 0, lParam
);
2544 case WM_GETMINMAXINFO
:
2545 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2549 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2550 LOWORD(lParam
), // hit test
2551 HIWORD(lParam
)); // mouse msg
2555 // returning TRUE stops the DefWindowProc() from further
2556 // processing this message - exactly what we need because we've
2557 // just set the cursor.
2562 #if defined(__WIN32__) && defined(WM_HELP)
2565 HELPINFO
* info
= (HELPINFO
*) lParam
;
2566 // Don't yet process menu help events, just windows
2567 if (info
->iContextType
== HELPINFO_WINDOW
)
2569 wxWindowMSW
* subjectOfHelp
= this;
2570 bool eventProcessed
= FALSE
;
2571 while (subjectOfHelp
&& !eventProcessed
)
2573 wxHelpEvent
helpEvent(wxEVT_HELP
,
2574 subjectOfHelp
->GetId(),
2575 wxPoint(info
->MousePos
.x
,
2576 info
->MousePos
.y
) );
2577 helpEvent
.SetEventObject(this);
2579 GetEventHandler()->ProcessEvent(helpEvent
);
2581 // Go up the window hierarchy until the event is
2583 subjectOfHelp
= subjectOfHelp
->GetParent();
2586 processed
= eventProcessed
;
2588 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2590 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2591 helpEvent
.SetEventObject(this);
2592 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2595 //else: processed is already FALSE
2599 case WM_CONTEXTMENU
:
2601 // we don't convert from screen to client coordinates as
2602 // the event may be handled by a parent window
2603 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2605 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2606 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2611 // unfortunately this doesn't really work as then window which
2612 // doesn't accept focus doesn't get any mouse events neither which
2613 // means it can't get any input at all
2614 #if 0 //def __WXUNIVERSAL__
2616 // we shouldn't allow the windows which don't want to get focus to
2618 if ( !AcceptsFocus() )
2620 rc
.result
= HTTRANSPARENT
;
2624 #endif // __WXUNIVERSAL__
2630 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2631 wxGetMessageName(message
));
2632 #endif // __WXDEBUG__
2633 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2639 // ----------------------------------------------------------------------------
2640 // wxWindow <-> HWND map
2641 // ----------------------------------------------------------------------------
2643 wxWinHashTable
*wxWinHandleHash
= NULL
;
2645 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2647 return wxWinHandleHash
->Get((long)hWnd
);
2650 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2652 // adding NULL hWnd is (first) surely a result of an error and
2653 // (secondly) breaks menu command processing
2654 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2655 wxT("attempt to add a NULL hWnd to window list ignored") );
2657 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2659 if ( oldWin
&& (oldWin
!= win
) )
2661 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2662 hWnd
, win
->GetClassInfo()->GetClassName());
2665 #endif // __WXDEBUG__
2668 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2672 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2674 wxWinHandleHash
->Delete((long)win
->GetHWND());
2677 // ----------------------------------------------------------------------------
2678 // various MSW speciic class dependent functions
2679 // ----------------------------------------------------------------------------
2681 // Default destroyer - override if you destroy it in some other way
2682 // (e.g. with MDI child windows)
2683 void wxWindowMSW::MSWDestroyWindow()
2687 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2690 int& w
, int& h
) const
2692 bool nonDefault
= FALSE
;
2696 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2697 // just as well set it to CW_USEDEFAULT as well
2704 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2710 NB: there used to be some code here which set the initial size of the
2711 window to the client size of the parent if no explicit size was
2712 specified. This was wrong because wxWindows programs often assume
2713 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2714 it. To see why, you should understand that Windows sends WM_SIZE from
2715 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2716 from some base class ctor and so this WM_SIZE is not processed in the
2717 real class' OnSize() (because it's not fully constructed yet and the
2718 event goes to some base class OnSize() instead). So the WM_SIZE we
2719 rely on is the one sent when the parent frame resizes its children
2720 but here is the problem: if the child already has just the right
2721 size, nothing will happen as both wxWindows and Windows check for
2722 this and ignore any attempts to change the window size to the size it
2723 already has - so no WM_SIZE would be sent.
2727 // as abobe, h is not used at all in this case anyhow
2734 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2742 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2743 const wxChar
*title
,
2747 WXDWORD extendedStyle
)
2749 // choose the position/size for the new window
2751 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2753 // find the correct parent HWND
2754 wxWindow
*parent
= GetParent();
2755 bool isChild
= (style
& WS_CHILD
) != 0;
2757 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2759 // popup windows should have desktop as parent because they shouldn't
2760 // be limited to the parents client area as child windows usually are
2761 hParent
= ::GetDesktopWindow();
2765 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2767 // this is either a normal child window or a top level window with
2768 // wxFRAME_TOOL_WINDOW style (see below)
2769 hParent
= GetHwndOf(parent
);
2773 // this is either a window for which no parent was specified (not
2774 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2775 // style: we should use NULL parent HWND for it or it would be
2776 // always on top of its parent which is not what we usually want
2777 // (in fact, we only want it for frames with the special
2778 // wxFRAME_TOOL_WINDOW as above)
2784 // controlId is menu handle for the top level windows, so set it to 0
2785 // unless we're creating a child window
2789 controlId
= GetId();
2791 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2793 style
|= WS_CLIPSIBLINGS
;
2801 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2802 // which is the same but without CS_[HV]REDRAW class styles so using it
2803 // ensures that the window is not fully repainted on each resize
2804 wxString
className(wclass
);
2805 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2807 className
+= wxT("NR");
2810 // do create the window
2811 wxWindowCreationHook
hook(this);
2813 m_hWnd
= (WXHWND
)::CreateWindowEx
2817 title
? title
: wxT(""),
2823 NULL
// no extra data
2828 wxLogSysError(_("Can't create window of class %s"), wclass
);
2833 SubclassWin(m_hWnd
);
2835 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2840 // ===========================================================================
2841 // MSW message handlers
2842 // ===========================================================================
2844 // ---------------------------------------------------------------------------
2846 // ---------------------------------------------------------------------------
2849 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2850 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2852 #ifndef __WXMICROWIN__
2853 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2854 HWND hWnd
= hdr
->hwndFrom
;
2855 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2857 // is this one of our windows?
2860 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2863 // try all our children
2864 wxWindowList::Node
*node
= GetChildren().GetFirst();
2867 wxWindow
*child
= node
->GetData();
2868 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2873 node
= node
->GetNext();
2876 // finally try this window too (catches toolbar case)
2877 return MSWOnNotify(idCtrl
, lParam
, result
);
2878 #else // __WXMICROWIN__
2883 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2885 WXLPARAM
* WXUNUSED(result
))
2888 NMHDR
* hdr
= (NMHDR
*)lParam
;
2889 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2891 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2892 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2897 #endif // wxUSE_TOOLTIPS
2903 // ---------------------------------------------------------------------------
2904 // end session messages
2905 // ---------------------------------------------------------------------------
2907 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2909 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2910 event
.SetEventObject(wxTheApp
);
2911 event
.SetCanVeto(TRUE
);
2912 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2914 bool rc
= wxTheApp
->ProcessEvent(event
);
2918 // we may end only if the app didn't veto session closing (double
2920 *mayEnd
= !event
.GetVeto();
2926 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2928 // do nothing if the session isn't ending
2933 if ( (this != wxTheApp
->GetTopWindow()) )
2936 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2937 event
.SetEventObject(wxTheApp
);
2938 event
.SetCanVeto(FALSE
);
2939 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2941 return wxTheApp
->ProcessEvent(event
);
2944 // ---------------------------------------------------------------------------
2945 // window creation/destruction
2946 // ---------------------------------------------------------------------------
2948 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2950 // TODO: should generate this event from WM_NCCREATE
2951 wxWindowCreateEvent
event((wxWindow
*)this);
2952 (void)GetEventHandler()->ProcessEvent(event
);
2959 bool wxWindowMSW::HandleDestroy()
2961 wxWindowDestroyEvent
event((wxWindow
*)this);
2962 (void)GetEventHandler()->ProcessEvent(event
);
2964 // delete our drop target if we've got one
2965 #if wxUSE_DRAG_AND_DROP
2966 if ( m_dropTarget
!= NULL
)
2968 m_dropTarget
->Revoke(m_hWnd
);
2970 delete m_dropTarget
;
2971 m_dropTarget
= NULL
;
2973 #endif // wxUSE_DRAG_AND_DROP
2975 // WM_DESTROY handled
2979 // ---------------------------------------------------------------------------
2981 // ---------------------------------------------------------------------------
2983 bool wxWindowMSW::HandleActivate(int state
,
2984 bool WXUNUSED(minimized
),
2985 WXHWND
WXUNUSED(activate
))
2987 wxActivateEvent
event(wxEVT_ACTIVATE
,
2988 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
2990 event
.SetEventObject(this);
2992 return GetEventHandler()->ProcessEvent(event
);
2995 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
2997 // notify the parent keeping track of focus for the kbd navigation
2998 // purposes that we got it
2999 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3000 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3006 m_caret
->OnSetFocus();
3008 #endif // wxUSE_CARET
3011 // If it's a wxTextCtrl don't send the event as it will be done
3012 // after the control gets to process it from EN_FOCUS handler
3013 if ( wxDynamicCastThis(wxTextCtrl
) )
3017 #endif // wxUSE_TEXTCTRL
3019 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3020 event
.SetEventObject(this);
3022 // wxFindWinFromHandle() may return NULL, it is ok
3023 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3025 return GetEventHandler()->ProcessEvent(event
);
3028 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3034 m_caret
->OnKillFocus();
3036 #endif // wxUSE_CARET
3039 // If it's a wxTextCtrl don't send the event as it will be done
3040 // after the control gets to process it.
3041 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3048 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3049 event
.SetEventObject(this);
3051 // wxFindWinFromHandle() may return NULL, it is ok
3052 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3054 return GetEventHandler()->ProcessEvent(event
);
3057 // ---------------------------------------------------------------------------
3059 // ---------------------------------------------------------------------------
3061 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3063 wxShowEvent
event(GetId(), show
);
3064 event
.m_eventObject
= this;
3066 return GetEventHandler()->ProcessEvent(event
);
3069 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3071 wxInitDialogEvent
event(GetId());
3072 event
.m_eventObject
= this;
3074 return GetEventHandler()->ProcessEvent(event
);
3077 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3079 #ifndef __WXMICROWIN__
3080 HDROP hFilesInfo
= (HDROP
) wParam
;
3082 // Get the total number of files dropped
3083 UINT gwFilesDropped
= ::DragQueryFile
3091 wxString
*files
= new wxString
[gwFilesDropped
];
3092 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3094 // first get the needed buffer length (+1 for terminating NUL)
3095 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3097 // and now get the file name
3098 ::DragQueryFile(hFilesInfo
, wIndex
,
3099 files
[wIndex
].GetWriteBuf(len
), len
);
3101 files
[wIndex
].UngetWriteBuf();
3103 DragFinish (hFilesInfo
);
3105 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3106 event
.m_eventObject
= this;
3109 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3110 event
.m_pos
.x
= dropPoint
.x
;
3111 event
.m_pos
.y
= dropPoint
.y
;
3113 return GetEventHandler()->ProcessEvent(event
);
3114 #else // __WXMICROWIN__
3119 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3121 int WXUNUSED(mouseMsg
))
3123 #ifndef __WXMICROWIN__
3124 // the logic is as follows:
3125 // -1. don't set cursor for non client area, including but not limited to
3126 // the title bar, scrollbars, &c
3127 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3128 // 1. if we have the cursor set it unless wxIsBusy()
3129 // 2. if we're a top level window, set some cursor anyhow
3130 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3132 if ( nHitTest
!= HTCLIENT
)
3137 HCURSOR hcursor
= 0;
3139 // first ask the user code - it may wish to set the cursor in some very
3140 // specific way (for example, depending on the current position)
3143 if ( !::GetCursorPos(&pt
) )
3145 wxLogLastError(wxT("GetCursorPos"));
3148 // In WIN16 it doesn't return a value.
3149 ::GetCursorPos(&pt
);
3154 ScreenToClient(&x
, &y
);
3155 wxSetCursorEvent
event(x
, y
);
3157 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3158 if ( processedEvtSetCursor
&& event
.HasCursor() )
3160 hcursor
= GetHcursorOf(event
.GetCursor());
3165 bool isBusy
= wxIsBusy();
3167 // the test for processedEvtSetCursor is here to prevent using m_cursor
3168 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3169 // it - this is a way to say that our cursor shouldn't be used for this
3171 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3173 hcursor
= GetHcursorOf(m_cursor
);
3180 hcursor
= wxGetCurrentBusyCursor();
3182 else if ( !hcursor
)
3184 const wxCursor
*cursor
= wxGetGlobalCursor();
3185 if ( cursor
&& cursor
->Ok() )
3187 hcursor
= GetHcursorOf(*cursor
);
3195 ::SetCursor(hcursor
);
3197 // cursor set, stop here
3200 #endif // __WXMICROWIN__
3202 // pass up the window chain
3206 // ---------------------------------------------------------------------------
3207 // owner drawn stuff
3208 // ---------------------------------------------------------------------------
3210 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3212 #if wxUSE_OWNER_DRAWN
3214 #if wxUSE_MENUS_NATIVE
3215 // is it a menu item?
3216 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3217 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3219 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3221 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3223 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3224 // the DC from being released
3225 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3226 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3227 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3228 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3230 return pMenuItem
->OnDrawItem
3234 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3235 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3238 #endif // wxUSE_MENUS_NATIVE
3241 wxWindow
*item
= FindItem(id
);
3242 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3244 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3246 #endif // wxUSE_CONTROLS
3248 #endif // USE_OWNER_DRAWN
3253 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3255 #if wxUSE_OWNER_DRAWN
3256 // is it a menu item?
3257 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3258 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3260 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3262 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3264 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3265 &pMeasureStruct
->itemHeight
);
3268 wxWindow
*item
= FindItem(id
);
3269 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3271 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3273 #endif // owner-drawn menus
3277 // ---------------------------------------------------------------------------
3278 // colours and palettes
3279 // ---------------------------------------------------------------------------
3281 bool wxWindowMSW::HandleSysColorChange()
3283 wxSysColourChangedEvent event
;
3284 event
.SetEventObject(this);
3286 (void)GetEventHandler()->ProcessEvent(event
);
3288 // always let the system carry on the default processing to allow the
3289 // native controls to react to the colours update
3293 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3301 #ifndef __WXMICROWIN__
3302 WXHBRUSH hBrush
= 0;
3304 if ( nCtlColor
== CTLCOLOR_DLG
)
3306 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3311 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3313 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3315 #endif // wxUSE_CONTROLS
3321 #else // __WXMICROWIN__
3326 // Define for each class of dialog and control
3327 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3328 WXHWND
WXUNUSED(hWnd
),
3329 WXUINT
WXUNUSED(nCtlColor
),
3330 WXUINT
WXUNUSED(message
),
3331 WXWPARAM
WXUNUSED(wParam
),
3332 WXLPARAM
WXUNUSED(lParam
))
3337 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3339 wxPaletteChangedEvent
event(GetId());
3340 event
.SetEventObject(this);
3341 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3343 return GetEventHandler()->ProcessEvent(event
);
3346 bool wxWindowMSW::HandleQueryNewPalette()
3348 wxQueryNewPaletteEvent
event(GetId());
3349 event
.SetEventObject(this);
3351 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3354 // Responds to colour changes: passes event on to children.
3355 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3357 // the top level window also reset the standard colour map as it might have
3358 // changed (there is no need to do it for the non top level windows as we
3359 // only have to do it once)
3363 gs_hasStdCmap
= FALSE
;
3365 wxWindowList::Node
*node
= GetChildren().GetFirst();
3368 // Only propagate to non-top-level windows because Windows already
3369 // sends this event to all top-level ones
3370 wxWindow
*win
= node
->GetData();
3371 if ( !win
->IsTopLevel() )
3373 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3374 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3375 // the standard controls
3376 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3379 node
= node
->GetNext();
3382 // update the colours we use if they were not set explicitly by the user:
3383 // this must be done or OnCtlColor() would continue to use the old colours
3386 m_foregroundColour
= wxSystemSettings::
3387 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3392 m_backgroundColour
= wxSystemSettings::
3393 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3397 extern wxCOLORMAP
*wxGetStdColourMap()
3399 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3400 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3402 if ( !gs_hasStdCmap
)
3404 static bool s_coloursInit
= FALSE
;
3406 if ( !s_coloursInit
)
3408 // When a bitmap is loaded, the RGB values can change (apparently
3409 // because Windows adjusts them to care for the old programs always
3410 // using 0xc0c0c0 while the transparent colour for the new Windows
3411 // versions is different). But we do this adjustment ourselves so
3412 // we want to avoid Windows' "help" and for this we need to have a
3413 // reference bitmap which can tell us what the RGB values change
3415 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3416 if ( stdColourBitmap
.Ok() )
3418 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3419 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3420 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3423 memDC
.SelectObject(stdColourBitmap
);
3426 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3428 memDC
.GetPixel(i
, 0, &colour
);
3429 s_stdColours
[i
] = wxColourToRGB(colour
);
3432 else // wxBITMAP_STD_COLOURS couldn't be loaded
3434 s_stdColours
[0] = RGB(000,000,000); // black
3435 s_stdColours
[1] = RGB(128,128,128); // dark grey
3436 s_stdColours
[2] = RGB(192,192,192); // light grey
3437 s_stdColours
[3] = RGB(255,255,255); // white
3438 //s_stdColours[4] = RGB(000,000,255); // blue
3439 //s_stdColours[5] = RGB(255,000,255); // magenta
3442 s_coloursInit
= TRUE
;
3445 gs_hasStdCmap
= TRUE
;
3447 // create the colour map
3448 #define INIT_CMAP_ENTRY(col) \
3449 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3450 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3452 INIT_CMAP_ENTRY(BTNTEXT
);
3453 INIT_CMAP_ENTRY(BTNSHADOW
);
3454 INIT_CMAP_ENTRY(BTNFACE
);
3455 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3457 #undef INIT_CMAP_ENTRY
3463 // ---------------------------------------------------------------------------
3465 // ---------------------------------------------------------------------------
3467 bool wxWindowMSW::HandlePaint()
3470 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3472 wxLogLastError(wxT("CreateRectRgn"));
3473 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3474 wxLogLastError(wxT("GetUpdateRgn"));
3476 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3479 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3481 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3482 updateRect
.right
- updateRect
.left
,
3483 updateRect
.bottom
- updateRect
.top
);
3486 wxPaintEvent
event(m_windowId
);
3487 event
.SetEventObject(this);
3489 bool processed
= GetEventHandler()->ProcessEvent(event
);
3491 // note that we must generate NC event after the normal one as otherwise
3492 // BeginPaint() will happily overwrite our decorations with the background
3494 wxNcPaintEvent
eventNc(m_windowId
);
3495 eventNc
.SetEventObject(this);
3496 GetEventHandler()->ProcessEvent(eventNc
);
3501 // Can be called from an application's OnPaint handler
3502 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3504 #ifdef __WXUNIVERSAL__
3507 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3510 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3515 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3517 // Prevents flicker when dragging
3518 if ( ::IsIconic(GetHwnd()) )
3524 dc
.SetWindow((wxWindow
*)this);
3527 wxEraseEvent
event(m_windowId
, &dc
);
3528 event
.SetEventObject(this);
3529 bool rc
= GetEventHandler()->ProcessEvent(event
);
3533 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3534 dc
.SelectOldObjects(hdc
);
3539 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3542 ::GetClientRect(GetHwnd(), &rect
);
3544 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3545 m_backgroundColour
.Green(),
3546 m_backgroundColour
.Blue());
3547 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3549 wxLogLastError(wxT("CreateSolidBrush"));
3551 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3553 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3555 ::FillRect(hdc
, &rect
, hBrush
);
3556 ::DeleteObject(hBrush
);
3557 ::SetMapMode(hdc
, mode
);
3560 // ---------------------------------------------------------------------------
3561 // moving and resizing
3562 // ---------------------------------------------------------------------------
3564 bool wxWindowMSW::HandleMinimize()
3566 wxIconizeEvent
event(m_windowId
);
3567 event
.SetEventObject(this);
3569 return GetEventHandler()->ProcessEvent(event
);
3572 bool wxWindowMSW::HandleMaximize()
3574 wxMaximizeEvent
event(m_windowId
);
3575 event
.SetEventObject(this);
3577 return GetEventHandler()->ProcessEvent(event
);
3580 bool wxWindowMSW::HandleMove(int x
, int y
)
3582 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3583 event
.SetEventObject(this);
3585 return GetEventHandler()->ProcessEvent(event
);
3588 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3590 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3591 event
.SetEventObject(this);
3593 return GetEventHandler()->ProcessEvent(event
);
3596 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3598 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3602 if ( m_minWidth
!= -1 )
3604 info
->ptMinTrackSize
.x
= m_minWidth
;
3608 if ( m_minHeight
!= -1 )
3610 info
->ptMinTrackSize
.y
= m_minHeight
;
3614 if ( m_maxWidth
!= -1 )
3616 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3620 if ( m_maxHeight
!= -1 )
3622 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3629 // ---------------------------------------------------------------------------
3631 // ---------------------------------------------------------------------------
3633 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3635 #if wxUSE_MENUS_NATIVE
3636 if ( !cmd
&& wxCurrentPopupMenu
)
3638 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3639 wxCurrentPopupMenu
= NULL
;
3641 return popupMenu
->MSWCommand(cmd
, id
);
3643 #endif // wxUSE_MENUS_NATIVE
3645 wxWindow
*win
= NULL
;
3647 // first try to find it from HWND - this works even with the broken
3648 // programs using the same ids for different controls
3651 win
= wxFindWinFromHandle(control
);
3657 // must cast to a signed type before comparing with other ids!
3658 win
= FindItem((signed short)id
);
3663 return win
->MSWCommand(cmd
, id
);
3666 // the messages sent from the in-place edit control used by the treectrl
3667 // for label editing have id == 0, but they should _not_ be treated as menu
3668 // messages (they are EN_XXX ones, in fact) so don't translate anything
3669 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3672 // If no child window, it may be an accelerator, e.g. for a popup menu
3675 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3676 event
.SetEventObject(this);
3680 return GetEventHandler()->ProcessEvent(event
);
3682 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3685 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3686 // notifications to its parent which we want to reflect back to
3688 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3689 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3692 #endif // wxUSE_SPINCTRL
3697 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3699 // 4 bits are reserved
3700 switch ( wParam
& 0xFFFFFFF0 )
3703 return HandleMaximize();
3706 return HandleMinimize();
3712 // ---------------------------------------------------------------------------
3714 // ---------------------------------------------------------------------------
3716 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3720 // our client coords are not quite the same as Windows ones
3721 wxPoint pt
= GetClientAreaOrigin();
3722 event
.m_x
= x
- pt
.x
;
3723 event
.m_y
= y
- pt
.y
;
3725 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3726 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3727 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3728 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3729 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3730 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3732 event
.SetTimestamp(s_currentMsg
.time
);
3733 event
.m_eventObject
= this;
3735 #if wxUSE_MOUSEEVENT_HACK
3738 m_lastMouseEvent
= event
.GetEventType();
3739 #endif // wxUSE_MOUSEEVENT_HACK
3742 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3744 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3745 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3746 // from the message id and take the value in the table to get wxWin event
3748 static const wxEventType eventsMouse
[] =
3762 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3763 InitMouseEvent(event
, x
, y
, flags
);
3765 return GetEventHandler()->ProcessEvent(event
);
3768 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3770 if ( !m_mouseInWindow
)
3772 // it would be wrong to assume that just because we get a mouse move
3773 // event that the mouse is inside the window: although this is usually
3774 // true, it is not if we had captured the mouse, so we need to check
3775 // the mouse coordinates here
3776 if ( !HasCapture() || IsMouseInWindow() )
3778 // Generate an ENTER event
3779 m_mouseInWindow
= TRUE
;
3781 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3782 InitMouseEvent(event
, x
, y
, flags
);
3784 (void)GetEventHandler()->ProcessEvent(event
);
3788 #if wxUSE_MOUSEEVENT_HACK
3789 // Window gets a click down message followed by a mouse move message even
3790 // if position isn't changed! We want to discard the trailing move event
3791 // if x and y are the same.
3792 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3793 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3794 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3795 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3797 m_lastMouseEvent
= wxEVT_MOTION
;
3801 #endif // wxUSE_MOUSEEVENT_HACK
3803 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3807 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3809 #if wxUSE_MOUSEWHEEL
3810 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3811 InitMouseEvent(event
,
3812 GET_X_LPARAM(lParam
),
3813 GET_Y_LPARAM(lParam
),
3815 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3816 event
.m_wheelDelta
= WHEEL_DELTA
;
3819 static int s_linesPerRotation
= -1;
3820 if ( s_linesPerRotation
== -1 )
3822 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3823 &s_linesPerRotation
, 0))
3825 // this is not supposed to happen
3826 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3828 // the default is 3, so use it if SystemParametersInfo() failed
3829 s_linesPerRotation
= 3;
3833 // no SystemParametersInfo() under Win16
3834 static const int s_linesPerRotation
= 3;
3837 event
.m_linesPerAction
= s_linesPerRotation
;
3838 return GetEventHandler()->ProcessEvent(event
);
3849 // ---------------------------------------------------------------------------
3850 // keyboard handling
3851 // ---------------------------------------------------------------------------
3853 // create the key event of the given type for the given key - used by
3854 // HandleChar and HandleKeyDown/Up
3855 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3857 WXLPARAM lParam
) const
3859 wxKeyEvent
event(evType
);
3860 event
.SetId(GetId());
3861 event
.m_shiftDown
= wxIsShiftDown();
3862 event
.m_controlDown
= wxIsCtrlDown();
3863 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3865 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3866 event
.m_keyCode
= id
;
3867 event
.SetTimestamp(s_currentMsg
.time
);
3869 // translate the position to client coords
3873 GetWindowRect(GetHwnd(),&rect
);
3883 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3885 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3887 bool ctrlDown
= FALSE
;
3892 // If 1 -> 26, translate to CTRL plus a letter.
3894 if ( (id
> 0) && (id
< 27) )
3916 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3918 // it's ASCII and will be processed here only when called from
3919 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3925 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3928 event
.m_controlDown
= TRUE
;
3931 if ( GetEventHandler()->ProcessEvent(event
) )
3938 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3940 int id
= wxCharCodeMSWToWX(wParam
);
3944 // normal ASCII char
3948 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3950 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3951 if ( GetEventHandler()->ProcessEvent(event
) )
3960 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3962 int id
= wxCharCodeMSWToWX(wParam
);
3966 // normal ASCII char
3970 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3972 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3973 if ( GetEventHandler()->ProcessEvent(event
) )
3980 // ---------------------------------------------------------------------------
3982 // ---------------------------------------------------------------------------
3984 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3988 if ( flags
& JOY_BUTTON1CHG
)
3989 change
= wxJOY_BUTTON1
;
3990 if ( flags
& JOY_BUTTON2CHG
)
3991 change
= wxJOY_BUTTON2
;
3992 if ( flags
& JOY_BUTTON3CHG
)
3993 change
= wxJOY_BUTTON3
;
3994 if ( flags
& JOY_BUTTON4CHG
)
3995 change
= wxJOY_BUTTON4
;
3998 if ( flags
& JOY_BUTTON1
)
3999 buttons
|= wxJOY_BUTTON1
;
4000 if ( flags
& JOY_BUTTON2
)
4001 buttons
|= wxJOY_BUTTON2
;
4002 if ( flags
& JOY_BUTTON3
)
4003 buttons
|= wxJOY_BUTTON3
;
4004 if ( flags
& JOY_BUTTON4
)
4005 buttons
|= wxJOY_BUTTON4
;
4007 // the event ids aren't consecutive so we can't use table based lookup
4009 wxEventType eventType
;
4014 eventType
= wxEVT_JOY_MOVE
;
4019 eventType
= wxEVT_JOY_MOVE
;
4024 eventType
= wxEVT_JOY_ZMOVE
;
4029 eventType
= wxEVT_JOY_ZMOVE
;
4032 case MM_JOY1BUTTONDOWN
:
4034 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4037 case MM_JOY2BUTTONDOWN
:
4039 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4042 case MM_JOY1BUTTONUP
:
4044 eventType
= wxEVT_JOY_BUTTON_UP
;
4047 case MM_JOY2BUTTONUP
:
4049 eventType
= wxEVT_JOY_BUTTON_UP
;
4053 wxFAIL_MSG(wxT("no such joystick event"));
4058 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4059 event
.SetPosition(wxPoint(x
, y
));
4060 event
.SetEventObject(this);
4062 return GetEventHandler()->ProcessEvent(event
);
4068 // ---------------------------------------------------------------------------
4070 // ---------------------------------------------------------------------------
4072 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4073 WXWORD pos
, WXHWND control
)
4077 wxWindow
*child
= wxFindWinFromHandle(control
);
4079 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4082 wxScrollWinEvent event
;
4083 event
.SetPosition(pos
);
4084 event
.SetOrientation(orientation
);
4085 event
.m_eventObject
= this;
4090 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4094 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4098 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4102 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4106 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4110 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4113 case SB_THUMBPOSITION
:
4116 // under Win32, the scrollbar range and position are 32 bit integers,
4117 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4118 // explicitly query the scrollbar for the correct position (this must
4119 // be done only for these two SB_ events as they are the only one
4120 // carrying the scrollbar position)
4122 SCROLLINFO scrollInfo
;
4123 wxZeroMemory(scrollInfo
);
4124 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4125 scrollInfo
.fMask
= SIF_TRACKPOS
;
4127 if ( !::GetScrollInfo(GetHwnd(),
4128 orientation
== wxHORIZONTAL
? SB_HORZ
4132 wxLogLastError(_T("GetScrollInfo"));
4135 event
.SetPosition(scrollInfo
.nTrackPos
);
4139 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4140 ? wxEVT_SCROLLWIN_THUMBRELEASE
4141 : wxEVT_SCROLLWIN_THUMBTRACK
;
4148 return GetEventHandler()->ProcessEvent(event
);
4151 // ===========================================================================
4153 // ===========================================================================
4155 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4158 HDC dc
= ::GetDC((HWND
) wnd
);
4163 // the_font->UseResource();
4164 // the_font->RealizeResource();
4165 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4167 was
= (HFONT
) SelectObject(dc
,fnt
);
4169 GetTextMetrics(dc
, &tm
);
4170 if ( the_font
&& fnt
&& was
)
4172 SelectObject(dc
,was
);
4174 ReleaseDC((HWND
)wnd
, dc
);
4177 *x
= tm
.tmAveCharWidth
;
4179 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4182 // the_font->ReleaseResource();
4185 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4186 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4187 int wxCharCodeMSWToWX(int keySym
)
4192 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4193 case VK_BACK
: id
= WXK_BACK
; break;
4194 case VK_TAB
: id
= WXK_TAB
; break;
4195 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4196 case VK_RETURN
: id
= WXK_RETURN
; break;
4197 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4198 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4199 case VK_MENU
: id
= WXK_MENU
; break;
4200 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4201 case VK_SPACE
: id
= WXK_SPACE
; break;
4202 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4203 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4204 case VK_NEXT
: id
= WXK_NEXT
; break;
4205 case VK_END
: id
= WXK_END
; break;
4206 case VK_HOME
: id
= WXK_HOME
; break;
4207 case VK_LEFT
: id
= WXK_LEFT
; break;
4208 case VK_UP
: id
= WXK_UP
; break;
4209 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4210 case VK_DOWN
: id
= WXK_DOWN
; break;
4211 case VK_SELECT
: id
= WXK_SELECT
; break;
4212 case VK_PRINT
: id
= WXK_PRINT
; break;
4213 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4214 case VK_INSERT
: id
= WXK_INSERT
; break;
4215 case VK_DELETE
: id
= WXK_DELETE
; break;
4216 case VK_HELP
: id
= WXK_HELP
; break;
4217 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4218 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4219 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4220 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4221 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4222 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4223 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4224 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4225 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4226 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4227 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4228 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4229 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4230 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4231 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4232 case VK_F1
: id
= WXK_F1
; break;
4233 case VK_F2
: id
= WXK_F2
; break;
4234 case VK_F3
: id
= WXK_F3
; break;
4235 case VK_F4
: id
= WXK_F4
; break;
4236 case VK_F5
: id
= WXK_F5
; break;
4237 case VK_F6
: id
= WXK_F6
; break;
4238 case VK_F7
: id
= WXK_F7
; break;
4239 case VK_F8
: id
= WXK_F8
; break;
4240 case VK_F9
: id
= WXK_F9
; break;
4241 case VK_F10
: id
= WXK_F10
; break;
4242 case VK_F11
: id
= WXK_F11
; break;
4243 case VK_F12
: id
= WXK_F12
; break;
4244 case VK_F13
: id
= WXK_F13
; break;
4245 case VK_F14
: id
= WXK_F14
; break;
4246 case VK_F15
: id
= WXK_F15
; break;
4247 case VK_F16
: id
= WXK_F16
; break;
4248 case VK_F17
: id
= WXK_F17
; break;
4249 case VK_F18
: id
= WXK_F18
; break;
4250 case VK_F19
: id
= WXK_F19
; break;
4251 case VK_F20
: id
= WXK_F20
; break;
4252 case VK_F21
: id
= WXK_F21
; break;
4253 case VK_F22
: id
= WXK_F22
; break;
4254 case VK_F23
: id
= WXK_F23
; break;
4255 case VK_F24
: id
= WXK_F24
; break;
4256 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4257 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4265 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4271 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4272 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4273 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4274 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4275 case WXK_MENU
: keySym
= VK_MENU
; break;
4276 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4277 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4278 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4279 case WXK_END
: keySym
= VK_END
; break;
4280 case WXK_HOME
: keySym
= VK_HOME
; break;
4281 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4282 case WXK_UP
: keySym
= VK_UP
; break;
4283 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4284 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4285 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4286 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4287 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4288 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4289 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4290 case WXK_HELP
: keySym
= VK_HELP
; break;
4291 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4292 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4293 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4294 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4295 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4296 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4297 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4298 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4299 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4300 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4301 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4302 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4303 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4304 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4305 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4306 case WXK_F1
: keySym
= VK_F1
; break;
4307 case WXK_F2
: keySym
= VK_F2
; break;
4308 case WXK_F3
: keySym
= VK_F3
; break;
4309 case WXK_F4
: keySym
= VK_F4
; break;
4310 case WXK_F5
: keySym
= VK_F5
; break;
4311 case WXK_F6
: keySym
= VK_F6
; break;
4312 case WXK_F7
: keySym
= VK_F7
; break;
4313 case WXK_F8
: keySym
= VK_F8
; break;
4314 case WXK_F9
: keySym
= VK_F9
; break;
4315 case WXK_F10
: keySym
= VK_F10
; break;
4316 case WXK_F11
: keySym
= VK_F11
; break;
4317 case WXK_F12
: keySym
= VK_F12
; break;
4318 case WXK_F13
: keySym
= VK_F13
; break;
4319 case WXK_F14
: keySym
= VK_F14
; break;
4320 case WXK_F15
: keySym
= VK_F15
; break;
4321 case WXK_F16
: keySym
= VK_F16
; break;
4322 case WXK_F17
: keySym
= VK_F17
; break;
4323 case WXK_F18
: keySym
= VK_F18
; break;
4324 case WXK_F19
: keySym
= VK_F19
; break;
4325 case WXK_F20
: keySym
= VK_F20
; break;
4326 case WXK_F21
: keySym
= VK_F21
; break;
4327 case WXK_F22
: keySym
= VK_F22
; break;
4328 case WXK_F23
: keySym
= VK_F23
; break;
4329 case WXK_F24
: keySym
= VK_F24
; break;
4330 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4331 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4342 wxWindow
*wxGetActiveWindow()
4344 HWND hWnd
= GetActiveWindow();
4347 return wxFindWinFromHandle((WXHWND
) hWnd
);
4352 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4354 HWND hwnd
= (HWND
)hWnd
;
4356 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4357 // by code in msw/radiobox.cpp), for all the others we just search up the
4359 wxWindow
*win
= (wxWindow
*)NULL
;
4362 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4365 // all these hacks only work under Win32 anyhow
4369 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4370 // wxWindow class which overrides WM_GETDLGCODE processing to
4371 // do it as well, win would be already non NULL
4372 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4374 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4376 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4377 #endif // wxUSE_RADIOBOX
4379 // spin control text buddy window should be mapped to spin ctrl
4380 // itself so try it too
4381 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4384 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4386 #endif // wxUSE_SPINCTRL
4392 while ( hwnd
&& !win
)
4394 // this is a really ugly hack needed to avoid mistakenly returning the
4395 // parent frame wxWindow for the find/replace modeless dialog HWND -
4396 // this, in turn, is needed to call IsDialogMessage() from
4397 // wxApp::ProcessMessage() as for this we must return NULL from here
4399 // FIXME: this is clearly not the best way to do it but I think we'll
4400 // need to change HWND <-> wxWindow code more heavily than I can
4401 // do it now to fix it
4402 #ifndef __WXMICROWIN__
4403 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4405 // it's a dialog box, don't go upwards
4410 hwnd
= ::GetParent(hwnd
);
4411 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4417 #ifndef __WXMICROWIN__
4419 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4420 // in active frames and dialogs, regardless of where the focus is.
4421 static HHOOK wxTheKeyboardHook
= 0;
4422 static FARPROC wxTheKeyboardHookProc
= 0;
4423 int APIENTRY _EXPORT
4424 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4426 void wxSetKeyboardHook(bool doIt
)
4430 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4431 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4433 #if defined(__WIN32__) && !defined(__TWIN32__)
4434 GetCurrentThreadId()
4435 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4443 UnhookWindowsHookEx(wxTheKeyboardHook
);
4445 // avoids warning about statement with no effect (FreeProcInstance
4446 // doesn't do anything under Win32)
4447 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4448 FreeProcInstance(wxTheKeyboardHookProc
);
4453 int APIENTRY _EXPORT
4454 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4456 DWORD hiWord
= HIWORD(lParam
);
4457 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4459 int id
= wxCharCodeMSWToWX(wParam
);
4462 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4463 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4464 event
.m_altDown
= TRUE
;
4466 event
.m_eventObject
= NULL
;
4467 event
.m_keyCode
= id
;
4468 event
.m_shiftDown
= wxIsShiftDown();
4469 event
.m_controlDown
= wxIsCtrlDown();
4470 event
.SetTimestamp(s_currentMsg
.time
);
4472 wxWindow
*win
= wxGetActiveWindow();
4473 wxEvtHandler
*handler
;
4476 handler
= win
->GetEventHandler();
4477 event
.SetId(win
->GetId());
4485 if ( handler
&& handler
->ProcessEvent(event
) )
4493 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4496 #endif // !__WXMICROWIN__
4499 const char *wxGetMessageName(int message
)
4503 case 0x0000: return "WM_NULL";
4504 case 0x0001: return "WM_CREATE";
4505 case 0x0002: return "WM_DESTROY";
4506 case 0x0003: return "WM_MOVE";
4507 case 0x0005: return "WM_SIZE";
4508 case 0x0006: return "WM_ACTIVATE";
4509 case 0x0007: return "WM_SETFOCUS";
4510 case 0x0008: return "WM_KILLFOCUS";
4511 case 0x000A: return "WM_ENABLE";
4512 case 0x000B: return "WM_SETREDRAW";
4513 case 0x000C: return "WM_SETTEXT";
4514 case 0x000D: return "WM_GETTEXT";
4515 case 0x000E: return "WM_GETTEXTLENGTH";
4516 case 0x000F: return "WM_PAINT";
4517 case 0x0010: return "WM_CLOSE";
4518 case 0x0011: return "WM_QUERYENDSESSION";
4519 case 0x0012: return "WM_QUIT";
4520 case 0x0013: return "WM_QUERYOPEN";
4521 case 0x0014: return "WM_ERASEBKGND";
4522 case 0x0015: return "WM_SYSCOLORCHANGE";
4523 case 0x0016: return "WM_ENDSESSION";
4524 case 0x0017: return "WM_SYSTEMERROR";
4525 case 0x0018: return "WM_SHOWWINDOW";
4526 case 0x0019: return "WM_CTLCOLOR";
4527 case 0x001A: return "WM_WININICHANGE";
4528 case 0x001B: return "WM_DEVMODECHANGE";
4529 case 0x001C: return "WM_ACTIVATEAPP";
4530 case 0x001D: return "WM_FONTCHANGE";
4531 case 0x001E: return "WM_TIMECHANGE";
4532 case 0x001F: return "WM_CANCELMODE";
4533 case 0x0020: return "WM_SETCURSOR";
4534 case 0x0021: return "WM_MOUSEACTIVATE";
4535 case 0x0022: return "WM_CHILDACTIVATE";
4536 case 0x0023: return "WM_QUEUESYNC";
4537 case 0x0024: return "WM_GETMINMAXINFO";
4538 case 0x0026: return "WM_PAINTICON";
4539 case 0x0027: return "WM_ICONERASEBKGND";
4540 case 0x0028: return "WM_NEXTDLGCTL";
4541 case 0x002A: return "WM_SPOOLERSTATUS";
4542 case 0x002B: return "WM_DRAWITEM";
4543 case 0x002C: return "WM_MEASUREITEM";
4544 case 0x002D: return "WM_DELETEITEM";
4545 case 0x002E: return "WM_VKEYTOITEM";
4546 case 0x002F: return "WM_CHARTOITEM";
4547 case 0x0030: return "WM_SETFONT";
4548 case 0x0031: return "WM_GETFONT";
4549 case 0x0037: return "WM_QUERYDRAGICON";
4550 case 0x0039: return "WM_COMPAREITEM";
4551 case 0x0041: return "WM_COMPACTING";
4552 case 0x0044: return "WM_COMMNOTIFY";
4553 case 0x0046: return "WM_WINDOWPOSCHANGING";
4554 case 0x0047: return "WM_WINDOWPOSCHANGED";
4555 case 0x0048: return "WM_POWER";
4558 case 0x004A: return "WM_COPYDATA";
4559 case 0x004B: return "WM_CANCELJOURNAL";
4560 case 0x004E: return "WM_NOTIFY";
4561 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4562 case 0x0051: return "WM_INPUTLANGCHANGE";
4563 case 0x0052: return "WM_TCARD";
4564 case 0x0053: return "WM_HELP";
4565 case 0x0054: return "WM_USERCHANGED";
4566 case 0x0055: return "WM_NOTIFYFORMAT";
4567 case 0x007B: return "WM_CONTEXTMENU";
4568 case 0x007C: return "WM_STYLECHANGING";
4569 case 0x007D: return "WM_STYLECHANGED";
4570 case 0x007E: return "WM_DISPLAYCHANGE";
4571 case 0x007F: return "WM_GETICON";
4572 case 0x0080: return "WM_SETICON";
4575 case 0x0081: return "WM_NCCREATE";
4576 case 0x0082: return "WM_NCDESTROY";
4577 case 0x0083: return "WM_NCCALCSIZE";
4578 case 0x0084: return "WM_NCHITTEST";
4579 case 0x0085: return "WM_NCPAINT";
4580 case 0x0086: return "WM_NCACTIVATE";
4581 case 0x0087: return "WM_GETDLGCODE";
4582 case 0x00A0: return "WM_NCMOUSEMOVE";
4583 case 0x00A1: return "WM_NCLBUTTONDOWN";
4584 case 0x00A2: return "WM_NCLBUTTONUP";
4585 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4586 case 0x00A4: return "WM_NCRBUTTONDOWN";
4587 case 0x00A5: return "WM_NCRBUTTONUP";
4588 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4589 case 0x00A7: return "WM_NCMBUTTONDOWN";
4590 case 0x00A8: return "WM_NCMBUTTONUP";
4591 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4592 case 0x0100: return "WM_KEYDOWN";
4593 case 0x0101: return "WM_KEYUP";
4594 case 0x0102: return "WM_CHAR";
4595 case 0x0103: return "WM_DEADCHAR";
4596 case 0x0104: return "WM_SYSKEYDOWN";
4597 case 0x0105: return "WM_SYSKEYUP";
4598 case 0x0106: return "WM_SYSCHAR";
4599 case 0x0107: return "WM_SYSDEADCHAR";
4600 case 0x0108: return "WM_KEYLAST";
4603 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4604 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4605 case 0x010F: return "WM_IME_COMPOSITION";
4608 case 0x0110: return "WM_INITDIALOG";
4609 case 0x0111: return "WM_COMMAND";
4610 case 0x0112: return "WM_SYSCOMMAND";
4611 case 0x0113: return "WM_TIMER";
4612 case 0x0114: return "WM_HSCROLL";
4613 case 0x0115: return "WM_VSCROLL";
4614 case 0x0116: return "WM_INITMENU";
4615 case 0x0117: return "WM_INITMENUPOPUP";
4616 case 0x011F: return "WM_MENUSELECT";
4617 case 0x0120: return "WM_MENUCHAR";
4618 case 0x0121: return "WM_ENTERIDLE";
4619 case 0x0200: return "WM_MOUSEMOVE";
4620 case 0x0201: return "WM_LBUTTONDOWN";
4621 case 0x0202: return "WM_LBUTTONUP";
4622 case 0x0203: return "WM_LBUTTONDBLCLK";
4623 case 0x0204: return "WM_RBUTTONDOWN";
4624 case 0x0205: return "WM_RBUTTONUP";
4625 case 0x0206: return "WM_RBUTTONDBLCLK";
4626 case 0x0207: return "WM_MBUTTONDOWN";
4627 case 0x0208: return "WM_MBUTTONUP";
4628 case 0x0209: return "WM_MBUTTONDBLCLK";
4629 case 0x020A: return "WM_MOUSEWHEEL";
4630 case 0x0210: return "WM_PARENTNOTIFY";
4631 case 0x0211: return "WM_ENTERMENULOOP";
4632 case 0x0212: return "WM_EXITMENULOOP";
4635 case 0x0213: return "WM_NEXTMENU";
4636 case 0x0214: return "WM_SIZING";
4637 case 0x0215: return "WM_CAPTURECHANGED";
4638 case 0x0216: return "WM_MOVING";
4639 case 0x0218: return "WM_POWERBROADCAST";
4640 case 0x0219: return "WM_DEVICECHANGE";
4643 case 0x0220: return "WM_MDICREATE";
4644 case 0x0221: return "WM_MDIDESTROY";
4645 case 0x0222: return "WM_MDIACTIVATE";
4646 case 0x0223: return "WM_MDIRESTORE";
4647 case 0x0224: return "WM_MDINEXT";
4648 case 0x0225: return "WM_MDIMAXIMIZE";
4649 case 0x0226: return "WM_MDITILE";
4650 case 0x0227: return "WM_MDICASCADE";
4651 case 0x0228: return "WM_MDIICONARRANGE";
4652 case 0x0229: return "WM_MDIGETACTIVE";
4653 case 0x0230: return "WM_MDISETMENU";
4654 case 0x0233: return "WM_DROPFILES";
4657 case 0x0281: return "WM_IME_SETCONTEXT";
4658 case 0x0282: return "WM_IME_NOTIFY";
4659 case 0x0283: return "WM_IME_CONTROL";
4660 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4661 case 0x0285: return "WM_IME_SELECT";
4662 case 0x0286: return "WM_IME_CHAR";
4663 case 0x0290: return "WM_IME_KEYDOWN";
4664 case 0x0291: return "WM_IME_KEYUP";
4667 case 0x0300: return "WM_CUT";
4668 case 0x0301: return "WM_COPY";
4669 case 0x0302: return "WM_PASTE";
4670 case 0x0303: return "WM_CLEAR";
4671 case 0x0304: return "WM_UNDO";
4672 case 0x0305: return "WM_RENDERFORMAT";
4673 case 0x0306: return "WM_RENDERALLFORMATS";
4674 case 0x0307: return "WM_DESTROYCLIPBOARD";
4675 case 0x0308: return "WM_DRAWCLIPBOARD";
4676 case 0x0309: return "WM_PAINTCLIPBOARD";
4677 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4678 case 0x030B: return "WM_SIZECLIPBOARD";
4679 case 0x030C: return "WM_ASKCBFORMATNAME";
4680 case 0x030D: return "WM_CHANGECBCHAIN";
4681 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4682 case 0x030F: return "WM_QUERYNEWPALETTE";
4683 case 0x0310: return "WM_PALETTEISCHANGING";
4684 case 0x0311: return "WM_PALETTECHANGED";
4687 // common controls messages - although they're not strictly speaking
4688 // standard, it's nice to decode them nevertheless
4691 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4692 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4693 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4694 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4695 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4696 case 0x1000 + 5: return "LVM_GETITEMA";
4697 case 0x1000 + 75: return "LVM_GETITEMW";
4698 case 0x1000 + 6: return "LVM_SETITEMA";
4699 case 0x1000 + 76: return "LVM_SETITEMW";
4700 case 0x1000 + 7: return "LVM_INSERTITEMA";
4701 case 0x1000 + 77: return "LVM_INSERTITEMW";
4702 case 0x1000 + 8: return "LVM_DELETEITEM";
4703 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4704 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4705 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4706 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4707 case 0x1000 + 13: return "LVM_FINDITEMA";
4708 case 0x1000 + 83: return "LVM_FINDITEMW";
4709 case 0x1000 + 14: return "LVM_GETITEMRECT";
4710 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4711 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4712 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4713 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4714 case 0x1000 + 18: return "LVM_HITTEST";
4715 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4716 case 0x1000 + 20: return "LVM_SCROLL";
4717 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4718 case 0x1000 + 22: return "LVM_ARRANGE";
4719 case 0x1000 + 23: return "LVM_EDITLABELA";
4720 case 0x1000 + 118: return "LVM_EDITLABELW";
4721 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4722 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4723 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4724 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4725 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4726 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4727 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4728 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4729 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4730 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4731 case 0x1000 + 31: return "LVM_GETHEADER";
4732 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4733 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4734 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4735 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4736 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4737 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4738 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4739 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4740 case 0x1000 + 41: return "LVM_GETORIGIN";
4741 case 0x1000 + 42: return "LVM_UPDATE";
4742 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4743 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4744 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4745 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4746 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4747 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4748 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4749 case 0x1000 + 48: return "LVM_SORTITEMS";
4750 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4751 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4752 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4753 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4754 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4755 case 0x1000 + 53: return "LVM_SETICONSPACING";
4756 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4757 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4758 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4759 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4760 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4761 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4762 case 0x1000 + 60: return "LVM_SETHOTITEM";
4763 case 0x1000 + 61: return "LVM_GETHOTITEM";
4764 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4765 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4766 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4767 case 0x1000 + 65: return "LVM_SETWORKAREA";
4770 case 0x1100 + 0: return "TVM_INSERTITEMA";
4771 case 0x1100 + 50: return "TVM_INSERTITEMW";
4772 case 0x1100 + 1: return "TVM_DELETEITEM";
4773 case 0x1100 + 2: return "TVM_EXPAND";
4774 case 0x1100 + 4: return "TVM_GETITEMRECT";
4775 case 0x1100 + 5: return "TVM_GETCOUNT";
4776 case 0x1100 + 6: return "TVM_GETINDENT";
4777 case 0x1100 + 7: return "TVM_SETINDENT";
4778 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4779 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4780 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4781 case 0x1100 + 11: return "TVM_SELECTITEM";
4782 case 0x1100 + 12: return "TVM_GETITEMA";
4783 case 0x1100 + 62: return "TVM_GETITEMW";
4784 case 0x1100 + 13: return "TVM_SETITEMA";
4785 case 0x1100 + 63: return "TVM_SETITEMW";
4786 case 0x1100 + 14: return "TVM_EDITLABELA";
4787 case 0x1100 + 65: return "TVM_EDITLABELW";
4788 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4789 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4790 case 0x1100 + 17: return "TVM_HITTEST";
4791 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4792 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4793 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4794 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4795 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4796 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4797 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4798 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4799 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4802 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4803 case 0x1200 + 1: return "HDM_INSERTITEMA";
4804 case 0x1200 + 10: return "HDM_INSERTITEMW";
4805 case 0x1200 + 2: return "HDM_DELETEITEM";
4806 case 0x1200 + 3: return "HDM_GETITEMA";
4807 case 0x1200 + 11: return "HDM_GETITEMW";
4808 case 0x1200 + 4: return "HDM_SETITEMA";
4809 case 0x1200 + 12: return "HDM_SETITEMW";
4810 case 0x1200 + 5: return "HDM_LAYOUT";
4811 case 0x1200 + 6: return "HDM_HITTEST";
4812 case 0x1200 + 7: return "HDM_GETITEMRECT";
4813 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4814 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4815 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4816 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4817 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4818 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4819 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4822 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4823 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4824 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4825 case 0x1300 + 5: return "TCM_GETITEMA";
4826 case 0x1300 + 60: return "TCM_GETITEMW";
4827 case 0x1300 + 6: return "TCM_SETITEMA";
4828 case 0x1300 + 61: return "TCM_SETITEMW";
4829 case 0x1300 + 7: return "TCM_INSERTITEMA";
4830 case 0x1300 + 62: return "TCM_INSERTITEMW";
4831 case 0x1300 + 8: return "TCM_DELETEITEM";
4832 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4833 case 0x1300 + 10: return "TCM_GETITEMRECT";
4834 case 0x1300 + 11: return "TCM_GETCURSEL";
4835 case 0x1300 + 12: return "TCM_SETCURSEL";
4836 case 0x1300 + 13: return "TCM_HITTEST";
4837 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4838 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4839 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4840 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4841 case 0x1300 + 43: return "TCM_SETPADDING";
4842 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4843 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4844 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4845 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4846 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4847 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4848 case 0x1300 + 50: return "TCM_DESELECTALL";
4851 case WM_USER
+1: return "TB_ENABLEBUTTON";
4852 case WM_USER
+2: return "TB_CHECKBUTTON";
4853 case WM_USER
+3: return "TB_PRESSBUTTON";
4854 case WM_USER
+4: return "TB_HIDEBUTTON";
4855 case WM_USER
+5: return "TB_INDETERMINATE";
4856 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4857 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4858 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4859 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4860 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4861 case WM_USER
+17: return "TB_SETSTATE";
4862 case WM_USER
+18: return "TB_GETSTATE";
4863 case WM_USER
+19: return "TB_ADDBITMAP";
4864 case WM_USER
+20: return "TB_ADDBUTTONS";
4865 case WM_USER
+21: return "TB_INSERTBUTTON";
4866 case WM_USER
+22: return "TB_DELETEBUTTON";
4867 case WM_USER
+23: return "TB_GETBUTTON";
4868 case WM_USER
+24: return "TB_BUTTONCOUNT";
4869 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4870 case WM_USER
+26: return "TB_SAVERESTOREA";
4871 case WM_USER
+76: return "TB_SAVERESTOREW";
4872 case WM_USER
+27: return "TB_CUSTOMIZE";
4873 case WM_USER
+28: return "TB_ADDSTRINGA";
4874 case WM_USER
+77: return "TB_ADDSTRINGW";
4875 case WM_USER
+29: return "TB_GETITEMRECT";
4876 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4877 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4878 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4879 case WM_USER
+33: return "TB_AUTOSIZE";
4880 case WM_USER
+35: return "TB_GETTOOLTIPS";
4881 case WM_USER
+36: return "TB_SETTOOLTIPS";
4882 case WM_USER
+37: return "TB_SETPARENT";
4883 case WM_USER
+39: return "TB_SETROWS";
4884 case WM_USER
+40: return "TB_GETROWS";
4885 case WM_USER
+42: return "TB_SETCMDID";
4886 case WM_USER
+43: return "TB_CHANGEBITMAP";
4887 case WM_USER
+44: return "TB_GETBITMAP";
4888 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4889 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4890 case WM_USER
+46: return "TB_REPLACEBITMAP";
4891 case WM_USER
+47: return "TB_SETINDENT";
4892 case WM_USER
+48: return "TB_SETIMAGELIST";
4893 case WM_USER
+49: return "TB_GETIMAGELIST";
4894 case WM_USER
+50: return "TB_LOADIMAGES";
4895 case WM_USER
+51: return "TB_GETRECT";
4896 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4897 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4898 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4899 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4900 case WM_USER
+56: return "TB_SETSTYLE";
4901 case WM_USER
+57: return "TB_GETSTYLE";
4902 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4903 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4904 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4905 case WM_USER
+61: return "TB_GETTEXTROWS";
4906 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4911 static char s_szBuf
[128];
4912 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4916 #endif //__WXDEBUG__
4918 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4919 int *x
, int *y
, WPARAM
*flags
)
4921 // construct the key mask
4922 WPARAM
& fwKeys
= *flags
;
4924 fwKeys
= MK_RBUTTON
;
4925 if ( wxIsCtrlDown() )
4926 fwKeys
|= MK_CONTROL
;
4927 if ( wxIsShiftDown() )
4930 // simulate right mouse button click
4931 DWORD dwPos
= ::GetMessagePos();
4932 *x
= GET_X_LPARAM(dwPos
);
4933 *y
= GET_Y_LPARAM(dwPos
);
4935 win
->ScreenToClient(x
, y
);
4938 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4942 HWND hwnd
= GetHwndOf(win
);
4943 HDC hdc
= ::GetDC(hwnd
);
4945 #if !wxDIALOG_UNIT_COMPATIBILITY
4946 // and select the current font into it
4947 HFONT hfont
= GetHfontOf(win
->GetFont());
4950 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4954 // finally retrieve the text metrics from it
4955 GetTextMetrics(hdc
, &tm
);
4957 #if !wxDIALOG_UNIT_COMPATIBILITY
4961 (void)::SelectObject(hdc
, hfont
);
4965 ::ReleaseDC(hwnd
, hdc
);
4970 // Find the wxWindow at the current mouse position, returning the mouse
4972 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4974 return wxFindWindowAtPoint(wxGetMousePosition());
4977 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4982 HWND hWndHit
= ::WindowFromPoint(pt2
);
4984 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4985 HWND hWnd
= hWndHit
;
4987 // Try to find a window with a wxWindow associated with it
4988 while (!win
&& (hWnd
!= 0))
4990 hWnd
= ::GetParent(hWnd
);
4991 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
4996 // Get the current mouse position.
4997 wxPoint
wxGetMousePosition()
5000 GetCursorPos( & pt
);
5001 return wxPoint(pt
.x
, pt
.y
);