1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/windows.cpp
4 // Author: Julian Smart
5 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
21 #pragma implementation "window.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
33 #include "wx/msw/winundef.h"
34 #include "wx/window.h"
39 #include "wx/dcclient.h"
40 #include "wx/dcmemory.h"
43 #include "wx/layout.h"
44 #include "wx/dialog.h"
46 #include "wx/listbox.h"
47 #include "wx/button.h"
48 #include "wx/msgdlg.h"
49 #include "wx/settings.h"
50 #include "wx/statbox.h"
54 #include "wx/ownerdrw.h"
57 #if wxUSE_DRAG_AND_DROP
61 #include "wx/menuitem.h"
64 #include "wx/msw/private.h"
67 #include "wx/tooltip.h"
75 #include "wx/spinctrl.h"
76 #endif // wxUSE_SPINCTRL
81 #include "wx/textctrl.h"
82 #include "wx/notebook.h"
86 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
95 #if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__)
99 #elif !defined(__WXMICROWIN__) // broken compiler
101 #include "wx/msw/gnuwin32/extra.h"
105 // This didn't appear in mingw until 2.95.2
107 #define SIF_TRACKPOS 16
111 #ifndef WM_MOUSEWHEEL
112 #define WM_MOUSEWHEEL 0x020A
115 #define WHEEL_DELTA 120
117 #ifndef SPI_GETWHEELSCROLLLINES
118 #define SPI_GETWHEELSCROLLLINES 104
122 // ---------------------------------------------------------------------------
124 // ---------------------------------------------------------------------------
126 // the last Windows message we got (FIXME-MT)
127 extern MSG s_currentMsg
;
129 #if wxUSE_MENUS_NATIVE
130 wxMenu
*wxCurrentPopupMenu
= NULL
;
131 #endif // wxUSE_MENUS_NATIVE
133 extern const wxChar
*wxCanvasClassName
;
135 // true if we had already created the std colour map, used by
136 // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
137 static bool gs_hasStdCmap
= FALSE
;
139 // ---------------------------------------------------------------------------
141 // ---------------------------------------------------------------------------
143 // the window proc for all our windows
144 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
145 WPARAM wParam
, LPARAM lParam
);
148 const char *wxGetMessageName(int message
);
151 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
152 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
153 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
155 // this magical function is used to translate VK_APPS key presses to right
157 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
158 int *x
, int *y
, WPARAM
*flags
);
160 // get the text metrics for the current font
161 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
163 // wrapper around BringWindowToTop() API
164 static inline void wxBringWindowToTop(HWND hwnd
)
166 #ifdef __WXMICROWIN__
167 // It seems that MicroWindows brings the _parent_ of the window to the top,
168 // which can be the wrong one.
170 // activate (set focus to) specified window
173 // raise top level parent to top of z order
174 ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
175 #else // !__WXMICROWIN__
176 if ( !::BringWindowToTop(hwnd
) )
178 wxLogLastError(_T("BringWindowToTop"));
180 #endif // __WXMICROWIN__/!__WXMICROWIN__
183 // ---------------------------------------------------------------------------
185 // ---------------------------------------------------------------------------
187 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
189 #ifdef __WXUNIVERSAL__
190 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
192 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
193 #endif // __WXUNIVERSAL__/__WXMSW__
195 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
196 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
197 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
198 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
199 EVT_IDLE(wxWindowMSW::OnIdle
)
202 // ===========================================================================
204 // ===========================================================================
206 // ---------------------------------------------------------------------------
207 // wxWindow utility functions
208 // ---------------------------------------------------------------------------
210 // Find an item given the MS Windows id
211 wxWindow
*wxWindowMSW::FindItem(long id
) const
214 wxControl
*item
= wxDynamicCastThis(wxControl
);
217 // is it we or one of our "internal" children?
218 if ( item
->GetId() == id
219 #ifndef __WXUNIVERSAL__
220 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
221 #endif // __WXUNIVERSAL__
227 #endif // wxUSE_CONTROLS
229 wxWindowList::Node
*current
= GetChildren().GetFirst();
232 wxWindow
*childWin
= current
->GetData();
234 wxWindow
*wnd
= childWin
->FindItem(id
);
238 current
= current
->GetNext();
244 // Find an item given the MS Windows handle
245 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
247 wxWindowList::Node
*current
= GetChildren().GetFirst();
250 wxWindow
*parent
= current
->GetData();
252 // Do a recursive search.
253 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
259 || parent
->IsKindOf(CLASSINFO(wxControl
))
260 #endif // wxUSE_CONTROLS
263 wxWindow
*item
= current
->GetData();
264 if ( item
->GetHWND() == hWnd
)
268 if ( item
->ContainsHWND(hWnd
) )
273 current
= current
->GetNext();
278 // Default command handler
279 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
284 // ----------------------------------------------------------------------------
285 // constructors and such
286 // ----------------------------------------------------------------------------
288 void wxWindowMSW::Init()
294 m_doubleClickAllowed
= 0;
296 m_isBeingDeleted
= FALSE
;
299 m_mouseInWindow
= FALSE
;
308 m_backgroundTransparent
= FALSE
;
310 // as all windows are created with WS_VISIBLE style...
313 #if wxUSE_MOUSEEVENT_HACK
316 m_lastMouseEvent
= -1;
317 #endif // wxUSE_MOUSEEVENT_HACK
321 wxWindowMSW::~wxWindowMSW()
323 m_isBeingDeleted
= TRUE
;
325 #ifndef __WXUNIVERSAL__
326 // VS: make sure there's no wxFrame with last focus set to us:
327 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
329 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
332 if ( frame
->GetLastFocus() == this )
334 frame
->SetLastFocus((wxWindow
*)NULL
);
339 #endif // __WXUNIVERSAL__
341 // VS: destroy children first and _then_ detach *this from its parent.
342 // If we'd do it the other way around, children wouldn't be able
343 // find their parent frame (see above).
347 m_parent
->RemoveChild(this);
351 // VZ: test temp removed to understand what really happens here
352 //if (::IsWindow(GetHwnd()))
354 if ( !::DestroyWindow(GetHwnd()) )
355 wxLogLastError(wxT("DestroyWindow"));
358 // remove hWnd <-> wxWindow association
359 wxRemoveHandleAssociation(this);
363 // real construction (Init() must have been called before!)
364 bool wxWindowMSW::Create(wxWindow
*parent
,
369 const wxString
& name
)
371 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
374 // wxGTK doesn't allow to create controls with static box as the parent so
375 // this will result in a crash when the program is ported to wxGTK - warn
378 // the correct solution is to create the controls as siblings of the
380 wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
),
381 _T("wxStaticBox can't be used as a window parent!") );
382 #endif // wxUSE_STATBOX
384 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
387 parent
->AddChild(this);
389 // note that all windows are created visible by default
391 DWORD msflags
= WS_VISIBLE
| MSWGetCreateWindowFlags(&exstyle
);
393 #ifdef __WXUNIVERSAL__
394 // no 3d effects, we draw them ourselves
396 #endif // wxUniversal
398 if ( style
& wxPOPUP_WINDOW
)
400 // a popup window floats on top of everything
401 exstyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
403 // it is also created hidden as other top level windows
404 msflags
&= ~WS_VISIBLE
;
408 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
);
411 // ---------------------------------------------------------------------------
413 // ---------------------------------------------------------------------------
415 void wxWindowMSW::SetFocus()
417 HWND hWnd
= GetHwnd();
418 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
420 #ifndef __WXMICROWIN__
424 if ( !::SetFocus(hWnd
) )
426 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
427 // was there really an error?
428 DWORD dwRes
= ::GetLastError();
431 HWND hwndFocus
= ::GetFocus();
432 if ( hwndFocus
!= hWnd
)
434 wxLogApiError(_T("SetFocus"), dwRes
);
441 // Get the window with the focus
442 wxWindow
*wxWindowBase::FindFocus()
444 HWND hWnd
= ::GetFocus();
447 return wxGetWindowFromHWND((WXHWND
)hWnd
);
453 bool wxWindowMSW::Enable(bool enable
)
455 if ( !wxWindowBase::Enable(enable
) )
458 HWND hWnd
= GetHwnd();
460 ::EnableWindow(hWnd
, (BOOL
)enable
);
462 // VZ: no, this is a bad idea: imagine that you have a dialog with some
463 // disabled controls and disable it - you really wouldn't like the
464 // disabled controls be reenabled too when you reenable the dialog!
466 wxWindowList::Node
*node
= GetChildren().GetFirst();
469 wxWindow
*child
= node
->GetData();
470 child
->Enable(enable
);
472 node
= node
->GetNext();
479 bool wxWindowMSW::Show(bool show
)
481 if ( !wxWindowBase::Show(show
) )
484 HWND hWnd
= GetHwnd();
485 int cshow
= show
? SW_SHOW
: SW_HIDE
;
486 ::ShowWindow(hWnd
, cshow
);
490 wxBringWindowToTop(hWnd
);
496 // Raise the window to the top of the Z order
497 void wxWindowMSW::Raise()
499 wxBringWindowToTop(GetHwnd());
502 // Lower the window to the bottom of the Z order
503 void wxWindowMSW::Lower()
505 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
506 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
509 void wxWindowMSW::SetTitle( const wxString
& title
)
511 SetWindowText(GetHwnd(), title
.c_str());
514 wxString
wxWindowMSW::GetTitle() const
516 return wxGetWindowText(GetHWND());
519 void wxWindowMSW::DoCaptureMouse()
521 HWND hWnd
= GetHwnd();
528 void wxWindowMSW::DoReleaseMouse()
530 if ( !::ReleaseCapture() )
532 wxLogLastError(_T("ReleaseCapture"));
536 /* static */ wxWindow
*wxWindowBase::GetCapture()
538 HWND hwnd
= ::GetCapture();
539 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
542 bool wxWindowMSW::SetFont(const wxFont
& font
)
544 if ( !wxWindowBase::SetFont(font
) )
550 HWND hWnd
= GetHwnd();
553 WXHANDLE hFont
= m_font
.GetResourceHandle();
555 wxASSERT_MSG( hFont
, wxT("should have valid font") );
557 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
562 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
564 if ( !wxWindowBase::SetCursor(cursor
) )
572 HWND hWnd
= GetHwnd();
574 // Change the cursor NOW if we're within the correct window
576 ::GetCursorPos(&point
);
578 RECT rect
= wxGetWindowRect(hWnd
);
580 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
581 ::SetCursor(GetHcursorOf(m_cursor
));
587 void wxWindowMSW::WarpPointer (int x
, int y
)
589 ClientToScreen(&x
, &y
);
591 if ( !::SetCursorPos(x
, y
) )
593 wxLogLastError(_T("SetCursorPos"));
597 #if WXWIN_COMPATIBILITY
598 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
601 #endif // WXWIN_COMPATIBILITY
603 // ---------------------------------------------------------------------------
605 // ---------------------------------------------------------------------------
607 #if WXWIN_COMPATIBILITY
608 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
610 #if defined(__WIN95__)
614 // Try to adjust the range to cope with page size > 1
615 // - a Windows API quirk
616 int pageSize
= GetScrollPage(orient
);
617 if ( pageSize
> 1 && range
> 0)
619 range1
+= (pageSize
- 1);
625 if ( orient
== wxHORIZONTAL
) {
631 info
.cbSize
= sizeof(SCROLLINFO
);
632 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
636 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
638 HWND hWnd
= GetHwnd();
640 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
643 if ( orient
== wxHORIZONTAL
)
648 HWND hWnd
= GetHwnd();
650 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
654 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
656 #if defined(__WIN95__)
660 if ( orient
== wxHORIZONTAL
) {
668 info
.cbSize
= sizeof(SCROLLINFO
);
671 info
.fMask
= SIF_PAGE
;
673 HWND hWnd
= GetHwnd();
675 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
677 if ( orient
== wxHORIZONTAL
)
684 int wxWindowMSW::OldGetScrollRange(int orient
) const
687 if ( orient
== wxHORIZONTAL
)
692 #if __WATCOMC__ && defined(__WINDOWS_386__)
693 short minPos
, maxPos
;
697 HWND hWnd
= GetHwnd();
700 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
701 #if defined(__WIN95__)
702 // Try to adjust the range to cope with page size > 1
703 // - a Windows API quirk
704 int pageSize
= GetScrollPage(orient
);
707 maxPos
-= (pageSize
- 1);
716 int wxWindowMSW::GetScrollPage(int orient
) const
718 if ( orient
== wxHORIZONTAL
)
724 #endif // WXWIN_COMPATIBILITY
726 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
728 #ifdef __WXMICROWIN__
729 return ::GetScrollPosWX(hWnd
, wOrient
);
731 return ::GetScrollPos(hWnd
, wOrient
);
735 int wxWindowMSW::GetScrollPos(int orient
) const
738 if ( orient
== wxHORIZONTAL
)
743 HWND hWnd
= GetHwnd();
744 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
746 return GetScrollPosition(hWnd
, wOrient
);
749 // This now returns the whole range, not just the number
750 // of positions that we can scroll.
751 int wxWindowMSW::GetScrollRange(int orient
) const
754 if ( orient
== wxHORIZONTAL
)
759 #if __WATCOMC__ && defined(__WINDOWS_386__)
760 short minPos
, maxPos
;
764 HWND hWnd
= GetHwnd();
767 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
768 #if defined(__WIN95__)
769 // Try to adjust the range to cope with page size > 1
770 // - a Windows API quirk
771 int pageSize
= GetScrollThumb(orient
);
774 maxPos
-= (pageSize
- 1);
776 // October 10th: new range concept.
786 int wxWindowMSW::GetScrollThumb(int orient
) const
788 if ( orient
== wxHORIZONTAL
)
794 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
796 HWND hWnd
= GetHwnd();
797 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
799 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
801 #if defined(__WIN95__)
803 info
.cbSize
= sizeof(SCROLLINFO
);
807 info
.fMask
= SIF_POS
;
809 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
811 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
812 #endif // __WIN95__/!__WIN95__
815 // New function that will replace some of the above.
816 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
817 int range
, bool refresh
)
819 #if defined(__WIN95__)
820 int oldRange
= range
- thumbVisible
;
822 int range1
= oldRange
;
824 // Try to adjust the range to cope with page size > 1
825 // - a Windows API quirk
826 int pageSize
= thumbVisible
;
827 if ( pageSize
> 1 && range
> 0)
829 range1
+= (pageSize
- 1);
835 if ( orient
== wxHORIZONTAL
) {
841 info
.cbSize
= sizeof(SCROLLINFO
);
842 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
846 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
848 HWND hWnd
= GetHwnd();
850 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
853 if ( orient
== wxHORIZONTAL
)
858 HWND hWnd
= GetHwnd();
861 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
862 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
865 if ( orient
== wxHORIZONTAL
) {
866 m_xThumbSize
= thumbVisible
;
868 m_yThumbSize
= thumbVisible
;
872 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
878 rect
.left
= prect
->x
;
880 rect
.right
= prect
->x
+ prect
->width
;
881 rect
.bottom
= prect
->y
+ prect
->height
;
889 ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
);
892 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
894 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
897 for ( int n
= 0; n
< count
; n
++ )
899 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
901 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
904 // don't bother to continue, we're already at top/bottom
911 return pos
!= posStart
;
914 bool wxWindowMSW::ScrollLines(int lines
)
916 bool down
= lines
> 0;
918 return ScrollVertically(GetHwnd(),
919 down
? SB_LINEDOWN
: SB_LINEUP
,
920 down
? lines
: -lines
);
923 bool wxWindowMSW::ScrollPages(int pages
)
925 bool down
= pages
> 0;
927 return ScrollVertically(GetHwnd(),
928 down
? SB_PAGEDOWN
: SB_PAGEUP
,
929 down
? pages
: -pages
);
932 // ---------------------------------------------------------------------------
934 // ---------------------------------------------------------------------------
936 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
938 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
940 HWND hwnd
= (HWND
)hWnd
;
941 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
943 wxAssociateWinWithHandle(hwnd
, this);
945 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
947 // we don't need to subclass the window of our own class (in the Windows
948 // sense of the word)
949 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
951 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
955 // don't bother restoring it neither
960 void wxWindowMSW::UnsubclassWin()
962 wxRemoveHandleAssociation(this);
964 // Restore old Window proc
965 HWND hwnd
= GetHwnd();
970 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
974 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
976 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
984 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
986 #if wxUSE_UNICODE_MSLU
987 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
988 // because it doesn't return pointer to the real wnd proc but rather a handle
989 // of a fake proc that does Unicode<->ANSI translation.
991 // The hack bellow works, because WNDCLASS contains original window handler
992 // rather that the unicows fake one. This may not be on purpose, though; if
993 // it stops working with future versions of unicows.dll, we can override
994 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
995 // Unicows_RegisterClass to our own versions that keep track of
996 // fake<->real wnd proc mapping.
998 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
999 // with RegisterClass!!
1001 static wxChar buffer
[512];
1004 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1005 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1006 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1008 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1012 // ----------------------------------------------------------------------------
1014 // ----------------------------------------------------------------------------
1016 void wxWindowMSW::SetWindowStyleFlag(long flags
)
1018 long flagsOld
= GetWindowStyleFlag();
1019 if ( flags
== flagsOld
)
1022 // update the internal variable
1023 wxWindowBase::SetWindowStyleFlag(flags
);
1025 // now update the Windows style as well if needed
1026 WXDWORD exstyle
, exstyleOld
;
1027 long style
= MSWGetStyle(flags
, &exstyle
),
1028 styleOld
= MSWGetStyle(flagsOld
, &exstyleOld
);
1030 if ( style
!= styleOld
)
1032 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1033 // this function so instead of simply setting the style to the new
1034 // value we clear the bits which were set in styleOld but are set in
1035 // the new one and set the ones which were not set before
1036 long styleReal
= ::GetWindowLong(GetHwnd(), GWL_STYLE
);
1037 styleReal
&= ~styleOld
;
1040 ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
);
1043 // and the extended style
1044 if ( exstyle
!= exstyleOld
)
1046 long exstyleReal
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
);
1047 exstyleReal
&= ~exstyleOld
;
1048 exstyleReal
|= exstyle
;
1050 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
);
1052 // we must call SetWindowPos() to flash the cached extended style and
1053 // also to make the change to wxSTAY_ON_TOP style take effect: just
1054 // setting the style simply doesn't work
1055 if ( !::SetWindowPos(GetHwnd(),
1056 exstyleReal
& WS_EX_TOPMOST
? HWND_TOPMOST
1059 SWP_NOMOVE
| SWP_NOSIZE
) )
1061 wxLogLastError(_T("SetWindowPos"));
1066 WXDWORD
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD
*exstyle
) const
1068 // translate the style
1069 WXDWORD style
= WS_CHILD
;
1071 if ( flags
& wxCLIP_CHILDREN
)
1072 style
|= WS_CLIPCHILDREN
;
1074 if ( flags
& wxCLIP_SIBLINGS
)
1075 style
|= WS_CLIPSIBLINGS
;
1077 if ( (flags
& wxBORDER_MASK
) != wxBORDER_NONE
)
1080 // now deal with ext style if the caller wants it
1085 if ( flags
& wxTRANSPARENT_WINDOW
)
1086 *exstyle
|= WS_EX_TRANSPARENT
;
1088 switch ( flags
& wxBORDER_MASK
)
1091 wxFAIL_MSG( _T("unknown border style") );
1095 case wxBORDER_SIMPLE
:
1098 case wxBORDER_STATIC
:
1099 *exstyle
|= WS_EX_STATICEDGE
;
1102 case wxBORDER_RAISED
:
1103 *exstyle
|= WS_EX_WINDOWEDGE
;
1106 case wxBORDER_DEFAULT
:
1107 case wxBORDER_SUNKEN
:
1108 *exstyle
|= WS_EX_CLIENTEDGE
;
1111 case wxBORDER_DOUBLE
:
1112 *exstyle
|= WS_EX_DLGMODALFRAME
;
1120 // Make a Windows extended style from the given wxWindows window style
1121 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1123 WXDWORD exStyle
= 0;
1124 if ( style
& wxTRANSPARENT_WINDOW
)
1125 exStyle
|= WS_EX_TRANSPARENT
;
1127 if ( !eliminateBorders
)
1129 if ( style
& wxSUNKEN_BORDER
)
1130 exStyle
|= WS_EX_CLIENTEDGE
;
1131 if ( style
& wxDOUBLE_BORDER
)
1132 exStyle
|= WS_EX_DLGMODALFRAME
;
1133 #if defined(__WIN95__)
1134 if ( style
& wxRAISED_BORDER
)
1135 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1136 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1137 if ( style
& wxSTATIC_BORDER
)
1138 exStyle
|= WS_EX_STATICEDGE
;
1145 // Determines whether native 3D effects or CTL3D should be used,
1146 // applying a default border style if required, and returning an extended
1147 // style to pass to CreateWindowEx.
1148 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1151 // If matches certain criteria, then assume no 3D effects
1152 // unless specifically requested (dealt with in MakeExtendedStyle)
1155 || !IsKindOf(CLASSINFO(wxControl
))
1156 #endif // wxUSE_CONTROLS
1157 || (m_windowStyle
& wxNO_BORDER
) )
1160 return MakeExtendedStyle(m_windowStyle
);
1163 // Determine whether we should be using 3D effects or not.
1164 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1166 // 1) App can specify global 3D effects
1167 *want3D
= wxTheApp
->GetAuto3D();
1169 // 2) If the parent is being drawn with user colours, or simple border specified,
1170 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1171 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1174 // 3) Control can override this global setting by defining
1175 // a border style, e.g. wxSUNKEN_BORDER
1176 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1179 // 4) If it's a special border, CTL3D can't cope so we want a native border
1180 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1181 (m_windowStyle
& wxSTATIC_BORDER
) )
1184 nativeBorder
= TRUE
;
1187 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1188 // effects from extended style
1191 nativeBorder
= FALSE
;
1194 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1196 // If we want 3D, but haven't specified a border here,
1197 // apply the default border style specified.
1198 // TODO what about non-Win95 WIN32? Does it have borders?
1199 #if defined(__WIN95__) && !wxUSE_CTL3D
1200 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1201 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1202 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1208 #if WXWIN_COMPATIBILITY
1209 // If nothing defined for this, try the parent.
1210 // E.g. we may be a button loaded from a resource, with no callback function
1212 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1214 if ( GetEventHandler()->ProcessEvent(event
) )
1217 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1219 #endif // WXWIN_COMPATIBILITY_2
1221 #if WXWIN_COMPATIBILITY
1222 wxObject
* wxWindowMSW::GetChild(int number
) const
1224 // Return a pointer to the Nth object in the Panel
1225 wxNode
*node
= GetChildren().First();
1228 node
= node
->Next();
1231 wxObject
*obj
= (wxObject
*)node
->Data();
1237 #endif // WXWIN_COMPATIBILITY
1239 // Setup background and foreground colours correctly
1240 void wxWindowMSW::SetupColours()
1243 SetBackgroundColour(GetParent()->GetBackgroundColour());
1246 bool wxWindowMSW::IsMouseInWindow() const
1248 // get the mouse position
1250 ::GetCursorPos(&pt
);
1252 // find the window which currently has the cursor and go up the window
1253 // chain until we find this window - or exhaust it
1254 HWND hwnd
= ::WindowFromPoint(pt
);
1255 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1256 hwnd
= ::GetParent(hwnd
);
1258 return hwnd
!= NULL
;
1261 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1263 // Check if we need to send a LEAVE event
1264 if ( m_mouseInWindow
)
1266 if ( !IsMouseInWindow() && !HasCapture())
1268 // Generate a LEAVE event
1269 m_mouseInWindow
= FALSE
;
1271 // Unfortunately the mouse button and keyboard state may have
1272 // changed by the time the OnIdle function is called, so 'state'
1273 // may be meaningless.
1275 if ( wxIsShiftDown() )
1277 if ( wxIsCtrlDown() )
1278 state
|= MK_CONTROL
;
1279 if ( GetKeyState( VK_LBUTTON
) )
1280 state
|= MK_LBUTTON
;
1281 if ( GetKeyState( VK_MBUTTON
) )
1282 state
|= MK_MBUTTON
;
1283 if ( GetKeyState( VK_RBUTTON
) )
1284 state
|= MK_RBUTTON
;
1287 if ( !::GetCursorPos(&pt
) )
1289 wxLogLastError(_T("GetCursorPos"));
1292 // we need to have client coordinates here for symmetry with
1293 // wxEVT_ENTER_WINDOW
1294 RECT rect
= wxGetWindowRect(GetHwnd());
1298 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1299 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1301 (void)GetEventHandler()->ProcessEvent(event2
);
1308 // Set this window to be the child of 'parent'.
1309 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1311 if ( !wxWindowBase::Reparent(parent
) )
1314 HWND hWndChild
= GetHwnd();
1315 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1317 ::SetParent(hWndChild
, hWndParent
);
1322 void wxWindowMSW::Clear()
1324 wxClientDC
dc((wxWindow
*)this);
1325 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1326 dc
.SetBackground(brush
);
1330 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1332 #ifndef __WXMICROWIN__
1333 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1337 void wxWindowMSW::Freeze()
1339 SendSetRedraw(GetHwnd(), FALSE
);
1342 void wxWindowMSW::Thaw()
1344 SendSetRedraw(GetHwnd(), TRUE
);
1346 // we need to refresh everything or otherwise he invalidated area is not
1351 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1353 HWND hWnd
= GetHwnd();
1359 mswRect
.left
= rect
->x
;
1360 mswRect
.top
= rect
->y
;
1361 mswRect
.right
= rect
->x
+ rect
->width
;
1362 mswRect
.bottom
= rect
->y
+ rect
->height
;
1364 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1367 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1371 void wxWindowMSW::Update()
1373 if ( !::UpdateWindow(GetHwnd()) )
1375 wxLogLastError(_T("UpdateWindow"));
1378 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1379 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1380 // handler needs to be really drawn right now
1385 // ---------------------------------------------------------------------------
1387 // ---------------------------------------------------------------------------
1389 #if wxUSE_DRAG_AND_DROP
1391 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1393 if ( m_dropTarget
!= 0 ) {
1394 m_dropTarget
->Revoke(m_hWnd
);
1395 delete m_dropTarget
;
1398 m_dropTarget
= pDropTarget
;
1399 if ( m_dropTarget
!= 0 )
1400 m_dropTarget
->Register(m_hWnd
);
1403 #endif // wxUSE_DRAG_AND_DROP
1405 // old style file-manager drag&drop support: we retain the old-style
1406 // DragAcceptFiles in parallel with SetDropTarget.
1407 void wxWindowMSW::DragAcceptFiles(bool accept
)
1409 HWND hWnd
= GetHwnd();
1411 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1414 // ----------------------------------------------------------------------------
1416 // ----------------------------------------------------------------------------
1420 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1422 wxWindowBase::DoSetToolTip(tooltip
);
1425 m_tooltip
->SetWindow(this);
1428 #endif // wxUSE_TOOLTIPS
1430 // ---------------------------------------------------------------------------
1431 // moving and resizing
1432 // ---------------------------------------------------------------------------
1435 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1437 RECT rect
= wxGetWindowRect(GetHwnd());
1440 *x
= rect
.right
- rect
.left
;
1442 *y
= rect
.bottom
- rect
.top
;
1445 // Get size *available for subwindows* i.e. excluding menu bar etc.
1446 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1448 RECT rect
= wxGetClientRect(GetHwnd());
1456 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1458 RECT rect
= wxGetWindowRect(GetHwnd());
1461 point
.x
= rect
.left
;
1464 // we do the adjustments with respect to the parent only for the "real"
1465 // children, not for the dialogs/frames
1466 if ( !IsTopLevel() )
1468 HWND hParentWnd
= 0;
1469 wxWindow
*parent
= GetParent();
1471 hParentWnd
= GetWinHwnd(parent
);
1473 // Since we now have the absolute screen coords, if there's a parent we
1474 // must subtract its top left corner
1477 ::ScreenToClient(hParentWnd
, &point
);
1482 // We may be faking the client origin. So a window that's really at (0,
1483 // 30) may appear (to wxWin apps) to be at (0, 0).
1484 wxPoint
pt(parent
->GetClientAreaOrigin());
1496 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1504 ::ScreenToClient(GetHwnd(), &pt
);
1512 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1520 ::ClientToScreen(GetHwnd(), &pt
);
1528 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1530 // TODO: is this consistent with other platforms?
1531 // Still, negative width or height shouldn't be allowed
1536 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1538 wxLogLastError(wxT("MoveWindow"));
1542 // set the size of the window: if the dimensions are positive, just use them,
1543 // but if any of them is equal to -1, it means that we must find the value for
1544 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1545 // which case -1 is a valid value for x and y)
1547 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1548 // the width/height to best suit our contents, otherwise we reuse the current
1550 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1552 // get the current size and position...
1553 int currentX
, currentY
;
1554 GetPosition(¤tX
, ¤tY
);
1555 int currentW
,currentH
;
1556 GetSize(¤tW
, ¤tH
);
1558 // ... and don't do anything (avoiding flicker) if it's already ok
1559 if ( x
== currentX
&& y
== currentY
&&
1560 width
== currentW
&& height
== currentH
)
1565 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1567 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1570 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1572 wxSize
size(-1, -1);
1575 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1577 size
= DoGetBestSize();
1582 // just take the current one
1589 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1593 size
= DoGetBestSize();
1595 //else: already called DoGetBestSize() above
1601 // just take the current one
1606 DoMoveWindow(x
, y
, width
, height
);
1609 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1611 // setting the client size is less obvious than it it could have been
1612 // because in the result of changing the total size the window scrollbar
1613 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1614 // will not be correct as the difference between the total and client size
1615 // changes - so we keep changing it until we get it right
1617 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1618 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1619 // may become 3 if the window had 0 size originally and so we didn't
1620 // calculate the scrollbar correction correctly during the first iteration)
1621 // but just to be on the safe side we check for it instead of making it an
1622 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1623 for ( int i
= 0; i
< 4; i
++ )
1626 ::GetClientRect(GetHwnd(), &rectClient
);
1628 // if the size is already ok, stop here (rectClient.left = top = 0)
1629 if ( (rectClient
.right
== width
|| width
== -1) &&
1630 (rectClient
.bottom
== height
|| height
== -1) )
1637 // how did it happen? maybe OnSize() handler does something really
1638 // strange in this class?
1639 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1644 int widthClient
= width
,
1645 heightClient
= height
;
1647 // Find the difference between the entire window (title bar and all)
1648 // and the client area; add this to the new client size to move the
1651 ::GetWindowRect(GetHwnd(), &rectWin
);
1653 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1654 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1657 point
.x
= rectWin
.left
;
1658 point
.y
= rectWin
.top
;
1660 // MoveWindow positions the child windows relative to the parent, so
1661 // adjust if necessary
1662 if ( !IsTopLevel() )
1664 wxWindow
*parent
= GetParent();
1667 ::ScreenToClient(GetHwndOf(parent
), &point
);
1671 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1675 // For implementation purposes - sometimes decorations make the client area
1677 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1679 return wxPoint(0, 0);
1682 // ---------------------------------------------------------------------------
1684 // ---------------------------------------------------------------------------
1686 int wxWindowMSW::GetCharHeight() const
1688 return wxGetTextMetrics(this).tmHeight
;
1691 int wxWindowMSW::GetCharWidth() const
1693 // +1 is needed because Windows apparently adds it when calculating the
1694 // dialog units size in pixels
1695 #if wxDIALOG_UNIT_COMPATIBILITY
1696 return wxGetTextMetrics(this).tmAveCharWidth
;
1698 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1702 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1704 int *descent
, int *externalLeading
,
1705 const wxFont
*theFont
) const
1707 const wxFont
*fontToUse
= theFont
;
1709 fontToUse
= &m_font
;
1711 HWND hWnd
= GetHwnd();
1712 HDC dc
= ::GetDC(hWnd
);
1716 if ( fontToUse
&& fontToUse
->Ok() )
1718 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1720 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1725 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1726 GetTextMetrics(dc
, &tm
);
1728 if ( fontToUse
&& fnt
&& hfontOld
)
1729 SelectObject(dc
, hfontOld
);
1731 ReleaseDC(hWnd
, dc
);
1738 *descent
= tm
.tmDescent
;
1739 if ( externalLeading
)
1740 *externalLeading
= tm
.tmExternalLeading
;
1743 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1744 // ---------------------------------------------------------------------------
1745 // Caret manipulation
1746 // ---------------------------------------------------------------------------
1748 void wxWindowMSW::CreateCaret(int w
, int h
)
1750 SetCaret(new wxCaret(this, w
, h
));
1753 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1755 wxFAIL_MSG("not implemented");
1758 void wxWindowMSW::ShowCaret(bool show
)
1760 wxCHECK_RET( m_caret
, "no caret to show" );
1762 m_caret
->Show(show
);
1765 void wxWindowMSW::DestroyCaret()
1770 void wxWindowMSW::SetCaretPos(int x
, int y
)
1772 wxCHECK_RET( m_caret
, "no caret to move" );
1774 m_caret
->Move(x
, y
);
1777 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1779 wxCHECK_RET( m_caret
, "no caret to get position of" );
1781 m_caret
->GetPosition(x
, y
);
1783 #endif // wxUSE_CARET
1785 // ---------------------------------------------------------------------------
1787 // ---------------------------------------------------------------------------
1789 #if wxUSE_MENUS_NATIVE
1791 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1792 // immediately, without waiting for the next event loop iteration
1794 // NB: this function should probably be made public later as it can almost
1795 // surely replace wxYield() elsewhere as well
1796 static void wxYieldForCommandsOnly()
1798 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1799 // want to process it here)
1801 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1802 && msg
.message
!= WM_QUIT
)
1804 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1808 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1810 menu
->SetInvokingWindow(this);
1813 HWND hWnd
= GetHwnd();
1814 HMENU hMenu
= GetHmenuOf(menu
);
1818 ::ClientToScreen(hWnd
, &point
);
1819 wxCurrentPopupMenu
= menu
;
1820 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1822 // we need to do it righ now as otherwise the events are never going to be
1823 // sent to wxCurrentPopupMenu from HandleCommand()
1825 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1826 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1827 // destroyed as soon as we return (it can be a local variable in the caller
1828 // for example) and so we do need to process the event immediately
1829 wxYieldForCommandsOnly();
1831 wxCurrentPopupMenu
= NULL
;
1833 menu
->SetInvokingWindow(NULL
);
1838 #endif // wxUSE_MENUS_NATIVE
1840 // ===========================================================================
1841 // pre/post message processing
1842 // ===========================================================================
1844 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1847 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1849 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1852 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1854 // wxUniversal implements tab traversal itself
1855 #ifndef __WXUNIVERSAL__
1856 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1858 // intercept dialog navigation keys
1859 MSG
*msg
= (MSG
*)pMsg
;
1861 // here we try to do all the job which ::IsDialogMessage() usually does
1864 bool bProcess
= TRUE
;
1865 if ( msg
->message
!= WM_KEYDOWN
)
1868 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1873 bool bCtrlDown
= wxIsCtrlDown();
1874 bool bShiftDown
= wxIsShiftDown();
1876 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1877 // don't process it if it's the case (except for Ctrl-Tab/Enter
1878 // combinations which are always processed)
1882 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1885 bool bForward
= TRUE
,
1886 bWindowChange
= FALSE
;
1888 switch ( msg
->wParam
)
1891 // assume that nobody wants Shift-TAB for himself - if we
1892 // don't do it there is no easy way for a control to grab
1893 // TABs but still let Shift-TAB work as navugation key
1894 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1898 // Ctrl-Tab cycles thru notebook pages
1899 bWindowChange
= bCtrlDown
;
1900 bForward
= !bShiftDown
;
1906 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1914 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1920 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1922 // control wants to process Enter itself, don't
1923 // call IsDialogMessage() which would interpret
1927 else if ( lDlgCode
& DLGC_BUTTON
)
1929 // let IsDialogMessage() handle this for all
1930 // buttons except the owner-drawn ones which it
1931 // just seems to ignore
1932 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1933 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1935 // emulate the button click
1936 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1938 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1943 // FIXME: this should be handled by
1944 // wxNavigationKeyEvent handler and not here!!
1948 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1950 if ( btn
&& btn
->IsEnabled() )
1952 // if we do have a default button, do press it
1953 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1957 else // no default button
1958 #endif // wxUSE_BUTTON
1960 // no special function for enter and don't even
1961 // let IsDialogMessage() have it: it seems to
1962 // do something really strange with it
1975 wxNavigationKeyEvent event
;
1976 event
.SetDirection(bForward
);
1977 event
.SetWindowChange(bWindowChange
);
1978 event
.SetEventObject(this);
1980 if ( GetEventHandler()->ProcessEvent(event
) )
1987 // let ::IsDialogMessage() do almost everything and handle just the
1988 // things it doesn't here: Ctrl-TAB for switching notebook pages
1989 if ( msg
->message
== WM_KEYDOWN
)
1991 // don't process system keys here
1992 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1994 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1996 // find the first notebook parent and change its page
1997 wxWindow
*win
= this;
1998 wxNotebook
*nbook
= NULL
;
1999 while ( win
&& !nbook
)
2001 nbook
= wxDynamicCast(win
, wxNotebook
);
2002 win
= win
->GetParent();
2007 bool forward
= !wxIsShiftDown();
2009 nbook
->AdvanceSelection(forward
);
2016 if ( ::IsDialogMessage(GetHwnd(), msg
) )
2018 // IsDialogMessage() did something...
2022 #endif // __WXUNIVERSAL__
2027 // relay mouse move events to the tooltip control
2028 MSG
*msg
= (MSG
*)pMsg
;
2029 if ( msg
->message
== WM_MOUSEMOVE
)
2030 m_tooltip
->RelayEvent(pMsg
);
2032 #endif // wxUSE_TOOLTIPS
2037 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
2039 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
2040 return m_acceleratorTable
.Translate(this, pMsg
);
2044 #endif // wxUSE_ACCEL
2047 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
))
2049 // preprocess all messages by default
2053 // ---------------------------------------------------------------------------
2054 // message params unpackers (different for Win16 and Win32)
2055 // ---------------------------------------------------------------------------
2059 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2060 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
2062 *id
= LOWORD(wParam
);
2063 *hwnd
= (WXHWND
)lParam
;
2064 *cmd
= HIWORD(wParam
);
2067 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2068 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2070 *state
= LOWORD(wParam
);
2071 *minimized
= HIWORD(wParam
);
2072 *hwnd
= (WXHWND
)lParam
;
2075 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2076 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2078 *code
= LOWORD(wParam
);
2079 *pos
= HIWORD(wParam
);
2080 *hwnd
= (WXHWND
)lParam
;
2083 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2084 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2086 #ifndef __WXMICROWIN__
2087 *nCtlColor
= CTLCOLOR_BTN
;
2088 *hwnd
= (WXHWND
)lParam
;
2089 *hdc
= (WXHDC
)wParam
;
2093 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2094 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2096 *item
= (WXWORD
)wParam
;
2097 *flags
= HIWORD(wParam
);
2098 *hmenu
= (WXHMENU
)lParam
;
2103 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2104 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2106 *id
= (WXWORD
)wParam
;
2107 *hwnd
= (WXHWND
)LOWORD(lParam
);
2108 *cmd
= HIWORD(lParam
);
2111 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2112 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2114 *state
= (WXWORD
)wParam
;
2115 *minimized
= LOWORD(lParam
);
2116 *hwnd
= (WXHWND
)HIWORD(lParam
);
2119 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2120 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2122 *code
= (WXWORD
)wParam
;
2123 *pos
= LOWORD(lParam
);
2124 *hwnd
= (WXHWND
)HIWORD(lParam
);
2127 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2128 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2130 *hwnd
= (WXHWND
)LOWORD(lParam
);
2131 *nCtlColor
= (int)HIWORD(lParam
);
2132 *hdc
= (WXHDC
)wParam
;
2135 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2136 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2138 *item
= (WXWORD
)wParam
;
2139 *flags
= LOWORD(lParam
);
2140 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2145 // ---------------------------------------------------------------------------
2146 // Main wxWindows window proc and the window proc for wxWindow
2147 // ---------------------------------------------------------------------------
2149 // Hook for new window just as it's being created, when the window isn't yet
2150 // associated with the handle
2151 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2153 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2154 // window being created and insures that it's always unset back later
2155 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2157 gs_winBeingCreated
= winBeingCreated
;
2160 wxWindowCreationHook::~wxWindowCreationHook()
2162 gs_winBeingCreated
= NULL
;
2166 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2168 // trace all messages - useful for the debugging
2170 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2171 wxGetMessageName(message
), wParam
, lParam
);
2172 #endif // __WXDEBUG__
2174 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2176 // when we get the first message for the HWND we just created, we associate
2177 // it with wxWindow stored in gs_winBeingCreated
2178 if ( !wnd
&& gs_winBeingCreated
)
2180 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2181 wnd
= gs_winBeingCreated
;
2182 gs_winBeingCreated
= NULL
;
2183 wnd
->SetHWND((WXHWND
)hWnd
);
2189 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2191 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2196 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2198 // did we process the message?
2199 bool processed
= FALSE
;
2210 // for most messages we should return 0 when we do process the message
2218 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2221 // return 0 to allow window creation
2222 rc
.result
= mayCreate
? 0 : -1;
2228 // never set processed to TRUE and *always* pass WM_DESTROY to
2229 // DefWindowProc() as Windows may do some internal cleanup when
2230 // processing it and failing to pass the message along may cause
2231 // memory and resource leaks!
2232 (void)HandleDestroy();
2236 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2244 // we're not interested in these messages at all
2247 case SIZE_MINIMIZED
:
2248 // we shouldn't send sizev events for these messages as the
2249 // client size may be negative which breaks existing code
2251 // OTOH we might send another (wxMinimizedEvent?) one or
2252 // add an additional parameter to wxSizeEvent if this is
2253 // useful to anybody
2257 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2258 // fall through nevertheless
2260 case SIZE_MAXIMIZED
:
2262 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2267 #ifndef __WXMICROWIN__
2268 case WM_ACTIVATEAPP
:
2269 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2275 WXWORD state
, minimized
;
2277 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2279 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2284 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2288 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2292 processed
= HandlePaint();
2296 // don't let the DefWindowProc() destroy our window - we'll do it
2297 // ourselves in ~wxWindow
2303 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2307 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2308 GET_Y_LPARAM(lParam
),
2312 #if wxUSE_MOUSEWHEEL
2314 processed
= HandleMouseWheel(wParam
, lParam
);
2318 case WM_LBUTTONDOWN
:
2320 case WM_LBUTTONDBLCLK
:
2321 case WM_RBUTTONDOWN
:
2323 case WM_RBUTTONDBLCLK
:
2324 case WM_MBUTTONDOWN
:
2326 case WM_MBUTTONDBLCLK
:
2329 #ifdef __WXMICROWIN__
2330 // MicroWindows seems to ignore the fact that a window is
2331 // disabled. So catch mouse events and throw them away if
2333 wxWindowMSW
* win
= this;
2336 if (!win
->IsEnabled())
2341 win
= win
->GetParent();
2342 if (win
&& win
->IsTopLevel())
2345 #endif // __WXMICROWIN__
2348 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2350 processed
= HandleMouseEvent(message
,
2351 GET_X_LPARAM(lParam
),
2352 GET_Y_LPARAM(lParam
),
2358 #ifdef __WXMICROWIN__
2359 case WM_NCLBUTTONDOWN
:
2360 case WM_NCLBUTTONUP
:
2361 case WM_NCLBUTTONDBLCLK
:
2362 case WM_NCRBUTTONDOWN
:
2363 case WM_NCRBUTTONUP
:
2364 case WM_NCRBUTTONDBLCLK
:
2366 case WM_NCMBUTTONDOWN
:
2367 case WM_NCMBUTTONUP
:
2368 case WM_NCMBUTTONDBLCLK
:
2371 // MicroWindows seems to ignore the fact that a window
2372 // is disabled. So catch mouse events and throw them away if necessary.
2374 wxWindowMSW
* win
= this;
2377 if (!win
->IsEnabled())
2382 win
= win
->GetParent();
2383 if (win
&& win
->IsTopLevel())
2388 #endif // __WXMICROWIN__
2395 case MM_JOY1BUTTONDOWN
:
2396 case MM_JOY2BUTTONDOWN
:
2397 case MM_JOY1BUTTONUP
:
2398 case MM_JOY2BUTTONUP
:
2399 processed
= HandleJoystickEvent(message
,
2400 GET_X_LPARAM(lParam
),
2401 GET_Y_LPARAM(lParam
),
2404 #endif // __WXMICROWIN__
2407 processed
= HandleSysCommand(wParam
, lParam
);
2414 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2416 processed
= HandleCommand(id
, cmd
, hwnd
);
2422 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2426 // for these messages we must return TRUE if process the message
2429 case WM_MEASUREITEM
:
2431 int idCtrl
= (UINT
)wParam
;
2432 if ( message
== WM_DRAWITEM
)
2434 processed
= MSWOnDrawItem(idCtrl
,
2435 (WXDRAWITEMSTRUCT
*)lParam
);
2439 processed
= MSWOnMeasureItem(idCtrl
,
2440 (WXMEASUREITEMSTRUCT
*)lParam
);
2447 #endif // defined(WM_DRAWITEM)
2450 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
2452 // want everything: i.e. all keys and WM_CHAR message
2453 rc
.result
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
2454 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
2457 //else: get the dlg code from the DefWindowProc()
2462 // If this has been processed by an event handler,
2463 // return 0 now (we've handled it).
2464 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2471 // we consider these message "not interesting" to OnChar
2472 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2481 // avoid duplicate messages to OnChar for these ASCII keys: they
2482 // will be translated by TranslateMessage() and received in WM_CHAR
2490 // but set processed to FALSE, not TRUE to still pass them to
2491 // the control's default window proc - otherwise built-in
2492 // keyboard handling won't work
2498 // special case of VK_APPS: treat it the same as right mouse
2499 // click because both usually pop up a context menu
2505 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2506 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2516 processed
= HandleChar((WORD
)wParam
, lParam
);
2523 // special case of VK_APPS: treat it the same as right mouse button
2524 if ( wParam
== VK_APPS
)
2529 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2530 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2535 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2540 case WM_CHAR
: // Always an ASCII character
2541 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2549 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2551 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2557 // CTLCOLOR messages are sent by children to query the parent for their
2558 // colors#ifndef __WXMICROWIN__
2559 #ifndef __WXMICROWIN__
2561 case WM_CTLCOLORMSGBOX
:
2562 case WM_CTLCOLOREDIT
:
2563 case WM_CTLCOLORLISTBOX
:
2564 case WM_CTLCOLORBTN
:
2565 case WM_CTLCOLORDLG
:
2566 case WM_CTLCOLORSCROLLBAR
:
2567 case WM_CTLCOLORSTATIC
:
2575 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2577 processed
= HandleCtlColor(&rc
.hBrush
,
2586 #endif // !__WXMICROWIN__
2588 case WM_SYSCOLORCHANGE
:
2589 // the return value for this message is ignored
2590 processed
= HandleSysColorChange();
2593 case WM_DISPLAYCHANGE
:
2594 processed
= HandleDisplayChange();
2597 case WM_PALETTECHANGED
:
2598 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2601 case WM_QUERYNEWPALETTE
:
2602 processed
= HandleQueryNewPalette();
2606 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2609 // we processed the message, i.e. erased the background
2615 processed
= HandleDropFiles(wParam
);
2619 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2623 // we never set focus from here
2628 case WM_QUERYENDSESSION
:
2629 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2633 processed
= HandleEndSession(wParam
!= 0, lParam
);
2636 case WM_GETMINMAXINFO
:
2637 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2641 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2642 LOWORD(lParam
), // hit test
2643 HIWORD(lParam
)); // mouse msg
2647 // returning TRUE stops the DefWindowProc() from further
2648 // processing this message - exactly what we need because we've
2649 // just set the cursor.
2654 #if defined(__WIN32__) && defined(WM_HELP)
2657 HELPINFO
* info
= (HELPINFO
*) lParam
;
2658 // Don't yet process menu help events, just windows
2659 if (info
->iContextType
== HELPINFO_WINDOW
)
2661 wxWindowMSW
* subjectOfHelp
= this;
2662 bool eventProcessed
= FALSE
;
2663 while (subjectOfHelp
&& !eventProcessed
)
2665 wxHelpEvent
helpEvent(wxEVT_HELP
,
2666 subjectOfHelp
->GetId(),
2667 wxPoint(info
->MousePos
.x
,
2668 info
->MousePos
.y
) );
2669 helpEvent
.SetEventObject(this);
2671 GetEventHandler()->ProcessEvent(helpEvent
);
2673 // Go up the window hierarchy until the event is
2675 subjectOfHelp
= subjectOfHelp
->GetParent();
2678 processed
= eventProcessed
;
2680 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2682 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2683 helpEvent
.SetEventObject(this);
2684 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2687 //else: processed is already FALSE
2691 case WM_CONTEXTMENU
:
2693 // we don't convert from screen to client coordinates as
2694 // the event may be handled by a parent window
2695 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2697 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2698 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2703 // unfortunately this doesn't really work as then window which
2704 // doesn't accept focus doesn't get any mouse events neither which
2705 // means it can't get any input at all
2706 #if 0 //def __WXUNIVERSAL__
2708 // we shouldn't allow the windows which don't want to get focus to
2710 if ( !AcceptsFocus() )
2712 rc
.result
= HTTRANSPARENT
;
2716 #endif // __WXUNIVERSAL__
2722 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2723 wxGetMessageName(message
));
2724 #endif // __WXDEBUG__
2725 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2731 // ----------------------------------------------------------------------------
2732 // wxWindow <-> HWND map
2733 // ----------------------------------------------------------------------------
2735 wxWinHashTable
*wxWinHandleHash
= NULL
;
2737 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2739 return wxWinHandleHash
->Get((long)hWnd
);
2742 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2744 // adding NULL hWnd is (first) surely a result of an error and
2745 // (secondly) breaks menu command processing
2746 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2747 wxT("attempt to add a NULL hWnd to window list ignored") );
2749 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2751 if ( oldWin
&& (oldWin
!= win
) )
2753 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2754 hWnd
, win
->GetClassInfo()->GetClassName());
2757 #endif // __WXDEBUG__
2760 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2764 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2766 wxWinHandleHash
->Delete((long)win
->GetHWND());
2769 // ----------------------------------------------------------------------------
2770 // various MSW speciic class dependent functions
2771 // ----------------------------------------------------------------------------
2773 // Default destroyer - override if you destroy it in some other way
2774 // (e.g. with MDI child windows)
2775 void wxWindowMSW::MSWDestroyWindow()
2779 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2782 int& w
, int& h
) const
2784 bool nonDefault
= FALSE
;
2788 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2789 // just as well set it to CW_USEDEFAULT as well
2796 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2802 NB: there used to be some code here which set the initial size of the
2803 window to the client size of the parent if no explicit size was
2804 specified. This was wrong because wxWindows programs often assume
2805 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2806 it. To see why, you should understand that Windows sends WM_SIZE from
2807 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2808 from some base class ctor and so this WM_SIZE is not processed in the
2809 real class' OnSize() (because it's not fully constructed yet and the
2810 event goes to some base class OnSize() instead). So the WM_SIZE we
2811 rely on is the one sent when the parent frame resizes its children
2812 but here is the problem: if the child already has just the right
2813 size, nothing will happen as both wxWindows and Windows check for
2814 this and ignore any attempts to change the window size to the size it
2815 already has - so no WM_SIZE would be sent.
2819 // as abobe, h is not used at all in this case anyhow
2826 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2834 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2835 const wxChar
*title
,
2839 WXDWORD extendedStyle
)
2841 // choose the position/size for the new window
2843 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2845 // find the correct parent HWND
2846 wxWindow
*parent
= GetParent();
2847 bool isChild
= (style
& WS_CHILD
) != 0;
2849 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2851 // popup windows should have desktop as parent because they shouldn't
2852 // be limited to the parents client area as child windows usually are
2853 hParent
= ::GetDesktopWindow();
2857 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2859 // this is either a normal child window or a top level window with
2860 // wxFRAME_TOOL_WINDOW style (see below)
2861 hParent
= GetHwndOf(parent
);
2865 // this is either a window for which no parent was specified (not
2866 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2867 // style: we should use NULL parent HWND for it or it would be
2868 // always on top of its parent which is not what we usually want
2869 // (in fact, we only want it for frames with the special
2870 // wxFRAME_TOOL_WINDOW as above)
2876 // controlId is menu handle for the top level windows, so set it to 0
2877 // unless we're creating a child window
2881 controlId
= GetId();
2883 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2885 style
|= WS_CLIPSIBLINGS
;
2893 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2894 // which is the same but without CS_[HV]REDRAW class styles so using it
2895 // ensures that the window is not fully repainted on each resize
2896 wxString
className(wclass
);
2897 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2899 className
+= wxT("NR");
2902 // do create the window
2903 wxWindowCreationHook
hook(this);
2905 m_hWnd
= (WXHWND
)::CreateWindowEx
2909 title
? title
: wxT(""),
2915 NULL
// no extra data
2920 wxLogSysError(_("Can't create window of class %s"), wclass
);
2925 SubclassWin(m_hWnd
);
2927 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2932 // ===========================================================================
2933 // MSW message handlers
2934 // ===========================================================================
2936 // ---------------------------------------------------------------------------
2938 // ---------------------------------------------------------------------------
2941 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2942 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2944 #ifndef __WXMICROWIN__
2945 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2946 HWND hWnd
= hdr
->hwndFrom
;
2947 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2949 // is this one of our windows?
2952 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2955 // try all our children
2956 wxWindowList::Node
*node
= GetChildren().GetFirst();
2959 wxWindow
*child
= node
->GetData();
2960 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2965 node
= node
->GetNext();
2968 // finally try this window too (catches toolbar case)
2969 return MSWOnNotify(idCtrl
, lParam
, result
);
2970 #else // __WXMICROWIN__
2975 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2977 WXLPARAM
* WXUNUSED(result
))
2980 NMHDR
* hdr
= (NMHDR
*)lParam
;
2981 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2983 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2984 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2989 #endif // wxUSE_TOOLTIPS
2995 // ---------------------------------------------------------------------------
2996 // end session messages
2997 // ---------------------------------------------------------------------------
2999 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
3001 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
3002 event
.SetEventObject(wxTheApp
);
3003 event
.SetCanVeto(TRUE
);
3004 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
3006 bool rc
= wxTheApp
->ProcessEvent(event
);
3010 // we may end only if the app didn't veto session closing (double
3012 *mayEnd
= !event
.GetVeto();
3018 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
3020 // do nothing if the session isn't ending
3025 if ( (this != wxTheApp
->GetTopWindow()) )
3028 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
3029 event
.SetEventObject(wxTheApp
);
3030 event
.SetCanVeto(FALSE
);
3031 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
3033 return wxTheApp
->ProcessEvent(event
);
3036 // ---------------------------------------------------------------------------
3037 // window creation/destruction
3038 // ---------------------------------------------------------------------------
3040 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
3042 // TODO: should generate this event from WM_NCCREATE
3043 wxWindowCreateEvent
event((wxWindow
*)this);
3044 (void)GetEventHandler()->ProcessEvent(event
);
3051 bool wxWindowMSW::HandleDestroy()
3053 wxWindowDestroyEvent
event((wxWindow
*)this);
3054 (void)GetEventHandler()->ProcessEvent(event
);
3056 // delete our drop target if we've got one
3057 #if wxUSE_DRAG_AND_DROP
3058 if ( m_dropTarget
!= NULL
)
3060 m_dropTarget
->Revoke(m_hWnd
);
3062 delete m_dropTarget
;
3063 m_dropTarget
= NULL
;
3065 #endif // wxUSE_DRAG_AND_DROP
3067 // WM_DESTROY handled
3071 // ---------------------------------------------------------------------------
3073 // ---------------------------------------------------------------------------
3075 bool wxWindowMSW::HandleActivate(int state
,
3076 bool WXUNUSED(minimized
),
3077 WXHWND
WXUNUSED(activate
))
3079 wxActivateEvent
event(wxEVT_ACTIVATE
,
3080 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3082 event
.SetEventObject(this);
3084 return GetEventHandler()->ProcessEvent(event
);
3087 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3089 // notify the parent keeping track of focus for the kbd navigation
3090 // purposes that we got it
3091 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3092 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3098 m_caret
->OnSetFocus();
3100 #endif // wxUSE_CARET
3103 // If it's a wxTextCtrl don't send the event as it will be done
3104 // after the control gets to process it from EN_FOCUS handler
3105 if ( wxDynamicCastThis(wxTextCtrl
) )
3109 #endif // wxUSE_TEXTCTRL
3111 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3112 event
.SetEventObject(this);
3114 // wxFindWinFromHandle() may return NULL, it is ok
3115 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3117 return GetEventHandler()->ProcessEvent(event
);
3120 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3126 m_caret
->OnKillFocus();
3128 #endif // wxUSE_CARET
3131 // If it's a wxTextCtrl don't send the event as it will be done
3132 // after the control gets to process it.
3133 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3140 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3141 event
.SetEventObject(this);
3143 // wxFindWinFromHandle() may return NULL, it is ok
3144 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3146 return GetEventHandler()->ProcessEvent(event
);
3149 // ---------------------------------------------------------------------------
3151 // ---------------------------------------------------------------------------
3153 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3155 wxShowEvent
event(GetId(), show
);
3156 event
.m_eventObject
= this;
3158 return GetEventHandler()->ProcessEvent(event
);
3161 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3163 wxInitDialogEvent
event(GetId());
3164 event
.m_eventObject
= this;
3166 return GetEventHandler()->ProcessEvent(event
);
3169 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3171 #ifndef __WXMICROWIN__
3172 HDROP hFilesInfo
= (HDROP
) wParam
;
3174 // Get the total number of files dropped
3175 UINT gwFilesDropped
= ::DragQueryFile
3183 wxString
*files
= new wxString
[gwFilesDropped
];
3184 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3186 // first get the needed buffer length (+1 for terminating NUL)
3187 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3189 // and now get the file name
3190 ::DragQueryFile(hFilesInfo
, wIndex
,
3191 files
[wIndex
].GetWriteBuf(len
), len
);
3193 files
[wIndex
].UngetWriteBuf();
3195 DragFinish (hFilesInfo
);
3197 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3198 event
.m_eventObject
= this;
3201 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3202 event
.m_pos
.x
= dropPoint
.x
;
3203 event
.m_pos
.y
= dropPoint
.y
;
3205 return GetEventHandler()->ProcessEvent(event
);
3206 #else // __WXMICROWIN__
3211 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3213 int WXUNUSED(mouseMsg
))
3215 #ifndef __WXMICROWIN__
3216 // the logic is as follows:
3217 // -1. don't set cursor for non client area, including but not limited to
3218 // the title bar, scrollbars, &c
3219 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3220 // 1. if we have the cursor set it unless wxIsBusy()
3221 // 2. if we're a top level window, set some cursor anyhow
3222 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3224 if ( nHitTest
!= HTCLIENT
)
3229 HCURSOR hcursor
= 0;
3231 // first ask the user code - it may wish to set the cursor in some very
3232 // specific way (for example, depending on the current position)
3235 if ( !::GetCursorPos(&pt
) )
3237 wxLogLastError(wxT("GetCursorPos"));
3240 // In WIN16 it doesn't return a value.
3241 ::GetCursorPos(&pt
);
3246 ScreenToClient(&x
, &y
);
3247 wxSetCursorEvent
event(x
, y
);
3249 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3250 if ( processedEvtSetCursor
&& event
.HasCursor() )
3252 hcursor
= GetHcursorOf(event
.GetCursor());
3257 bool isBusy
= wxIsBusy();
3259 // the test for processedEvtSetCursor is here to prevent using m_cursor
3260 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3261 // it - this is a way to say that our cursor shouldn't be used for this
3263 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3265 hcursor
= GetHcursorOf(m_cursor
);
3272 hcursor
= wxGetCurrentBusyCursor();
3274 else if ( !hcursor
)
3276 const wxCursor
*cursor
= wxGetGlobalCursor();
3277 if ( cursor
&& cursor
->Ok() )
3279 hcursor
= GetHcursorOf(*cursor
);
3287 ::SetCursor(hcursor
);
3289 // cursor set, stop here
3292 #endif // __WXMICROWIN__
3294 // pass up the window chain
3298 // ---------------------------------------------------------------------------
3299 // owner drawn stuff
3300 // ---------------------------------------------------------------------------
3302 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3304 #if wxUSE_OWNER_DRAWN
3306 #if wxUSE_MENUS_NATIVE
3307 // is it a menu item?
3308 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3309 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3311 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3313 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3315 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3316 // the DC from being released
3317 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3318 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3319 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3320 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3322 return pMenuItem
->OnDrawItem
3326 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3327 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3330 #endif // wxUSE_MENUS_NATIVE
3333 wxWindow
*item
= FindItem(id
);
3334 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3336 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3338 #endif // wxUSE_CONTROLS
3340 #endif // USE_OWNER_DRAWN
3345 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3347 #if wxUSE_OWNER_DRAWN
3348 // is it a menu item?
3349 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3350 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3352 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3354 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3356 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3357 &pMeasureStruct
->itemHeight
);
3360 wxWindow
*item
= FindItem(id
);
3361 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3363 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3365 #endif // owner-drawn menus
3369 // ---------------------------------------------------------------------------
3370 // colours and palettes
3371 // ---------------------------------------------------------------------------
3373 bool wxWindowMSW::HandleSysColorChange()
3375 wxSysColourChangedEvent event
;
3376 event
.SetEventObject(this);
3378 (void)GetEventHandler()->ProcessEvent(event
);
3380 // always let the system carry on the default processing to allow the
3381 // native controls to react to the colours update
3385 bool wxWindowMSW::HandleDisplayChange()
3387 wxDisplayChangedEvent event
;
3388 event
.SetEventObject(this);
3390 return GetEventHandler()->ProcessEvent(event
);
3393 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3401 #ifndef __WXMICROWIN__
3402 WXHBRUSH hBrush
= 0;
3404 if ( nCtlColor
== CTLCOLOR_DLG
)
3406 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3411 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3413 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3415 #endif // wxUSE_CONTROLS
3421 #else // __WXMICROWIN__
3426 // Define for each class of dialog and control
3427 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3428 WXHWND
WXUNUSED(hWnd
),
3429 WXUINT
WXUNUSED(nCtlColor
),
3430 WXUINT
WXUNUSED(message
),
3431 WXWPARAM
WXUNUSED(wParam
),
3432 WXLPARAM
WXUNUSED(lParam
))
3437 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3440 // same as below except we don't respond to our own messages
3441 if ( hWndPalChange
!= GetHWND() )
3443 // check to see if we our our parents have a custom palette
3444 wxWindow
*win
= this;
3445 while ( win
&& !win
->HasCustomPalette() )
3447 win
= win
->GetParent();
3450 if ( win
&& win
->HasCustomPalette() )
3452 // realize the palette to see whether redrawing is needed
3453 HDC hdc
= ::GetDC((HWND
) hWndPalChange
);
3454 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3455 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3457 int result
= ::RealizePalette(hdc
);
3459 // restore the palette (before releasing the DC)
3460 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3461 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3462 ::RealizePalette(hdc
);
3463 ::ReleaseDC((HWND
) hWndPalChange
, hdc
);
3465 // now check for the need to redraw
3467 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
);
3471 #endif // wxUSE_PALETTE
3473 wxPaletteChangedEvent
event(GetId());
3474 event
.SetEventObject(this);
3475 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3477 return GetEventHandler()->ProcessEvent(event
);
3480 bool wxWindowMSW::HandleQueryNewPalette()
3484 // check to see if we our our parents have a custom palette
3485 wxWindow
*win
= this;
3486 while (!win
->HasCustomPalette() && win
->GetParent()) win
= win
->GetParent();
3487 if (win
->HasCustomPalette()) {
3488 /* realize the palette to see whether redrawing is needed */
3489 HDC hdc
= GetDC((HWND
) GetHWND());
3490 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3491 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) );
3493 int result
= ::RealizePalette(hdc
);
3494 /* restore the palette (before releasing the DC) */
3495 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3496 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) );
3497 ::RealizePalette(hdc
);
3498 ::ReleaseDC((HWND
) GetHWND(), hdc
);
3499 /* now check for the need to redraw */
3501 ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
);
3503 #endif // wxUSE_PALETTE
3505 wxQueryNewPaletteEvent
event(GetId());
3506 event
.SetEventObject(this);
3508 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3511 // Responds to colour changes: passes event on to children.
3512 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
))
3514 // the top level window also reset the standard colour map as it might have
3515 // changed (there is no need to do it for the non top level windows as we
3516 // only have to do it once)
3520 gs_hasStdCmap
= FALSE
;
3522 wxWindowList::Node
*node
= GetChildren().GetFirst();
3525 // Only propagate to non-top-level windows because Windows already
3526 // sends this event to all top-level ones
3527 wxWindow
*win
= node
->GetData();
3528 if ( !win
->IsTopLevel() )
3530 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3531 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3532 // the standard controls
3533 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3536 node
= node
->GetNext();
3539 // update the colours we use if they were not set explicitly by the user:
3540 // this must be done or OnCtlColor() would continue to use the old colours
3543 m_foregroundColour
= wxSystemSettings::
3544 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3549 m_backgroundColour
= wxSystemSettings::
3550 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3554 extern wxCOLORMAP
*wxGetStdColourMap()
3556 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3557 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3559 if ( !gs_hasStdCmap
)
3561 static bool s_coloursInit
= FALSE
;
3563 if ( !s_coloursInit
)
3565 // When a bitmap is loaded, the RGB values can change (apparently
3566 // because Windows adjusts them to care for the old programs always
3567 // using 0xc0c0c0 while the transparent colour for the new Windows
3568 // versions is different). But we do this adjustment ourselves so
3569 // we want to avoid Windows' "help" and for this we need to have a
3570 // reference bitmap which can tell us what the RGB values change
3572 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3573 if ( stdColourBitmap
.Ok() )
3575 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3576 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3577 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3580 memDC
.SelectObject(stdColourBitmap
);
3583 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3585 memDC
.GetPixel(i
, 0, &colour
);
3586 s_stdColours
[i
] = wxColourToRGB(colour
);
3589 else // wxBITMAP_STD_COLOURS couldn't be loaded
3591 s_stdColours
[0] = RGB(000,000,000); // black
3592 s_stdColours
[1] = RGB(128,128,128); // dark grey
3593 s_stdColours
[2] = RGB(192,192,192); // light grey
3594 s_stdColours
[3] = RGB(255,255,255); // white
3595 //s_stdColours[4] = RGB(000,000,255); // blue
3596 //s_stdColours[5] = RGB(255,000,255); // magenta
3599 s_coloursInit
= TRUE
;
3602 gs_hasStdCmap
= TRUE
;
3604 // create the colour map
3605 #define INIT_CMAP_ENTRY(col) \
3606 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3607 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3609 INIT_CMAP_ENTRY(BTNTEXT
);
3610 INIT_CMAP_ENTRY(BTNSHADOW
);
3611 INIT_CMAP_ENTRY(BTNFACE
);
3612 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3614 #undef INIT_CMAP_ENTRY
3620 // ---------------------------------------------------------------------------
3622 // ---------------------------------------------------------------------------
3624 bool wxWindowMSW::HandlePaint()
3627 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3629 wxLogLastError(wxT("CreateRectRgn"));
3630 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3631 wxLogLastError(wxT("GetUpdateRgn"));
3633 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3636 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3638 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3639 updateRect
.right
- updateRect
.left
,
3640 updateRect
.bottom
- updateRect
.top
);
3643 wxPaintEvent
event(m_windowId
);
3644 event
.SetEventObject(this);
3646 bool processed
= GetEventHandler()->ProcessEvent(event
);
3648 // note that we must generate NC event after the normal one as otherwise
3649 // BeginPaint() will happily overwrite our decorations with the background
3651 wxNcPaintEvent
eventNc(m_windowId
);
3652 eventNc
.SetEventObject(this);
3653 GetEventHandler()->ProcessEvent(eventNc
);
3658 // Can be called from an application's OnPaint handler
3659 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3661 #ifdef __WXUNIVERSAL__
3664 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3667 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3672 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3674 // Prevents flicker when dragging
3675 if ( ::IsIconic(GetHwnd()) )
3681 dc
.SetWindow((wxWindow
*)this);
3684 wxEraseEvent
event(m_windowId
, &dc
);
3685 event
.SetEventObject(this);
3686 bool rc
= GetEventHandler()->ProcessEvent(event
);
3690 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3691 dc
.SelectOldObjects(hdc
);
3696 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3699 ::GetClientRect(GetHwnd(), &rect
);
3701 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3702 m_backgroundColour
.Green(),
3703 m_backgroundColour
.Blue());
3704 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3706 wxLogLastError(wxT("CreateSolidBrush"));
3708 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3710 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3712 ::FillRect(hdc
, &rect
, hBrush
);
3713 ::DeleteObject(hBrush
);
3714 ::SetMapMode(hdc
, mode
);
3717 // ---------------------------------------------------------------------------
3718 // moving and resizing
3719 // ---------------------------------------------------------------------------
3721 bool wxWindowMSW::HandleMinimize()
3723 wxIconizeEvent
event(m_windowId
);
3724 event
.SetEventObject(this);
3726 return GetEventHandler()->ProcessEvent(event
);
3729 bool wxWindowMSW::HandleMaximize()
3731 wxMaximizeEvent
event(m_windowId
);
3732 event
.SetEventObject(this);
3734 return GetEventHandler()->ProcessEvent(event
);
3737 bool wxWindowMSW::HandleMove(int x
, int y
)
3739 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3740 event
.SetEventObject(this);
3742 return GetEventHandler()->ProcessEvent(event
);
3745 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3747 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3748 event
.SetEventObject(this);
3750 return GetEventHandler()->ProcessEvent(event
);
3753 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3755 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3759 int minWidth
= GetMinWidth(),
3760 minHeight
= GetMinHeight(),
3761 maxWidth
= GetMaxWidth(),
3762 maxHeight
= GetMaxHeight();
3764 if ( minWidth
!= -1 )
3766 info
->ptMinTrackSize
.x
= minWidth
;
3770 if ( minHeight
!= -1 )
3772 info
->ptMinTrackSize
.y
= minHeight
;
3776 if ( maxWidth
!= -1 )
3778 info
->ptMaxTrackSize
.x
= maxWidth
;
3782 if ( maxHeight
!= -1 )
3784 info
->ptMaxTrackSize
.y
= maxHeight
;
3791 // ---------------------------------------------------------------------------
3793 // ---------------------------------------------------------------------------
3795 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3797 #if wxUSE_MENUS_NATIVE
3798 if ( !cmd
&& wxCurrentPopupMenu
)
3800 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3801 wxCurrentPopupMenu
= NULL
;
3803 return popupMenu
->MSWCommand(cmd
, id
);
3805 #endif // wxUSE_MENUS_NATIVE
3807 wxWindow
*win
= NULL
;
3809 // first try to find it from HWND - this works even with the broken
3810 // programs using the same ids for different controls
3813 win
= wxFindWinFromHandle(control
);
3819 // must cast to a signed type before comparing with other ids!
3820 win
= FindItem((signed short)id
);
3825 return win
->MSWCommand(cmd
, id
);
3828 // the messages sent from the in-place edit control used by the treectrl
3829 // for label editing have id == 0, but they should _not_ be treated as menu
3830 // messages (they are EN_XXX ones, in fact) so don't translate anything
3831 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3834 // If no child window, it may be an accelerator, e.g. for a popup menu
3837 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3838 event
.SetEventObject(this);
3842 return GetEventHandler()->ProcessEvent(event
);
3844 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3847 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3848 // notifications to its parent which we want to reflect back to
3850 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3851 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3854 #endif // wxUSE_SPINCTRL
3859 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3861 // 4 bits are reserved
3862 switch ( wParam
& 0xFFFFFFF0 )
3865 return HandleMaximize();
3868 return HandleMinimize();
3874 // ---------------------------------------------------------------------------
3876 // ---------------------------------------------------------------------------
3878 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3882 // our client coords are not quite the same as Windows ones
3883 wxPoint pt
= GetClientAreaOrigin();
3884 event
.m_x
= x
- pt
.x
;
3885 event
.m_y
= y
- pt
.y
;
3887 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3888 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3889 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3890 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3891 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3892 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3894 event
.SetTimestamp(s_currentMsg
.time
);
3895 event
.m_eventObject
= this;
3897 #if wxUSE_MOUSEEVENT_HACK
3900 m_lastMouseEvent
= event
.GetEventType();
3901 #endif // wxUSE_MOUSEEVENT_HACK
3904 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3906 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3907 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3908 // from the message id and take the value in the table to get wxWin event
3910 static const wxEventType eventsMouse
[] =
3924 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3925 InitMouseEvent(event
, x
, y
, flags
);
3927 return GetEventHandler()->ProcessEvent(event
);
3930 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3932 if ( !m_mouseInWindow
)
3934 // it would be wrong to assume that just because we get a mouse move
3935 // event that the mouse is inside the window: although this is usually
3936 // true, it is not if we had captured the mouse, so we need to check
3937 // the mouse coordinates here
3938 if ( !HasCapture() || IsMouseInWindow() )
3940 // Generate an ENTER event
3941 m_mouseInWindow
= TRUE
;
3943 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3944 InitMouseEvent(event
, x
, y
, flags
);
3946 (void)GetEventHandler()->ProcessEvent(event
);
3950 #if wxUSE_MOUSEEVENT_HACK
3951 // Window gets a click down message followed by a mouse move message even
3952 // if position isn't changed! We want to discard the trailing move event
3953 // if x and y are the same.
3954 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3955 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3956 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3957 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3959 m_lastMouseEvent
= wxEVT_MOTION
;
3963 #endif // wxUSE_MOUSEEVENT_HACK
3965 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3969 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3971 #if wxUSE_MOUSEWHEEL
3972 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3973 InitMouseEvent(event
,
3974 GET_X_LPARAM(lParam
),
3975 GET_Y_LPARAM(lParam
),
3977 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3978 event
.m_wheelDelta
= WHEEL_DELTA
;
3981 static int s_linesPerRotation
= -1;
3982 if ( s_linesPerRotation
== -1 )
3984 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3985 &s_linesPerRotation
, 0))
3987 // this is not supposed to happen
3988 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3990 // the default is 3, so use it if SystemParametersInfo() failed
3991 s_linesPerRotation
= 3;
3995 // no SystemParametersInfo() under Win16
3996 static const int s_linesPerRotation
= 3;
3999 event
.m_linesPerAction
= s_linesPerRotation
;
4000 return GetEventHandler()->ProcessEvent(event
);
4011 // ---------------------------------------------------------------------------
4012 // keyboard handling
4013 // ---------------------------------------------------------------------------
4015 // create the key event of the given type for the given key - used by
4016 // HandleChar and HandleKeyDown/Up
4017 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
4019 WXLPARAM lParam
) const
4021 wxKeyEvent
event(evType
);
4022 event
.SetId(GetId());
4023 event
.m_shiftDown
= wxIsShiftDown();
4024 event
.m_controlDown
= wxIsCtrlDown();
4025 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
4027 event
.m_eventObject
= (wxWindow
*)this; // const_cast
4028 event
.m_keyCode
= id
;
4029 event
.SetTimestamp(s_currentMsg
.time
);
4031 // translate the position to client coords
4035 GetWindowRect(GetHwnd(),&rect
);
4045 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
4047 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
4049 bool ctrlDown
= FALSE
;
4054 // If 1 -> 26, translate to CTRL plus a letter.
4056 if ( (id
> 0) && (id
< 27) )
4078 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
4080 // it's ASCII and will be processed here only when called from
4081 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
4087 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
4090 event
.m_controlDown
= TRUE
;
4093 if ( GetEventHandler()->ProcessEvent(event
) )
4100 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
4102 int id
= wxCharCodeMSWToWX(wParam
);
4106 // normal ASCII char
4110 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4112 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
4113 if ( GetEventHandler()->ProcessEvent(event
) )
4122 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
4124 int id
= wxCharCodeMSWToWX(wParam
);
4128 // normal ASCII char
4132 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4134 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
4135 if ( GetEventHandler()->ProcessEvent(event
) )
4142 // ---------------------------------------------------------------------------
4144 // ---------------------------------------------------------------------------
4146 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4150 if ( flags
& JOY_BUTTON1CHG
)
4151 change
= wxJOY_BUTTON1
;
4152 if ( flags
& JOY_BUTTON2CHG
)
4153 change
= wxJOY_BUTTON2
;
4154 if ( flags
& JOY_BUTTON3CHG
)
4155 change
= wxJOY_BUTTON3
;
4156 if ( flags
& JOY_BUTTON4CHG
)
4157 change
= wxJOY_BUTTON4
;
4160 if ( flags
& JOY_BUTTON1
)
4161 buttons
|= wxJOY_BUTTON1
;
4162 if ( flags
& JOY_BUTTON2
)
4163 buttons
|= wxJOY_BUTTON2
;
4164 if ( flags
& JOY_BUTTON3
)
4165 buttons
|= wxJOY_BUTTON3
;
4166 if ( flags
& JOY_BUTTON4
)
4167 buttons
|= wxJOY_BUTTON4
;
4169 // the event ids aren't consecutive so we can't use table based lookup
4171 wxEventType eventType
;
4176 eventType
= wxEVT_JOY_MOVE
;
4181 eventType
= wxEVT_JOY_MOVE
;
4186 eventType
= wxEVT_JOY_ZMOVE
;
4191 eventType
= wxEVT_JOY_ZMOVE
;
4194 case MM_JOY1BUTTONDOWN
:
4196 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4199 case MM_JOY2BUTTONDOWN
:
4201 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4204 case MM_JOY1BUTTONUP
:
4206 eventType
= wxEVT_JOY_BUTTON_UP
;
4209 case MM_JOY2BUTTONUP
:
4211 eventType
= wxEVT_JOY_BUTTON_UP
;
4215 wxFAIL_MSG(wxT("no such joystick event"));
4220 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4221 event
.SetPosition(wxPoint(x
, y
));
4222 event
.SetEventObject(this);
4224 return GetEventHandler()->ProcessEvent(event
);
4230 // ---------------------------------------------------------------------------
4232 // ---------------------------------------------------------------------------
4234 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4235 WXWORD pos
, WXHWND control
)
4239 wxWindow
*child
= wxFindWinFromHandle(control
);
4241 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4244 wxScrollWinEvent event
;
4245 event
.SetPosition(pos
);
4246 event
.SetOrientation(orientation
);
4247 event
.m_eventObject
= this;
4252 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4256 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4260 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4264 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4268 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4272 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4275 case SB_THUMBPOSITION
:
4278 // under Win32, the scrollbar range and position are 32 bit integers,
4279 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4280 // explicitly query the scrollbar for the correct position (this must
4281 // be done only for these two SB_ events as they are the only one
4282 // carrying the scrollbar position)
4284 SCROLLINFO scrollInfo
;
4285 wxZeroMemory(scrollInfo
);
4286 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4287 scrollInfo
.fMask
= SIF_TRACKPOS
;
4289 if ( !::GetScrollInfo(GetHwnd(),
4290 orientation
== wxHORIZONTAL
? SB_HORZ
4294 wxLogLastError(_T("GetScrollInfo"));
4297 event
.SetPosition(scrollInfo
.nTrackPos
);
4301 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4302 ? wxEVT_SCROLLWIN_THUMBRELEASE
4303 : wxEVT_SCROLLWIN_THUMBTRACK
;
4310 return GetEventHandler()->ProcessEvent(event
);
4313 // ===========================================================================
4315 // ===========================================================================
4317 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4320 HDC dc
= ::GetDC((HWND
) wnd
);
4325 // the_font->UseResource();
4326 // the_font->RealizeResource();
4327 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4329 was
= (HFONT
) SelectObject(dc
,fnt
);
4331 GetTextMetrics(dc
, &tm
);
4332 if ( the_font
&& fnt
&& was
)
4334 SelectObject(dc
,was
);
4336 ReleaseDC((HWND
)wnd
, dc
);
4339 *x
= tm
.tmAveCharWidth
;
4341 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4344 // the_font->ReleaseResource();
4347 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4348 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4349 int wxCharCodeMSWToWX(int keySym
)
4354 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4355 case VK_BACK
: id
= WXK_BACK
; break;
4356 case VK_TAB
: id
= WXK_TAB
; break;
4357 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4358 case VK_RETURN
: id
= WXK_RETURN
; break;
4359 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4360 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4361 case VK_MENU
: id
= WXK_MENU
; break;
4362 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4363 case VK_SPACE
: id
= WXK_SPACE
; break;
4364 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4365 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4366 case VK_NEXT
: id
= WXK_NEXT
; break;
4367 case VK_END
: id
= WXK_END
; break;
4368 case VK_HOME
: id
= WXK_HOME
; break;
4369 case VK_LEFT
: id
= WXK_LEFT
; break;
4370 case VK_UP
: id
= WXK_UP
; break;
4371 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4372 case VK_DOWN
: id
= WXK_DOWN
; break;
4373 case VK_SELECT
: id
= WXK_SELECT
; break;
4374 case VK_PRINT
: id
= WXK_PRINT
; break;
4375 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4376 case VK_INSERT
: id
= WXK_INSERT
; break;
4377 case VK_DELETE
: id
= WXK_DELETE
; break;
4378 case VK_HELP
: id
= WXK_HELP
; break;
4379 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4380 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4381 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4382 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4383 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4384 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4385 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4386 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4387 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4388 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4389 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4390 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4391 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4392 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4393 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4394 case VK_F1
: id
= WXK_F1
; break;
4395 case VK_F2
: id
= WXK_F2
; break;
4396 case VK_F3
: id
= WXK_F3
; break;
4397 case VK_F4
: id
= WXK_F4
; break;
4398 case VK_F5
: id
= WXK_F5
; break;
4399 case VK_F6
: id
= WXK_F6
; break;
4400 case VK_F7
: id
= WXK_F7
; break;
4401 case VK_F8
: id
= WXK_F8
; break;
4402 case VK_F9
: id
= WXK_F9
; break;
4403 case VK_F10
: id
= WXK_F10
; break;
4404 case VK_F11
: id
= WXK_F11
; break;
4405 case VK_F12
: id
= WXK_F12
; break;
4406 case VK_F13
: id
= WXK_F13
; break;
4407 case VK_F14
: id
= WXK_F14
; break;
4408 case VK_F15
: id
= WXK_F15
; break;
4409 case VK_F16
: id
= WXK_F16
; break;
4410 case VK_F17
: id
= WXK_F17
; break;
4411 case VK_F18
: id
= WXK_F18
; break;
4412 case VK_F19
: id
= WXK_F19
; break;
4413 case VK_F20
: id
= WXK_F20
; break;
4414 case VK_F21
: id
= WXK_F21
; break;
4415 case VK_F22
: id
= WXK_F22
; break;
4416 case VK_F23
: id
= WXK_F23
; break;
4417 case VK_F24
: id
= WXK_F24
; break;
4418 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4419 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4427 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4433 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4434 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4435 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4436 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4437 case WXK_MENU
: keySym
= VK_MENU
; break;
4438 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4439 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4440 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4441 case WXK_END
: keySym
= VK_END
; break;
4442 case WXK_HOME
: keySym
= VK_HOME
; break;
4443 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4444 case WXK_UP
: keySym
= VK_UP
; break;
4445 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4446 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4447 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4448 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4449 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4450 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4451 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4452 case WXK_HELP
: keySym
= VK_HELP
; break;
4453 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4454 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4455 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4456 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4457 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4458 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4459 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4460 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4461 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4462 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4463 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4464 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4465 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4466 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4467 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4468 case WXK_F1
: keySym
= VK_F1
; break;
4469 case WXK_F2
: keySym
= VK_F2
; break;
4470 case WXK_F3
: keySym
= VK_F3
; break;
4471 case WXK_F4
: keySym
= VK_F4
; break;
4472 case WXK_F5
: keySym
= VK_F5
; break;
4473 case WXK_F6
: keySym
= VK_F6
; break;
4474 case WXK_F7
: keySym
= VK_F7
; break;
4475 case WXK_F8
: keySym
= VK_F8
; break;
4476 case WXK_F9
: keySym
= VK_F9
; break;
4477 case WXK_F10
: keySym
= VK_F10
; break;
4478 case WXK_F11
: keySym
= VK_F11
; break;
4479 case WXK_F12
: keySym
= VK_F12
; break;
4480 case WXK_F13
: keySym
= VK_F13
; break;
4481 case WXK_F14
: keySym
= VK_F14
; break;
4482 case WXK_F15
: keySym
= VK_F15
; break;
4483 case WXK_F16
: keySym
= VK_F16
; break;
4484 case WXK_F17
: keySym
= VK_F17
; break;
4485 case WXK_F18
: keySym
= VK_F18
; break;
4486 case WXK_F19
: keySym
= VK_F19
; break;
4487 case WXK_F20
: keySym
= VK_F20
; break;
4488 case WXK_F21
: keySym
= VK_F21
; break;
4489 case WXK_F22
: keySym
= VK_F22
; break;
4490 case WXK_F23
: keySym
= VK_F23
; break;
4491 case WXK_F24
: keySym
= VK_F24
; break;
4492 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4493 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4504 wxWindow
*wxGetActiveWindow()
4506 HWND hWnd
= GetActiveWindow();
4509 return wxFindWinFromHandle((WXHWND
) hWnd
);
4514 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4516 HWND hwnd
= (HWND
)hWnd
;
4518 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4519 // by code in msw/radiobox.cpp), for all the others we just search up the
4521 wxWindow
*win
= (wxWindow
*)NULL
;
4524 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4527 // all these hacks only work under Win32 anyhow
4531 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4532 // wxWindow class which overrides WM_GETDLGCODE processing to
4533 // do it as well, win would be already non NULL
4534 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4536 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4538 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4539 #endif // wxUSE_RADIOBOX
4541 // spin control text buddy window should be mapped to spin ctrl
4542 // itself so try it too
4543 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4546 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4548 #endif // wxUSE_SPINCTRL
4554 while ( hwnd
&& !win
)
4556 // this is a really ugly hack needed to avoid mistakenly returning the
4557 // parent frame wxWindow for the find/replace modeless dialog HWND -
4558 // this, in turn, is needed to call IsDialogMessage() from
4559 // wxApp::ProcessMessage() as for this we must return NULL from here
4561 // FIXME: this is clearly not the best way to do it but I think we'll
4562 // need to change HWND <-> wxWindow code more heavily than I can
4563 // do it now to fix it
4564 #ifndef __WXMICROWIN__
4565 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4567 // it's a dialog box, don't go upwards
4572 hwnd
= ::GetParent(hwnd
);
4573 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4579 #ifndef __WXMICROWIN__
4581 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4582 // in active frames and dialogs, regardless of where the focus is.
4583 static HHOOK wxTheKeyboardHook
= 0;
4584 static FARPROC wxTheKeyboardHookProc
= 0;
4585 int APIENTRY _EXPORT
4586 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4588 void wxSetKeyboardHook(bool doIt
)
4592 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4593 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4595 #if defined(__WIN32__) && !defined(__TWIN32__)
4596 GetCurrentThreadId()
4597 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4605 UnhookWindowsHookEx(wxTheKeyboardHook
);
4607 // avoids warning about statement with no effect (FreeProcInstance
4608 // doesn't do anything under Win32)
4609 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4610 FreeProcInstance(wxTheKeyboardHookProc
);
4615 int APIENTRY _EXPORT
4616 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4618 DWORD hiWord
= HIWORD(lParam
);
4619 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4621 int id
= wxCharCodeMSWToWX(wParam
);
4624 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4625 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4626 event
.m_altDown
= TRUE
;
4628 event
.m_eventObject
= NULL
;
4629 event
.m_keyCode
= id
;
4630 event
.m_shiftDown
= wxIsShiftDown();
4631 event
.m_controlDown
= wxIsCtrlDown();
4632 event
.SetTimestamp(s_currentMsg
.time
);
4634 wxWindow
*win
= wxGetActiveWindow();
4635 wxEvtHandler
*handler
;
4638 handler
= win
->GetEventHandler();
4639 event
.SetId(win
->GetId());
4647 if ( handler
&& handler
->ProcessEvent(event
) )
4655 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4658 #endif // !__WXMICROWIN__
4661 const char *wxGetMessageName(int message
)
4665 case 0x0000: return "WM_NULL";
4666 case 0x0001: return "WM_CREATE";
4667 case 0x0002: return "WM_DESTROY";
4668 case 0x0003: return "WM_MOVE";
4669 case 0x0005: return "WM_SIZE";
4670 case 0x0006: return "WM_ACTIVATE";
4671 case 0x0007: return "WM_SETFOCUS";
4672 case 0x0008: return "WM_KILLFOCUS";
4673 case 0x000A: return "WM_ENABLE";
4674 case 0x000B: return "WM_SETREDRAW";
4675 case 0x000C: return "WM_SETTEXT";
4676 case 0x000D: return "WM_GETTEXT";
4677 case 0x000E: return "WM_GETTEXTLENGTH";
4678 case 0x000F: return "WM_PAINT";
4679 case 0x0010: return "WM_CLOSE";
4680 case 0x0011: return "WM_QUERYENDSESSION";
4681 case 0x0012: return "WM_QUIT";
4682 case 0x0013: return "WM_QUERYOPEN";
4683 case 0x0014: return "WM_ERASEBKGND";
4684 case 0x0015: return "WM_SYSCOLORCHANGE";
4685 case 0x0016: return "WM_ENDSESSION";
4686 case 0x0017: return "WM_SYSTEMERROR";
4687 case 0x0018: return "WM_SHOWWINDOW";
4688 case 0x0019: return "WM_CTLCOLOR";
4689 case 0x001A: return "WM_WININICHANGE";
4690 case 0x001B: return "WM_DEVMODECHANGE";
4691 case 0x001C: return "WM_ACTIVATEAPP";
4692 case 0x001D: return "WM_FONTCHANGE";
4693 case 0x001E: return "WM_TIMECHANGE";
4694 case 0x001F: return "WM_CANCELMODE";
4695 case 0x0020: return "WM_SETCURSOR";
4696 case 0x0021: return "WM_MOUSEACTIVATE";
4697 case 0x0022: return "WM_CHILDACTIVATE";
4698 case 0x0023: return "WM_QUEUESYNC";
4699 case 0x0024: return "WM_GETMINMAXINFO";
4700 case 0x0026: return "WM_PAINTICON";
4701 case 0x0027: return "WM_ICONERASEBKGND";
4702 case 0x0028: return "WM_NEXTDLGCTL";
4703 case 0x002A: return "WM_SPOOLERSTATUS";
4704 case 0x002B: return "WM_DRAWITEM";
4705 case 0x002C: return "WM_MEASUREITEM";
4706 case 0x002D: return "WM_DELETEITEM";
4707 case 0x002E: return "WM_VKEYTOITEM";
4708 case 0x002F: return "WM_CHARTOITEM";
4709 case 0x0030: return "WM_SETFONT";
4710 case 0x0031: return "WM_GETFONT";
4711 case 0x0037: return "WM_QUERYDRAGICON";
4712 case 0x0039: return "WM_COMPAREITEM";
4713 case 0x0041: return "WM_COMPACTING";
4714 case 0x0044: return "WM_COMMNOTIFY";
4715 case 0x0046: return "WM_WINDOWPOSCHANGING";
4716 case 0x0047: return "WM_WINDOWPOSCHANGED";
4717 case 0x0048: return "WM_POWER";
4720 case 0x004A: return "WM_COPYDATA";
4721 case 0x004B: return "WM_CANCELJOURNAL";
4722 case 0x004E: return "WM_NOTIFY";
4723 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4724 case 0x0051: return "WM_INPUTLANGCHANGE";
4725 case 0x0052: return "WM_TCARD";
4726 case 0x0053: return "WM_HELP";
4727 case 0x0054: return "WM_USERCHANGED";
4728 case 0x0055: return "WM_NOTIFYFORMAT";
4729 case 0x007B: return "WM_CONTEXTMENU";
4730 case 0x007C: return "WM_STYLECHANGING";
4731 case 0x007D: return "WM_STYLECHANGED";
4732 case 0x007E: return "WM_DISPLAYCHANGE";
4733 case 0x007F: return "WM_GETICON";
4734 case 0x0080: return "WM_SETICON";
4737 case 0x0081: return "WM_NCCREATE";
4738 case 0x0082: return "WM_NCDESTROY";
4739 case 0x0083: return "WM_NCCALCSIZE";
4740 case 0x0084: return "WM_NCHITTEST";
4741 case 0x0085: return "WM_NCPAINT";
4742 case 0x0086: return "WM_NCACTIVATE";
4743 case 0x0087: return "WM_GETDLGCODE";
4744 case 0x00A0: return "WM_NCMOUSEMOVE";
4745 case 0x00A1: return "WM_NCLBUTTONDOWN";
4746 case 0x00A2: return "WM_NCLBUTTONUP";
4747 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4748 case 0x00A4: return "WM_NCRBUTTONDOWN";
4749 case 0x00A5: return "WM_NCRBUTTONUP";
4750 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4751 case 0x00A7: return "WM_NCMBUTTONDOWN";
4752 case 0x00A8: return "WM_NCMBUTTONUP";
4753 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4754 case 0x0100: return "WM_KEYDOWN";
4755 case 0x0101: return "WM_KEYUP";
4756 case 0x0102: return "WM_CHAR";
4757 case 0x0103: return "WM_DEADCHAR";
4758 case 0x0104: return "WM_SYSKEYDOWN";
4759 case 0x0105: return "WM_SYSKEYUP";
4760 case 0x0106: return "WM_SYSCHAR";
4761 case 0x0107: return "WM_SYSDEADCHAR";
4762 case 0x0108: return "WM_KEYLAST";
4765 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4766 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4767 case 0x010F: return "WM_IME_COMPOSITION";
4770 case 0x0110: return "WM_INITDIALOG";
4771 case 0x0111: return "WM_COMMAND";
4772 case 0x0112: return "WM_SYSCOMMAND";
4773 case 0x0113: return "WM_TIMER";
4774 case 0x0114: return "WM_HSCROLL";
4775 case 0x0115: return "WM_VSCROLL";
4776 case 0x0116: return "WM_INITMENU";
4777 case 0x0117: return "WM_INITMENUPOPUP";
4778 case 0x011F: return "WM_MENUSELECT";
4779 case 0x0120: return "WM_MENUCHAR";
4780 case 0x0121: return "WM_ENTERIDLE";
4781 case 0x0200: return "WM_MOUSEMOVE";
4782 case 0x0201: return "WM_LBUTTONDOWN";
4783 case 0x0202: return "WM_LBUTTONUP";
4784 case 0x0203: return "WM_LBUTTONDBLCLK";
4785 case 0x0204: return "WM_RBUTTONDOWN";
4786 case 0x0205: return "WM_RBUTTONUP";
4787 case 0x0206: return "WM_RBUTTONDBLCLK";
4788 case 0x0207: return "WM_MBUTTONDOWN";
4789 case 0x0208: return "WM_MBUTTONUP";
4790 case 0x0209: return "WM_MBUTTONDBLCLK";
4791 case 0x020A: return "WM_MOUSEWHEEL";
4792 case 0x0210: return "WM_PARENTNOTIFY";
4793 case 0x0211: return "WM_ENTERMENULOOP";
4794 case 0x0212: return "WM_EXITMENULOOP";
4797 case 0x0213: return "WM_NEXTMENU";
4798 case 0x0214: return "WM_SIZING";
4799 case 0x0215: return "WM_CAPTURECHANGED";
4800 case 0x0216: return "WM_MOVING";
4801 case 0x0218: return "WM_POWERBROADCAST";
4802 case 0x0219: return "WM_DEVICECHANGE";
4805 case 0x0220: return "WM_MDICREATE";
4806 case 0x0221: return "WM_MDIDESTROY";
4807 case 0x0222: return "WM_MDIACTIVATE";
4808 case 0x0223: return "WM_MDIRESTORE";
4809 case 0x0224: return "WM_MDINEXT";
4810 case 0x0225: return "WM_MDIMAXIMIZE";
4811 case 0x0226: return "WM_MDITILE";
4812 case 0x0227: return "WM_MDICASCADE";
4813 case 0x0228: return "WM_MDIICONARRANGE";
4814 case 0x0229: return "WM_MDIGETACTIVE";
4815 case 0x0230: return "WM_MDISETMENU";
4816 case 0x0233: return "WM_DROPFILES";
4819 case 0x0281: return "WM_IME_SETCONTEXT";
4820 case 0x0282: return "WM_IME_NOTIFY";
4821 case 0x0283: return "WM_IME_CONTROL";
4822 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4823 case 0x0285: return "WM_IME_SELECT";
4824 case 0x0286: return "WM_IME_CHAR";
4825 case 0x0290: return "WM_IME_KEYDOWN";
4826 case 0x0291: return "WM_IME_KEYUP";
4829 case 0x0300: return "WM_CUT";
4830 case 0x0301: return "WM_COPY";
4831 case 0x0302: return "WM_PASTE";
4832 case 0x0303: return "WM_CLEAR";
4833 case 0x0304: return "WM_UNDO";
4834 case 0x0305: return "WM_RENDERFORMAT";
4835 case 0x0306: return "WM_RENDERALLFORMATS";
4836 case 0x0307: return "WM_DESTROYCLIPBOARD";
4837 case 0x0308: return "WM_DRAWCLIPBOARD";
4838 case 0x0309: return "WM_PAINTCLIPBOARD";
4839 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4840 case 0x030B: return "WM_SIZECLIPBOARD";
4841 case 0x030C: return "WM_ASKCBFORMATNAME";
4842 case 0x030D: return "WM_CHANGECBCHAIN";
4843 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4844 case 0x030F: return "WM_QUERYNEWPALETTE";
4845 case 0x0310: return "WM_PALETTEISCHANGING";
4846 case 0x0311: return "WM_PALETTECHANGED";
4849 // common controls messages - although they're not strictly speaking
4850 // standard, it's nice to decode them nevertheless
4853 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4854 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4855 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4856 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4857 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4858 case 0x1000 + 5: return "LVM_GETITEMA";
4859 case 0x1000 + 75: return "LVM_GETITEMW";
4860 case 0x1000 + 6: return "LVM_SETITEMA";
4861 case 0x1000 + 76: return "LVM_SETITEMW";
4862 case 0x1000 + 7: return "LVM_INSERTITEMA";
4863 case 0x1000 + 77: return "LVM_INSERTITEMW";
4864 case 0x1000 + 8: return "LVM_DELETEITEM";
4865 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4866 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4867 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4868 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4869 case 0x1000 + 13: return "LVM_FINDITEMA";
4870 case 0x1000 + 83: return "LVM_FINDITEMW";
4871 case 0x1000 + 14: return "LVM_GETITEMRECT";
4872 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4873 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4874 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4875 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4876 case 0x1000 + 18: return "LVM_HITTEST";
4877 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4878 case 0x1000 + 20: return "LVM_SCROLL";
4879 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4880 case 0x1000 + 22: return "LVM_ARRANGE";
4881 case 0x1000 + 23: return "LVM_EDITLABELA";
4882 case 0x1000 + 118: return "LVM_EDITLABELW";
4883 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4884 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4885 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4886 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4887 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4888 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4889 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4890 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4891 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4892 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4893 case 0x1000 + 31: return "LVM_GETHEADER";
4894 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4895 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4896 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4897 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4898 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4899 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4900 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4901 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4902 case 0x1000 + 41: return "LVM_GETORIGIN";
4903 case 0x1000 + 42: return "LVM_UPDATE";
4904 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4905 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4906 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4907 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4908 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4909 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4910 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4911 case 0x1000 + 48: return "LVM_SORTITEMS";
4912 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4913 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4914 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4915 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4916 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4917 case 0x1000 + 53: return "LVM_SETICONSPACING";
4918 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4919 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4920 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4921 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4922 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4923 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4924 case 0x1000 + 60: return "LVM_SETHOTITEM";
4925 case 0x1000 + 61: return "LVM_GETHOTITEM";
4926 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4927 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4928 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4929 case 0x1000 + 65: return "LVM_SETWORKAREA";
4932 case 0x1100 + 0: return "TVM_INSERTITEMA";
4933 case 0x1100 + 50: return "TVM_INSERTITEMW";
4934 case 0x1100 + 1: return "TVM_DELETEITEM";
4935 case 0x1100 + 2: return "TVM_EXPAND";
4936 case 0x1100 + 4: return "TVM_GETITEMRECT";
4937 case 0x1100 + 5: return "TVM_GETCOUNT";
4938 case 0x1100 + 6: return "TVM_GETINDENT";
4939 case 0x1100 + 7: return "TVM_SETINDENT";
4940 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4941 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4942 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4943 case 0x1100 + 11: return "TVM_SELECTITEM";
4944 case 0x1100 + 12: return "TVM_GETITEMA";
4945 case 0x1100 + 62: return "TVM_GETITEMW";
4946 case 0x1100 + 13: return "TVM_SETITEMA";
4947 case 0x1100 + 63: return "TVM_SETITEMW";
4948 case 0x1100 + 14: return "TVM_EDITLABELA";
4949 case 0x1100 + 65: return "TVM_EDITLABELW";
4950 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4951 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4952 case 0x1100 + 17: return "TVM_HITTEST";
4953 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4954 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4955 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4956 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4957 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4958 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4959 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4960 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4961 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4964 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4965 case 0x1200 + 1: return "HDM_INSERTITEMA";
4966 case 0x1200 + 10: return "HDM_INSERTITEMW";
4967 case 0x1200 + 2: return "HDM_DELETEITEM";
4968 case 0x1200 + 3: return "HDM_GETITEMA";
4969 case 0x1200 + 11: return "HDM_GETITEMW";
4970 case 0x1200 + 4: return "HDM_SETITEMA";
4971 case 0x1200 + 12: return "HDM_SETITEMW";
4972 case 0x1200 + 5: return "HDM_LAYOUT";
4973 case 0x1200 + 6: return "HDM_HITTEST";
4974 case 0x1200 + 7: return "HDM_GETITEMRECT";
4975 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4976 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4977 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4978 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4979 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4980 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4981 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4984 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4985 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4986 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4987 case 0x1300 + 5: return "TCM_GETITEMA";
4988 case 0x1300 + 60: return "TCM_GETITEMW";
4989 case 0x1300 + 6: return "TCM_SETITEMA";
4990 case 0x1300 + 61: return "TCM_SETITEMW";
4991 case 0x1300 + 7: return "TCM_INSERTITEMA";
4992 case 0x1300 + 62: return "TCM_INSERTITEMW";
4993 case 0x1300 + 8: return "TCM_DELETEITEM";
4994 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4995 case 0x1300 + 10: return "TCM_GETITEMRECT";
4996 case 0x1300 + 11: return "TCM_GETCURSEL";
4997 case 0x1300 + 12: return "TCM_SETCURSEL";
4998 case 0x1300 + 13: return "TCM_HITTEST";
4999 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
5000 case 0x1300 + 40: return "TCM_ADJUSTRECT";
5001 case 0x1300 + 41: return "TCM_SETITEMSIZE";
5002 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
5003 case 0x1300 + 43: return "TCM_SETPADDING";
5004 case 0x1300 + 44: return "TCM_GETROWCOUNT";
5005 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
5006 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
5007 case 0x1300 + 47: return "TCM_GETCURFOCUS";
5008 case 0x1300 + 48: return "TCM_SETCURFOCUS";
5009 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
5010 case 0x1300 + 50: return "TCM_DESELECTALL";
5013 case WM_USER
+1: return "TB_ENABLEBUTTON";
5014 case WM_USER
+2: return "TB_CHECKBUTTON";
5015 case WM_USER
+3: return "TB_PRESSBUTTON";
5016 case WM_USER
+4: return "TB_HIDEBUTTON";
5017 case WM_USER
+5: return "TB_INDETERMINATE";
5018 case WM_USER
+9: return "TB_ISBUTTONENABLED";
5019 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
5020 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
5021 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
5022 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
5023 case WM_USER
+17: return "TB_SETSTATE";
5024 case WM_USER
+18: return "TB_GETSTATE";
5025 case WM_USER
+19: return "TB_ADDBITMAP";
5026 case WM_USER
+20: return "TB_ADDBUTTONS";
5027 case WM_USER
+21: return "TB_INSERTBUTTON";
5028 case WM_USER
+22: return "TB_DELETEBUTTON";
5029 case WM_USER
+23: return "TB_GETBUTTON";
5030 case WM_USER
+24: return "TB_BUTTONCOUNT";
5031 case WM_USER
+25: return "TB_COMMANDTOINDEX";
5032 case WM_USER
+26: return "TB_SAVERESTOREA";
5033 case WM_USER
+76: return "TB_SAVERESTOREW";
5034 case WM_USER
+27: return "TB_CUSTOMIZE";
5035 case WM_USER
+28: return "TB_ADDSTRINGA";
5036 case WM_USER
+77: return "TB_ADDSTRINGW";
5037 case WM_USER
+29: return "TB_GETITEMRECT";
5038 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
5039 case WM_USER
+31: return "TB_SETBUTTONSIZE";
5040 case WM_USER
+32: return "TB_SETBITMAPSIZE";
5041 case WM_USER
+33: return "TB_AUTOSIZE";
5042 case WM_USER
+35: return "TB_GETTOOLTIPS";
5043 case WM_USER
+36: return "TB_SETTOOLTIPS";
5044 case WM_USER
+37: return "TB_SETPARENT";
5045 case WM_USER
+39: return "TB_SETROWS";
5046 case WM_USER
+40: return "TB_GETROWS";
5047 case WM_USER
+42: return "TB_SETCMDID";
5048 case WM_USER
+43: return "TB_CHANGEBITMAP";
5049 case WM_USER
+44: return "TB_GETBITMAP";
5050 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
5051 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
5052 case WM_USER
+46: return "TB_REPLACEBITMAP";
5053 case WM_USER
+47: return "TB_SETINDENT";
5054 case WM_USER
+48: return "TB_SETIMAGELIST";
5055 case WM_USER
+49: return "TB_GETIMAGELIST";
5056 case WM_USER
+50: return "TB_LOADIMAGES";
5057 case WM_USER
+51: return "TB_GETRECT";
5058 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
5059 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
5060 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
5061 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
5062 case WM_USER
+56: return "TB_SETSTYLE";
5063 case WM_USER
+57: return "TB_GETSTYLE";
5064 case WM_USER
+58: return "TB_GETBUTTONSIZE";
5065 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
5066 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
5067 case WM_USER
+61: return "TB_GETTEXTROWS";
5068 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
5073 static char s_szBuf
[128];
5074 sprintf(s_szBuf
, "<unknown message = %d>", message
);
5078 #endif //__WXDEBUG__
5080 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
5081 int *x
, int *y
, WPARAM
*flags
)
5083 // construct the key mask
5084 WPARAM
& fwKeys
= *flags
;
5086 fwKeys
= MK_RBUTTON
;
5087 if ( wxIsCtrlDown() )
5088 fwKeys
|= MK_CONTROL
;
5089 if ( wxIsShiftDown() )
5092 // simulate right mouse button click
5093 DWORD dwPos
= ::GetMessagePos();
5094 *x
= GET_X_LPARAM(dwPos
);
5095 *y
= GET_Y_LPARAM(dwPos
);
5097 win
->ScreenToClient(x
, y
);
5100 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
5104 HWND hwnd
= GetHwndOf(win
);
5105 HDC hdc
= ::GetDC(hwnd
);
5107 #if !wxDIALOG_UNIT_COMPATIBILITY
5108 // and select the current font into it
5109 HFONT hfont
= GetHfontOf(win
->GetFont());
5112 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
5116 // finally retrieve the text metrics from it
5117 GetTextMetrics(hdc
, &tm
);
5119 #if !wxDIALOG_UNIT_COMPATIBILITY
5123 (void)::SelectObject(hdc
, hfont
);
5127 ::ReleaseDC(hwnd
, hdc
);
5132 // Find the wxWindow at the current mouse position, returning the mouse
5134 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
5136 return wxFindWindowAtPoint(wxGetMousePosition());
5139 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
5144 HWND hWndHit
= ::WindowFromPoint(pt2
);
5146 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
5147 HWND hWnd
= hWndHit
;
5149 // Try to find a window with a wxWindow associated with it
5150 while (!win
&& (hWnd
!= 0))
5152 hWnd
= ::GetParent(hWnd
);
5153 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
5158 // Get the current mouse position.
5159 wxPoint
wxGetMousePosition()
5162 GetCursorPos( & pt
);
5163 return wxPoint(pt
.x
, pt
.y
);