1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/windows.cpp
4 // Author: Julian Smart
5 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
21 #pragma implementation "window.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
33 #include "wx/msw/winundef.h"
34 #include "wx/window.h"
39 #include "wx/dcclient.h"
40 #include "wx/dcmemory.h"
43 #include "wx/layout.h"
44 #include "wx/dialog.h"
46 #include "wx/listbox.h"
47 #include "wx/button.h"
48 #include "wx/msgdlg.h"
49 #include "wx/settings.h"
50 #include "wx/statbox.h"
54 #include "wx/ownerdrw.h"
57 #if wxUSE_DRAG_AND_DROP
61 #include "wx/menuitem.h"
64 #include "wx/msw/private.h"
67 #include "wx/tooltip.h"
75 #include "wx/spinctrl.h"
76 #endif // wxUSE_SPINCTRL
81 #include "wx/textctrl.h"
82 #include "wx/notebook.h"
86 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
95 #if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
99 #elif !defined(__WXMICROWIN__) // broken compiler
101 #include "wx/msw/gnuwin32/extra.h"
105 // This didn't appear in mingw until 2.95.2
107 #define SIF_TRACKPOS 16
111 #ifndef WM_MOUSEWHEEL
112 #define WM_MOUSEWHEEL 0x020A
115 #define WHEEL_DELTA 120
117 #ifndef SPI_GETWHEELSCROLLLINES
118 #define SPI_GETWHEELSCROLLLINES 104
122 // ---------------------------------------------------------------------------
124 // ---------------------------------------------------------------------------
126 // the last Windows message we got (FIXME-MT)
127 extern MSG s_currentMsg
;
129 #if wxUSE_MENUS_NATIVE
130 wxMenu
*wxCurrentPopupMenu
= NULL
;
131 #endif // wxUSE_MENUS_NATIVE
133 extern const wxChar
*wxCanvasClassName
;
135 // true if we had already created the std colour map, used by
136 // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
137 static bool gs_hasStdCmap
= FALSE
;
139 // ---------------------------------------------------------------------------
141 // ---------------------------------------------------------------------------
143 // the window proc for all our windows
144 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
145 WPARAM wParam
, LPARAM lParam
);
148 const char *wxGetMessageName(int message
);
151 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
152 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
153 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
155 // this magical function is used to translate VK_APPS key presses to right
157 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
158 int *x
, int *y
, WPARAM
*flags
);
160 // get the text metrics for the current font
161 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
163 // wrapper around BringWindowToTop() API
164 static inline void wxBringWindowToTop(HWND hwnd
)
166 #ifdef __WXMICROWIN__
167 // It seems that MicroWindows brings the _parent_ of the window to the top,
168 // which can be the wrong one.
170 // activate (set focus to) specified window
173 // raise top level parent to top of z order
174 ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
175 #else // !__WXMICROWIN__
176 if ( !::BringWindowToTop(hwnd
) )
178 wxLogLastError(_T("BringWindowToTop"));
180 #endif // __WXMICROWIN__/!__WXMICROWIN__
183 // ---------------------------------------------------------------------------
185 // ---------------------------------------------------------------------------
187 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
189 #ifdef __WXUNIVERSAL__
190 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
192 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
193 #endif // __WXUNIVERSAL__/__WXMSW__
195 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
196 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
197 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
198 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
199 EVT_IDLE(wxWindowMSW::OnIdle
)
202 // ===========================================================================
204 // ===========================================================================
206 // ---------------------------------------------------------------------------
207 // wxWindow utility functions
208 // ---------------------------------------------------------------------------
210 // Find an item given the MS Windows id
211 wxWindow
*wxWindowMSW::FindItem(long id
) const
214 wxControl
*item
= wxDynamicCastThis(wxControl
);
217 // is it we or one of our "internal" children?
218 if ( item
->GetId() == id
219 #ifndef __WXUNIVERSAL__
220 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
221 #endif // __WXUNIVERSAL__
227 #endif // wxUSE_CONTROLS
229 wxWindowList::Node
*current
= GetChildren().GetFirst();
232 wxWindow
*childWin
= current
->GetData();
234 wxWindow
*wnd
= childWin
->FindItem(id
);
238 current
= current
->GetNext();
244 // Find an item given the MS Windows handle
245 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
247 wxWindowList::Node
*current
= GetChildren().GetFirst();
250 wxWindow
*parent
= current
->GetData();
252 // Do a recursive search.
253 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
259 || parent
->IsKindOf(CLASSINFO(wxControl
))
260 #endif // wxUSE_CONTROLS
263 wxWindow
*item
= current
->GetData();
264 if ( item
->GetHWND() == hWnd
)
268 if ( item
->ContainsHWND(hWnd
) )
273 current
= current
->GetNext();
278 // Default command handler
279 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
284 // ----------------------------------------------------------------------------
285 // constructors and such
286 // ----------------------------------------------------------------------------
288 void wxWindowMSW::Init()
294 m_doubleClickAllowed
= 0;
296 m_isBeingDeleted
= FALSE
;
299 m_mouseInWindow
= FALSE
;
306 // pass WM_GETDLGCODE to DefWindowProc()
311 m_backgroundTransparent
= FALSE
;
313 // as all windows are created with WS_VISIBLE style...
316 #if wxUSE_MOUSEEVENT_HACK
319 m_lastMouseEvent
= -1;
320 #endif // wxUSE_MOUSEEVENT_HACK
324 wxWindowMSW::~wxWindowMSW()
326 m_isBeingDeleted
= TRUE
;
328 #ifndef __WXUNIVERSAL__
329 // VS: make sure there's no wxFrame with last focus set to us:
330 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
332 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
335 if ( frame
->GetLastFocus() == this )
337 frame
->SetLastFocus((wxWindow
*)NULL
);
342 #endif // __WXUNIVERSAL__
344 // VS: destroy children first and _then_ detach *this from its parent.
345 // If we'd do it the other way around, children wouldn't be able
346 // find their parent frame (see above).
350 m_parent
->RemoveChild(this);
354 // VZ: test temp removed to understand what really happens here
355 //if (::IsWindow(GetHwnd()))
357 if ( !::DestroyWindow(GetHwnd()) )
358 wxLogLastError(wxT("DestroyWindow"));
361 // remove hWnd <-> wxWindow association
362 wxRemoveHandleAssociation(this);
366 // real construction (Init() must have been called before!)
367 bool wxWindowMSW::Create(wxWindow
*parent
,
372 const wxString
& name
)
374 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
377 // wxGTK doesn't allow to create controls with static box as the parent so
378 // this will result in a crash when the program is ported to wxGTK - warn
381 // the correct solution is to create the controls as siblings of the
383 wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
),
384 _T("wxStaticBox can't be used as a window parent!") );
385 #endif // wxUSE_STATBOX
387 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
390 parent
->AddChild(this);
392 // all windows are created visible
393 DWORD msflags
= WS_CHILD
| WS_VISIBLE
;
395 #ifdef __WXUNIVERSAL__
396 // no 3d effects, we draw them ourselves
398 #else // !wxUniversal
399 if ( style
& wxCLIP_CHILDREN
)
400 msflags
|= WS_CLIPCHILDREN
;
401 if ( style
& wxCLIP_SIBLINGS
)
402 msflags
|= WS_CLIPSIBLINGS
;
405 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
);
407 // Even with extended styles, need to combine with WS_BORDER
408 // for them to look right.
410 (m_windowStyle
& (wxBORDER
|
416 msflags
|= WS_BORDER
;
419 // calculate the value to return from WM_GETDLGCODE handler
420 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
422 // want everything: i.e. all keys and WM_CHAR message
423 m_lDlgCode
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
424 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
426 #endif // wxUniversal/!wxUniversal
428 if ( style
& wxPOPUP_WINDOW
)
430 // a popup window floats on top of everything
431 exStyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
433 // it is also created hidden as other top level windows
434 msflags
&= ~WS_VISIBLE
;
438 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exStyle
);
441 // ---------------------------------------------------------------------------
443 // ---------------------------------------------------------------------------
445 void wxWindowMSW::SetFocus()
447 HWND hWnd
= GetHwnd();
448 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
450 #ifndef __WXMICROWIN__
454 if ( !::SetFocus(hWnd
) )
456 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
457 // was there really an error?
458 DWORD dwRes
= ::GetLastError();
461 HWND hwndFocus
= ::GetFocus();
462 if ( hwndFocus
!= hWnd
)
464 wxLogApiError(_T("SetFocus"), dwRes
);
471 // Get the window with the focus
472 wxWindow
*wxWindowBase::FindFocus()
474 HWND hWnd
= ::GetFocus();
477 return wxGetWindowFromHWND((WXHWND
)hWnd
);
483 bool wxWindowMSW::Enable(bool enable
)
485 if ( !wxWindowBase::Enable(enable
) )
488 HWND hWnd
= GetHwnd();
490 ::EnableWindow(hWnd
, (BOOL
)enable
);
492 // VZ: no, this is a bad idea: imagine that you have a dialog with some
493 // disabled controls and disable it - you really wouldn't like the
494 // disabled controls be reenabled too when you reenable the dialog!
496 wxWindowList::Node
*node
= GetChildren().GetFirst();
499 wxWindow
*child
= node
->GetData();
500 child
->Enable(enable
);
502 node
= node
->GetNext();
509 bool wxWindowMSW::Show(bool show
)
511 if ( !wxWindowBase::Show(show
) )
514 HWND hWnd
= GetHwnd();
515 int cshow
= show
? SW_SHOW
: SW_HIDE
;
516 ::ShowWindow(hWnd
, cshow
);
520 wxBringWindowToTop(hWnd
);
526 // Raise the window to the top of the Z order
527 void wxWindowMSW::Raise()
529 wxBringWindowToTop(GetHwnd());
532 // Lower the window to the bottom of the Z order
533 void wxWindowMSW::Lower()
535 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
536 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
539 void wxWindowMSW::SetTitle( const wxString
& title
)
541 SetWindowText(GetHwnd(), title
.c_str());
544 wxString
wxWindowMSW::GetTitle() const
546 return wxGetWindowText(GetHWND());
549 void wxWindowMSW::DoCaptureMouse()
551 HWND hWnd
= GetHwnd();
558 void wxWindowMSW::DoReleaseMouse()
560 if ( !::ReleaseCapture() )
562 wxLogLastError(_T("ReleaseCapture"));
566 /* static */ wxWindow
*wxWindowBase::GetCapture()
568 HWND hwnd
= ::GetCapture();
569 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
572 bool wxWindowMSW::SetFont(const wxFont
& font
)
574 if ( !wxWindowBase::SetFont(font
) )
580 HWND hWnd
= GetHwnd();
583 WXHANDLE hFont
= m_font
.GetResourceHandle();
585 wxASSERT_MSG( hFont
, wxT("should have valid font") );
587 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
592 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
594 if ( !wxWindowBase::SetCursor(cursor
) )
602 HWND hWnd
= GetHwnd();
604 // Change the cursor NOW if we're within the correct window
606 ::GetCursorPos(&point
);
608 RECT rect
= wxGetWindowRect(hWnd
);
610 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
611 ::SetCursor(GetHcursorOf(m_cursor
));
617 void wxWindowMSW::WarpPointer (int x
, int y
)
619 ClientToScreen(&x
, &y
);
621 if ( !::SetCursorPos(x
, y
) )
623 wxLogLastError(_T("SetCursorPos"));
627 #if WXWIN_COMPATIBILITY
628 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
631 #endif // WXWIN_COMPATIBILITY
633 // ---------------------------------------------------------------------------
635 // ---------------------------------------------------------------------------
637 #if WXWIN_COMPATIBILITY
638 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
640 #if defined(__WIN95__)
644 // Try to adjust the range to cope with page size > 1
645 // - a Windows API quirk
646 int pageSize
= GetScrollPage(orient
);
647 if ( pageSize
> 1 && range
> 0)
649 range1
+= (pageSize
- 1);
655 if ( orient
== wxHORIZONTAL
) {
661 info
.cbSize
= sizeof(SCROLLINFO
);
662 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
666 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
668 HWND hWnd
= GetHwnd();
670 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
673 if ( orient
== wxHORIZONTAL
)
678 HWND hWnd
= GetHwnd();
680 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
684 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
686 #if defined(__WIN95__)
690 if ( orient
== wxHORIZONTAL
) {
698 info
.cbSize
= sizeof(SCROLLINFO
);
701 info
.fMask
= SIF_PAGE
;
703 HWND hWnd
= GetHwnd();
705 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
707 if ( orient
== wxHORIZONTAL
)
714 int wxWindowMSW::OldGetScrollRange(int orient
) const
717 if ( orient
== wxHORIZONTAL
)
722 #if __WATCOMC__ && defined(__WINDOWS_386__)
723 short minPos
, maxPos
;
727 HWND hWnd
= GetHwnd();
730 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
731 #if defined(__WIN95__)
732 // Try to adjust the range to cope with page size > 1
733 // - a Windows API quirk
734 int pageSize
= GetScrollPage(orient
);
737 maxPos
-= (pageSize
- 1);
746 int wxWindowMSW::GetScrollPage(int orient
) const
748 if ( orient
== wxHORIZONTAL
)
754 #endif // WXWIN_COMPATIBILITY
756 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
758 #ifdef __WXMICROWIN__
759 return ::GetScrollPosWX(hWnd
, wOrient
);
761 return ::GetScrollPos(hWnd
, wOrient
);
765 int wxWindowMSW::GetScrollPos(int orient
) const
768 if ( orient
== wxHORIZONTAL
)
773 HWND hWnd
= GetHwnd();
774 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
776 return GetScrollPosition(hWnd
, wOrient
);
779 // This now returns the whole range, not just the number
780 // of positions that we can scroll.
781 int wxWindowMSW::GetScrollRange(int orient
) const
784 if ( orient
== wxHORIZONTAL
)
789 #if __WATCOMC__ && defined(__WINDOWS_386__)
790 short minPos
, maxPos
;
794 HWND hWnd
= GetHwnd();
797 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
798 #if defined(__WIN95__)
799 // Try to adjust the range to cope with page size > 1
800 // - a Windows API quirk
801 int pageSize
= GetScrollThumb(orient
);
804 maxPos
-= (pageSize
- 1);
806 // October 10th: new range concept.
816 int wxWindowMSW::GetScrollThumb(int orient
) const
818 if ( orient
== wxHORIZONTAL
)
824 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
826 HWND hWnd
= GetHwnd();
827 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
829 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
831 #if defined(__WIN95__)
833 info
.cbSize
= sizeof(SCROLLINFO
);
837 info
.fMask
= SIF_POS
;
839 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
841 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
842 #endif // __WIN95__/!__WIN95__
845 // New function that will replace some of the above.
846 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
847 int range
, bool refresh
)
849 #if defined(__WIN95__)
850 int oldRange
= range
- thumbVisible
;
852 int range1
= oldRange
;
854 // Try to adjust the range to cope with page size > 1
855 // - a Windows API quirk
856 int pageSize
= thumbVisible
;
857 if ( pageSize
> 1 && range
> 0)
859 range1
+= (pageSize
- 1);
865 if ( orient
== wxHORIZONTAL
) {
871 info
.cbSize
= sizeof(SCROLLINFO
);
872 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
876 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
878 HWND hWnd
= GetHwnd();
880 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
883 if ( orient
== wxHORIZONTAL
)
888 HWND hWnd
= GetHwnd();
891 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
892 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
895 if ( orient
== wxHORIZONTAL
) {
896 m_xThumbSize
= thumbVisible
;
898 m_yThumbSize
= thumbVisible
;
902 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
907 rect
.left
= prect
->x
;
909 rect
.right
= prect
->x
+ prect
->width
;
910 rect
.bottom
= prect
->y
+ prect
->height
;
913 ::ScrollWindow(GetHwnd(), dx
, dy
, prect
? &rect
: NULL
, NULL
);
916 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
918 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
921 for ( int n
= 0; n
< count
; n
++ )
923 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
925 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
928 // don't bother to continue, we're already at top/bottom
935 return pos
!= posStart
;
938 bool wxWindowMSW::ScrollLines(int lines
)
940 bool down
= lines
> 0;
942 return ScrollVertically(GetHwnd(),
943 down
? SB_LINEDOWN
: SB_LINEUP
,
944 down
? lines
: -lines
);
947 bool wxWindowMSW::ScrollPages(int pages
)
949 bool down
= pages
> 0;
951 return ScrollVertically(GetHwnd(),
952 down
? SB_PAGEDOWN
: SB_PAGEUP
,
953 down
? pages
: -pages
);
956 // ---------------------------------------------------------------------------
958 // ---------------------------------------------------------------------------
960 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
962 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
964 HWND hwnd
= (HWND
)hWnd
;
965 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
967 wxAssociateWinWithHandle(hwnd
, this);
969 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
971 // we don't need to subclass the window of our own class (in the Windows
972 // sense of the word)
973 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
975 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
979 // don't bother restoring it neither
984 void wxWindowMSW::UnsubclassWin()
986 wxRemoveHandleAssociation(this);
988 // Restore old Window proc
989 HWND hwnd
= GetHwnd();
994 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
998 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
1000 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1003 m_oldWndProc
= NULL
;
1008 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
1010 #if wxUSE_UNICODE_MSLU
1011 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
1012 // because it doesn't return pointer to the real wnd proc but rather a handle
1013 // of a fake proc that does Unicode<->ANSI translation.
1015 // The hack bellow works, because WNDCLASS contains original window handler
1016 // rather that the unicows fake one. This may not be on purpose, though; if
1017 // it stops working with future versions of unicows.dll, we can override
1018 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
1019 // Unicows_RegisterClass to our own versions that keep track of
1020 // fake<->real wnd proc mapping.
1022 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
1023 // with RegisterClass!!
1025 static wxChar buffer
[512];
1028 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1029 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1030 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1032 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1037 // Make a Windows extended style from the given wxWindows window style
1038 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1040 WXDWORD exStyle
= 0;
1041 if ( style
& wxTRANSPARENT_WINDOW
)
1042 exStyle
|= WS_EX_TRANSPARENT
;
1044 if ( !eliminateBorders
)
1046 if ( style
& wxSUNKEN_BORDER
)
1047 exStyle
|= WS_EX_CLIENTEDGE
;
1048 if ( style
& wxDOUBLE_BORDER
)
1049 exStyle
|= WS_EX_DLGMODALFRAME
;
1050 #if defined(__WIN95__)
1051 if ( style
& wxRAISED_BORDER
)
1052 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1053 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1054 if ( style
& wxSTATIC_BORDER
)
1055 exStyle
|= WS_EX_STATICEDGE
;
1062 // Determines whether native 3D effects or CTL3D should be used,
1063 // applying a default border style if required, and returning an extended
1064 // style to pass to CreateWindowEx.
1065 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1068 // If matches certain criteria, then assume no 3D effects
1069 // unless specifically requested (dealt with in MakeExtendedStyle)
1072 || !IsKindOf(CLASSINFO(wxControl
))
1073 #endif // wxUSE_CONTROLS
1074 || (m_windowStyle
& wxNO_BORDER
) )
1077 return MakeExtendedStyle(m_windowStyle
);
1080 // Determine whether we should be using 3D effects or not.
1081 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1083 // 1) App can specify global 3D effects
1084 *want3D
= wxTheApp
->GetAuto3D();
1086 // 2) If the parent is being drawn with user colours, or simple border specified,
1087 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1088 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1091 // 3) Control can override this global setting by defining
1092 // a border style, e.g. wxSUNKEN_BORDER
1093 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1096 // 4) If it's a special border, CTL3D can't cope so we want a native border
1097 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1098 (m_windowStyle
& wxSTATIC_BORDER
) )
1101 nativeBorder
= TRUE
;
1104 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1105 // effects from extended style
1108 nativeBorder
= FALSE
;
1111 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1113 // If we want 3D, but haven't specified a border here,
1114 // apply the default border style specified.
1115 // TODO what about non-Win95 WIN32? Does it have borders?
1116 #if defined(__WIN95__) && !wxUSE_CTL3D
1117 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1118 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1119 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1125 #if WXWIN_COMPATIBILITY
1126 // If nothing defined for this, try the parent.
1127 // E.g. we may be a button loaded from a resource, with no callback function
1129 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1131 if ( GetEventHandler()->ProcessEvent(event
) )
1134 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1136 #endif // WXWIN_COMPATIBILITY_2
1138 #if WXWIN_COMPATIBILITY
1139 wxObject
* wxWindowMSW::GetChild(int number
) const
1141 // Return a pointer to the Nth object in the Panel
1142 wxNode
*node
= GetChildren().First();
1145 node
= node
->Next();
1148 wxObject
*obj
= (wxObject
*)node
->Data();
1154 #endif // WXWIN_COMPATIBILITY
1156 // Setup background and foreground colours correctly
1157 void wxWindowMSW::SetupColours()
1160 SetBackgroundColour(GetParent()->GetBackgroundColour());
1163 bool wxWindowMSW::IsMouseInWindow() const
1165 // get the mouse position
1167 ::GetCursorPos(&pt
);
1169 // find the window which currently has the cursor and go up the window
1170 // chain until we find this window - or exhaust it
1171 HWND hwnd
= ::WindowFromPoint(pt
);
1172 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1173 hwnd
= ::GetParent(hwnd
);
1175 return hwnd
!= NULL
;
1178 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1180 // Check if we need to send a LEAVE event
1181 if ( m_mouseInWindow
)
1183 if ( !IsMouseInWindow() )
1185 // Generate a LEAVE event
1186 m_mouseInWindow
= FALSE
;
1188 // Unfortunately the mouse button and keyboard state may have
1189 // changed by the time the OnIdle function is called, so 'state'
1190 // may be meaningless.
1192 if ( wxIsShiftDown() )
1194 if ( wxIsCtrlDown() )
1195 state
|= MK_CONTROL
;
1196 if ( GetKeyState( VK_LBUTTON
) )
1197 state
|= MK_LBUTTON
;
1198 if ( GetKeyState( VK_MBUTTON
) )
1199 state
|= MK_MBUTTON
;
1200 if ( GetKeyState( VK_RBUTTON
) )
1201 state
|= MK_RBUTTON
;
1204 if ( !::GetCursorPos(&pt
) )
1206 wxLogLastError(_T("GetCursorPos"));
1209 // we need to have client coordinates here for symmetry with
1210 // wxEVT_ENTER_WINDOW
1211 RECT rect
= wxGetWindowRect(GetHwnd());
1215 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1216 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1218 (void)GetEventHandler()->ProcessEvent(event2
);
1225 // Set this window to be the child of 'parent'.
1226 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1228 if ( !wxWindowBase::Reparent(parent
) )
1231 HWND hWndChild
= GetHwnd();
1232 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1234 ::SetParent(hWndChild
, hWndParent
);
1239 void wxWindowMSW::Clear()
1241 wxClientDC
dc((wxWindow
*)this);
1242 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1243 dc
.SetBackground(brush
);
1247 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1249 #ifndef __WXMICROWIN__
1250 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1254 void wxWindowMSW::Freeze()
1256 SendSetRedraw(GetHwnd(), FALSE
);
1259 void wxWindowMSW::Thaw()
1261 SendSetRedraw(GetHwnd(), TRUE
);
1263 // we need to refresh everything or otherwise he invalidated area is not
1268 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1270 HWND hWnd
= GetHwnd();
1276 mswRect
.left
= rect
->x
;
1277 mswRect
.top
= rect
->y
;
1278 mswRect
.right
= rect
->x
+ rect
->width
;
1279 mswRect
.bottom
= rect
->y
+ rect
->height
;
1281 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1284 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1288 void wxWindowMSW::Update()
1290 if ( !::UpdateWindow(GetHwnd()) )
1292 wxLogLastError(_T("UpdateWindow"));
1295 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1296 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1297 // handler needs to be really drawn right now
1302 // ---------------------------------------------------------------------------
1304 // ---------------------------------------------------------------------------
1306 #if wxUSE_DRAG_AND_DROP
1308 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1310 if ( m_dropTarget
!= 0 ) {
1311 m_dropTarget
->Revoke(m_hWnd
);
1312 delete m_dropTarget
;
1315 m_dropTarget
= pDropTarget
;
1316 if ( m_dropTarget
!= 0 )
1317 m_dropTarget
->Register(m_hWnd
);
1320 #endif // wxUSE_DRAG_AND_DROP
1322 // old style file-manager drag&drop support: we retain the old-style
1323 // DragAcceptFiles in parallel with SetDropTarget.
1324 void wxWindowMSW::DragAcceptFiles(bool accept
)
1326 HWND hWnd
= GetHwnd();
1328 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1331 // ----------------------------------------------------------------------------
1333 // ----------------------------------------------------------------------------
1337 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1339 wxWindowBase::DoSetToolTip(tooltip
);
1342 m_tooltip
->SetWindow(this);
1345 #endif // wxUSE_TOOLTIPS
1347 // ---------------------------------------------------------------------------
1348 // moving and resizing
1349 // ---------------------------------------------------------------------------
1352 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1354 RECT rect
= wxGetWindowRect(GetHwnd());
1357 *x
= rect
.right
- rect
.left
;
1359 *y
= rect
.bottom
- rect
.top
;
1362 // Get size *available for subwindows* i.e. excluding menu bar etc.
1363 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1365 RECT rect
= wxGetClientRect(GetHwnd());
1373 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1375 RECT rect
= wxGetWindowRect(GetHwnd());
1378 point
.x
= rect
.left
;
1381 // we do the adjustments with respect to the parent only for the "real"
1382 // children, not for the dialogs/frames
1383 if ( !IsTopLevel() )
1385 HWND hParentWnd
= 0;
1386 wxWindow
*parent
= GetParent();
1388 hParentWnd
= GetWinHwnd(parent
);
1390 // Since we now have the absolute screen coords, if there's a parent we
1391 // must subtract its top left corner
1394 ::ScreenToClient(hParentWnd
, &point
);
1399 // We may be faking the client origin. So a window that's really at (0,
1400 // 30) may appear (to wxWin apps) to be at (0, 0).
1401 wxPoint
pt(parent
->GetClientAreaOrigin());
1413 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1421 ::ScreenToClient(GetHwnd(), &pt
);
1429 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1437 ::ClientToScreen(GetHwnd(), &pt
);
1445 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1447 // TODO: is this consistent with other platforms?
1448 // Still, negative width or height shouldn't be allowed
1453 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1455 wxLogLastError(wxT("MoveWindow"));
1459 // set the size of the window: if the dimensions are positive, just use them,
1460 // but if any of them is equal to -1, it means that we must find the value for
1461 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1462 // which case -1 is a valid value for x and y)
1464 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1465 // the width/height to best suit our contents, otherwise we reuse the current
1467 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1469 // get the current size and position...
1470 int currentX
, currentY
;
1471 GetPosition(¤tX
, ¤tY
);
1472 int currentW
,currentH
;
1473 GetSize(¤tW
, ¤tH
);
1475 // ... and don't do anything (avoiding flicker) if it's already ok
1476 if ( x
== currentX
&& y
== currentY
&&
1477 width
== currentW
&& height
== currentH
)
1482 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1484 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1487 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1489 wxSize
size(-1, -1);
1492 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1494 size
= DoGetBestSize();
1499 // just take the current one
1506 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1510 size
= DoGetBestSize();
1512 //else: already called DoGetBestSize() above
1518 // just take the current one
1523 DoMoveWindow(x
, y
, width
, height
);
1526 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1528 // setting the client size is less obvious than it it could have been
1529 // because in the result of changing the total size the window scrollbar
1530 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1531 // will not be correct as the difference between the total and client size
1532 // changes - so we keep changing it until we get it right
1534 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1535 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1536 // may become 3 if the window had 0 size originally and so we didn't
1537 // calculate the scrollbar correction correctly during the first iteration)
1538 // but just to be on the safe side we check for it instead of making it an
1539 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1540 for ( int i
= 0; i
< 4; i
++ )
1543 ::GetClientRect(GetHwnd(), &rectClient
);
1545 // if the size is already ok, stop here (rectClient.left = top = 0)
1546 if ( rectClient
.right
== width
&& rectClient
.bottom
== height
)
1553 // how did it happen? maybe OnSize() handler does something really
1554 // strange in this class?
1555 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1560 int widthClient
= width
,
1561 heightClient
= height
;
1563 // Find the difference between the entire window (title bar and all)
1564 // and the client area; add this to the new client size to move the
1567 ::GetWindowRect(GetHwnd(), &rectWin
);
1569 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1570 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1573 point
.x
= rectWin
.left
;
1574 point
.y
= rectWin
.top
;
1576 // MoveWindow positions the child windows relative to the parent, so
1577 // adjust if necessary
1578 if ( !IsTopLevel() )
1580 wxWindow
*parent
= GetParent();
1583 ::ScreenToClient(GetHwndOf(parent
), &point
);
1587 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1591 // For implementation purposes - sometimes decorations make the client area
1593 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1595 return wxPoint(0, 0);
1598 // ---------------------------------------------------------------------------
1600 // ---------------------------------------------------------------------------
1602 int wxWindowMSW::GetCharHeight() const
1604 return wxGetTextMetrics(this).tmHeight
;
1607 int wxWindowMSW::GetCharWidth() const
1609 // +1 is needed because Windows apparently adds it when calculating the
1610 // dialog units size in pixels
1611 #if wxDIALOG_UNIT_COMPATIBILITY
1612 return wxGetTextMetrics(this).tmAveCharWidth
;
1614 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1618 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1620 int *descent
, int *externalLeading
,
1621 const wxFont
*theFont
) const
1623 const wxFont
*fontToUse
= theFont
;
1625 fontToUse
= &m_font
;
1627 HWND hWnd
= GetHwnd();
1628 HDC dc
= ::GetDC(hWnd
);
1632 if ( fontToUse
&& fontToUse
->Ok() )
1634 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1636 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1641 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1642 GetTextMetrics(dc
, &tm
);
1644 if ( fontToUse
&& fnt
&& hfontOld
)
1645 SelectObject(dc
, hfontOld
);
1647 ReleaseDC(hWnd
, dc
);
1654 *descent
= tm
.tmDescent
;
1655 if ( externalLeading
)
1656 *externalLeading
= tm
.tmExternalLeading
;
1659 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1660 // ---------------------------------------------------------------------------
1661 // Caret manipulation
1662 // ---------------------------------------------------------------------------
1664 void wxWindowMSW::CreateCaret(int w
, int h
)
1666 SetCaret(new wxCaret(this, w
, h
));
1669 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1671 wxFAIL_MSG("not implemented");
1674 void wxWindowMSW::ShowCaret(bool show
)
1676 wxCHECK_RET( m_caret
, "no caret to show" );
1678 m_caret
->Show(show
);
1681 void wxWindowMSW::DestroyCaret()
1686 void wxWindowMSW::SetCaretPos(int x
, int y
)
1688 wxCHECK_RET( m_caret
, "no caret to move" );
1690 m_caret
->Move(x
, y
);
1693 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1695 wxCHECK_RET( m_caret
, "no caret to get position of" );
1697 m_caret
->GetPosition(x
, y
);
1699 #endif // wxUSE_CARET
1701 // ---------------------------------------------------------------------------
1703 // ---------------------------------------------------------------------------
1705 #if wxUSE_MENUS_NATIVE
1707 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1708 // immediately, without waiting for the next event loop iteration
1710 // NB: this function should probably be made public later as it can almost
1711 // surely replace wxYield() elsewhere as well
1712 static void wxYieldForCommandsOnly()
1714 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1715 // want to process it here)
1717 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1718 && msg
.message
!= WM_QUIT
)
1720 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1724 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1726 menu
->SetInvokingWindow(this);
1729 HWND hWnd
= GetHwnd();
1730 HMENU hMenu
= GetHmenuOf(menu
);
1734 ::ClientToScreen(hWnd
, &point
);
1735 wxCurrentPopupMenu
= menu
;
1736 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1738 // we need to do it righ now as otherwise the events are never going to be
1739 // sent to wxCurrentPopupMenu from HandleCommand()
1741 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1742 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1743 // destroyed as soon as we return (it can be a local variable in the caller
1744 // for example) and so we do need to process the event immediately
1745 wxYieldForCommandsOnly();
1747 wxCurrentPopupMenu
= NULL
;
1749 menu
->SetInvokingWindow(NULL
);
1754 #endif // wxUSE_MENUS_NATIVE
1756 // ===========================================================================
1757 // pre/post message processing
1758 // ===========================================================================
1760 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1763 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1765 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1768 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1770 // wxUniversal implements tab traversal itself
1771 #ifndef __WXUNIVERSAL__
1772 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1774 // intercept dialog navigation keys
1775 MSG
*msg
= (MSG
*)pMsg
;
1777 // here we try to do all the job which ::IsDialogMessage() usually does
1780 bool bProcess
= TRUE
;
1781 if ( msg
->message
!= WM_KEYDOWN
)
1784 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1789 bool bCtrlDown
= wxIsCtrlDown();
1790 bool bShiftDown
= wxIsShiftDown();
1792 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1793 // don't process it if it's the case (except for Ctrl-Tab/Enter
1794 // combinations which are always processed)
1798 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1801 bool bForward
= TRUE
,
1802 bWindowChange
= FALSE
;
1804 switch ( msg
->wParam
)
1807 // assume that nobody wants Shift-TAB for himself - if we
1808 // don't do it there is no easy way for a control to grab
1809 // TABs but still let Shift-TAB work as navugation key
1810 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1814 // Ctrl-Tab cycles thru notebook pages
1815 bWindowChange
= bCtrlDown
;
1816 bForward
= !bShiftDown
;
1822 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1830 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1836 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1838 // control wants to process Enter itself, don't
1839 // call IsDialogMessage() which would interpret
1843 else if ( lDlgCode
& DLGC_BUTTON
)
1845 // let IsDialogMessage() handle this for all
1846 // buttons except the owner-drawn ones which it
1847 // just seems to ignore
1848 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1849 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1851 // emulate the button click
1852 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1854 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1859 // FIXME: this should be handled by
1860 // wxNavigationKeyEvent handler and not here!!
1864 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1866 if ( btn
&& btn
->IsEnabled() )
1868 // if we do have a default button, do press it
1869 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1873 else // no default button
1874 #endif // wxUSE_BUTTON
1876 // no special function for enter and don't even
1877 // let IsDialogMessage() have it: it seems to
1878 // do something really strange with it
1891 wxNavigationKeyEvent event
;
1892 event
.SetDirection(bForward
);
1893 event
.SetWindowChange(bWindowChange
);
1894 event
.SetEventObject(this);
1896 if ( GetEventHandler()->ProcessEvent(event
) )
1903 // let ::IsDialogMessage() do almost everything and handle just the
1904 // things it doesn't here: Ctrl-TAB for switching notebook pages
1905 if ( msg
->message
== WM_KEYDOWN
)
1907 // don't process system keys here
1908 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1910 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1912 // find the first notebook parent and change its page
1913 wxWindow
*win
= this;
1914 wxNotebook
*nbook
= NULL
;
1915 while ( win
&& !nbook
)
1917 nbook
= wxDynamicCast(win
, wxNotebook
);
1918 win
= win
->GetParent();
1923 bool forward
= !wxIsShiftDown();
1925 nbook
->AdvanceSelection(forward
);
1932 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1934 // IsDialogMessage() did something...
1938 #endif // __WXUNIVERSAL__
1943 // relay mouse move events to the tooltip control
1944 MSG
*msg
= (MSG
*)pMsg
;
1945 if ( msg
->message
== WM_MOUSEMOVE
)
1946 m_tooltip
->RelayEvent(pMsg
);
1948 #endif // wxUSE_TOOLTIPS
1953 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1955 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1956 return m_acceleratorTable
.Translate(this, pMsg
);
1959 #endif // wxUSE_ACCEL
1962 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1964 // preprocess all messages by default
1968 // ---------------------------------------------------------------------------
1969 // message params unpackers (different for Win16 and Win32)
1970 // ---------------------------------------------------------------------------
1974 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1975 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1977 *id
= LOWORD(wParam
);
1978 *hwnd
= (WXHWND
)lParam
;
1979 *cmd
= HIWORD(wParam
);
1982 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1983 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1985 *state
= LOWORD(wParam
);
1986 *minimized
= HIWORD(wParam
);
1987 *hwnd
= (WXHWND
)lParam
;
1990 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1991 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1993 *code
= LOWORD(wParam
);
1994 *pos
= HIWORD(wParam
);
1995 *hwnd
= (WXHWND
)lParam
;
1998 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
1999 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2001 #ifndef __WXMICROWIN__
2002 *nCtlColor
= CTLCOLOR_BTN
;
2003 *hwnd
= (WXHWND
)lParam
;
2004 *hdc
= (WXHDC
)wParam
;
2008 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2009 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2011 *item
= (WXWORD
)wParam
;
2012 *flags
= HIWORD(wParam
);
2013 *hmenu
= (WXHMENU
)lParam
;
2018 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2019 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2021 *id
= (WXWORD
)wParam
;
2022 *hwnd
= (WXHWND
)LOWORD(lParam
);
2023 *cmd
= HIWORD(lParam
);
2026 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2027 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2029 *state
= (WXWORD
)wParam
;
2030 *minimized
= LOWORD(lParam
);
2031 *hwnd
= (WXHWND
)HIWORD(lParam
);
2034 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2035 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2037 *code
= (WXWORD
)wParam
;
2038 *pos
= LOWORD(lParam
);
2039 *hwnd
= (WXHWND
)HIWORD(lParam
);
2042 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2043 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2045 *hwnd
= (WXHWND
)LOWORD(lParam
);
2046 *nCtlColor
= (int)HIWORD(lParam
);
2047 *hdc
= (WXHDC
)wParam
;
2050 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2051 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2053 *item
= (WXWORD
)wParam
;
2054 *flags
= LOWORD(lParam
);
2055 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2060 // ---------------------------------------------------------------------------
2061 // Main wxWindows window proc and the window proc for wxWindow
2062 // ---------------------------------------------------------------------------
2064 // Hook for new window just as it's being created, when the window isn't yet
2065 // associated with the handle
2066 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2068 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2069 // window being created and insures that it's always unset back later
2070 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2072 gs_winBeingCreated
= winBeingCreated
;
2075 wxWindowCreationHook::~wxWindowCreationHook()
2077 gs_winBeingCreated
= NULL
;
2081 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2083 // trace all messages - useful for the debugging
2085 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2086 wxGetMessageName(message
), wParam
, lParam
);
2087 #endif // __WXDEBUG__
2089 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2091 // when we get the first message for the HWND we just created, we associate
2092 // it with wxWindow stored in gs_winBeingCreated
2093 if ( !wnd
&& gs_winBeingCreated
)
2095 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2096 wnd
= gs_winBeingCreated
;
2097 gs_winBeingCreated
= NULL
;
2098 wnd
->SetHWND((WXHWND
)hWnd
);
2104 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2106 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2111 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2113 // did we process the message?
2114 bool processed
= FALSE
;
2125 // for most messages we should return 0 when we do process the message
2133 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2136 // return 0 to allow window creation
2137 rc
.result
= mayCreate
? 0 : -1;
2143 // never set processed to TRUE and *always* pass WM_DESTROY to
2144 // DefWindowProc() as Windows may do some internal cleanup when
2145 // processing it and failing to pass the message along may cause
2146 // memory and resource leaks!
2147 (void)HandleDestroy();
2151 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2159 // we're not interested in these messages at all
2162 case SIZE_MINIMIZED
:
2163 // we shouldn't send sizev events for these messages as the
2164 // client size may be negative which breaks existing code
2166 // OTOH we might send another (wxMinimizedEvent?) one or
2167 // add an additional parameter to wxSizeEvent if this is
2168 // useful to anybody
2172 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2173 // fall through nevertheless
2175 case SIZE_MAXIMIZED
:
2177 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2182 #ifndef __WXMICROWIN__
2183 case WM_ACTIVATEAPP
:
2184 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2190 WXWORD state
, minimized
;
2192 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2194 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2199 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2203 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2207 processed
= HandlePaint();
2211 // don't let the DefWindowProc() destroy our window - we'll do it
2212 // ourselves in ~wxWindow
2218 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2222 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2223 GET_Y_LPARAM(lParam
),
2227 #if wxUSE_MOUSEWHEEL
2229 processed
= HandleMouseWheel(wParam
, lParam
);
2233 case WM_LBUTTONDOWN
:
2235 case WM_LBUTTONDBLCLK
:
2236 case WM_RBUTTONDOWN
:
2238 case WM_RBUTTONDBLCLK
:
2239 case WM_MBUTTONDOWN
:
2241 case WM_MBUTTONDBLCLK
:
2244 #ifdef __WXMICROWIN__
2245 // MicroWindows seems to ignore the fact that a window is
2246 // disabled. So catch mouse events and throw them away if
2248 wxWindowMSW
* win
= this;
2251 if (!win
->IsEnabled())
2256 win
= win
->GetParent();
2257 if (win
&& win
->IsTopLevel())
2260 #endif // __WXMICROWIN__
2263 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2265 processed
= HandleMouseEvent(message
,
2266 GET_X_LPARAM(lParam
),
2267 GET_Y_LPARAM(lParam
),
2273 #ifdef __WXMICROWIN__
2274 case WM_NCLBUTTONDOWN
:
2275 case WM_NCLBUTTONUP
:
2276 case WM_NCLBUTTONDBLCLK
:
2277 case WM_NCRBUTTONDOWN
:
2278 case WM_NCRBUTTONUP
:
2279 case WM_NCRBUTTONDBLCLK
:
2281 case WM_NCMBUTTONDOWN
:
2282 case WM_NCMBUTTONUP
:
2283 case WM_NCMBUTTONDBLCLK
:
2286 // MicroWindows seems to ignore the fact that a window
2287 // is disabled. So catch mouse events and throw them away if necessary.
2289 wxWindowMSW
* win
= this;
2292 if (!win
->IsEnabled())
2297 win
= win
->GetParent();
2298 if (win
&& win
->IsTopLevel())
2303 #endif // __WXMICROWIN__
2310 case MM_JOY1BUTTONDOWN
:
2311 case MM_JOY2BUTTONDOWN
:
2312 case MM_JOY1BUTTONUP
:
2313 case MM_JOY2BUTTONUP
:
2314 processed
= HandleJoystickEvent(message
,
2315 GET_X_LPARAM(lParam
),
2316 GET_Y_LPARAM(lParam
),
2319 #endif // __WXMICROWIN__
2322 processed
= HandleSysCommand(wParam
, lParam
);
2329 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2331 processed
= HandleCommand(id
, cmd
, hwnd
);
2337 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2341 // for these messages we must return TRUE if process the message
2344 case WM_MEASUREITEM
:
2346 int idCtrl
= (UINT
)wParam
;
2347 if ( message
== WM_DRAWITEM
)
2349 processed
= MSWOnDrawItem(idCtrl
,
2350 (WXDRAWITEMSTRUCT
*)lParam
);
2354 processed
= MSWOnMeasureItem(idCtrl
,
2355 (WXMEASUREITEMSTRUCT
*)lParam
);
2362 #endif // defined(WM_DRAWITEM)
2367 rc
.result
= m_lDlgCode
;
2370 //else: get the dlg code from the DefWindowProc()
2375 // If this has been processed by an event handler,
2376 // return 0 now (we've handled it).
2377 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2384 // we consider these message "not interesting" to OnChar
2385 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2394 // avoid duplicate messages to OnChar for these ASCII keys: they
2395 // will be translated by TranslateMessage() and received in WM_CHAR
2403 // but set processed to FALSE, not TRUE to still pass them to
2404 // the control's default window proc - otherwise built-in
2405 // keyboard handling won't work
2411 // special case of VK_APPS: treat it the same as right mouse
2412 // click because both usually pop up a context menu
2418 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2419 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2429 processed
= HandleChar((WORD
)wParam
, lParam
);
2436 // special case of VK_APPS: treat it the same as right mouse button
2437 if ( wParam
== VK_APPS
)
2442 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2443 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2448 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2453 case WM_CHAR
: // Always an ASCII character
2454 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2462 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2464 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2470 // CTLCOLOR messages are sent by children to query the parent for their
2471 // colors#ifndef __WXMICROWIN__
2472 #ifndef __WXMICROWIN__
2474 case WM_CTLCOLORMSGBOX
:
2475 case WM_CTLCOLOREDIT
:
2476 case WM_CTLCOLORLISTBOX
:
2477 case WM_CTLCOLORBTN
:
2478 case WM_CTLCOLORDLG
:
2479 case WM_CTLCOLORSCROLLBAR
:
2480 case WM_CTLCOLORSTATIC
:
2488 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2490 processed
= HandleCtlColor(&rc
.hBrush
,
2499 #endif // !__WXMICROWIN__
2501 case WM_SYSCOLORCHANGE
:
2502 // the return value for this message is ignored
2503 processed
= HandleSysColorChange();
2506 case WM_PALETTECHANGED
:
2507 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2510 case WM_QUERYNEWPALETTE
:
2511 processed
= HandleQueryNewPalette();
2515 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2518 // we processed the message, i.e. erased the background
2524 processed
= HandleDropFiles(wParam
);
2528 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2532 // we never set focus from here
2537 case WM_QUERYENDSESSION
:
2538 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2542 processed
= HandleEndSession(wParam
!= 0, lParam
);
2545 case WM_GETMINMAXINFO
:
2546 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2550 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2551 LOWORD(lParam
), // hit test
2552 HIWORD(lParam
)); // mouse msg
2556 // returning TRUE stops the DefWindowProc() from further
2557 // processing this message - exactly what we need because we've
2558 // just set the cursor.
2563 #if defined(__WIN32__) && defined(WM_HELP)
2566 HELPINFO
* info
= (HELPINFO
*) lParam
;
2567 // Don't yet process menu help events, just windows
2568 if (info
->iContextType
== HELPINFO_WINDOW
)
2570 wxWindowMSW
* subjectOfHelp
= this;
2571 bool eventProcessed
= FALSE
;
2572 while (subjectOfHelp
&& !eventProcessed
)
2574 wxHelpEvent
helpEvent(wxEVT_HELP
,
2575 subjectOfHelp
->GetId(),
2576 wxPoint(info
->MousePos
.x
,
2577 info
->MousePos
.y
) );
2578 helpEvent
.SetEventObject(this);
2580 GetEventHandler()->ProcessEvent(helpEvent
);
2582 // Go up the window hierarchy until the event is
2584 subjectOfHelp
= subjectOfHelp
->GetParent();
2587 processed
= eventProcessed
;
2589 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2591 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2592 helpEvent
.SetEventObject(this);
2593 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2596 //else: processed is already FALSE
2600 case WM_CONTEXTMENU
:
2602 // we don't convert from screen to client coordinates as
2603 // the event may be handled by a parent window
2604 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2606 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2607 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2612 // unfortunately this doesn't really work as then window which
2613 // doesn't accept focus doesn't get any mouse events neither which
2614 // means it can't get any input at all
2615 #if 0 //def __WXUNIVERSAL__
2617 // we shouldn't allow the windows which don't want to get focus to
2619 if ( !AcceptsFocus() )
2621 rc
.result
= HTTRANSPARENT
;
2625 #endif // __WXUNIVERSAL__
2631 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2632 wxGetMessageName(message
));
2633 #endif // __WXDEBUG__
2634 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2640 // ----------------------------------------------------------------------------
2641 // wxWindow <-> HWND map
2642 // ----------------------------------------------------------------------------
2644 wxWinHashTable
*wxWinHandleHash
= NULL
;
2646 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2648 return wxWinHandleHash
->Get((long)hWnd
);
2651 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2653 // adding NULL hWnd is (first) surely a result of an error and
2654 // (secondly) breaks menu command processing
2655 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2656 wxT("attempt to add a NULL hWnd to window list ignored") );
2658 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2660 if ( oldWin
&& (oldWin
!= win
) )
2662 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2663 hWnd
, win
->GetClassInfo()->GetClassName());
2666 #endif // __WXDEBUG__
2669 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2673 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2675 wxWinHandleHash
->Delete((long)win
->GetHWND());
2678 // ----------------------------------------------------------------------------
2679 // various MSW speciic class dependent functions
2680 // ----------------------------------------------------------------------------
2682 // Default destroyer - override if you destroy it in some other way
2683 // (e.g. with MDI child windows)
2684 void wxWindowMSW::MSWDestroyWindow()
2688 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2691 int& w
, int& h
) const
2693 bool nonDefault
= FALSE
;
2697 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2698 // just as well set it to CW_USEDEFAULT as well
2705 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2711 NB: there used to be some code here which set the initial size of the
2712 window to the client size of the parent if no explicit size was
2713 specified. This was wrong because wxWindows programs often assume
2714 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2715 it. To see why, you should understand that Windows sends WM_SIZE from
2716 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2717 from some base class ctor and so this WM_SIZE is not processed in the
2718 real class' OnSize() (because it's not fully constructed yet and the
2719 event goes to some base class OnSize() instead). So the WM_SIZE we
2720 rely on is the one sent when the parent frame resizes its children
2721 but here is the problem: if the child already has just the right
2722 size, nothing will happen as both wxWindows and Windows check for
2723 this and ignore any attempts to change the window size to the size it
2724 already has - so no WM_SIZE would be sent.
2728 // as abobe, h is not used at all in this case anyhow
2735 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2743 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2744 const wxChar
*title
,
2748 WXDWORD extendedStyle
)
2750 // choose the position/size for the new window
2752 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2754 // find the correct parent HWND
2755 wxWindow
*parent
= GetParent();
2756 bool isChild
= (style
& WS_CHILD
) != 0;
2758 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2760 // popup windows should have desktop as parent because they shouldn't
2761 // be limited to the parents client area as child windows usually are
2762 hParent
= ::GetDesktopWindow();
2766 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2768 // this is either a normal child window or a top level window with
2769 // wxFRAME_TOOL_WINDOW style (see below)
2770 hParent
= GetHwndOf(parent
);
2774 // this is either a window for which no parent was specified (not
2775 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2776 // style: we should use NULL parent HWND for it or it would be
2777 // always on top of its parent which is not what we usually want
2778 // (in fact, we only want it for frames with the special
2779 // wxFRAME_TOOL_WINDOW as above)
2785 // controlId is menu handle for the top level windows, so set it to 0
2786 // unless we're creating a child window
2790 controlId
= GetId();
2792 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2794 style
|= WS_CLIPSIBLINGS
;
2802 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2803 // which is the same but without CS_[HV]REDRAW class styles so using it
2804 // ensures that the window is not fully repainted on each resize
2805 wxString
className(wclass
);
2806 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2808 className
+= wxT("NR");
2811 // do create the window
2812 wxWindowCreationHook
hook(this);
2814 m_hWnd
= (WXHWND
)::CreateWindowEx
2818 title
? title
: wxT(""),
2824 NULL
// no extra data
2829 wxLogSysError(_("Can't create window of class %s"), wclass
);
2834 SubclassWin(m_hWnd
);
2836 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2841 // ===========================================================================
2842 // MSW message handlers
2843 // ===========================================================================
2845 // ---------------------------------------------------------------------------
2847 // ---------------------------------------------------------------------------
2850 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2851 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2853 #ifndef __WXMICROWIN__
2854 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2855 HWND hWnd
= hdr
->hwndFrom
;
2856 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2858 // is this one of our windows?
2861 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2864 // try all our children
2865 wxWindowList::Node
*node
= GetChildren().GetFirst();
2868 wxWindow
*child
= node
->GetData();
2869 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2874 node
= node
->GetNext();
2877 // finally try this window too (catches toolbar case)
2878 return MSWOnNotify(idCtrl
, lParam
, result
);
2879 #else // __WXMICROWIN__
2884 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2886 WXLPARAM
* WXUNUSED(result
))
2889 NMHDR
* hdr
= (NMHDR
*)lParam
;
2890 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2892 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2893 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2898 #endif // wxUSE_TOOLTIPS
2904 // ---------------------------------------------------------------------------
2905 // end session messages
2906 // ---------------------------------------------------------------------------
2908 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2910 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2911 event
.SetEventObject(wxTheApp
);
2912 event
.SetCanVeto(TRUE
);
2913 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2915 bool rc
= wxTheApp
->ProcessEvent(event
);
2919 // we may end only if the app didn't veto session closing (double
2921 *mayEnd
= !event
.GetVeto();
2927 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2929 // do nothing if the session isn't ending
2934 if ( (this != wxTheApp
->GetTopWindow()) )
2937 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2938 event
.SetEventObject(wxTheApp
);
2939 event
.SetCanVeto(FALSE
);
2940 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2942 return wxTheApp
->ProcessEvent(event
);
2945 // ---------------------------------------------------------------------------
2946 // window creation/destruction
2947 // ---------------------------------------------------------------------------
2949 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2951 // TODO: should generate this event from WM_NCCREATE
2952 wxWindowCreateEvent
event((wxWindow
*)this);
2953 (void)GetEventHandler()->ProcessEvent(event
);
2960 bool wxWindowMSW::HandleDestroy()
2962 wxWindowDestroyEvent
event((wxWindow
*)this);
2963 (void)GetEventHandler()->ProcessEvent(event
);
2965 // delete our drop target if we've got one
2966 #if wxUSE_DRAG_AND_DROP
2967 if ( m_dropTarget
!= NULL
)
2969 m_dropTarget
->Revoke(m_hWnd
);
2971 delete m_dropTarget
;
2972 m_dropTarget
= NULL
;
2974 #endif // wxUSE_DRAG_AND_DROP
2976 // WM_DESTROY handled
2980 // ---------------------------------------------------------------------------
2982 // ---------------------------------------------------------------------------
2984 bool wxWindowMSW::HandleActivate(int state
,
2985 bool WXUNUSED(minimized
),
2986 WXHWND
WXUNUSED(activate
))
2988 wxActivateEvent
event(wxEVT_ACTIVATE
,
2989 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
2991 event
.SetEventObject(this);
2993 return GetEventHandler()->ProcessEvent(event
);
2996 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
2998 // notify the parent keeping track of focus for the kbd navigation
2999 // purposes that we got it
3000 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3001 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3007 m_caret
->OnSetFocus();
3009 #endif // wxUSE_CARET
3012 // If it's a wxTextCtrl don't send the event as it will be done
3013 // after the control gets to process it from EN_FOCUS handler
3014 if ( wxDynamicCastThis(wxTextCtrl
) )
3018 #endif // wxUSE_TEXTCTRL
3020 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3021 event
.SetEventObject(this);
3023 // wxFindWinFromHandle() may return NULL, it is ok
3024 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3026 return GetEventHandler()->ProcessEvent(event
);
3029 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3035 m_caret
->OnKillFocus();
3037 #endif // wxUSE_CARET
3040 // If it's a wxTextCtrl don't send the event as it will be done
3041 // after the control gets to process it.
3042 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3049 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3050 event
.SetEventObject(this);
3052 // wxFindWinFromHandle() may return NULL, it is ok
3053 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3055 return GetEventHandler()->ProcessEvent(event
);
3058 // ---------------------------------------------------------------------------
3060 // ---------------------------------------------------------------------------
3062 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3064 wxShowEvent
event(GetId(), show
);
3065 event
.m_eventObject
= this;
3067 return GetEventHandler()->ProcessEvent(event
);
3070 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3072 wxInitDialogEvent
event(GetId());
3073 event
.m_eventObject
= this;
3075 return GetEventHandler()->ProcessEvent(event
);
3078 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3080 #ifndef __WXMICROWIN__
3081 HDROP hFilesInfo
= (HDROP
) wParam
;
3083 // Get the total number of files dropped
3084 UINT gwFilesDropped
= ::DragQueryFile
3092 wxString
*files
= new wxString
[gwFilesDropped
];
3093 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3095 // first get the needed buffer length (+1 for terminating NUL)
3096 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3098 // and now get the file name
3099 ::DragQueryFile(hFilesInfo
, wIndex
,
3100 files
[wIndex
].GetWriteBuf(len
), len
);
3102 files
[wIndex
].UngetWriteBuf();
3104 DragFinish (hFilesInfo
);
3106 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3107 event
.m_eventObject
= this;
3110 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3111 event
.m_pos
.x
= dropPoint
.x
;
3112 event
.m_pos
.y
= dropPoint
.y
;
3114 return GetEventHandler()->ProcessEvent(event
);
3115 #else // __WXMICROWIN__
3120 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3122 int WXUNUSED(mouseMsg
))
3124 #ifndef __WXMICROWIN__
3125 // the logic is as follows:
3126 // -1. don't set cursor for non client area, including but not limited to
3127 // the title bar, scrollbars, &c
3128 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3129 // 1. if we have the cursor set it unless wxIsBusy()
3130 // 2. if we're a top level window, set some cursor anyhow
3131 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3133 if ( nHitTest
!= HTCLIENT
)
3138 HCURSOR hcursor
= 0;
3140 // first ask the user code - it may wish to set the cursor in some very
3141 // specific way (for example, depending on the current position)
3144 if ( !::GetCursorPos(&pt
) )
3146 wxLogLastError(wxT("GetCursorPos"));
3149 // In WIN16 it doesn't return a value.
3150 ::GetCursorPos(&pt
);
3155 ScreenToClient(&x
, &y
);
3156 wxSetCursorEvent
event(x
, y
);
3158 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3159 if ( processedEvtSetCursor
&& event
.HasCursor() )
3161 hcursor
= GetHcursorOf(event
.GetCursor());
3166 bool isBusy
= wxIsBusy();
3168 // the test for processedEvtSetCursor is here to prevent using m_cursor
3169 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3170 // it - this is a way to say that our cursor shouldn't be used for this
3172 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3174 hcursor
= GetHcursorOf(m_cursor
);
3181 hcursor
= wxGetCurrentBusyCursor();
3183 else if ( !hcursor
)
3185 const wxCursor
*cursor
= wxGetGlobalCursor();
3186 if ( cursor
&& cursor
->Ok() )
3188 hcursor
= GetHcursorOf(*cursor
);
3196 ::SetCursor(hcursor
);
3198 // cursor set, stop here
3201 #endif // __WXMICROWIN__
3203 // pass up the window chain
3207 // ---------------------------------------------------------------------------
3208 // owner drawn stuff
3209 // ---------------------------------------------------------------------------
3211 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3213 #if wxUSE_OWNER_DRAWN
3215 #if wxUSE_MENUS_NATIVE
3216 // is it a menu item?
3217 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3218 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3220 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3222 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3224 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3225 // the DC from being released
3226 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3227 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3228 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3229 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3231 return pMenuItem
->OnDrawItem
3235 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3236 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3239 #endif // wxUSE_MENUS_NATIVE
3242 wxWindow
*item
= FindItem(id
);
3243 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3245 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3247 #endif // wxUSE_CONTROLS
3249 #endif // USE_OWNER_DRAWN
3254 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3256 #if wxUSE_OWNER_DRAWN
3257 // is it a menu item?
3258 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3259 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3261 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3263 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3265 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3266 &pMeasureStruct
->itemHeight
);
3269 wxWindow
*item
= FindItem(id
);
3270 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3272 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3274 #endif // owner-drawn menus
3278 // ---------------------------------------------------------------------------
3279 // colours and palettes
3280 // ---------------------------------------------------------------------------
3282 bool wxWindowMSW::HandleSysColorChange()
3284 wxSysColourChangedEvent event
;
3285 event
.SetEventObject(this);
3287 (void)GetEventHandler()->ProcessEvent(event
);
3289 // always let the system carry on the default processing to allow the
3290 // native controls to react to the colours update
3294 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3302 #ifndef __WXMICROWIN__
3303 WXHBRUSH hBrush
= 0;
3305 if ( nCtlColor
== CTLCOLOR_DLG
)
3307 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3312 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3314 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3316 #endif // wxUSE_CONTROLS
3322 #else // __WXMICROWIN__
3327 // Define for each class of dialog and control
3328 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3329 WXHWND
WXUNUSED(hWnd
),
3330 WXUINT
WXUNUSED(nCtlColor
),
3331 WXUINT
WXUNUSED(message
),
3332 WXWPARAM
WXUNUSED(wParam
),
3333 WXLPARAM
WXUNUSED(lParam
))
3338 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3340 wxPaletteChangedEvent
event(GetId());
3341 event
.SetEventObject(this);
3342 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3344 return GetEventHandler()->ProcessEvent(event
);
3347 bool wxWindowMSW::HandleQueryNewPalette()
3349 wxQueryNewPaletteEvent
event(GetId());
3350 event
.SetEventObject(this);
3352 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3355 // Responds to colour changes: passes event on to children.
3356 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3358 // the top level window also reset the standard colour map as it might have
3359 // changed (there is no need to do it for the non top level windows as we
3360 // only have to do it once)
3364 gs_hasStdCmap
= FALSE
;
3366 wxWindowList::Node
*node
= GetChildren().GetFirst();
3369 // Only propagate to non-top-level windows because Windows already
3370 // sends this event to all top-level ones
3371 wxWindow
*win
= node
->GetData();
3372 if ( !win
->IsTopLevel() )
3374 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3375 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3376 // the standard controls
3377 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3380 node
= node
->GetNext();
3383 // update the colours we use if they were not set explicitly by the user:
3384 // this must be done or OnCtlColor() would continue to use the old colours
3387 m_foregroundColour
= wxSystemSettings::
3388 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3393 m_backgroundColour
= wxSystemSettings::
3394 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3398 extern wxCOLORMAP
*wxGetStdColourMap()
3400 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3401 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3403 if ( !gs_hasStdCmap
)
3405 static bool s_coloursInit
= FALSE
;
3407 if ( !s_coloursInit
)
3409 // When a bitmap is loaded, the RGB values can change (apparently
3410 // because Windows adjusts them to care for the old programs always
3411 // using 0xc0c0c0 while the transparent colour for the new Windows
3412 // versions is different). But we do this adjustment ourselves so
3413 // we want to avoid Windows' "help" and for this we need to have a
3414 // reference bitmap which can tell us what the RGB values change
3416 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3417 if ( stdColourBitmap
.Ok() )
3419 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3420 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3421 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3424 memDC
.SelectObject(stdColourBitmap
);
3427 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3429 memDC
.GetPixel(i
, 0, &colour
);
3430 s_stdColours
[i
] = wxColourToRGB(colour
);
3433 else // wxBITMAP_STD_COLOURS couldn't be loaded
3435 s_stdColours
[0] = RGB(000,000,000); // black
3436 s_stdColours
[1] = RGB(128,128,128); // dark grey
3437 s_stdColours
[2] = RGB(192,192,192); // light grey
3438 s_stdColours
[3] = RGB(255,255,255); // white
3439 //s_stdColours[4] = RGB(000,000,255); // blue
3440 //s_stdColours[5] = RGB(255,000,255); // magenta
3443 s_coloursInit
= TRUE
;
3446 gs_hasStdCmap
= TRUE
;
3448 // create the colour map
3449 #define INIT_CMAP_ENTRY(col) \
3450 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3451 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3453 INIT_CMAP_ENTRY(BTNTEXT
);
3454 INIT_CMAP_ENTRY(BTNSHADOW
);
3455 INIT_CMAP_ENTRY(BTNFACE
);
3456 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3458 #undef INIT_CMAP_ENTRY
3464 // ---------------------------------------------------------------------------
3466 // ---------------------------------------------------------------------------
3468 bool wxWindowMSW::HandlePaint()
3471 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3473 wxLogLastError(wxT("CreateRectRgn"));
3474 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3475 wxLogLastError(wxT("GetUpdateRgn"));
3477 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3480 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3482 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3483 updateRect
.right
- updateRect
.left
,
3484 updateRect
.bottom
- updateRect
.top
);
3487 wxPaintEvent
event(m_windowId
);
3488 event
.SetEventObject(this);
3490 bool processed
= GetEventHandler()->ProcessEvent(event
);
3492 // note that we must generate NC event after the normal one as otherwise
3493 // BeginPaint() will happily overwrite our decorations with the background
3495 wxNcPaintEvent
eventNc(m_windowId
);
3496 eventNc
.SetEventObject(this);
3497 GetEventHandler()->ProcessEvent(eventNc
);
3502 // Can be called from an application's OnPaint handler
3503 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3505 #ifdef __WXUNIVERSAL__
3508 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3511 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3516 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3518 // Prevents flicker when dragging
3519 if ( ::IsIconic(GetHwnd()) )
3525 dc
.SetWindow((wxWindow
*)this);
3528 wxEraseEvent
event(m_windowId
, &dc
);
3529 event
.SetEventObject(this);
3530 bool rc
= GetEventHandler()->ProcessEvent(event
);
3534 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3535 dc
.SelectOldObjects(hdc
);
3540 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3543 ::GetClientRect(GetHwnd(), &rect
);
3545 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3546 m_backgroundColour
.Green(),
3547 m_backgroundColour
.Blue());
3548 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3550 wxLogLastError(wxT("CreateSolidBrush"));
3552 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3554 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3556 ::FillRect(hdc
, &rect
, hBrush
);
3557 ::DeleteObject(hBrush
);
3558 ::SetMapMode(hdc
, mode
);
3561 // ---------------------------------------------------------------------------
3562 // moving and resizing
3563 // ---------------------------------------------------------------------------
3565 bool wxWindowMSW::HandleMinimize()
3567 wxIconizeEvent
event(m_windowId
);
3568 event
.SetEventObject(this);
3570 return GetEventHandler()->ProcessEvent(event
);
3573 bool wxWindowMSW::HandleMaximize()
3575 wxMaximizeEvent
event(m_windowId
);
3576 event
.SetEventObject(this);
3578 return GetEventHandler()->ProcessEvent(event
);
3581 bool wxWindowMSW::HandleMove(int x
, int y
)
3583 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3584 event
.SetEventObject(this);
3586 return GetEventHandler()->ProcessEvent(event
);
3589 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3591 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3592 event
.SetEventObject(this);
3594 return GetEventHandler()->ProcessEvent(event
);
3597 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3599 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3603 if ( m_minWidth
!= -1 )
3605 info
->ptMinTrackSize
.x
= m_minWidth
;
3609 if ( m_minHeight
!= -1 )
3611 info
->ptMinTrackSize
.y
= m_minHeight
;
3615 if ( m_maxWidth
!= -1 )
3617 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3621 if ( m_maxHeight
!= -1 )
3623 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3630 // ---------------------------------------------------------------------------
3632 // ---------------------------------------------------------------------------
3634 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3636 #if wxUSE_MENUS_NATIVE
3637 if ( !cmd
&& wxCurrentPopupMenu
)
3639 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3640 wxCurrentPopupMenu
= NULL
;
3642 return popupMenu
->MSWCommand(cmd
, id
);
3644 #endif // wxUSE_MENUS_NATIVE
3646 wxWindow
*win
= NULL
;
3648 // first try to find it from HWND - this works even with the broken
3649 // programs using the same ids for different controls
3652 win
= wxFindWinFromHandle(control
);
3658 // must cast to a signed type before comparing with other ids!
3659 win
= FindItem((signed short)id
);
3664 return win
->MSWCommand(cmd
, id
);
3667 // the messages sent from the in-place edit control used by the treectrl
3668 // for label editing have id == 0, but they should _not_ be treated as menu
3669 // messages (they are EN_XXX ones, in fact) so don't translate anything
3670 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3673 // If no child window, it may be an accelerator, e.g. for a popup menu
3676 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3677 event
.SetEventObject(this);
3681 return GetEventHandler()->ProcessEvent(event
);
3683 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3686 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3687 // notifications to its parent which we want to reflect back to
3689 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3690 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3693 #endif // wxUSE_SPINCTRL
3698 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3700 // 4 bits are reserved
3701 switch ( wParam
& 0xFFFFFFF0 )
3704 return HandleMaximize();
3707 return HandleMinimize();
3713 // ---------------------------------------------------------------------------
3715 // ---------------------------------------------------------------------------
3717 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3721 // our client coords are not quite the same as Windows ones
3722 wxPoint pt
= GetClientAreaOrigin();
3723 event
.m_x
= x
- pt
.x
;
3724 event
.m_y
= y
- pt
.y
;
3726 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3727 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3728 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3729 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3730 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3731 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3733 event
.SetTimestamp(s_currentMsg
.time
);
3734 event
.m_eventObject
= this;
3736 #if wxUSE_MOUSEEVENT_HACK
3739 m_lastMouseEvent
= event
.GetEventType();
3740 #endif // wxUSE_MOUSEEVENT_HACK
3743 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3745 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3746 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3747 // from the message id and take the value in the table to get wxWin event
3749 static const wxEventType eventsMouse
[] =
3763 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3764 InitMouseEvent(event
, x
, y
, flags
);
3766 return GetEventHandler()->ProcessEvent(event
);
3769 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3771 if ( !m_mouseInWindow
)
3773 // it would be wrong to assume that just because we get a mouse move
3774 // event that the mouse is inside the window: although this is usually
3775 // true, it is not if we had captured the mouse, so we need to check
3776 // the mouse coordinates here
3777 if ( !HasCapture() || IsMouseInWindow() )
3779 // Generate an ENTER event
3780 m_mouseInWindow
= TRUE
;
3782 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3783 InitMouseEvent(event
, x
, y
, flags
);
3785 (void)GetEventHandler()->ProcessEvent(event
);
3789 #if wxUSE_MOUSEEVENT_HACK
3790 // Window gets a click down message followed by a mouse move message even
3791 // if position isn't changed! We want to discard the trailing move event
3792 // if x and y are the same.
3793 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3794 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3795 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3796 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3798 m_lastMouseEvent
= wxEVT_MOTION
;
3802 #endif // wxUSE_MOUSEEVENT_HACK
3804 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3808 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3810 #if wxUSE_MOUSEWHEEL
3811 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3812 InitMouseEvent(event
,
3813 GET_X_LPARAM(lParam
),
3814 GET_Y_LPARAM(lParam
),
3816 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3817 event
.m_wheelDelta
= WHEEL_DELTA
;
3820 static int s_linesPerRotation
= -1;
3821 if ( s_linesPerRotation
== -1 )
3823 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3824 &s_linesPerRotation
, 0))
3826 // this is not supposed to happen
3827 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3829 // the default is 3, so use it if SystemParametersInfo() failed
3830 s_linesPerRotation
= 3;
3834 // no SystemParametersInfo() under Win16
3835 static const int s_linesPerRotation
= 3;
3838 event
.m_linesPerAction
= s_linesPerRotation
;
3839 return GetEventHandler()->ProcessEvent(event
);
3850 // ---------------------------------------------------------------------------
3851 // keyboard handling
3852 // ---------------------------------------------------------------------------
3854 // create the key event of the given type for the given key - used by
3855 // HandleChar and HandleKeyDown/Up
3856 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3858 WXLPARAM lParam
) const
3860 wxKeyEvent
event(evType
);
3861 event
.SetId(GetId());
3862 event
.m_shiftDown
= wxIsShiftDown();
3863 event
.m_controlDown
= wxIsCtrlDown();
3864 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3866 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3867 event
.m_keyCode
= id
;
3868 event
.SetTimestamp(s_currentMsg
.time
);
3870 // translate the position to client coords
3874 GetWindowRect(GetHwnd(),&rect
);
3884 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3886 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3888 bool ctrlDown
= FALSE
;
3893 // If 1 -> 26, translate to CTRL plus a letter.
3895 if ( (id
> 0) && (id
< 27) )
3917 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3919 // it's ASCII and will be processed here only when called from
3920 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3926 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3929 event
.m_controlDown
= TRUE
;
3932 if ( GetEventHandler()->ProcessEvent(event
) )
3939 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3941 int id
= wxCharCodeMSWToWX(wParam
);
3945 // normal ASCII char
3949 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3951 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3952 if ( GetEventHandler()->ProcessEvent(event
) )
3961 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3963 int id
= wxCharCodeMSWToWX(wParam
);
3967 // normal ASCII char
3971 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3973 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3974 if ( GetEventHandler()->ProcessEvent(event
) )
3981 // ---------------------------------------------------------------------------
3983 // ---------------------------------------------------------------------------
3985 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3989 if ( flags
& JOY_BUTTON1CHG
)
3990 change
= wxJOY_BUTTON1
;
3991 if ( flags
& JOY_BUTTON2CHG
)
3992 change
= wxJOY_BUTTON2
;
3993 if ( flags
& JOY_BUTTON3CHG
)
3994 change
= wxJOY_BUTTON3
;
3995 if ( flags
& JOY_BUTTON4CHG
)
3996 change
= wxJOY_BUTTON4
;
3999 if ( flags
& JOY_BUTTON1
)
4000 buttons
|= wxJOY_BUTTON1
;
4001 if ( flags
& JOY_BUTTON2
)
4002 buttons
|= wxJOY_BUTTON2
;
4003 if ( flags
& JOY_BUTTON3
)
4004 buttons
|= wxJOY_BUTTON3
;
4005 if ( flags
& JOY_BUTTON4
)
4006 buttons
|= wxJOY_BUTTON4
;
4008 // the event ids aren't consecutive so we can't use table based lookup
4010 wxEventType eventType
;
4015 eventType
= wxEVT_JOY_MOVE
;
4020 eventType
= wxEVT_JOY_MOVE
;
4025 eventType
= wxEVT_JOY_ZMOVE
;
4030 eventType
= wxEVT_JOY_ZMOVE
;
4033 case MM_JOY1BUTTONDOWN
:
4035 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4038 case MM_JOY2BUTTONDOWN
:
4040 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4043 case MM_JOY1BUTTONUP
:
4045 eventType
= wxEVT_JOY_BUTTON_UP
;
4048 case MM_JOY2BUTTONUP
:
4050 eventType
= wxEVT_JOY_BUTTON_UP
;
4054 wxFAIL_MSG(wxT("no such joystick event"));
4059 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4060 event
.SetPosition(wxPoint(x
, y
));
4061 event
.SetEventObject(this);
4063 return GetEventHandler()->ProcessEvent(event
);
4069 // ---------------------------------------------------------------------------
4071 // ---------------------------------------------------------------------------
4073 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4074 WXWORD pos
, WXHWND control
)
4078 wxWindow
*child
= wxFindWinFromHandle(control
);
4080 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4083 wxScrollWinEvent event
;
4084 event
.SetPosition(pos
);
4085 event
.SetOrientation(orientation
);
4086 event
.m_eventObject
= this;
4091 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4095 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4099 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4103 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4107 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4111 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4114 case SB_THUMBPOSITION
:
4117 // under Win32, the scrollbar range and position are 32 bit integers,
4118 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4119 // explicitly query the scrollbar for the correct position (this must
4120 // be done only for these two SB_ events as they are the only one
4121 // carrying the scrollbar position)
4123 SCROLLINFO scrollInfo
;
4124 wxZeroMemory(scrollInfo
);
4125 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4126 scrollInfo
.fMask
= SIF_TRACKPOS
;
4128 if ( !::GetScrollInfo(GetHwnd(),
4129 orientation
== wxHORIZONTAL
? SB_HORZ
4133 wxLogLastError(_T("GetScrollInfo"));
4136 event
.SetPosition(scrollInfo
.nTrackPos
);
4140 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4141 ? wxEVT_SCROLLWIN_THUMBRELEASE
4142 : wxEVT_SCROLLWIN_THUMBTRACK
;
4149 return GetEventHandler()->ProcessEvent(event
);
4152 // ===========================================================================
4154 // ===========================================================================
4156 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4159 HDC dc
= ::GetDC((HWND
) wnd
);
4164 // the_font->UseResource();
4165 // the_font->RealizeResource();
4166 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4168 was
= (HFONT
) SelectObject(dc
,fnt
);
4170 GetTextMetrics(dc
, &tm
);
4171 if ( the_font
&& fnt
&& was
)
4173 SelectObject(dc
,was
);
4175 ReleaseDC((HWND
)wnd
, dc
);
4178 *x
= tm
.tmAveCharWidth
;
4180 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4183 // the_font->ReleaseResource();
4186 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4187 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4188 int wxCharCodeMSWToWX(int keySym
)
4193 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4194 case VK_BACK
: id
= WXK_BACK
; break;
4195 case VK_TAB
: id
= WXK_TAB
; break;
4196 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4197 case VK_RETURN
: id
= WXK_RETURN
; break;
4198 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4199 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4200 case VK_MENU
: id
= WXK_MENU
; break;
4201 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4202 case VK_SPACE
: id
= WXK_SPACE
; break;
4203 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4204 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4205 case VK_NEXT
: id
= WXK_NEXT
; break;
4206 case VK_END
: id
= WXK_END
; break;
4207 case VK_HOME
: id
= WXK_HOME
; break;
4208 case VK_LEFT
: id
= WXK_LEFT
; break;
4209 case VK_UP
: id
= WXK_UP
; break;
4210 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4211 case VK_DOWN
: id
= WXK_DOWN
; break;
4212 case VK_SELECT
: id
= WXK_SELECT
; break;
4213 case VK_PRINT
: id
= WXK_PRINT
; break;
4214 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4215 case VK_INSERT
: id
= WXK_INSERT
; break;
4216 case VK_DELETE
: id
= WXK_DELETE
; break;
4217 case VK_HELP
: id
= WXK_HELP
; break;
4218 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4219 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4220 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4221 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4222 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4223 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4224 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4225 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4226 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4227 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4228 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4229 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4230 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4231 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4232 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4233 case VK_F1
: id
= WXK_F1
; break;
4234 case VK_F2
: id
= WXK_F2
; break;
4235 case VK_F3
: id
= WXK_F3
; break;
4236 case VK_F4
: id
= WXK_F4
; break;
4237 case VK_F5
: id
= WXK_F5
; break;
4238 case VK_F6
: id
= WXK_F6
; break;
4239 case VK_F7
: id
= WXK_F7
; break;
4240 case VK_F8
: id
= WXK_F8
; break;
4241 case VK_F9
: id
= WXK_F9
; break;
4242 case VK_F10
: id
= WXK_F10
; break;
4243 case VK_F11
: id
= WXK_F11
; break;
4244 case VK_F12
: id
= WXK_F12
; break;
4245 case VK_F13
: id
= WXK_F13
; break;
4246 case VK_F14
: id
= WXK_F14
; break;
4247 case VK_F15
: id
= WXK_F15
; break;
4248 case VK_F16
: id
= WXK_F16
; break;
4249 case VK_F17
: id
= WXK_F17
; break;
4250 case VK_F18
: id
= WXK_F18
; break;
4251 case VK_F19
: id
= WXK_F19
; break;
4252 case VK_F20
: id
= WXK_F20
; break;
4253 case VK_F21
: id
= WXK_F21
; break;
4254 case VK_F22
: id
= WXK_F22
; break;
4255 case VK_F23
: id
= WXK_F23
; break;
4256 case VK_F24
: id
= WXK_F24
; break;
4257 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4258 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4266 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4272 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4273 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4274 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4275 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4276 case WXK_MENU
: keySym
= VK_MENU
; break;
4277 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4278 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4279 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4280 case WXK_END
: keySym
= VK_END
; break;
4281 case WXK_HOME
: keySym
= VK_HOME
; break;
4282 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4283 case WXK_UP
: keySym
= VK_UP
; break;
4284 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4285 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4286 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4287 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4288 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4289 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4290 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4291 case WXK_HELP
: keySym
= VK_HELP
; break;
4292 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4293 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4294 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4295 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4296 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4297 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4298 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4299 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4300 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4301 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4302 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4303 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4304 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4305 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4306 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4307 case WXK_F1
: keySym
= VK_F1
; break;
4308 case WXK_F2
: keySym
= VK_F2
; break;
4309 case WXK_F3
: keySym
= VK_F3
; break;
4310 case WXK_F4
: keySym
= VK_F4
; break;
4311 case WXK_F5
: keySym
= VK_F5
; break;
4312 case WXK_F6
: keySym
= VK_F6
; break;
4313 case WXK_F7
: keySym
= VK_F7
; break;
4314 case WXK_F8
: keySym
= VK_F8
; break;
4315 case WXK_F9
: keySym
= VK_F9
; break;
4316 case WXK_F10
: keySym
= VK_F10
; break;
4317 case WXK_F11
: keySym
= VK_F11
; break;
4318 case WXK_F12
: keySym
= VK_F12
; break;
4319 case WXK_F13
: keySym
= VK_F13
; break;
4320 case WXK_F14
: keySym
= VK_F14
; break;
4321 case WXK_F15
: keySym
= VK_F15
; break;
4322 case WXK_F16
: keySym
= VK_F16
; break;
4323 case WXK_F17
: keySym
= VK_F17
; break;
4324 case WXK_F18
: keySym
= VK_F18
; break;
4325 case WXK_F19
: keySym
= VK_F19
; break;
4326 case WXK_F20
: keySym
= VK_F20
; break;
4327 case WXK_F21
: keySym
= VK_F21
; break;
4328 case WXK_F22
: keySym
= VK_F22
; break;
4329 case WXK_F23
: keySym
= VK_F23
; break;
4330 case WXK_F24
: keySym
= VK_F24
; break;
4331 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4332 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4343 wxWindow
*wxGetActiveWindow()
4345 HWND hWnd
= GetActiveWindow();
4348 return wxFindWinFromHandle((WXHWND
) hWnd
);
4353 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4355 HWND hwnd
= (HWND
)hWnd
;
4357 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4358 // by code in msw/radiobox.cpp), for all the others we just search up the
4360 wxWindow
*win
= (wxWindow
*)NULL
;
4363 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4366 // all these hacks only work under Win32 anyhow
4370 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4371 // wxWindow class which overrides WM_GETDLGCODE processing to
4372 // do it as well, win would be already non NULL
4373 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4375 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4377 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4378 #endif // wxUSE_RADIOBOX
4380 // spin control text buddy window should be mapped to spin ctrl
4381 // itself so try it too
4382 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4385 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4387 #endif // wxUSE_SPINCTRL
4393 while ( hwnd
&& !win
)
4395 // this is a really ugly hack needed to avoid mistakenly returning the
4396 // parent frame wxWindow for the find/replace modeless dialog HWND -
4397 // this, in turn, is needed to call IsDialogMessage() from
4398 // wxApp::ProcessMessage() as for this we must return NULL from here
4400 // FIXME: this is clearly not the best way to do it but I think we'll
4401 // need to change HWND <-> wxWindow code more heavily than I can
4402 // do it now to fix it
4403 #ifndef __WXMICROWIN__
4404 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4406 // it's a dialog box, don't go upwards
4411 hwnd
= ::GetParent(hwnd
);
4412 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4418 #ifndef __WXMICROWIN__
4420 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4421 // in active frames and dialogs, regardless of where the focus is.
4422 static HHOOK wxTheKeyboardHook
= 0;
4423 static FARPROC wxTheKeyboardHookProc
= 0;
4424 int APIENTRY _EXPORT
4425 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4427 void wxSetKeyboardHook(bool doIt
)
4431 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4432 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4434 #if defined(__WIN32__) && !defined(__TWIN32__)
4435 GetCurrentThreadId()
4436 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4444 UnhookWindowsHookEx(wxTheKeyboardHook
);
4446 // avoids warning about statement with no effect (FreeProcInstance
4447 // doesn't do anything under Win32)
4448 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4449 FreeProcInstance(wxTheKeyboardHookProc
);
4454 int APIENTRY _EXPORT
4455 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4457 DWORD hiWord
= HIWORD(lParam
);
4458 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4460 int id
= wxCharCodeMSWToWX(wParam
);
4463 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4464 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4465 event
.m_altDown
= TRUE
;
4467 event
.m_eventObject
= NULL
;
4468 event
.m_keyCode
= id
;
4469 event
.m_shiftDown
= wxIsShiftDown();
4470 event
.m_controlDown
= wxIsCtrlDown();
4471 event
.SetTimestamp(s_currentMsg
.time
);
4473 wxWindow
*win
= wxGetActiveWindow();
4474 wxEvtHandler
*handler
;
4477 handler
= win
->GetEventHandler();
4478 event
.SetId(win
->GetId());
4486 if ( handler
&& handler
->ProcessEvent(event
) )
4494 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4497 #endif // !__WXMICROWIN__
4500 const char *wxGetMessageName(int message
)
4504 case 0x0000: return "WM_NULL";
4505 case 0x0001: return "WM_CREATE";
4506 case 0x0002: return "WM_DESTROY";
4507 case 0x0003: return "WM_MOVE";
4508 case 0x0005: return "WM_SIZE";
4509 case 0x0006: return "WM_ACTIVATE";
4510 case 0x0007: return "WM_SETFOCUS";
4511 case 0x0008: return "WM_KILLFOCUS";
4512 case 0x000A: return "WM_ENABLE";
4513 case 0x000B: return "WM_SETREDRAW";
4514 case 0x000C: return "WM_SETTEXT";
4515 case 0x000D: return "WM_GETTEXT";
4516 case 0x000E: return "WM_GETTEXTLENGTH";
4517 case 0x000F: return "WM_PAINT";
4518 case 0x0010: return "WM_CLOSE";
4519 case 0x0011: return "WM_QUERYENDSESSION";
4520 case 0x0012: return "WM_QUIT";
4521 case 0x0013: return "WM_QUERYOPEN";
4522 case 0x0014: return "WM_ERASEBKGND";
4523 case 0x0015: return "WM_SYSCOLORCHANGE";
4524 case 0x0016: return "WM_ENDSESSION";
4525 case 0x0017: return "WM_SYSTEMERROR";
4526 case 0x0018: return "WM_SHOWWINDOW";
4527 case 0x0019: return "WM_CTLCOLOR";
4528 case 0x001A: return "WM_WININICHANGE";
4529 case 0x001B: return "WM_DEVMODECHANGE";
4530 case 0x001C: return "WM_ACTIVATEAPP";
4531 case 0x001D: return "WM_FONTCHANGE";
4532 case 0x001E: return "WM_TIMECHANGE";
4533 case 0x001F: return "WM_CANCELMODE";
4534 case 0x0020: return "WM_SETCURSOR";
4535 case 0x0021: return "WM_MOUSEACTIVATE";
4536 case 0x0022: return "WM_CHILDACTIVATE";
4537 case 0x0023: return "WM_QUEUESYNC";
4538 case 0x0024: return "WM_GETMINMAXINFO";
4539 case 0x0026: return "WM_PAINTICON";
4540 case 0x0027: return "WM_ICONERASEBKGND";
4541 case 0x0028: return "WM_NEXTDLGCTL";
4542 case 0x002A: return "WM_SPOOLERSTATUS";
4543 case 0x002B: return "WM_DRAWITEM";
4544 case 0x002C: return "WM_MEASUREITEM";
4545 case 0x002D: return "WM_DELETEITEM";
4546 case 0x002E: return "WM_VKEYTOITEM";
4547 case 0x002F: return "WM_CHARTOITEM";
4548 case 0x0030: return "WM_SETFONT";
4549 case 0x0031: return "WM_GETFONT";
4550 case 0x0037: return "WM_QUERYDRAGICON";
4551 case 0x0039: return "WM_COMPAREITEM";
4552 case 0x0041: return "WM_COMPACTING";
4553 case 0x0044: return "WM_COMMNOTIFY";
4554 case 0x0046: return "WM_WINDOWPOSCHANGING";
4555 case 0x0047: return "WM_WINDOWPOSCHANGED";
4556 case 0x0048: return "WM_POWER";
4559 case 0x004A: return "WM_COPYDATA";
4560 case 0x004B: return "WM_CANCELJOURNAL";
4561 case 0x004E: return "WM_NOTIFY";
4562 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4563 case 0x0051: return "WM_INPUTLANGCHANGE";
4564 case 0x0052: return "WM_TCARD";
4565 case 0x0053: return "WM_HELP";
4566 case 0x0054: return "WM_USERCHANGED";
4567 case 0x0055: return "WM_NOTIFYFORMAT";
4568 case 0x007B: return "WM_CONTEXTMENU";
4569 case 0x007C: return "WM_STYLECHANGING";
4570 case 0x007D: return "WM_STYLECHANGED";
4571 case 0x007E: return "WM_DISPLAYCHANGE";
4572 case 0x007F: return "WM_GETICON";
4573 case 0x0080: return "WM_SETICON";
4576 case 0x0081: return "WM_NCCREATE";
4577 case 0x0082: return "WM_NCDESTROY";
4578 case 0x0083: return "WM_NCCALCSIZE";
4579 case 0x0084: return "WM_NCHITTEST";
4580 case 0x0085: return "WM_NCPAINT";
4581 case 0x0086: return "WM_NCACTIVATE";
4582 case 0x0087: return "WM_GETDLGCODE";
4583 case 0x00A0: return "WM_NCMOUSEMOVE";
4584 case 0x00A1: return "WM_NCLBUTTONDOWN";
4585 case 0x00A2: return "WM_NCLBUTTONUP";
4586 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4587 case 0x00A4: return "WM_NCRBUTTONDOWN";
4588 case 0x00A5: return "WM_NCRBUTTONUP";
4589 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4590 case 0x00A7: return "WM_NCMBUTTONDOWN";
4591 case 0x00A8: return "WM_NCMBUTTONUP";
4592 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4593 case 0x0100: return "WM_KEYDOWN";
4594 case 0x0101: return "WM_KEYUP";
4595 case 0x0102: return "WM_CHAR";
4596 case 0x0103: return "WM_DEADCHAR";
4597 case 0x0104: return "WM_SYSKEYDOWN";
4598 case 0x0105: return "WM_SYSKEYUP";
4599 case 0x0106: return "WM_SYSCHAR";
4600 case 0x0107: return "WM_SYSDEADCHAR";
4601 case 0x0108: return "WM_KEYLAST";
4604 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4605 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4606 case 0x010F: return "WM_IME_COMPOSITION";
4609 case 0x0110: return "WM_INITDIALOG";
4610 case 0x0111: return "WM_COMMAND";
4611 case 0x0112: return "WM_SYSCOMMAND";
4612 case 0x0113: return "WM_TIMER";
4613 case 0x0114: return "WM_HSCROLL";
4614 case 0x0115: return "WM_VSCROLL";
4615 case 0x0116: return "WM_INITMENU";
4616 case 0x0117: return "WM_INITMENUPOPUP";
4617 case 0x011F: return "WM_MENUSELECT";
4618 case 0x0120: return "WM_MENUCHAR";
4619 case 0x0121: return "WM_ENTERIDLE";
4620 case 0x0200: return "WM_MOUSEMOVE";
4621 case 0x0201: return "WM_LBUTTONDOWN";
4622 case 0x0202: return "WM_LBUTTONUP";
4623 case 0x0203: return "WM_LBUTTONDBLCLK";
4624 case 0x0204: return "WM_RBUTTONDOWN";
4625 case 0x0205: return "WM_RBUTTONUP";
4626 case 0x0206: return "WM_RBUTTONDBLCLK";
4627 case 0x0207: return "WM_MBUTTONDOWN";
4628 case 0x0208: return "WM_MBUTTONUP";
4629 case 0x0209: return "WM_MBUTTONDBLCLK";
4630 case 0x020A: return "WM_MOUSEWHEEL";
4631 case 0x0210: return "WM_PARENTNOTIFY";
4632 case 0x0211: return "WM_ENTERMENULOOP";
4633 case 0x0212: return "WM_EXITMENULOOP";
4636 case 0x0213: return "WM_NEXTMENU";
4637 case 0x0214: return "WM_SIZING";
4638 case 0x0215: return "WM_CAPTURECHANGED";
4639 case 0x0216: return "WM_MOVING";
4640 case 0x0218: return "WM_POWERBROADCAST";
4641 case 0x0219: return "WM_DEVICECHANGE";
4644 case 0x0220: return "WM_MDICREATE";
4645 case 0x0221: return "WM_MDIDESTROY";
4646 case 0x0222: return "WM_MDIACTIVATE";
4647 case 0x0223: return "WM_MDIRESTORE";
4648 case 0x0224: return "WM_MDINEXT";
4649 case 0x0225: return "WM_MDIMAXIMIZE";
4650 case 0x0226: return "WM_MDITILE";
4651 case 0x0227: return "WM_MDICASCADE";
4652 case 0x0228: return "WM_MDIICONARRANGE";
4653 case 0x0229: return "WM_MDIGETACTIVE";
4654 case 0x0230: return "WM_MDISETMENU";
4655 case 0x0233: return "WM_DROPFILES";
4658 case 0x0281: return "WM_IME_SETCONTEXT";
4659 case 0x0282: return "WM_IME_NOTIFY";
4660 case 0x0283: return "WM_IME_CONTROL";
4661 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4662 case 0x0285: return "WM_IME_SELECT";
4663 case 0x0286: return "WM_IME_CHAR";
4664 case 0x0290: return "WM_IME_KEYDOWN";
4665 case 0x0291: return "WM_IME_KEYUP";
4668 case 0x0300: return "WM_CUT";
4669 case 0x0301: return "WM_COPY";
4670 case 0x0302: return "WM_PASTE";
4671 case 0x0303: return "WM_CLEAR";
4672 case 0x0304: return "WM_UNDO";
4673 case 0x0305: return "WM_RENDERFORMAT";
4674 case 0x0306: return "WM_RENDERALLFORMATS";
4675 case 0x0307: return "WM_DESTROYCLIPBOARD";
4676 case 0x0308: return "WM_DRAWCLIPBOARD";
4677 case 0x0309: return "WM_PAINTCLIPBOARD";
4678 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4679 case 0x030B: return "WM_SIZECLIPBOARD";
4680 case 0x030C: return "WM_ASKCBFORMATNAME";
4681 case 0x030D: return "WM_CHANGECBCHAIN";
4682 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4683 case 0x030F: return "WM_QUERYNEWPALETTE";
4684 case 0x0310: return "WM_PALETTEISCHANGING";
4685 case 0x0311: return "WM_PALETTECHANGED";
4688 // common controls messages - although they're not strictly speaking
4689 // standard, it's nice to decode them nevertheless
4692 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4693 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4694 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4695 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4696 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4697 case 0x1000 + 5: return "LVM_GETITEMA";
4698 case 0x1000 + 75: return "LVM_GETITEMW";
4699 case 0x1000 + 6: return "LVM_SETITEMA";
4700 case 0x1000 + 76: return "LVM_SETITEMW";
4701 case 0x1000 + 7: return "LVM_INSERTITEMA";
4702 case 0x1000 + 77: return "LVM_INSERTITEMW";
4703 case 0x1000 + 8: return "LVM_DELETEITEM";
4704 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4705 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4706 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4707 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4708 case 0x1000 + 13: return "LVM_FINDITEMA";
4709 case 0x1000 + 83: return "LVM_FINDITEMW";
4710 case 0x1000 + 14: return "LVM_GETITEMRECT";
4711 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4712 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4713 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4714 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4715 case 0x1000 + 18: return "LVM_HITTEST";
4716 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4717 case 0x1000 + 20: return "LVM_SCROLL";
4718 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4719 case 0x1000 + 22: return "LVM_ARRANGE";
4720 case 0x1000 + 23: return "LVM_EDITLABELA";
4721 case 0x1000 + 118: return "LVM_EDITLABELW";
4722 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4723 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4724 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4725 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4726 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4727 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4728 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4729 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4730 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4731 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4732 case 0x1000 + 31: return "LVM_GETHEADER";
4733 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4734 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4735 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4736 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4737 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4738 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4739 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4740 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4741 case 0x1000 + 41: return "LVM_GETORIGIN";
4742 case 0x1000 + 42: return "LVM_UPDATE";
4743 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4744 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4745 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4746 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4747 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4748 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4749 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4750 case 0x1000 + 48: return "LVM_SORTITEMS";
4751 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4752 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4753 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4754 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4755 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4756 case 0x1000 + 53: return "LVM_SETICONSPACING";
4757 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4758 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4759 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4760 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4761 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4762 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4763 case 0x1000 + 60: return "LVM_SETHOTITEM";
4764 case 0x1000 + 61: return "LVM_GETHOTITEM";
4765 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4766 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4767 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4768 case 0x1000 + 65: return "LVM_SETWORKAREA";
4771 case 0x1100 + 0: return "TVM_INSERTITEMA";
4772 case 0x1100 + 50: return "TVM_INSERTITEMW";
4773 case 0x1100 + 1: return "TVM_DELETEITEM";
4774 case 0x1100 + 2: return "TVM_EXPAND";
4775 case 0x1100 + 4: return "TVM_GETITEMRECT";
4776 case 0x1100 + 5: return "TVM_GETCOUNT";
4777 case 0x1100 + 6: return "TVM_GETINDENT";
4778 case 0x1100 + 7: return "TVM_SETINDENT";
4779 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4780 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4781 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4782 case 0x1100 + 11: return "TVM_SELECTITEM";
4783 case 0x1100 + 12: return "TVM_GETITEMA";
4784 case 0x1100 + 62: return "TVM_GETITEMW";
4785 case 0x1100 + 13: return "TVM_SETITEMA";
4786 case 0x1100 + 63: return "TVM_SETITEMW";
4787 case 0x1100 + 14: return "TVM_EDITLABELA";
4788 case 0x1100 + 65: return "TVM_EDITLABELW";
4789 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4790 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4791 case 0x1100 + 17: return "TVM_HITTEST";
4792 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4793 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4794 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4795 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4796 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4797 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4798 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4799 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4800 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4803 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4804 case 0x1200 + 1: return "HDM_INSERTITEMA";
4805 case 0x1200 + 10: return "HDM_INSERTITEMW";
4806 case 0x1200 + 2: return "HDM_DELETEITEM";
4807 case 0x1200 + 3: return "HDM_GETITEMA";
4808 case 0x1200 + 11: return "HDM_GETITEMW";
4809 case 0x1200 + 4: return "HDM_SETITEMA";
4810 case 0x1200 + 12: return "HDM_SETITEMW";
4811 case 0x1200 + 5: return "HDM_LAYOUT";
4812 case 0x1200 + 6: return "HDM_HITTEST";
4813 case 0x1200 + 7: return "HDM_GETITEMRECT";
4814 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4815 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4816 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4817 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4818 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4819 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4820 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4823 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4824 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4825 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4826 case 0x1300 + 5: return "TCM_GETITEMA";
4827 case 0x1300 + 60: return "TCM_GETITEMW";
4828 case 0x1300 + 6: return "TCM_SETITEMA";
4829 case 0x1300 + 61: return "TCM_SETITEMW";
4830 case 0x1300 + 7: return "TCM_INSERTITEMA";
4831 case 0x1300 + 62: return "TCM_INSERTITEMW";
4832 case 0x1300 + 8: return "TCM_DELETEITEM";
4833 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4834 case 0x1300 + 10: return "TCM_GETITEMRECT";
4835 case 0x1300 + 11: return "TCM_GETCURSEL";
4836 case 0x1300 + 12: return "TCM_SETCURSEL";
4837 case 0x1300 + 13: return "TCM_HITTEST";
4838 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4839 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4840 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4841 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4842 case 0x1300 + 43: return "TCM_SETPADDING";
4843 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4844 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4845 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4846 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4847 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4848 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4849 case 0x1300 + 50: return "TCM_DESELECTALL";
4852 case WM_USER
+1: return "TB_ENABLEBUTTON";
4853 case WM_USER
+2: return "TB_CHECKBUTTON";
4854 case WM_USER
+3: return "TB_PRESSBUTTON";
4855 case WM_USER
+4: return "TB_HIDEBUTTON";
4856 case WM_USER
+5: return "TB_INDETERMINATE";
4857 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4858 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4859 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4860 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4861 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4862 case WM_USER
+17: return "TB_SETSTATE";
4863 case WM_USER
+18: return "TB_GETSTATE";
4864 case WM_USER
+19: return "TB_ADDBITMAP";
4865 case WM_USER
+20: return "TB_ADDBUTTONS";
4866 case WM_USER
+21: return "TB_INSERTBUTTON";
4867 case WM_USER
+22: return "TB_DELETEBUTTON";
4868 case WM_USER
+23: return "TB_GETBUTTON";
4869 case WM_USER
+24: return "TB_BUTTONCOUNT";
4870 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4871 case WM_USER
+26: return "TB_SAVERESTOREA";
4872 case WM_USER
+76: return "TB_SAVERESTOREW";
4873 case WM_USER
+27: return "TB_CUSTOMIZE";
4874 case WM_USER
+28: return "TB_ADDSTRINGA";
4875 case WM_USER
+77: return "TB_ADDSTRINGW";
4876 case WM_USER
+29: return "TB_GETITEMRECT";
4877 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4878 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4879 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4880 case WM_USER
+33: return "TB_AUTOSIZE";
4881 case WM_USER
+35: return "TB_GETTOOLTIPS";
4882 case WM_USER
+36: return "TB_SETTOOLTIPS";
4883 case WM_USER
+37: return "TB_SETPARENT";
4884 case WM_USER
+39: return "TB_SETROWS";
4885 case WM_USER
+40: return "TB_GETROWS";
4886 case WM_USER
+42: return "TB_SETCMDID";
4887 case WM_USER
+43: return "TB_CHANGEBITMAP";
4888 case WM_USER
+44: return "TB_GETBITMAP";
4889 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4890 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4891 case WM_USER
+46: return "TB_REPLACEBITMAP";
4892 case WM_USER
+47: return "TB_SETINDENT";
4893 case WM_USER
+48: return "TB_SETIMAGELIST";
4894 case WM_USER
+49: return "TB_GETIMAGELIST";
4895 case WM_USER
+50: return "TB_LOADIMAGES";
4896 case WM_USER
+51: return "TB_GETRECT";
4897 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4898 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4899 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4900 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4901 case WM_USER
+56: return "TB_SETSTYLE";
4902 case WM_USER
+57: return "TB_GETSTYLE";
4903 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4904 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4905 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4906 case WM_USER
+61: return "TB_GETTEXTROWS";
4907 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4912 static char s_szBuf
[128];
4913 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4917 #endif //__WXDEBUG__
4919 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4920 int *x
, int *y
, WPARAM
*flags
)
4922 // construct the key mask
4923 WPARAM
& fwKeys
= *flags
;
4925 fwKeys
= MK_RBUTTON
;
4926 if ( wxIsCtrlDown() )
4927 fwKeys
|= MK_CONTROL
;
4928 if ( wxIsShiftDown() )
4931 // simulate right mouse button click
4932 DWORD dwPos
= ::GetMessagePos();
4933 *x
= GET_X_LPARAM(dwPos
);
4934 *y
= GET_Y_LPARAM(dwPos
);
4936 win
->ScreenToClient(x
, y
);
4939 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4943 HWND hwnd
= GetHwndOf(win
);
4944 HDC hdc
= ::GetDC(hwnd
);
4946 #if !wxDIALOG_UNIT_COMPATIBILITY
4947 // and select the current font into it
4948 HFONT hfont
= GetHfontOf(win
->GetFont());
4951 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4955 // finally retrieve the text metrics from it
4956 GetTextMetrics(hdc
, &tm
);
4958 #if !wxDIALOG_UNIT_COMPATIBILITY
4962 (void)::SelectObject(hdc
, hfont
);
4966 ::ReleaseDC(hwnd
, hdc
);
4971 // Find the wxWindow at the current mouse position, returning the mouse
4973 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4975 return wxFindWindowAtPoint(wxGetMousePosition());
4978 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4983 HWND hWndHit
= ::WindowFromPoint(pt2
);
4985 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4986 HWND hWnd
= hWndHit
;
4988 // Try to find a window with a wxWindow associated with it
4989 while (!win
&& (hWnd
!= 0))
4991 hWnd
= ::GetParent(hWnd
);
4992 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
4997 // Get the current mouse position.
4998 wxPoint
wxGetMousePosition()
5001 GetCursorPos( & pt
);
5002 return wxPoint(pt
.x
, pt
.y
);