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() && HasCapture())
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
|| width
== -1) &&
1547 (rectClient
.bottom
== height
|| height
== -1) )
1554 // how did it happen? maybe OnSize() handler does something really
1555 // strange in this class?
1556 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1561 int widthClient
= width
,
1562 heightClient
= height
;
1564 // Find the difference between the entire window (title bar and all)
1565 // and the client area; add this to the new client size to move the
1568 ::GetWindowRect(GetHwnd(), &rectWin
);
1570 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1571 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1574 point
.x
= rectWin
.left
;
1575 point
.y
= rectWin
.top
;
1577 // MoveWindow positions the child windows relative to the parent, so
1578 // adjust if necessary
1579 if ( !IsTopLevel() )
1581 wxWindow
*parent
= GetParent();
1584 ::ScreenToClient(GetHwndOf(parent
), &point
);
1588 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1592 // For implementation purposes - sometimes decorations make the client area
1594 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1596 return wxPoint(0, 0);
1599 // ---------------------------------------------------------------------------
1601 // ---------------------------------------------------------------------------
1603 int wxWindowMSW::GetCharHeight() const
1605 return wxGetTextMetrics(this).tmHeight
;
1608 int wxWindowMSW::GetCharWidth() const
1610 // +1 is needed because Windows apparently adds it when calculating the
1611 // dialog units size in pixels
1612 #if wxDIALOG_UNIT_COMPATIBILITY
1613 return wxGetTextMetrics(this).tmAveCharWidth
;
1615 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1619 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1621 int *descent
, int *externalLeading
,
1622 const wxFont
*theFont
) const
1624 const wxFont
*fontToUse
= theFont
;
1626 fontToUse
= &m_font
;
1628 HWND hWnd
= GetHwnd();
1629 HDC dc
= ::GetDC(hWnd
);
1633 if ( fontToUse
&& fontToUse
->Ok() )
1635 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1637 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1642 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1643 GetTextMetrics(dc
, &tm
);
1645 if ( fontToUse
&& fnt
&& hfontOld
)
1646 SelectObject(dc
, hfontOld
);
1648 ReleaseDC(hWnd
, dc
);
1655 *descent
= tm
.tmDescent
;
1656 if ( externalLeading
)
1657 *externalLeading
= tm
.tmExternalLeading
;
1660 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1661 // ---------------------------------------------------------------------------
1662 // Caret manipulation
1663 // ---------------------------------------------------------------------------
1665 void wxWindowMSW::CreateCaret(int w
, int h
)
1667 SetCaret(new wxCaret(this, w
, h
));
1670 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1672 wxFAIL_MSG("not implemented");
1675 void wxWindowMSW::ShowCaret(bool show
)
1677 wxCHECK_RET( m_caret
, "no caret to show" );
1679 m_caret
->Show(show
);
1682 void wxWindowMSW::DestroyCaret()
1687 void wxWindowMSW::SetCaretPos(int x
, int y
)
1689 wxCHECK_RET( m_caret
, "no caret to move" );
1691 m_caret
->Move(x
, y
);
1694 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1696 wxCHECK_RET( m_caret
, "no caret to get position of" );
1698 m_caret
->GetPosition(x
, y
);
1700 #endif // wxUSE_CARET
1702 // ---------------------------------------------------------------------------
1704 // ---------------------------------------------------------------------------
1706 #if wxUSE_MENUS_NATIVE
1708 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1709 // immediately, without waiting for the next event loop iteration
1711 // NB: this function should probably be made public later as it can almost
1712 // surely replace wxYield() elsewhere as well
1713 static void wxYieldForCommandsOnly()
1715 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1716 // want to process it here)
1718 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1719 && msg
.message
!= WM_QUIT
)
1721 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1725 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1727 menu
->SetInvokingWindow(this);
1730 HWND hWnd
= GetHwnd();
1731 HMENU hMenu
= GetHmenuOf(menu
);
1735 ::ClientToScreen(hWnd
, &point
);
1736 wxCurrentPopupMenu
= menu
;
1737 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1739 // we need to do it righ now as otherwise the events are never going to be
1740 // sent to wxCurrentPopupMenu from HandleCommand()
1742 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1743 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1744 // destroyed as soon as we return (it can be a local variable in the caller
1745 // for example) and so we do need to process the event immediately
1746 wxYieldForCommandsOnly();
1748 wxCurrentPopupMenu
= NULL
;
1750 menu
->SetInvokingWindow(NULL
);
1755 #endif // wxUSE_MENUS_NATIVE
1757 // ===========================================================================
1758 // pre/post message processing
1759 // ===========================================================================
1761 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1764 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1766 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1769 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1771 // wxUniversal implements tab traversal itself
1772 #ifndef __WXUNIVERSAL__
1773 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1775 // intercept dialog navigation keys
1776 MSG
*msg
= (MSG
*)pMsg
;
1778 // here we try to do all the job which ::IsDialogMessage() usually does
1781 bool bProcess
= TRUE
;
1782 if ( msg
->message
!= WM_KEYDOWN
)
1785 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1790 bool bCtrlDown
= wxIsCtrlDown();
1791 bool bShiftDown
= wxIsShiftDown();
1793 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1794 // don't process it if it's the case (except for Ctrl-Tab/Enter
1795 // combinations which are always processed)
1799 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1802 bool bForward
= TRUE
,
1803 bWindowChange
= FALSE
;
1805 switch ( msg
->wParam
)
1808 // assume that nobody wants Shift-TAB for himself - if we
1809 // don't do it there is no easy way for a control to grab
1810 // TABs but still let Shift-TAB work as navugation key
1811 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1815 // Ctrl-Tab cycles thru notebook pages
1816 bWindowChange
= bCtrlDown
;
1817 bForward
= !bShiftDown
;
1823 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1831 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1837 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1839 // control wants to process Enter itself, don't
1840 // call IsDialogMessage() which would interpret
1844 else if ( lDlgCode
& DLGC_BUTTON
)
1846 // let IsDialogMessage() handle this for all
1847 // buttons except the owner-drawn ones which it
1848 // just seems to ignore
1849 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1850 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1852 // emulate the button click
1853 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1855 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1860 // FIXME: this should be handled by
1861 // wxNavigationKeyEvent handler and not here!!
1865 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1867 if ( btn
&& btn
->IsEnabled() )
1869 // if we do have a default button, do press it
1870 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1874 else // no default button
1875 #endif // wxUSE_BUTTON
1877 // no special function for enter and don't even
1878 // let IsDialogMessage() have it: it seems to
1879 // do something really strange with it
1892 wxNavigationKeyEvent event
;
1893 event
.SetDirection(bForward
);
1894 event
.SetWindowChange(bWindowChange
);
1895 event
.SetEventObject(this);
1897 if ( GetEventHandler()->ProcessEvent(event
) )
1904 // let ::IsDialogMessage() do almost everything and handle just the
1905 // things it doesn't here: Ctrl-TAB for switching notebook pages
1906 if ( msg
->message
== WM_KEYDOWN
)
1908 // don't process system keys here
1909 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1911 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1913 // find the first notebook parent and change its page
1914 wxWindow
*win
= this;
1915 wxNotebook
*nbook
= NULL
;
1916 while ( win
&& !nbook
)
1918 nbook
= wxDynamicCast(win
, wxNotebook
);
1919 win
= win
->GetParent();
1924 bool forward
= !wxIsShiftDown();
1926 nbook
->AdvanceSelection(forward
);
1933 if ( ::IsDialogMessage(GetHwnd(), msg
) )
1935 // IsDialogMessage() did something...
1939 #endif // __WXUNIVERSAL__
1944 // relay mouse move events to the tooltip control
1945 MSG
*msg
= (MSG
*)pMsg
;
1946 if ( msg
->message
== WM_MOUSEMOVE
)
1947 m_tooltip
->RelayEvent(pMsg
);
1949 #endif // wxUSE_TOOLTIPS
1954 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1956 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
1957 return m_acceleratorTable
.Translate(this, pMsg
);
1960 #endif // wxUSE_ACCEL
1963 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* pMsg
)
1965 // preprocess all messages by default
1969 // ---------------------------------------------------------------------------
1970 // message params unpackers (different for Win16 and Win32)
1971 // ---------------------------------------------------------------------------
1975 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
1976 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
1978 *id
= LOWORD(wParam
);
1979 *hwnd
= (WXHWND
)lParam
;
1980 *cmd
= HIWORD(wParam
);
1983 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
1984 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
1986 *state
= LOWORD(wParam
);
1987 *minimized
= HIWORD(wParam
);
1988 *hwnd
= (WXHWND
)lParam
;
1991 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
1992 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
1994 *code
= LOWORD(wParam
);
1995 *pos
= HIWORD(wParam
);
1996 *hwnd
= (WXHWND
)lParam
;
1999 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2000 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2002 #ifndef __WXMICROWIN__
2003 *nCtlColor
= CTLCOLOR_BTN
;
2004 *hwnd
= (WXHWND
)lParam
;
2005 *hdc
= (WXHDC
)wParam
;
2009 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2010 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2012 *item
= (WXWORD
)wParam
;
2013 *flags
= HIWORD(wParam
);
2014 *hmenu
= (WXHMENU
)lParam
;
2019 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2020 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2022 *id
= (WXWORD
)wParam
;
2023 *hwnd
= (WXHWND
)LOWORD(lParam
);
2024 *cmd
= HIWORD(lParam
);
2027 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2028 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2030 *state
= (WXWORD
)wParam
;
2031 *minimized
= LOWORD(lParam
);
2032 *hwnd
= (WXHWND
)HIWORD(lParam
);
2035 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2036 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2038 *code
= (WXWORD
)wParam
;
2039 *pos
= LOWORD(lParam
);
2040 *hwnd
= (WXHWND
)HIWORD(lParam
);
2043 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2044 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2046 *hwnd
= (WXHWND
)LOWORD(lParam
);
2047 *nCtlColor
= (int)HIWORD(lParam
);
2048 *hdc
= (WXHDC
)wParam
;
2051 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2052 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2054 *item
= (WXWORD
)wParam
;
2055 *flags
= LOWORD(lParam
);
2056 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2061 // ---------------------------------------------------------------------------
2062 // Main wxWindows window proc and the window proc for wxWindow
2063 // ---------------------------------------------------------------------------
2065 // Hook for new window just as it's being created, when the window isn't yet
2066 // associated with the handle
2067 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2069 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2070 // window being created and insures that it's always unset back later
2071 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2073 gs_winBeingCreated
= winBeingCreated
;
2076 wxWindowCreationHook::~wxWindowCreationHook()
2078 gs_winBeingCreated
= NULL
;
2082 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2084 // trace all messages - useful for the debugging
2086 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2087 wxGetMessageName(message
), wParam
, lParam
);
2088 #endif // __WXDEBUG__
2090 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2092 // when we get the first message for the HWND we just created, we associate
2093 // it with wxWindow stored in gs_winBeingCreated
2094 if ( !wnd
&& gs_winBeingCreated
)
2096 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2097 wnd
= gs_winBeingCreated
;
2098 gs_winBeingCreated
= NULL
;
2099 wnd
->SetHWND((WXHWND
)hWnd
);
2105 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2107 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2112 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2114 // did we process the message?
2115 bool processed
= FALSE
;
2126 // for most messages we should return 0 when we do process the message
2134 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2137 // return 0 to allow window creation
2138 rc
.result
= mayCreate
? 0 : -1;
2144 // never set processed to TRUE and *always* pass WM_DESTROY to
2145 // DefWindowProc() as Windows may do some internal cleanup when
2146 // processing it and failing to pass the message along may cause
2147 // memory and resource leaks!
2148 (void)HandleDestroy();
2152 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2160 // we're not interested in these messages at all
2163 case SIZE_MINIMIZED
:
2164 // we shouldn't send sizev events for these messages as the
2165 // client size may be negative which breaks existing code
2167 // OTOH we might send another (wxMinimizedEvent?) one or
2168 // add an additional parameter to wxSizeEvent if this is
2169 // useful to anybody
2173 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2174 // fall through nevertheless
2176 case SIZE_MAXIMIZED
:
2178 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2183 #ifndef __WXMICROWIN__
2184 case WM_ACTIVATEAPP
:
2185 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2191 WXWORD state
, minimized
;
2193 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2195 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2200 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2204 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2208 processed
= HandlePaint();
2212 // don't let the DefWindowProc() destroy our window - we'll do it
2213 // ourselves in ~wxWindow
2219 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2223 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2224 GET_Y_LPARAM(lParam
),
2228 #if wxUSE_MOUSEWHEEL
2230 processed
= HandleMouseWheel(wParam
, lParam
);
2234 case WM_LBUTTONDOWN
:
2236 case WM_LBUTTONDBLCLK
:
2237 case WM_RBUTTONDOWN
:
2239 case WM_RBUTTONDBLCLK
:
2240 case WM_MBUTTONDOWN
:
2242 case WM_MBUTTONDBLCLK
:
2245 #ifdef __WXMICROWIN__
2246 // MicroWindows seems to ignore the fact that a window is
2247 // disabled. So catch mouse events and throw them away if
2249 wxWindowMSW
* win
= this;
2252 if (!win
->IsEnabled())
2257 win
= win
->GetParent();
2258 if (win
&& win
->IsTopLevel())
2261 #endif // __WXMICROWIN__
2264 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2266 processed
= HandleMouseEvent(message
,
2267 GET_X_LPARAM(lParam
),
2268 GET_Y_LPARAM(lParam
),
2274 #ifdef __WXMICROWIN__
2275 case WM_NCLBUTTONDOWN
:
2276 case WM_NCLBUTTONUP
:
2277 case WM_NCLBUTTONDBLCLK
:
2278 case WM_NCRBUTTONDOWN
:
2279 case WM_NCRBUTTONUP
:
2280 case WM_NCRBUTTONDBLCLK
:
2282 case WM_NCMBUTTONDOWN
:
2283 case WM_NCMBUTTONUP
:
2284 case WM_NCMBUTTONDBLCLK
:
2287 // MicroWindows seems to ignore the fact that a window
2288 // is disabled. So catch mouse events and throw them away if necessary.
2290 wxWindowMSW
* win
= this;
2293 if (!win
->IsEnabled())
2298 win
= win
->GetParent();
2299 if (win
&& win
->IsTopLevel())
2304 #endif // __WXMICROWIN__
2311 case MM_JOY1BUTTONDOWN
:
2312 case MM_JOY2BUTTONDOWN
:
2313 case MM_JOY1BUTTONUP
:
2314 case MM_JOY2BUTTONUP
:
2315 processed
= HandleJoystickEvent(message
,
2316 GET_X_LPARAM(lParam
),
2317 GET_Y_LPARAM(lParam
),
2320 #endif // __WXMICROWIN__
2323 processed
= HandleSysCommand(wParam
, lParam
);
2330 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2332 processed
= HandleCommand(id
, cmd
, hwnd
);
2338 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2342 // for these messages we must return TRUE if process the message
2345 case WM_MEASUREITEM
:
2347 int idCtrl
= (UINT
)wParam
;
2348 if ( message
== WM_DRAWITEM
)
2350 processed
= MSWOnDrawItem(idCtrl
,
2351 (WXDRAWITEMSTRUCT
*)lParam
);
2355 processed
= MSWOnMeasureItem(idCtrl
,
2356 (WXMEASUREITEMSTRUCT
*)lParam
);
2363 #endif // defined(WM_DRAWITEM)
2368 rc
.result
= m_lDlgCode
;
2371 //else: get the dlg code from the DefWindowProc()
2376 // If this has been processed by an event handler,
2377 // return 0 now (we've handled it).
2378 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2385 // we consider these message "not interesting" to OnChar
2386 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2395 // avoid duplicate messages to OnChar for these ASCII keys: they
2396 // will be translated by TranslateMessage() and received in WM_CHAR
2404 // but set processed to FALSE, not TRUE to still pass them to
2405 // the control's default window proc - otherwise built-in
2406 // keyboard handling won't work
2412 // special case of VK_APPS: treat it the same as right mouse
2413 // click because both usually pop up a context menu
2419 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2420 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2430 processed
= HandleChar((WORD
)wParam
, lParam
);
2437 // special case of VK_APPS: treat it the same as right mouse button
2438 if ( wParam
== VK_APPS
)
2443 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2444 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2449 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2454 case WM_CHAR
: // Always an ASCII character
2455 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2463 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2465 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2471 // CTLCOLOR messages are sent by children to query the parent for their
2472 // colors#ifndef __WXMICROWIN__
2473 #ifndef __WXMICROWIN__
2475 case WM_CTLCOLORMSGBOX
:
2476 case WM_CTLCOLOREDIT
:
2477 case WM_CTLCOLORLISTBOX
:
2478 case WM_CTLCOLORBTN
:
2479 case WM_CTLCOLORDLG
:
2480 case WM_CTLCOLORSCROLLBAR
:
2481 case WM_CTLCOLORSTATIC
:
2489 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2491 processed
= HandleCtlColor(&rc
.hBrush
,
2500 #endif // !__WXMICROWIN__
2502 case WM_SYSCOLORCHANGE
:
2503 // the return value for this message is ignored
2504 processed
= HandleSysColorChange();
2507 case WM_PALETTECHANGED
:
2508 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2511 case WM_QUERYNEWPALETTE
:
2512 processed
= HandleQueryNewPalette();
2516 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2519 // we processed the message, i.e. erased the background
2525 processed
= HandleDropFiles(wParam
);
2529 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2533 // we never set focus from here
2538 case WM_QUERYENDSESSION
:
2539 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2543 processed
= HandleEndSession(wParam
!= 0, lParam
);
2546 case WM_GETMINMAXINFO
:
2547 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2551 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2552 LOWORD(lParam
), // hit test
2553 HIWORD(lParam
)); // mouse msg
2557 // returning TRUE stops the DefWindowProc() from further
2558 // processing this message - exactly what we need because we've
2559 // just set the cursor.
2564 #if defined(__WIN32__) && defined(WM_HELP)
2567 HELPINFO
* info
= (HELPINFO
*) lParam
;
2568 // Don't yet process menu help events, just windows
2569 if (info
->iContextType
== HELPINFO_WINDOW
)
2571 wxWindowMSW
* subjectOfHelp
= this;
2572 bool eventProcessed
= FALSE
;
2573 while (subjectOfHelp
&& !eventProcessed
)
2575 wxHelpEvent
helpEvent(wxEVT_HELP
,
2576 subjectOfHelp
->GetId(),
2577 wxPoint(info
->MousePos
.x
,
2578 info
->MousePos
.y
) );
2579 helpEvent
.SetEventObject(this);
2581 GetEventHandler()->ProcessEvent(helpEvent
);
2583 // Go up the window hierarchy until the event is
2585 subjectOfHelp
= subjectOfHelp
->GetParent();
2588 processed
= eventProcessed
;
2590 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2592 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2593 helpEvent
.SetEventObject(this);
2594 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2597 //else: processed is already FALSE
2601 case WM_CONTEXTMENU
:
2603 // we don't convert from screen to client coordinates as
2604 // the event may be handled by a parent window
2605 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2607 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2608 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2613 // unfortunately this doesn't really work as then window which
2614 // doesn't accept focus doesn't get any mouse events neither which
2615 // means it can't get any input at all
2616 #if 0 //def __WXUNIVERSAL__
2618 // we shouldn't allow the windows which don't want to get focus to
2620 if ( !AcceptsFocus() )
2622 rc
.result
= HTTRANSPARENT
;
2626 #endif // __WXUNIVERSAL__
2632 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2633 wxGetMessageName(message
));
2634 #endif // __WXDEBUG__
2635 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2641 // ----------------------------------------------------------------------------
2642 // wxWindow <-> HWND map
2643 // ----------------------------------------------------------------------------
2645 wxWinHashTable
*wxWinHandleHash
= NULL
;
2647 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2649 return wxWinHandleHash
->Get((long)hWnd
);
2652 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2654 // adding NULL hWnd is (first) surely a result of an error and
2655 // (secondly) breaks menu command processing
2656 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2657 wxT("attempt to add a NULL hWnd to window list ignored") );
2659 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2661 if ( oldWin
&& (oldWin
!= win
) )
2663 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2664 hWnd
, win
->GetClassInfo()->GetClassName());
2667 #endif // __WXDEBUG__
2670 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2674 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2676 wxWinHandleHash
->Delete((long)win
->GetHWND());
2679 // ----------------------------------------------------------------------------
2680 // various MSW speciic class dependent functions
2681 // ----------------------------------------------------------------------------
2683 // Default destroyer - override if you destroy it in some other way
2684 // (e.g. with MDI child windows)
2685 void wxWindowMSW::MSWDestroyWindow()
2689 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2692 int& w
, int& h
) const
2694 bool nonDefault
= FALSE
;
2698 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2699 // just as well set it to CW_USEDEFAULT as well
2706 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2712 NB: there used to be some code here which set the initial size of the
2713 window to the client size of the parent if no explicit size was
2714 specified. This was wrong because wxWindows programs often assume
2715 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2716 it. To see why, you should understand that Windows sends WM_SIZE from
2717 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2718 from some base class ctor and so this WM_SIZE is not processed in the
2719 real class' OnSize() (because it's not fully constructed yet and the
2720 event goes to some base class OnSize() instead). So the WM_SIZE we
2721 rely on is the one sent when the parent frame resizes its children
2722 but here is the problem: if the child already has just the right
2723 size, nothing will happen as both wxWindows and Windows check for
2724 this and ignore any attempts to change the window size to the size it
2725 already has - so no WM_SIZE would be sent.
2729 // as abobe, h is not used at all in this case anyhow
2736 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2744 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2745 const wxChar
*title
,
2749 WXDWORD extendedStyle
)
2751 // choose the position/size for the new window
2753 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2755 // find the correct parent HWND
2756 wxWindow
*parent
= GetParent();
2757 bool isChild
= (style
& WS_CHILD
) != 0;
2759 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2761 // popup windows should have desktop as parent because they shouldn't
2762 // be limited to the parents client area as child windows usually are
2763 hParent
= ::GetDesktopWindow();
2767 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2769 // this is either a normal child window or a top level window with
2770 // wxFRAME_TOOL_WINDOW style (see below)
2771 hParent
= GetHwndOf(parent
);
2775 // this is either a window for which no parent was specified (not
2776 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2777 // style: we should use NULL parent HWND for it or it would be
2778 // always on top of its parent which is not what we usually want
2779 // (in fact, we only want it for frames with the special
2780 // wxFRAME_TOOL_WINDOW as above)
2786 // controlId is menu handle for the top level windows, so set it to 0
2787 // unless we're creating a child window
2791 controlId
= GetId();
2793 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2795 style
|= WS_CLIPSIBLINGS
;
2803 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2804 // which is the same but without CS_[HV]REDRAW class styles so using it
2805 // ensures that the window is not fully repainted on each resize
2806 wxString
className(wclass
);
2807 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2809 className
+= wxT("NR");
2812 // do create the window
2813 wxWindowCreationHook
hook(this);
2815 m_hWnd
= (WXHWND
)::CreateWindowEx
2819 title
? title
: wxT(""),
2825 NULL
// no extra data
2830 wxLogSysError(_("Can't create window of class %s"), wclass
);
2835 SubclassWin(m_hWnd
);
2837 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2842 // ===========================================================================
2843 // MSW message handlers
2844 // ===========================================================================
2846 // ---------------------------------------------------------------------------
2848 // ---------------------------------------------------------------------------
2851 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2852 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2854 #ifndef __WXMICROWIN__
2855 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2856 HWND hWnd
= hdr
->hwndFrom
;
2857 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2859 // is this one of our windows?
2862 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2865 // try all our children
2866 wxWindowList::Node
*node
= GetChildren().GetFirst();
2869 wxWindow
*child
= node
->GetData();
2870 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2875 node
= node
->GetNext();
2878 // finally try this window too (catches toolbar case)
2879 return MSWOnNotify(idCtrl
, lParam
, result
);
2880 #else // __WXMICROWIN__
2885 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2887 WXLPARAM
* WXUNUSED(result
))
2890 NMHDR
* hdr
= (NMHDR
*)lParam
;
2891 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2893 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2894 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2899 #endif // wxUSE_TOOLTIPS
2905 // ---------------------------------------------------------------------------
2906 // end session messages
2907 // ---------------------------------------------------------------------------
2909 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2911 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2912 event
.SetEventObject(wxTheApp
);
2913 event
.SetCanVeto(TRUE
);
2914 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
2916 bool rc
= wxTheApp
->ProcessEvent(event
);
2920 // we may end only if the app didn't veto session closing (double
2922 *mayEnd
= !event
.GetVeto();
2928 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
2930 // do nothing if the session isn't ending
2935 if ( (this != wxTheApp
->GetTopWindow()) )
2938 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
2939 event
.SetEventObject(wxTheApp
);
2940 event
.SetCanVeto(FALSE
);
2941 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
2943 return wxTheApp
->ProcessEvent(event
);
2946 // ---------------------------------------------------------------------------
2947 // window creation/destruction
2948 // ---------------------------------------------------------------------------
2950 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
2952 // TODO: should generate this event from WM_NCCREATE
2953 wxWindowCreateEvent
event((wxWindow
*)this);
2954 (void)GetEventHandler()->ProcessEvent(event
);
2961 bool wxWindowMSW::HandleDestroy()
2963 wxWindowDestroyEvent
event((wxWindow
*)this);
2964 (void)GetEventHandler()->ProcessEvent(event
);
2966 // delete our drop target if we've got one
2967 #if wxUSE_DRAG_AND_DROP
2968 if ( m_dropTarget
!= NULL
)
2970 m_dropTarget
->Revoke(m_hWnd
);
2972 delete m_dropTarget
;
2973 m_dropTarget
= NULL
;
2975 #endif // wxUSE_DRAG_AND_DROP
2977 // WM_DESTROY handled
2981 // ---------------------------------------------------------------------------
2983 // ---------------------------------------------------------------------------
2985 bool wxWindowMSW::HandleActivate(int state
,
2986 bool WXUNUSED(minimized
),
2987 WXHWND
WXUNUSED(activate
))
2989 wxActivateEvent
event(wxEVT_ACTIVATE
,
2990 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
2992 event
.SetEventObject(this);
2994 return GetEventHandler()->ProcessEvent(event
);
2997 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
2999 // notify the parent keeping track of focus for the kbd navigation
3000 // purposes that we got it
3001 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3002 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3008 m_caret
->OnSetFocus();
3010 #endif // wxUSE_CARET
3013 // If it's a wxTextCtrl don't send the event as it will be done
3014 // after the control gets to process it from EN_FOCUS handler
3015 if ( wxDynamicCastThis(wxTextCtrl
) )
3019 #endif // wxUSE_TEXTCTRL
3021 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3022 event
.SetEventObject(this);
3024 // wxFindWinFromHandle() may return NULL, it is ok
3025 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3027 return GetEventHandler()->ProcessEvent(event
);
3030 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3036 m_caret
->OnKillFocus();
3038 #endif // wxUSE_CARET
3041 // If it's a wxTextCtrl don't send the event as it will be done
3042 // after the control gets to process it.
3043 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3050 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3051 event
.SetEventObject(this);
3053 // wxFindWinFromHandle() may return NULL, it is ok
3054 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3056 return GetEventHandler()->ProcessEvent(event
);
3059 // ---------------------------------------------------------------------------
3061 // ---------------------------------------------------------------------------
3063 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3065 wxShowEvent
event(GetId(), show
);
3066 event
.m_eventObject
= this;
3068 return GetEventHandler()->ProcessEvent(event
);
3071 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3073 wxInitDialogEvent
event(GetId());
3074 event
.m_eventObject
= this;
3076 return GetEventHandler()->ProcessEvent(event
);
3079 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3081 #ifndef __WXMICROWIN__
3082 HDROP hFilesInfo
= (HDROP
) wParam
;
3084 // Get the total number of files dropped
3085 UINT gwFilesDropped
= ::DragQueryFile
3093 wxString
*files
= new wxString
[gwFilesDropped
];
3094 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3096 // first get the needed buffer length (+1 for terminating NUL)
3097 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3099 // and now get the file name
3100 ::DragQueryFile(hFilesInfo
, wIndex
,
3101 files
[wIndex
].GetWriteBuf(len
), len
);
3103 files
[wIndex
].UngetWriteBuf();
3105 DragFinish (hFilesInfo
);
3107 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3108 event
.m_eventObject
= this;
3111 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3112 event
.m_pos
.x
= dropPoint
.x
;
3113 event
.m_pos
.y
= dropPoint
.y
;
3115 return GetEventHandler()->ProcessEvent(event
);
3116 #else // __WXMICROWIN__
3121 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3123 int WXUNUSED(mouseMsg
))
3125 #ifndef __WXMICROWIN__
3126 // the logic is as follows:
3127 // -1. don't set cursor for non client area, including but not limited to
3128 // the title bar, scrollbars, &c
3129 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3130 // 1. if we have the cursor set it unless wxIsBusy()
3131 // 2. if we're a top level window, set some cursor anyhow
3132 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3134 if ( nHitTest
!= HTCLIENT
)
3139 HCURSOR hcursor
= 0;
3141 // first ask the user code - it may wish to set the cursor in some very
3142 // specific way (for example, depending on the current position)
3145 if ( !::GetCursorPos(&pt
) )
3147 wxLogLastError(wxT("GetCursorPos"));
3150 // In WIN16 it doesn't return a value.
3151 ::GetCursorPos(&pt
);
3156 ScreenToClient(&x
, &y
);
3157 wxSetCursorEvent
event(x
, y
);
3159 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3160 if ( processedEvtSetCursor
&& event
.HasCursor() )
3162 hcursor
= GetHcursorOf(event
.GetCursor());
3167 bool isBusy
= wxIsBusy();
3169 // the test for processedEvtSetCursor is here to prevent using m_cursor
3170 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3171 // it - this is a way to say that our cursor shouldn't be used for this
3173 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3175 hcursor
= GetHcursorOf(m_cursor
);
3182 hcursor
= wxGetCurrentBusyCursor();
3184 else if ( !hcursor
)
3186 const wxCursor
*cursor
= wxGetGlobalCursor();
3187 if ( cursor
&& cursor
->Ok() )
3189 hcursor
= GetHcursorOf(*cursor
);
3197 ::SetCursor(hcursor
);
3199 // cursor set, stop here
3202 #endif // __WXMICROWIN__
3204 // pass up the window chain
3208 // ---------------------------------------------------------------------------
3209 // owner drawn stuff
3210 // ---------------------------------------------------------------------------
3212 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3214 #if wxUSE_OWNER_DRAWN
3216 #if wxUSE_MENUS_NATIVE
3217 // is it a menu item?
3218 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3219 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3221 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3223 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3225 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3226 // the DC from being released
3227 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3228 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3229 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3230 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3232 return pMenuItem
->OnDrawItem
3236 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3237 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3240 #endif // wxUSE_MENUS_NATIVE
3243 wxWindow
*item
= FindItem(id
);
3244 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3246 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3248 #endif // wxUSE_CONTROLS
3250 #endif // USE_OWNER_DRAWN
3255 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3257 #if wxUSE_OWNER_DRAWN
3258 // is it a menu item?
3259 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3260 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3262 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3264 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3266 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3267 &pMeasureStruct
->itemHeight
);
3270 wxWindow
*item
= FindItem(id
);
3271 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3273 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3275 #endif // owner-drawn menus
3279 // ---------------------------------------------------------------------------
3280 // colours and palettes
3281 // ---------------------------------------------------------------------------
3283 bool wxWindowMSW::HandleSysColorChange()
3285 wxSysColourChangedEvent event
;
3286 event
.SetEventObject(this);
3288 (void)GetEventHandler()->ProcessEvent(event
);
3290 // always let the system carry on the default processing to allow the
3291 // native controls to react to the colours update
3295 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3303 #ifndef __WXMICROWIN__
3304 WXHBRUSH hBrush
= 0;
3306 if ( nCtlColor
== CTLCOLOR_DLG
)
3308 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3313 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3315 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3317 #endif // wxUSE_CONTROLS
3323 #else // __WXMICROWIN__
3328 // Define for each class of dialog and control
3329 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3330 WXHWND
WXUNUSED(hWnd
),
3331 WXUINT
WXUNUSED(nCtlColor
),
3332 WXUINT
WXUNUSED(message
),
3333 WXWPARAM
WXUNUSED(wParam
),
3334 WXLPARAM
WXUNUSED(lParam
))
3339 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3341 wxPaletteChangedEvent
event(GetId());
3342 event
.SetEventObject(this);
3343 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3345 return GetEventHandler()->ProcessEvent(event
);
3348 bool wxWindowMSW::HandleQueryNewPalette()
3350 wxQueryNewPaletteEvent
event(GetId());
3351 event
.SetEventObject(this);
3353 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3356 // Responds to colour changes: passes event on to children.
3357 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& event
)
3359 // the top level window also reset the standard colour map as it might have
3360 // changed (there is no need to do it for the non top level windows as we
3361 // only have to do it once)
3365 gs_hasStdCmap
= FALSE
;
3367 wxWindowList::Node
*node
= GetChildren().GetFirst();
3370 // Only propagate to non-top-level windows because Windows already
3371 // sends this event to all top-level ones
3372 wxWindow
*win
= node
->GetData();
3373 if ( !win
->IsTopLevel() )
3375 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3376 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3377 // the standard controls
3378 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3381 node
= node
->GetNext();
3384 // update the colours we use if they were not set explicitly by the user:
3385 // this must be done or OnCtlColor() would continue to use the old colours
3388 m_foregroundColour
= wxSystemSettings::
3389 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3394 m_backgroundColour
= wxSystemSettings::
3395 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3399 extern wxCOLORMAP
*wxGetStdColourMap()
3401 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3402 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3404 if ( !gs_hasStdCmap
)
3406 static bool s_coloursInit
= FALSE
;
3408 if ( !s_coloursInit
)
3410 // When a bitmap is loaded, the RGB values can change (apparently
3411 // because Windows adjusts them to care for the old programs always
3412 // using 0xc0c0c0 while the transparent colour for the new Windows
3413 // versions is different). But we do this adjustment ourselves so
3414 // we want to avoid Windows' "help" and for this we need to have a
3415 // reference bitmap which can tell us what the RGB values change
3417 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3418 if ( stdColourBitmap
.Ok() )
3420 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3421 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3422 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3425 memDC
.SelectObject(stdColourBitmap
);
3428 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3430 memDC
.GetPixel(i
, 0, &colour
);
3431 s_stdColours
[i
] = wxColourToRGB(colour
);
3434 else // wxBITMAP_STD_COLOURS couldn't be loaded
3436 s_stdColours
[0] = RGB(000,000,000); // black
3437 s_stdColours
[1] = RGB(128,128,128); // dark grey
3438 s_stdColours
[2] = RGB(192,192,192); // light grey
3439 s_stdColours
[3] = RGB(255,255,255); // white
3440 //s_stdColours[4] = RGB(000,000,255); // blue
3441 //s_stdColours[5] = RGB(255,000,255); // magenta
3444 s_coloursInit
= TRUE
;
3447 gs_hasStdCmap
= TRUE
;
3449 // create the colour map
3450 #define INIT_CMAP_ENTRY(col) \
3451 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3452 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3454 INIT_CMAP_ENTRY(BTNTEXT
);
3455 INIT_CMAP_ENTRY(BTNSHADOW
);
3456 INIT_CMAP_ENTRY(BTNFACE
);
3457 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3459 #undef INIT_CMAP_ENTRY
3465 // ---------------------------------------------------------------------------
3467 // ---------------------------------------------------------------------------
3469 bool wxWindowMSW::HandlePaint()
3472 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3474 wxLogLastError(wxT("CreateRectRgn"));
3475 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3476 wxLogLastError(wxT("GetUpdateRgn"));
3478 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3481 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3483 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3484 updateRect
.right
- updateRect
.left
,
3485 updateRect
.bottom
- updateRect
.top
);
3488 wxPaintEvent
event(m_windowId
);
3489 event
.SetEventObject(this);
3491 bool processed
= GetEventHandler()->ProcessEvent(event
);
3493 // note that we must generate NC event after the normal one as otherwise
3494 // BeginPaint() will happily overwrite our decorations with the background
3496 wxNcPaintEvent
eventNc(m_windowId
);
3497 eventNc
.SetEventObject(this);
3498 GetEventHandler()->ProcessEvent(eventNc
);
3503 // Can be called from an application's OnPaint handler
3504 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3506 #ifdef __WXUNIVERSAL__
3509 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3512 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3517 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3519 // Prevents flicker when dragging
3520 if ( ::IsIconic(GetHwnd()) )
3526 dc
.SetWindow((wxWindow
*)this);
3529 wxEraseEvent
event(m_windowId
, &dc
);
3530 event
.SetEventObject(this);
3531 bool rc
= GetEventHandler()->ProcessEvent(event
);
3535 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3536 dc
.SelectOldObjects(hdc
);
3541 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3544 ::GetClientRect(GetHwnd(), &rect
);
3546 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3547 m_backgroundColour
.Green(),
3548 m_backgroundColour
.Blue());
3549 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3551 wxLogLastError(wxT("CreateSolidBrush"));
3553 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3555 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3557 ::FillRect(hdc
, &rect
, hBrush
);
3558 ::DeleteObject(hBrush
);
3559 ::SetMapMode(hdc
, mode
);
3562 // ---------------------------------------------------------------------------
3563 // moving and resizing
3564 // ---------------------------------------------------------------------------
3566 bool wxWindowMSW::HandleMinimize()
3568 wxIconizeEvent
event(m_windowId
);
3569 event
.SetEventObject(this);
3571 return GetEventHandler()->ProcessEvent(event
);
3574 bool wxWindowMSW::HandleMaximize()
3576 wxMaximizeEvent
event(m_windowId
);
3577 event
.SetEventObject(this);
3579 return GetEventHandler()->ProcessEvent(event
);
3582 bool wxWindowMSW::HandleMove(int x
, int y
)
3584 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3585 event
.SetEventObject(this);
3587 return GetEventHandler()->ProcessEvent(event
);
3590 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3592 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3593 event
.SetEventObject(this);
3595 return GetEventHandler()->ProcessEvent(event
);
3598 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3600 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3604 if ( m_minWidth
!= -1 )
3606 info
->ptMinTrackSize
.x
= m_minWidth
;
3610 if ( m_minHeight
!= -1 )
3612 info
->ptMinTrackSize
.y
= m_minHeight
;
3616 if ( m_maxWidth
!= -1 )
3618 info
->ptMaxTrackSize
.x
= m_maxWidth
;
3622 if ( m_maxHeight
!= -1 )
3624 info
->ptMaxTrackSize
.y
= m_maxHeight
;
3631 // ---------------------------------------------------------------------------
3633 // ---------------------------------------------------------------------------
3635 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3637 #if wxUSE_MENUS_NATIVE
3638 if ( !cmd
&& wxCurrentPopupMenu
)
3640 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3641 wxCurrentPopupMenu
= NULL
;
3643 return popupMenu
->MSWCommand(cmd
, id
);
3645 #endif // wxUSE_MENUS_NATIVE
3647 wxWindow
*win
= NULL
;
3649 // first try to find it from HWND - this works even with the broken
3650 // programs using the same ids for different controls
3653 win
= wxFindWinFromHandle(control
);
3659 // must cast to a signed type before comparing with other ids!
3660 win
= FindItem((signed short)id
);
3665 return win
->MSWCommand(cmd
, id
);
3668 // the messages sent from the in-place edit control used by the treectrl
3669 // for label editing have id == 0, but they should _not_ be treated as menu
3670 // messages (they are EN_XXX ones, in fact) so don't translate anything
3671 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3674 // If no child window, it may be an accelerator, e.g. for a popup menu
3677 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3678 event
.SetEventObject(this);
3682 return GetEventHandler()->ProcessEvent(event
);
3684 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3687 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3688 // notifications to its parent which we want to reflect back to
3690 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3691 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3694 #endif // wxUSE_SPINCTRL
3699 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3701 // 4 bits are reserved
3702 switch ( wParam
& 0xFFFFFFF0 )
3705 return HandleMaximize();
3708 return HandleMinimize();
3714 // ---------------------------------------------------------------------------
3716 // ---------------------------------------------------------------------------
3718 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3722 // our client coords are not quite the same as Windows ones
3723 wxPoint pt
= GetClientAreaOrigin();
3724 event
.m_x
= x
- pt
.x
;
3725 event
.m_y
= y
- pt
.y
;
3727 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3728 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3729 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3730 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3731 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3732 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3734 event
.SetTimestamp(s_currentMsg
.time
);
3735 event
.m_eventObject
= this;
3737 #if wxUSE_MOUSEEVENT_HACK
3740 m_lastMouseEvent
= event
.GetEventType();
3741 #endif // wxUSE_MOUSEEVENT_HACK
3744 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3746 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3747 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3748 // from the message id and take the value in the table to get wxWin event
3750 static const wxEventType eventsMouse
[] =
3764 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3765 InitMouseEvent(event
, x
, y
, flags
);
3767 return GetEventHandler()->ProcessEvent(event
);
3770 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3772 if ( !m_mouseInWindow
)
3774 // it would be wrong to assume that just because we get a mouse move
3775 // event that the mouse is inside the window: although this is usually
3776 // true, it is not if we had captured the mouse, so we need to check
3777 // the mouse coordinates here
3778 if ( !HasCapture() || IsMouseInWindow() )
3780 // Generate an ENTER event
3781 m_mouseInWindow
= TRUE
;
3783 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3784 InitMouseEvent(event
, x
, y
, flags
);
3786 (void)GetEventHandler()->ProcessEvent(event
);
3790 #if wxUSE_MOUSEEVENT_HACK
3791 // Window gets a click down message followed by a mouse move message even
3792 // if position isn't changed! We want to discard the trailing move event
3793 // if x and y are the same.
3794 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3795 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3796 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3797 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3799 m_lastMouseEvent
= wxEVT_MOTION
;
3803 #endif // wxUSE_MOUSEEVENT_HACK
3805 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3809 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3811 #if wxUSE_MOUSEWHEEL
3812 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3813 InitMouseEvent(event
,
3814 GET_X_LPARAM(lParam
),
3815 GET_Y_LPARAM(lParam
),
3817 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3818 event
.m_wheelDelta
= WHEEL_DELTA
;
3821 static int s_linesPerRotation
= -1;
3822 if ( s_linesPerRotation
== -1 )
3824 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3825 &s_linesPerRotation
, 0))
3827 // this is not supposed to happen
3828 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3830 // the default is 3, so use it if SystemParametersInfo() failed
3831 s_linesPerRotation
= 3;
3835 // no SystemParametersInfo() under Win16
3836 static const int s_linesPerRotation
= 3;
3839 event
.m_linesPerAction
= s_linesPerRotation
;
3840 return GetEventHandler()->ProcessEvent(event
);
3851 // ---------------------------------------------------------------------------
3852 // keyboard handling
3853 // ---------------------------------------------------------------------------
3855 // create the key event of the given type for the given key - used by
3856 // HandleChar and HandleKeyDown/Up
3857 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
3859 WXLPARAM lParam
) const
3861 wxKeyEvent
event(evType
);
3862 event
.SetId(GetId());
3863 event
.m_shiftDown
= wxIsShiftDown();
3864 event
.m_controlDown
= wxIsCtrlDown();
3865 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
3867 event
.m_eventObject
= (wxWindow
*)this; // const_cast
3868 event
.m_keyCode
= id
;
3869 event
.SetTimestamp(s_currentMsg
.time
);
3871 // translate the position to client coords
3875 GetWindowRect(GetHwnd(),&rect
);
3885 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
3887 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
3889 bool ctrlDown
= FALSE
;
3894 // If 1 -> 26, translate to CTRL plus a letter.
3896 if ( (id
> 0) && (id
< 27) )
3918 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
3920 // it's ASCII and will be processed here only when called from
3921 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
3927 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
3930 event
.m_controlDown
= TRUE
;
3933 if ( GetEventHandler()->ProcessEvent(event
) )
3940 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
3942 int id
= wxCharCodeMSWToWX(wParam
);
3946 // normal ASCII char
3950 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3952 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
3953 if ( GetEventHandler()->ProcessEvent(event
) )
3962 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
3964 int id
= wxCharCodeMSWToWX(wParam
);
3968 // normal ASCII char
3972 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
3974 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
3975 if ( GetEventHandler()->ProcessEvent(event
) )
3982 // ---------------------------------------------------------------------------
3984 // ---------------------------------------------------------------------------
3986 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3990 if ( flags
& JOY_BUTTON1CHG
)
3991 change
= wxJOY_BUTTON1
;
3992 if ( flags
& JOY_BUTTON2CHG
)
3993 change
= wxJOY_BUTTON2
;
3994 if ( flags
& JOY_BUTTON3CHG
)
3995 change
= wxJOY_BUTTON3
;
3996 if ( flags
& JOY_BUTTON4CHG
)
3997 change
= wxJOY_BUTTON4
;
4000 if ( flags
& JOY_BUTTON1
)
4001 buttons
|= wxJOY_BUTTON1
;
4002 if ( flags
& JOY_BUTTON2
)
4003 buttons
|= wxJOY_BUTTON2
;
4004 if ( flags
& JOY_BUTTON3
)
4005 buttons
|= wxJOY_BUTTON3
;
4006 if ( flags
& JOY_BUTTON4
)
4007 buttons
|= wxJOY_BUTTON4
;
4009 // the event ids aren't consecutive so we can't use table based lookup
4011 wxEventType eventType
;
4016 eventType
= wxEVT_JOY_MOVE
;
4021 eventType
= wxEVT_JOY_MOVE
;
4026 eventType
= wxEVT_JOY_ZMOVE
;
4031 eventType
= wxEVT_JOY_ZMOVE
;
4034 case MM_JOY1BUTTONDOWN
:
4036 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4039 case MM_JOY2BUTTONDOWN
:
4041 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4044 case MM_JOY1BUTTONUP
:
4046 eventType
= wxEVT_JOY_BUTTON_UP
;
4049 case MM_JOY2BUTTONUP
:
4051 eventType
= wxEVT_JOY_BUTTON_UP
;
4055 wxFAIL_MSG(wxT("no such joystick event"));
4060 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4061 event
.SetPosition(wxPoint(x
, y
));
4062 event
.SetEventObject(this);
4064 return GetEventHandler()->ProcessEvent(event
);
4070 // ---------------------------------------------------------------------------
4072 // ---------------------------------------------------------------------------
4074 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4075 WXWORD pos
, WXHWND control
)
4079 wxWindow
*child
= wxFindWinFromHandle(control
);
4081 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4084 wxScrollWinEvent event
;
4085 event
.SetPosition(pos
);
4086 event
.SetOrientation(orientation
);
4087 event
.m_eventObject
= this;
4092 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4096 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4100 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4104 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4108 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4112 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4115 case SB_THUMBPOSITION
:
4118 // under Win32, the scrollbar range and position are 32 bit integers,
4119 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4120 // explicitly query the scrollbar for the correct position (this must
4121 // be done only for these two SB_ events as they are the only one
4122 // carrying the scrollbar position)
4124 SCROLLINFO scrollInfo
;
4125 wxZeroMemory(scrollInfo
);
4126 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4127 scrollInfo
.fMask
= SIF_TRACKPOS
;
4129 if ( !::GetScrollInfo(GetHwnd(),
4130 orientation
== wxHORIZONTAL
? SB_HORZ
4134 wxLogLastError(_T("GetScrollInfo"));
4137 event
.SetPosition(scrollInfo
.nTrackPos
);
4141 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4142 ? wxEVT_SCROLLWIN_THUMBRELEASE
4143 : wxEVT_SCROLLWIN_THUMBTRACK
;
4150 return GetEventHandler()->ProcessEvent(event
);
4153 // ===========================================================================
4155 // ===========================================================================
4157 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4160 HDC dc
= ::GetDC((HWND
) wnd
);
4165 // the_font->UseResource();
4166 // the_font->RealizeResource();
4167 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4169 was
= (HFONT
) SelectObject(dc
,fnt
);
4171 GetTextMetrics(dc
, &tm
);
4172 if ( the_font
&& fnt
&& was
)
4174 SelectObject(dc
,was
);
4176 ReleaseDC((HWND
)wnd
, dc
);
4179 *x
= tm
.tmAveCharWidth
;
4181 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4184 // the_font->ReleaseResource();
4187 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4188 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4189 int wxCharCodeMSWToWX(int keySym
)
4194 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4195 case VK_BACK
: id
= WXK_BACK
; break;
4196 case VK_TAB
: id
= WXK_TAB
; break;
4197 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4198 case VK_RETURN
: id
= WXK_RETURN
; break;
4199 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4200 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4201 case VK_MENU
: id
= WXK_MENU
; break;
4202 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4203 case VK_SPACE
: id
= WXK_SPACE
; break;
4204 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4205 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4206 case VK_NEXT
: id
= WXK_NEXT
; break;
4207 case VK_END
: id
= WXK_END
; break;
4208 case VK_HOME
: id
= WXK_HOME
; break;
4209 case VK_LEFT
: id
= WXK_LEFT
; break;
4210 case VK_UP
: id
= WXK_UP
; break;
4211 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4212 case VK_DOWN
: id
= WXK_DOWN
; break;
4213 case VK_SELECT
: id
= WXK_SELECT
; break;
4214 case VK_PRINT
: id
= WXK_PRINT
; break;
4215 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4216 case VK_INSERT
: id
= WXK_INSERT
; break;
4217 case VK_DELETE
: id
= WXK_DELETE
; break;
4218 case VK_HELP
: id
= WXK_HELP
; break;
4219 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4220 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4221 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4222 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4223 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4224 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4225 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4226 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4227 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4228 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4229 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4230 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4231 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4232 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4233 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4234 case VK_F1
: id
= WXK_F1
; break;
4235 case VK_F2
: id
= WXK_F2
; break;
4236 case VK_F3
: id
= WXK_F3
; break;
4237 case VK_F4
: id
= WXK_F4
; break;
4238 case VK_F5
: id
= WXK_F5
; break;
4239 case VK_F6
: id
= WXK_F6
; break;
4240 case VK_F7
: id
= WXK_F7
; break;
4241 case VK_F8
: id
= WXK_F8
; break;
4242 case VK_F9
: id
= WXK_F9
; break;
4243 case VK_F10
: id
= WXK_F10
; break;
4244 case VK_F11
: id
= WXK_F11
; break;
4245 case VK_F12
: id
= WXK_F12
; break;
4246 case VK_F13
: id
= WXK_F13
; break;
4247 case VK_F14
: id
= WXK_F14
; break;
4248 case VK_F15
: id
= WXK_F15
; break;
4249 case VK_F16
: id
= WXK_F16
; break;
4250 case VK_F17
: id
= WXK_F17
; break;
4251 case VK_F18
: id
= WXK_F18
; break;
4252 case VK_F19
: id
= WXK_F19
; break;
4253 case VK_F20
: id
= WXK_F20
; break;
4254 case VK_F21
: id
= WXK_F21
; break;
4255 case VK_F22
: id
= WXK_F22
; break;
4256 case VK_F23
: id
= WXK_F23
; break;
4257 case VK_F24
: id
= WXK_F24
; break;
4258 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4259 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4267 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4273 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4274 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4275 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4276 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4277 case WXK_MENU
: keySym
= VK_MENU
; break;
4278 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4279 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4280 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4281 case WXK_END
: keySym
= VK_END
; break;
4282 case WXK_HOME
: keySym
= VK_HOME
; break;
4283 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4284 case WXK_UP
: keySym
= VK_UP
; break;
4285 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4286 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4287 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4288 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4289 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4290 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4291 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4292 case WXK_HELP
: keySym
= VK_HELP
; break;
4293 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4294 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4295 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4296 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4297 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4298 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4299 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4300 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4301 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4302 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4303 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4304 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4305 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4306 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4307 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4308 case WXK_F1
: keySym
= VK_F1
; break;
4309 case WXK_F2
: keySym
= VK_F2
; break;
4310 case WXK_F3
: keySym
= VK_F3
; break;
4311 case WXK_F4
: keySym
= VK_F4
; break;
4312 case WXK_F5
: keySym
= VK_F5
; break;
4313 case WXK_F6
: keySym
= VK_F6
; break;
4314 case WXK_F7
: keySym
= VK_F7
; break;
4315 case WXK_F8
: keySym
= VK_F8
; break;
4316 case WXK_F9
: keySym
= VK_F9
; break;
4317 case WXK_F10
: keySym
= VK_F10
; break;
4318 case WXK_F11
: keySym
= VK_F11
; break;
4319 case WXK_F12
: keySym
= VK_F12
; break;
4320 case WXK_F13
: keySym
= VK_F13
; break;
4321 case WXK_F14
: keySym
= VK_F14
; break;
4322 case WXK_F15
: keySym
= VK_F15
; break;
4323 case WXK_F16
: keySym
= VK_F16
; break;
4324 case WXK_F17
: keySym
= VK_F17
; break;
4325 case WXK_F18
: keySym
= VK_F18
; break;
4326 case WXK_F19
: keySym
= VK_F19
; break;
4327 case WXK_F20
: keySym
= VK_F20
; break;
4328 case WXK_F21
: keySym
= VK_F21
; break;
4329 case WXK_F22
: keySym
= VK_F22
; break;
4330 case WXK_F23
: keySym
= VK_F23
; break;
4331 case WXK_F24
: keySym
= VK_F24
; break;
4332 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4333 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4344 wxWindow
*wxGetActiveWindow()
4346 HWND hWnd
= GetActiveWindow();
4349 return wxFindWinFromHandle((WXHWND
) hWnd
);
4354 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4356 HWND hwnd
= (HWND
)hWnd
;
4358 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4359 // by code in msw/radiobox.cpp), for all the others we just search up the
4361 wxWindow
*win
= (wxWindow
*)NULL
;
4364 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4367 // all these hacks only work under Win32 anyhow
4371 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4372 // wxWindow class which overrides WM_GETDLGCODE processing to
4373 // do it as well, win would be already non NULL
4374 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4376 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4378 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4379 #endif // wxUSE_RADIOBOX
4381 // spin control text buddy window should be mapped to spin ctrl
4382 // itself so try it too
4383 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4386 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4388 #endif // wxUSE_SPINCTRL
4394 while ( hwnd
&& !win
)
4396 // this is a really ugly hack needed to avoid mistakenly returning the
4397 // parent frame wxWindow for the find/replace modeless dialog HWND -
4398 // this, in turn, is needed to call IsDialogMessage() from
4399 // wxApp::ProcessMessage() as for this we must return NULL from here
4401 // FIXME: this is clearly not the best way to do it but I think we'll
4402 // need to change HWND <-> wxWindow code more heavily than I can
4403 // do it now to fix it
4404 #ifndef __WXMICROWIN__
4405 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4407 // it's a dialog box, don't go upwards
4412 hwnd
= ::GetParent(hwnd
);
4413 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4419 #ifndef __WXMICROWIN__
4421 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4422 // in active frames and dialogs, regardless of where the focus is.
4423 static HHOOK wxTheKeyboardHook
= 0;
4424 static FARPROC wxTheKeyboardHookProc
= 0;
4425 int APIENTRY _EXPORT
4426 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4428 void wxSetKeyboardHook(bool doIt
)
4432 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4433 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4435 #if defined(__WIN32__) && !defined(__TWIN32__)
4436 GetCurrentThreadId()
4437 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4445 UnhookWindowsHookEx(wxTheKeyboardHook
);
4447 // avoids warning about statement with no effect (FreeProcInstance
4448 // doesn't do anything under Win32)
4449 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4450 FreeProcInstance(wxTheKeyboardHookProc
);
4455 int APIENTRY _EXPORT
4456 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4458 DWORD hiWord
= HIWORD(lParam
);
4459 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4461 int id
= wxCharCodeMSWToWX(wParam
);
4464 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4465 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4466 event
.m_altDown
= TRUE
;
4468 event
.m_eventObject
= NULL
;
4469 event
.m_keyCode
= id
;
4470 event
.m_shiftDown
= wxIsShiftDown();
4471 event
.m_controlDown
= wxIsCtrlDown();
4472 event
.SetTimestamp(s_currentMsg
.time
);
4474 wxWindow
*win
= wxGetActiveWindow();
4475 wxEvtHandler
*handler
;
4478 handler
= win
->GetEventHandler();
4479 event
.SetId(win
->GetId());
4487 if ( handler
&& handler
->ProcessEvent(event
) )
4495 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4498 #endif // !__WXMICROWIN__
4501 const char *wxGetMessageName(int message
)
4505 case 0x0000: return "WM_NULL";
4506 case 0x0001: return "WM_CREATE";
4507 case 0x0002: return "WM_DESTROY";
4508 case 0x0003: return "WM_MOVE";
4509 case 0x0005: return "WM_SIZE";
4510 case 0x0006: return "WM_ACTIVATE";
4511 case 0x0007: return "WM_SETFOCUS";
4512 case 0x0008: return "WM_KILLFOCUS";
4513 case 0x000A: return "WM_ENABLE";
4514 case 0x000B: return "WM_SETREDRAW";
4515 case 0x000C: return "WM_SETTEXT";
4516 case 0x000D: return "WM_GETTEXT";
4517 case 0x000E: return "WM_GETTEXTLENGTH";
4518 case 0x000F: return "WM_PAINT";
4519 case 0x0010: return "WM_CLOSE";
4520 case 0x0011: return "WM_QUERYENDSESSION";
4521 case 0x0012: return "WM_QUIT";
4522 case 0x0013: return "WM_QUERYOPEN";
4523 case 0x0014: return "WM_ERASEBKGND";
4524 case 0x0015: return "WM_SYSCOLORCHANGE";
4525 case 0x0016: return "WM_ENDSESSION";
4526 case 0x0017: return "WM_SYSTEMERROR";
4527 case 0x0018: return "WM_SHOWWINDOW";
4528 case 0x0019: return "WM_CTLCOLOR";
4529 case 0x001A: return "WM_WININICHANGE";
4530 case 0x001B: return "WM_DEVMODECHANGE";
4531 case 0x001C: return "WM_ACTIVATEAPP";
4532 case 0x001D: return "WM_FONTCHANGE";
4533 case 0x001E: return "WM_TIMECHANGE";
4534 case 0x001F: return "WM_CANCELMODE";
4535 case 0x0020: return "WM_SETCURSOR";
4536 case 0x0021: return "WM_MOUSEACTIVATE";
4537 case 0x0022: return "WM_CHILDACTIVATE";
4538 case 0x0023: return "WM_QUEUESYNC";
4539 case 0x0024: return "WM_GETMINMAXINFO";
4540 case 0x0026: return "WM_PAINTICON";
4541 case 0x0027: return "WM_ICONERASEBKGND";
4542 case 0x0028: return "WM_NEXTDLGCTL";
4543 case 0x002A: return "WM_SPOOLERSTATUS";
4544 case 0x002B: return "WM_DRAWITEM";
4545 case 0x002C: return "WM_MEASUREITEM";
4546 case 0x002D: return "WM_DELETEITEM";
4547 case 0x002E: return "WM_VKEYTOITEM";
4548 case 0x002F: return "WM_CHARTOITEM";
4549 case 0x0030: return "WM_SETFONT";
4550 case 0x0031: return "WM_GETFONT";
4551 case 0x0037: return "WM_QUERYDRAGICON";
4552 case 0x0039: return "WM_COMPAREITEM";
4553 case 0x0041: return "WM_COMPACTING";
4554 case 0x0044: return "WM_COMMNOTIFY";
4555 case 0x0046: return "WM_WINDOWPOSCHANGING";
4556 case 0x0047: return "WM_WINDOWPOSCHANGED";
4557 case 0x0048: return "WM_POWER";
4560 case 0x004A: return "WM_COPYDATA";
4561 case 0x004B: return "WM_CANCELJOURNAL";
4562 case 0x004E: return "WM_NOTIFY";
4563 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4564 case 0x0051: return "WM_INPUTLANGCHANGE";
4565 case 0x0052: return "WM_TCARD";
4566 case 0x0053: return "WM_HELP";
4567 case 0x0054: return "WM_USERCHANGED";
4568 case 0x0055: return "WM_NOTIFYFORMAT";
4569 case 0x007B: return "WM_CONTEXTMENU";
4570 case 0x007C: return "WM_STYLECHANGING";
4571 case 0x007D: return "WM_STYLECHANGED";
4572 case 0x007E: return "WM_DISPLAYCHANGE";
4573 case 0x007F: return "WM_GETICON";
4574 case 0x0080: return "WM_SETICON";
4577 case 0x0081: return "WM_NCCREATE";
4578 case 0x0082: return "WM_NCDESTROY";
4579 case 0x0083: return "WM_NCCALCSIZE";
4580 case 0x0084: return "WM_NCHITTEST";
4581 case 0x0085: return "WM_NCPAINT";
4582 case 0x0086: return "WM_NCACTIVATE";
4583 case 0x0087: return "WM_GETDLGCODE";
4584 case 0x00A0: return "WM_NCMOUSEMOVE";
4585 case 0x00A1: return "WM_NCLBUTTONDOWN";
4586 case 0x00A2: return "WM_NCLBUTTONUP";
4587 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4588 case 0x00A4: return "WM_NCRBUTTONDOWN";
4589 case 0x00A5: return "WM_NCRBUTTONUP";
4590 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4591 case 0x00A7: return "WM_NCMBUTTONDOWN";
4592 case 0x00A8: return "WM_NCMBUTTONUP";
4593 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4594 case 0x0100: return "WM_KEYDOWN";
4595 case 0x0101: return "WM_KEYUP";
4596 case 0x0102: return "WM_CHAR";
4597 case 0x0103: return "WM_DEADCHAR";
4598 case 0x0104: return "WM_SYSKEYDOWN";
4599 case 0x0105: return "WM_SYSKEYUP";
4600 case 0x0106: return "WM_SYSCHAR";
4601 case 0x0107: return "WM_SYSDEADCHAR";
4602 case 0x0108: return "WM_KEYLAST";
4605 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4606 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4607 case 0x010F: return "WM_IME_COMPOSITION";
4610 case 0x0110: return "WM_INITDIALOG";
4611 case 0x0111: return "WM_COMMAND";
4612 case 0x0112: return "WM_SYSCOMMAND";
4613 case 0x0113: return "WM_TIMER";
4614 case 0x0114: return "WM_HSCROLL";
4615 case 0x0115: return "WM_VSCROLL";
4616 case 0x0116: return "WM_INITMENU";
4617 case 0x0117: return "WM_INITMENUPOPUP";
4618 case 0x011F: return "WM_MENUSELECT";
4619 case 0x0120: return "WM_MENUCHAR";
4620 case 0x0121: return "WM_ENTERIDLE";
4621 case 0x0200: return "WM_MOUSEMOVE";
4622 case 0x0201: return "WM_LBUTTONDOWN";
4623 case 0x0202: return "WM_LBUTTONUP";
4624 case 0x0203: return "WM_LBUTTONDBLCLK";
4625 case 0x0204: return "WM_RBUTTONDOWN";
4626 case 0x0205: return "WM_RBUTTONUP";
4627 case 0x0206: return "WM_RBUTTONDBLCLK";
4628 case 0x0207: return "WM_MBUTTONDOWN";
4629 case 0x0208: return "WM_MBUTTONUP";
4630 case 0x0209: return "WM_MBUTTONDBLCLK";
4631 case 0x020A: return "WM_MOUSEWHEEL";
4632 case 0x0210: return "WM_PARENTNOTIFY";
4633 case 0x0211: return "WM_ENTERMENULOOP";
4634 case 0x0212: return "WM_EXITMENULOOP";
4637 case 0x0213: return "WM_NEXTMENU";
4638 case 0x0214: return "WM_SIZING";
4639 case 0x0215: return "WM_CAPTURECHANGED";
4640 case 0x0216: return "WM_MOVING";
4641 case 0x0218: return "WM_POWERBROADCAST";
4642 case 0x0219: return "WM_DEVICECHANGE";
4645 case 0x0220: return "WM_MDICREATE";
4646 case 0x0221: return "WM_MDIDESTROY";
4647 case 0x0222: return "WM_MDIACTIVATE";
4648 case 0x0223: return "WM_MDIRESTORE";
4649 case 0x0224: return "WM_MDINEXT";
4650 case 0x0225: return "WM_MDIMAXIMIZE";
4651 case 0x0226: return "WM_MDITILE";
4652 case 0x0227: return "WM_MDICASCADE";
4653 case 0x0228: return "WM_MDIICONARRANGE";
4654 case 0x0229: return "WM_MDIGETACTIVE";
4655 case 0x0230: return "WM_MDISETMENU";
4656 case 0x0233: return "WM_DROPFILES";
4659 case 0x0281: return "WM_IME_SETCONTEXT";
4660 case 0x0282: return "WM_IME_NOTIFY";
4661 case 0x0283: return "WM_IME_CONTROL";
4662 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4663 case 0x0285: return "WM_IME_SELECT";
4664 case 0x0286: return "WM_IME_CHAR";
4665 case 0x0290: return "WM_IME_KEYDOWN";
4666 case 0x0291: return "WM_IME_KEYUP";
4669 case 0x0300: return "WM_CUT";
4670 case 0x0301: return "WM_COPY";
4671 case 0x0302: return "WM_PASTE";
4672 case 0x0303: return "WM_CLEAR";
4673 case 0x0304: return "WM_UNDO";
4674 case 0x0305: return "WM_RENDERFORMAT";
4675 case 0x0306: return "WM_RENDERALLFORMATS";
4676 case 0x0307: return "WM_DESTROYCLIPBOARD";
4677 case 0x0308: return "WM_DRAWCLIPBOARD";
4678 case 0x0309: return "WM_PAINTCLIPBOARD";
4679 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4680 case 0x030B: return "WM_SIZECLIPBOARD";
4681 case 0x030C: return "WM_ASKCBFORMATNAME";
4682 case 0x030D: return "WM_CHANGECBCHAIN";
4683 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4684 case 0x030F: return "WM_QUERYNEWPALETTE";
4685 case 0x0310: return "WM_PALETTEISCHANGING";
4686 case 0x0311: return "WM_PALETTECHANGED";
4689 // common controls messages - although they're not strictly speaking
4690 // standard, it's nice to decode them nevertheless
4693 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4694 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4695 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4696 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4697 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4698 case 0x1000 + 5: return "LVM_GETITEMA";
4699 case 0x1000 + 75: return "LVM_GETITEMW";
4700 case 0x1000 + 6: return "LVM_SETITEMA";
4701 case 0x1000 + 76: return "LVM_SETITEMW";
4702 case 0x1000 + 7: return "LVM_INSERTITEMA";
4703 case 0x1000 + 77: return "LVM_INSERTITEMW";
4704 case 0x1000 + 8: return "LVM_DELETEITEM";
4705 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4706 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4707 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4708 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4709 case 0x1000 + 13: return "LVM_FINDITEMA";
4710 case 0x1000 + 83: return "LVM_FINDITEMW";
4711 case 0x1000 + 14: return "LVM_GETITEMRECT";
4712 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4713 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4714 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4715 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4716 case 0x1000 + 18: return "LVM_HITTEST";
4717 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4718 case 0x1000 + 20: return "LVM_SCROLL";
4719 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4720 case 0x1000 + 22: return "LVM_ARRANGE";
4721 case 0x1000 + 23: return "LVM_EDITLABELA";
4722 case 0x1000 + 118: return "LVM_EDITLABELW";
4723 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4724 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4725 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4726 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4727 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4728 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4729 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4730 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4731 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4732 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4733 case 0x1000 + 31: return "LVM_GETHEADER";
4734 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4735 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4736 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4737 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4738 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4739 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4740 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4741 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4742 case 0x1000 + 41: return "LVM_GETORIGIN";
4743 case 0x1000 + 42: return "LVM_UPDATE";
4744 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4745 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4746 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4747 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4748 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4749 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4750 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4751 case 0x1000 + 48: return "LVM_SORTITEMS";
4752 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4753 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4754 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4755 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4756 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4757 case 0x1000 + 53: return "LVM_SETICONSPACING";
4758 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4759 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4760 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4761 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4762 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4763 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4764 case 0x1000 + 60: return "LVM_SETHOTITEM";
4765 case 0x1000 + 61: return "LVM_GETHOTITEM";
4766 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4767 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4768 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4769 case 0x1000 + 65: return "LVM_SETWORKAREA";
4772 case 0x1100 + 0: return "TVM_INSERTITEMA";
4773 case 0x1100 + 50: return "TVM_INSERTITEMW";
4774 case 0x1100 + 1: return "TVM_DELETEITEM";
4775 case 0x1100 + 2: return "TVM_EXPAND";
4776 case 0x1100 + 4: return "TVM_GETITEMRECT";
4777 case 0x1100 + 5: return "TVM_GETCOUNT";
4778 case 0x1100 + 6: return "TVM_GETINDENT";
4779 case 0x1100 + 7: return "TVM_SETINDENT";
4780 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4781 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4782 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4783 case 0x1100 + 11: return "TVM_SELECTITEM";
4784 case 0x1100 + 12: return "TVM_GETITEMA";
4785 case 0x1100 + 62: return "TVM_GETITEMW";
4786 case 0x1100 + 13: return "TVM_SETITEMA";
4787 case 0x1100 + 63: return "TVM_SETITEMW";
4788 case 0x1100 + 14: return "TVM_EDITLABELA";
4789 case 0x1100 + 65: return "TVM_EDITLABELW";
4790 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4791 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4792 case 0x1100 + 17: return "TVM_HITTEST";
4793 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4794 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4795 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4796 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4797 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4798 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4799 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4800 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4801 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4804 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4805 case 0x1200 + 1: return "HDM_INSERTITEMA";
4806 case 0x1200 + 10: return "HDM_INSERTITEMW";
4807 case 0x1200 + 2: return "HDM_DELETEITEM";
4808 case 0x1200 + 3: return "HDM_GETITEMA";
4809 case 0x1200 + 11: return "HDM_GETITEMW";
4810 case 0x1200 + 4: return "HDM_SETITEMA";
4811 case 0x1200 + 12: return "HDM_SETITEMW";
4812 case 0x1200 + 5: return "HDM_LAYOUT";
4813 case 0x1200 + 6: return "HDM_HITTEST";
4814 case 0x1200 + 7: return "HDM_GETITEMRECT";
4815 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4816 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4817 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4818 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4819 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4820 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4821 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4824 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4825 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4826 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4827 case 0x1300 + 5: return "TCM_GETITEMA";
4828 case 0x1300 + 60: return "TCM_GETITEMW";
4829 case 0x1300 + 6: return "TCM_SETITEMA";
4830 case 0x1300 + 61: return "TCM_SETITEMW";
4831 case 0x1300 + 7: return "TCM_INSERTITEMA";
4832 case 0x1300 + 62: return "TCM_INSERTITEMW";
4833 case 0x1300 + 8: return "TCM_DELETEITEM";
4834 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4835 case 0x1300 + 10: return "TCM_GETITEMRECT";
4836 case 0x1300 + 11: return "TCM_GETCURSEL";
4837 case 0x1300 + 12: return "TCM_SETCURSEL";
4838 case 0x1300 + 13: return "TCM_HITTEST";
4839 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4840 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4841 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4842 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
4843 case 0x1300 + 43: return "TCM_SETPADDING";
4844 case 0x1300 + 44: return "TCM_GETROWCOUNT";
4845 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
4846 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
4847 case 0x1300 + 47: return "TCM_GETCURFOCUS";
4848 case 0x1300 + 48: return "TCM_SETCURFOCUS";
4849 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
4850 case 0x1300 + 50: return "TCM_DESELECTALL";
4853 case WM_USER
+1: return "TB_ENABLEBUTTON";
4854 case WM_USER
+2: return "TB_CHECKBUTTON";
4855 case WM_USER
+3: return "TB_PRESSBUTTON";
4856 case WM_USER
+4: return "TB_HIDEBUTTON";
4857 case WM_USER
+5: return "TB_INDETERMINATE";
4858 case WM_USER
+9: return "TB_ISBUTTONENABLED";
4859 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
4860 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
4861 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
4862 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
4863 case WM_USER
+17: return "TB_SETSTATE";
4864 case WM_USER
+18: return "TB_GETSTATE";
4865 case WM_USER
+19: return "TB_ADDBITMAP";
4866 case WM_USER
+20: return "TB_ADDBUTTONS";
4867 case WM_USER
+21: return "TB_INSERTBUTTON";
4868 case WM_USER
+22: return "TB_DELETEBUTTON";
4869 case WM_USER
+23: return "TB_GETBUTTON";
4870 case WM_USER
+24: return "TB_BUTTONCOUNT";
4871 case WM_USER
+25: return "TB_COMMANDTOINDEX";
4872 case WM_USER
+26: return "TB_SAVERESTOREA";
4873 case WM_USER
+76: return "TB_SAVERESTOREW";
4874 case WM_USER
+27: return "TB_CUSTOMIZE";
4875 case WM_USER
+28: return "TB_ADDSTRINGA";
4876 case WM_USER
+77: return "TB_ADDSTRINGW";
4877 case WM_USER
+29: return "TB_GETITEMRECT";
4878 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
4879 case WM_USER
+31: return "TB_SETBUTTONSIZE";
4880 case WM_USER
+32: return "TB_SETBITMAPSIZE";
4881 case WM_USER
+33: return "TB_AUTOSIZE";
4882 case WM_USER
+35: return "TB_GETTOOLTIPS";
4883 case WM_USER
+36: return "TB_SETTOOLTIPS";
4884 case WM_USER
+37: return "TB_SETPARENT";
4885 case WM_USER
+39: return "TB_SETROWS";
4886 case WM_USER
+40: return "TB_GETROWS";
4887 case WM_USER
+42: return "TB_SETCMDID";
4888 case WM_USER
+43: return "TB_CHANGEBITMAP";
4889 case WM_USER
+44: return "TB_GETBITMAP";
4890 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
4891 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
4892 case WM_USER
+46: return "TB_REPLACEBITMAP";
4893 case WM_USER
+47: return "TB_SETINDENT";
4894 case WM_USER
+48: return "TB_SETIMAGELIST";
4895 case WM_USER
+49: return "TB_GETIMAGELIST";
4896 case WM_USER
+50: return "TB_LOADIMAGES";
4897 case WM_USER
+51: return "TB_GETRECT";
4898 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
4899 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
4900 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
4901 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
4902 case WM_USER
+56: return "TB_SETSTYLE";
4903 case WM_USER
+57: return "TB_GETSTYLE";
4904 case WM_USER
+58: return "TB_GETBUTTONSIZE";
4905 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
4906 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
4907 case WM_USER
+61: return "TB_GETTEXTROWS";
4908 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
4913 static char s_szBuf
[128];
4914 sprintf(s_szBuf
, "<unknown message = %d>", message
);
4918 #endif //__WXDEBUG__
4920 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
4921 int *x
, int *y
, WPARAM
*flags
)
4923 // construct the key mask
4924 WPARAM
& fwKeys
= *flags
;
4926 fwKeys
= MK_RBUTTON
;
4927 if ( wxIsCtrlDown() )
4928 fwKeys
|= MK_CONTROL
;
4929 if ( wxIsShiftDown() )
4932 // simulate right mouse button click
4933 DWORD dwPos
= ::GetMessagePos();
4934 *x
= GET_X_LPARAM(dwPos
);
4935 *y
= GET_Y_LPARAM(dwPos
);
4937 win
->ScreenToClient(x
, y
);
4940 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
4944 HWND hwnd
= GetHwndOf(win
);
4945 HDC hdc
= ::GetDC(hwnd
);
4947 #if !wxDIALOG_UNIT_COMPATIBILITY
4948 // and select the current font into it
4949 HFONT hfont
= GetHfontOf(win
->GetFont());
4952 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
4956 // finally retrieve the text metrics from it
4957 GetTextMetrics(hdc
, &tm
);
4959 #if !wxDIALOG_UNIT_COMPATIBILITY
4963 (void)::SelectObject(hdc
, hfont
);
4967 ::ReleaseDC(hwnd
, hdc
);
4972 // Find the wxWindow at the current mouse position, returning the mouse
4974 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
4976 return wxFindWindowAtPoint(wxGetMousePosition());
4979 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
4984 HWND hWndHit
= ::WindowFromPoint(pt2
);
4986 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
4987 HWND hWnd
= hWndHit
;
4989 // Try to find a window with a wxWindow associated with it
4990 while (!win
&& (hWnd
!= 0))
4992 hWnd
= ::GetParent(hWnd
);
4993 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
4998 // Get the current mouse position.
4999 wxPoint
wxGetMousePosition()
5002 GetCursorPos( & pt
);
5003 return wxPoint(pt
.x
, pt
.y
);