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 borders, we draw them ourselves
396 msflags
&= ~WS_BORDER
;
397 #endif // wxUniversal
399 if ( style
& wxPOPUP_WINDOW
)
401 // a popup window floats on top of everything
402 exstyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
404 // it is also created hidden as other top level windows
405 msflags
&= ~WS_VISIBLE
;
409 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
);
412 // ---------------------------------------------------------------------------
414 // ---------------------------------------------------------------------------
416 void wxWindowMSW::SetFocus()
418 HWND hWnd
= GetHwnd();
419 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
421 #ifndef __WXMICROWIN__
425 if ( !::SetFocus(hWnd
) )
427 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
428 // was there really an error?
429 DWORD dwRes
= ::GetLastError();
432 HWND hwndFocus
= ::GetFocus();
433 if ( hwndFocus
!= hWnd
)
435 wxLogApiError(_T("SetFocus"), dwRes
);
442 // Get the window with the focus
443 wxWindow
*wxWindowBase::FindFocus()
445 HWND hWnd
= ::GetFocus();
448 return wxGetWindowFromHWND((WXHWND
)hWnd
);
454 bool wxWindowMSW::Enable(bool enable
)
456 if ( !wxWindowBase::Enable(enable
) )
459 HWND hWnd
= GetHwnd();
461 ::EnableWindow(hWnd
, (BOOL
)enable
);
463 // VZ: no, this is a bad idea: imagine that you have a dialog with some
464 // disabled controls and disable it - you really wouldn't like the
465 // disabled controls be reenabled too when you reenable the dialog!
467 wxWindowList::Node
*node
= GetChildren().GetFirst();
470 wxWindow
*child
= node
->GetData();
471 child
->Enable(enable
);
473 node
= node
->GetNext();
480 bool wxWindowMSW::Show(bool show
)
482 if ( !wxWindowBase::Show(show
) )
485 HWND hWnd
= GetHwnd();
486 int cshow
= show
? SW_SHOW
: SW_HIDE
;
487 ::ShowWindow(hWnd
, cshow
);
491 wxBringWindowToTop(hWnd
);
497 // Raise the window to the top of the Z order
498 void wxWindowMSW::Raise()
500 wxBringWindowToTop(GetHwnd());
503 // Lower the window to the bottom of the Z order
504 void wxWindowMSW::Lower()
506 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
507 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
510 void wxWindowMSW::SetTitle( const wxString
& title
)
512 SetWindowText(GetHwnd(), title
.c_str());
515 wxString
wxWindowMSW::GetTitle() const
517 return wxGetWindowText(GetHWND());
520 void wxWindowMSW::DoCaptureMouse()
522 HWND hWnd
= GetHwnd();
529 void wxWindowMSW::DoReleaseMouse()
531 if ( !::ReleaseCapture() )
533 wxLogLastError(_T("ReleaseCapture"));
537 /* static */ wxWindow
*wxWindowBase::GetCapture()
539 HWND hwnd
= ::GetCapture();
540 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
543 bool wxWindowMSW::SetFont(const wxFont
& font
)
545 if ( !wxWindowBase::SetFont(font
) )
551 HWND hWnd
= GetHwnd();
554 WXHANDLE hFont
= m_font
.GetResourceHandle();
556 wxASSERT_MSG( hFont
, wxT("should have valid font") );
558 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
563 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
565 if ( !wxWindowBase::SetCursor(cursor
) )
573 HWND hWnd
= GetHwnd();
575 // Change the cursor NOW if we're within the correct window
577 ::GetCursorPos(&point
);
579 RECT rect
= wxGetWindowRect(hWnd
);
581 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
582 ::SetCursor(GetHcursorOf(m_cursor
));
588 void wxWindowMSW::WarpPointer (int x
, int y
)
590 ClientToScreen(&x
, &y
);
592 if ( !::SetCursorPos(x
, y
) )
594 wxLogLastError(_T("SetCursorPos"));
598 #if WXWIN_COMPATIBILITY
599 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
602 #endif // WXWIN_COMPATIBILITY
604 // ---------------------------------------------------------------------------
606 // ---------------------------------------------------------------------------
608 #if WXWIN_COMPATIBILITY
609 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
611 #if defined(__WIN95__)
615 // Try to adjust the range to cope with page size > 1
616 // - a Windows API quirk
617 int pageSize
= GetScrollPage(orient
);
618 if ( pageSize
> 1 && range
> 0)
620 range1
+= (pageSize
- 1);
626 if ( orient
== wxHORIZONTAL
) {
632 info
.cbSize
= sizeof(SCROLLINFO
);
633 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
637 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
639 HWND hWnd
= GetHwnd();
641 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
644 if ( orient
== wxHORIZONTAL
)
649 HWND hWnd
= GetHwnd();
651 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
655 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
657 #if defined(__WIN95__)
661 if ( orient
== wxHORIZONTAL
) {
669 info
.cbSize
= sizeof(SCROLLINFO
);
672 info
.fMask
= SIF_PAGE
;
674 HWND hWnd
= GetHwnd();
676 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
678 if ( orient
== wxHORIZONTAL
)
685 int wxWindowMSW::OldGetScrollRange(int orient
) const
688 if ( orient
== wxHORIZONTAL
)
693 #if __WATCOMC__ && defined(__WINDOWS_386__)
694 short minPos
, maxPos
;
698 HWND hWnd
= GetHwnd();
701 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
702 #if defined(__WIN95__)
703 // Try to adjust the range to cope with page size > 1
704 // - a Windows API quirk
705 int pageSize
= GetScrollPage(orient
);
708 maxPos
-= (pageSize
- 1);
717 int wxWindowMSW::GetScrollPage(int orient
) const
719 if ( orient
== wxHORIZONTAL
)
725 #endif // WXWIN_COMPATIBILITY
727 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
729 #ifdef __WXMICROWIN__
730 return ::GetScrollPosWX(hWnd
, wOrient
);
732 return ::GetScrollPos(hWnd
, wOrient
);
736 int wxWindowMSW::GetScrollPos(int orient
) const
739 if ( orient
== wxHORIZONTAL
)
744 HWND hWnd
= GetHwnd();
745 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
747 return GetScrollPosition(hWnd
, wOrient
);
750 // This now returns the whole range, not just the number
751 // of positions that we can scroll.
752 int wxWindowMSW::GetScrollRange(int orient
) const
755 if ( orient
== wxHORIZONTAL
)
760 #if __WATCOMC__ && defined(__WINDOWS_386__)
761 short minPos
, maxPos
;
765 HWND hWnd
= GetHwnd();
768 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
769 #if defined(__WIN95__)
770 // Try to adjust the range to cope with page size > 1
771 // - a Windows API quirk
772 int pageSize
= GetScrollThumb(orient
);
775 maxPos
-= (pageSize
- 1);
777 // October 10th: new range concept.
787 int wxWindowMSW::GetScrollThumb(int orient
) const
789 if ( orient
== wxHORIZONTAL
)
795 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
797 HWND hWnd
= GetHwnd();
798 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
800 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
802 #if defined(__WIN95__)
804 info
.cbSize
= sizeof(SCROLLINFO
);
808 info
.fMask
= SIF_POS
;
810 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
812 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
813 #endif // __WIN95__/!__WIN95__
816 // New function that will replace some of the above.
817 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
818 int range
, bool refresh
)
820 #if defined(__WIN95__)
821 int oldRange
= range
- thumbVisible
;
823 int range1
= oldRange
;
825 // Try to adjust the range to cope with page size > 1
826 // - a Windows API quirk
827 int pageSize
= thumbVisible
;
828 if ( pageSize
> 1 && range
> 0)
830 range1
+= (pageSize
- 1);
836 if ( orient
== wxHORIZONTAL
) {
842 info
.cbSize
= sizeof(SCROLLINFO
);
843 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
847 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
849 HWND hWnd
= GetHwnd();
851 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
854 if ( orient
== wxHORIZONTAL
)
859 HWND hWnd
= GetHwnd();
862 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
863 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
866 if ( orient
== wxHORIZONTAL
) {
867 m_xThumbSize
= thumbVisible
;
869 m_yThumbSize
= thumbVisible
;
873 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
879 rect
.left
= prect
->x
;
881 rect
.right
= prect
->x
+ prect
->width
;
882 rect
.bottom
= prect
->y
+ prect
->height
;
890 ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
);
893 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
895 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
898 for ( int n
= 0; n
< count
; n
++ )
900 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
902 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
905 // don't bother to continue, we're already at top/bottom
912 return pos
!= posStart
;
915 bool wxWindowMSW::ScrollLines(int lines
)
917 bool down
= lines
> 0;
919 return ScrollVertically(GetHwnd(),
920 down
? SB_LINEDOWN
: SB_LINEUP
,
921 down
? lines
: -lines
);
924 bool wxWindowMSW::ScrollPages(int pages
)
926 bool down
= pages
> 0;
928 return ScrollVertically(GetHwnd(),
929 down
? SB_PAGEDOWN
: SB_PAGEUP
,
930 down
? pages
: -pages
);
933 // ---------------------------------------------------------------------------
935 // ---------------------------------------------------------------------------
937 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
939 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
941 HWND hwnd
= (HWND
)hWnd
;
942 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
944 wxAssociateWinWithHandle(hwnd
, this);
946 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
948 // we don't need to subclass the window of our own class (in the Windows
949 // sense of the word)
950 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
952 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
956 // don't bother restoring it neither
961 void wxWindowMSW::UnsubclassWin()
963 wxRemoveHandleAssociation(this);
965 // Restore old Window proc
966 HWND hwnd
= GetHwnd();
971 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
975 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
977 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
985 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
987 #if wxUSE_UNICODE_MSLU
988 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
989 // because it doesn't return pointer to the real wnd proc but rather a handle
990 // of a fake proc that does Unicode<->ANSI translation.
992 // The hack bellow works, because WNDCLASS contains original window handler
993 // rather that the unicows fake one. This may not be on purpose, though; if
994 // it stops working with future versions of unicows.dll, we can override
995 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
996 // Unicows_RegisterClass to our own versions that keep track of
997 // fake<->real wnd proc mapping.
999 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
1000 // with RegisterClass!!
1002 if ( wxUsingUnicowsDll() )
1004 static wxChar buffer
[512];
1007 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1008 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1009 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1014 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1018 // ----------------------------------------------------------------------------
1020 // ----------------------------------------------------------------------------
1022 void wxWindowMSW::SetWindowStyleFlag(long flags
)
1024 long flagsOld
= GetWindowStyleFlag();
1025 if ( flags
== flagsOld
)
1028 // update the internal variable
1029 wxWindowBase::SetWindowStyleFlag(flags
);
1031 // now update the Windows style as well if needed - and if the window had
1032 // been already created
1036 WXDWORD exstyle
, exstyleOld
;
1037 long style
= MSWGetStyle(flags
, &exstyle
),
1038 styleOld
= MSWGetStyle(flagsOld
, &exstyleOld
);
1040 if ( style
!= styleOld
)
1042 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1043 // this function so instead of simply setting the style to the new
1044 // value we clear the bits which were set in styleOld but are set in
1045 // the new one and set the ones which were not set before
1046 long styleReal
= ::GetWindowLong(GetHwnd(), GWL_STYLE
);
1047 styleReal
&= ~styleOld
;
1050 ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
);
1053 // and the extended style
1054 if ( exstyle
!= exstyleOld
)
1056 long exstyleReal
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
);
1057 exstyleReal
&= ~exstyleOld
;
1058 exstyleReal
|= exstyle
;
1060 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
);
1062 // we must call SetWindowPos() to flash the cached extended style and
1063 // also to make the change to wxSTAY_ON_TOP style take effect: just
1064 // setting the style simply doesn't work
1065 if ( !::SetWindowPos(GetHwnd(),
1066 exstyleReal
& WS_EX_TOPMOST
? HWND_TOPMOST
1069 SWP_NOMOVE
| SWP_NOSIZE
) )
1071 wxLogLastError(_T("SetWindowPos"));
1076 WXDWORD
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD
*exstyle
) const
1078 // translate the style
1079 WXDWORD style
= WS_CHILD
;
1081 if ( flags
& wxCLIP_CHILDREN
)
1082 style
|= WS_CLIPCHILDREN
;
1084 if ( flags
& wxCLIP_SIBLINGS
)
1085 style
|= WS_CLIPSIBLINGS
;
1087 if ( (flags
& wxBORDER_MASK
) != wxBORDER_NONE
)
1090 // now deal with ext style if the caller wants it
1095 if ( flags
& wxTRANSPARENT_WINDOW
)
1096 *exstyle
|= WS_EX_TRANSPARENT
;
1098 switch ( flags
& wxBORDER_MASK
)
1101 wxFAIL_MSG( _T("unknown border style") );
1105 case wxBORDER_SIMPLE
:
1108 case wxBORDER_STATIC
:
1109 *exstyle
|= WS_EX_STATICEDGE
;
1112 case wxBORDER_RAISED
:
1113 *exstyle
|= WS_EX_WINDOWEDGE
;
1116 case wxBORDER_DEFAULT
:
1117 case wxBORDER_SUNKEN
:
1118 *exstyle
|= WS_EX_CLIENTEDGE
;
1121 case wxBORDER_DOUBLE
:
1122 *exstyle
|= WS_EX_DLGMODALFRAME
;
1130 // Make a Windows extended style from the given wxWindows window style
1131 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1133 WXDWORD exStyle
= 0;
1134 if ( style
& wxTRANSPARENT_WINDOW
)
1135 exStyle
|= WS_EX_TRANSPARENT
;
1137 if ( !eliminateBorders
)
1139 if ( style
& wxSUNKEN_BORDER
)
1140 exStyle
|= WS_EX_CLIENTEDGE
;
1141 if ( style
& wxDOUBLE_BORDER
)
1142 exStyle
|= WS_EX_DLGMODALFRAME
;
1143 #if defined(__WIN95__)
1144 if ( style
& wxRAISED_BORDER
)
1145 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1146 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1147 if ( style
& wxSTATIC_BORDER
)
1148 exStyle
|= WS_EX_STATICEDGE
;
1155 // Determines whether native 3D effects or CTL3D should be used,
1156 // applying a default border style if required, and returning an extended
1157 // style to pass to CreateWindowEx.
1158 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1161 // If matches certain criteria, then assume no 3D effects
1162 // unless specifically requested (dealt with in MakeExtendedStyle)
1165 || !IsKindOf(CLASSINFO(wxControl
))
1166 #endif // wxUSE_CONTROLS
1167 || (m_windowStyle
& wxNO_BORDER
) )
1170 return MakeExtendedStyle(m_windowStyle
);
1173 // Determine whether we should be using 3D effects or not.
1174 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1176 // 1) App can specify global 3D effects
1177 *want3D
= wxTheApp
->GetAuto3D();
1179 // 2) If the parent is being drawn with user colours, or simple border specified,
1180 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1181 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1184 // 3) Control can override this global setting by defining
1185 // a border style, e.g. wxSUNKEN_BORDER
1186 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1189 // 4) If it's a special border, CTL3D can't cope so we want a native border
1190 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1191 (m_windowStyle
& wxSTATIC_BORDER
) )
1194 nativeBorder
= TRUE
;
1197 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1198 // effects from extended style
1201 nativeBorder
= FALSE
;
1204 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1206 // If we want 3D, but haven't specified a border here,
1207 // apply the default border style specified.
1208 // TODO what about non-Win95 WIN32? Does it have borders?
1209 #if defined(__WIN95__) && !wxUSE_CTL3D
1210 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1211 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1212 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1218 #if WXWIN_COMPATIBILITY
1219 // If nothing defined for this, try the parent.
1220 // E.g. we may be a button loaded from a resource, with no callback function
1222 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1224 if ( GetEventHandler()->ProcessEvent(event
) )
1227 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1229 #endif // WXWIN_COMPATIBILITY_2
1231 #if WXWIN_COMPATIBILITY
1232 wxObject
* wxWindowMSW::GetChild(int number
) const
1234 // Return a pointer to the Nth object in the Panel
1235 wxNode
*node
= GetChildren().First();
1238 node
= node
->Next();
1241 wxObject
*obj
= (wxObject
*)node
->Data();
1247 #endif // WXWIN_COMPATIBILITY
1249 // Setup background and foreground colours correctly
1250 void wxWindowMSW::SetupColours()
1253 SetBackgroundColour(GetParent()->GetBackgroundColour());
1256 bool wxWindowMSW::IsMouseInWindow() const
1258 // get the mouse position
1260 ::GetCursorPos(&pt
);
1262 // find the window which currently has the cursor and go up the window
1263 // chain until we find this window - or exhaust it
1264 HWND hwnd
= ::WindowFromPoint(pt
);
1265 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1266 hwnd
= ::GetParent(hwnd
);
1268 return hwnd
!= NULL
;
1271 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1273 // Check if we need to send a LEAVE event
1274 if ( m_mouseInWindow
)
1276 // note that we should generate the leave event whether the window has
1277 // or doesn't have mouse capture
1278 if ( !IsMouseInWindow() )
1280 // Generate a LEAVE event
1281 m_mouseInWindow
= FALSE
;
1283 // Unfortunately the mouse button and keyboard state may have
1284 // changed by the time the OnIdle function is called, so 'state'
1285 // may be meaningless.
1287 if ( wxIsShiftDown() )
1289 if ( wxIsCtrlDown() )
1290 state
|= MK_CONTROL
;
1291 if ( GetKeyState( VK_LBUTTON
) )
1292 state
|= MK_LBUTTON
;
1293 if ( GetKeyState( VK_MBUTTON
) )
1294 state
|= MK_MBUTTON
;
1295 if ( GetKeyState( VK_RBUTTON
) )
1296 state
|= MK_RBUTTON
;
1299 if ( !::GetCursorPos(&pt
) )
1301 wxLogLastError(_T("GetCursorPos"));
1304 // we need to have client coordinates here for symmetry with
1305 // wxEVT_ENTER_WINDOW
1306 RECT rect
= wxGetWindowRect(GetHwnd());
1310 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1311 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1313 (void)GetEventHandler()->ProcessEvent(event2
);
1320 // Set this window to be the child of 'parent'.
1321 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1323 if ( !wxWindowBase::Reparent(parent
) )
1326 HWND hWndChild
= GetHwnd();
1327 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1329 ::SetParent(hWndChild
, hWndParent
);
1334 void wxWindowMSW::Clear()
1336 wxClientDC
dc((wxWindow
*)this);
1337 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1338 dc
.SetBackground(brush
);
1342 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1344 #ifndef __WXMICROWIN__
1345 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1349 void wxWindowMSW::Freeze()
1351 SendSetRedraw(GetHwnd(), FALSE
);
1354 void wxWindowMSW::Thaw()
1356 SendSetRedraw(GetHwnd(), TRUE
);
1358 // we need to refresh everything or otherwise he invalidated area is not
1363 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1365 HWND hWnd
= GetHwnd();
1371 mswRect
.left
= rect
->x
;
1372 mswRect
.top
= rect
->y
;
1373 mswRect
.right
= rect
->x
+ rect
->width
;
1374 mswRect
.bottom
= rect
->y
+ rect
->height
;
1376 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1379 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1383 void wxWindowMSW::Update()
1385 if ( !::UpdateWindow(GetHwnd()) )
1387 wxLogLastError(_T("UpdateWindow"));
1390 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1391 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1392 // handler needs to be really drawn right now
1397 // ---------------------------------------------------------------------------
1399 // ---------------------------------------------------------------------------
1401 #if wxUSE_DRAG_AND_DROP
1403 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1405 if ( m_dropTarget
!= 0 ) {
1406 m_dropTarget
->Revoke(m_hWnd
);
1407 delete m_dropTarget
;
1410 m_dropTarget
= pDropTarget
;
1411 if ( m_dropTarget
!= 0 )
1412 m_dropTarget
->Register(m_hWnd
);
1415 #endif // wxUSE_DRAG_AND_DROP
1417 // old style file-manager drag&drop support: we retain the old-style
1418 // DragAcceptFiles in parallel with SetDropTarget.
1419 void wxWindowMSW::DragAcceptFiles(bool accept
)
1421 HWND hWnd
= GetHwnd();
1423 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1426 // ----------------------------------------------------------------------------
1428 // ----------------------------------------------------------------------------
1432 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1434 wxWindowBase::DoSetToolTip(tooltip
);
1437 m_tooltip
->SetWindow(this);
1440 #endif // wxUSE_TOOLTIPS
1442 // ---------------------------------------------------------------------------
1443 // moving and resizing
1444 // ---------------------------------------------------------------------------
1447 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1449 RECT rect
= wxGetWindowRect(GetHwnd());
1452 *x
= rect
.right
- rect
.left
;
1454 *y
= rect
.bottom
- rect
.top
;
1457 // Get size *available for subwindows* i.e. excluding menu bar etc.
1458 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1460 RECT rect
= wxGetClientRect(GetHwnd());
1468 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1470 RECT rect
= wxGetWindowRect(GetHwnd());
1473 point
.x
= rect
.left
;
1476 // we do the adjustments with respect to the parent only for the "real"
1477 // children, not for the dialogs/frames
1478 if ( !IsTopLevel() )
1480 HWND hParentWnd
= 0;
1481 wxWindow
*parent
= GetParent();
1483 hParentWnd
= GetWinHwnd(parent
);
1485 // Since we now have the absolute screen coords, if there's a parent we
1486 // must subtract its top left corner
1489 ::ScreenToClient(hParentWnd
, &point
);
1494 // We may be faking the client origin. So a window that's really at (0,
1495 // 30) may appear (to wxWin apps) to be at (0, 0).
1496 wxPoint
pt(parent
->GetClientAreaOrigin());
1508 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1516 ::ScreenToClient(GetHwnd(), &pt
);
1524 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1532 ::ClientToScreen(GetHwnd(), &pt
);
1540 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1542 // TODO: is this consistent with other platforms?
1543 // Still, negative width or height shouldn't be allowed
1548 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1550 wxLogLastError(wxT("MoveWindow"));
1554 // set the size of the window: if the dimensions are positive, just use them,
1555 // but if any of them is equal to -1, it means that we must find the value for
1556 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1557 // which case -1 is a valid value for x and y)
1559 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1560 // the width/height to best suit our contents, otherwise we reuse the current
1562 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1564 // get the current size and position...
1565 int currentX
, currentY
;
1566 GetPosition(¤tX
, ¤tY
);
1567 int currentW
,currentH
;
1568 GetSize(¤tW
, ¤tH
);
1570 // ... and don't do anything (avoiding flicker) if it's already ok
1571 if ( x
== currentX
&& y
== currentY
&&
1572 width
== currentW
&& height
== currentH
)
1577 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1579 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1582 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1584 wxSize
size(-1, -1);
1587 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1589 size
= DoGetBestSize();
1594 // just take the current one
1601 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1605 size
= DoGetBestSize();
1607 //else: already called DoGetBestSize() above
1613 // just take the current one
1618 DoMoveWindow(x
, y
, width
, height
);
1621 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1623 // setting the client size is less obvious than it it could have been
1624 // because in the result of changing the total size the window scrollbar
1625 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1626 // will not be correct as the difference between the total and client size
1627 // changes - so we keep changing it until we get it right
1629 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1630 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1631 // may become 3 if the window had 0 size originally and so we didn't
1632 // calculate the scrollbar correction correctly during the first iteration)
1633 // but just to be on the safe side we check for it instead of making it an
1634 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1635 for ( int i
= 0; i
< 4; i
++ )
1638 ::GetClientRect(GetHwnd(), &rectClient
);
1640 // if the size is already ok, stop here (rectClient.left = top = 0)
1641 if ( (rectClient
.right
== width
|| width
== -1) &&
1642 (rectClient
.bottom
== height
|| height
== -1) )
1649 // how did it happen? maybe OnSize() handler does something really
1650 // strange in this class?
1651 wxFAIL_MSG( _T("logic error in DoSetClientSize") );
1656 int widthClient
= width
,
1657 heightClient
= height
;
1659 // Find the difference between the entire window (title bar and all)
1660 // and the client area; add this to the new client size to move the
1663 ::GetWindowRect(GetHwnd(), &rectWin
);
1665 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1666 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1669 point
.x
= rectWin
.left
;
1670 point
.y
= rectWin
.top
;
1672 // MoveWindow positions the child windows relative to the parent, so
1673 // adjust if necessary
1674 if ( !IsTopLevel() )
1676 wxWindow
*parent
= GetParent();
1679 ::ScreenToClient(GetHwndOf(parent
), &point
);
1683 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1687 // For implementation purposes - sometimes decorations make the client area
1689 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1691 return wxPoint(0, 0);
1694 // ---------------------------------------------------------------------------
1696 // ---------------------------------------------------------------------------
1698 int wxWindowMSW::GetCharHeight() const
1700 return wxGetTextMetrics(this).tmHeight
;
1703 int wxWindowMSW::GetCharWidth() const
1705 // +1 is needed because Windows apparently adds it when calculating the
1706 // dialog units size in pixels
1707 #if wxDIALOG_UNIT_COMPATIBILITY
1708 return wxGetTextMetrics(this).tmAveCharWidth
;
1710 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1714 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1716 int *descent
, int *externalLeading
,
1717 const wxFont
*theFont
) const
1719 const wxFont
*fontToUse
= theFont
;
1721 fontToUse
= &m_font
;
1723 HWND hWnd
= GetHwnd();
1724 HDC dc
= ::GetDC(hWnd
);
1728 if ( fontToUse
&& fontToUse
->Ok() )
1730 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1732 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1737 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1738 GetTextMetrics(dc
, &tm
);
1740 if ( fontToUse
&& fnt
&& hfontOld
)
1741 SelectObject(dc
, hfontOld
);
1743 ReleaseDC(hWnd
, dc
);
1750 *descent
= tm
.tmDescent
;
1751 if ( externalLeading
)
1752 *externalLeading
= tm
.tmExternalLeading
;
1755 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1756 // ---------------------------------------------------------------------------
1757 // Caret manipulation
1758 // ---------------------------------------------------------------------------
1760 void wxWindowMSW::CreateCaret(int w
, int h
)
1762 SetCaret(new wxCaret(this, w
, h
));
1765 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1767 wxFAIL_MSG("not implemented");
1770 void wxWindowMSW::ShowCaret(bool show
)
1772 wxCHECK_RET( m_caret
, "no caret to show" );
1774 m_caret
->Show(show
);
1777 void wxWindowMSW::DestroyCaret()
1782 void wxWindowMSW::SetCaretPos(int x
, int y
)
1784 wxCHECK_RET( m_caret
, "no caret to move" );
1786 m_caret
->Move(x
, y
);
1789 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1791 wxCHECK_RET( m_caret
, "no caret to get position of" );
1793 m_caret
->GetPosition(x
, y
);
1795 #endif // wxUSE_CARET
1797 // ---------------------------------------------------------------------------
1799 // ---------------------------------------------------------------------------
1801 #if wxUSE_MENUS_NATIVE
1803 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1804 // immediately, without waiting for the next event loop iteration
1806 // NB: this function should probably be made public later as it can almost
1807 // surely replace wxYield() elsewhere as well
1808 static void wxYieldForCommandsOnly()
1810 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1811 // want to process it here)
1813 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1814 && msg
.message
!= WM_QUIT
)
1816 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1820 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1822 menu
->SetInvokingWindow(this);
1825 HWND hWnd
= GetHwnd();
1826 HMENU hMenu
= GetHmenuOf(menu
);
1830 ::ClientToScreen(hWnd
, &point
);
1831 wxCurrentPopupMenu
= menu
;
1832 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1834 // we need to do it righ now as otherwise the events are never going to be
1835 // sent to wxCurrentPopupMenu from HandleCommand()
1837 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1838 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1839 // destroyed as soon as we return (it can be a local variable in the caller
1840 // for example) and so we do need to process the event immediately
1841 wxYieldForCommandsOnly();
1843 wxCurrentPopupMenu
= NULL
;
1845 menu
->SetInvokingWindow(NULL
);
1850 #endif // wxUSE_MENUS_NATIVE
1852 // ===========================================================================
1853 // pre/post message processing
1854 // ===========================================================================
1856 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1859 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1861 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1864 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1866 // wxUniversal implements tab traversal itself
1867 #ifndef __WXUNIVERSAL__
1868 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1870 // intercept dialog navigation keys
1871 MSG
*msg
= (MSG
*)pMsg
;
1873 // here we try to do all the job which ::IsDialogMessage() usually does
1876 bool bProcess
= TRUE
;
1877 if ( msg
->message
!= WM_KEYDOWN
)
1880 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1885 bool bCtrlDown
= wxIsCtrlDown();
1886 bool bShiftDown
= wxIsShiftDown();
1888 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1889 // don't process it if it's the case (except for Ctrl-Tab/Enter
1890 // combinations which are always processed)
1894 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1897 bool bForward
= TRUE
,
1898 bWindowChange
= FALSE
;
1900 switch ( msg
->wParam
)
1903 // assume that nobody wants Shift-TAB for himself - if we
1904 // don't do it there is no easy way for a control to grab
1905 // TABs but still let Shift-TAB work as navugation key
1906 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1910 // Ctrl-Tab cycles thru notebook pages
1911 bWindowChange
= bCtrlDown
;
1912 bForward
= !bShiftDown
;
1918 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1926 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1932 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1934 // control wants to process Enter itself, don't
1935 // call IsDialogMessage() which would interpret
1939 else if ( lDlgCode
& DLGC_BUTTON
)
1941 // let IsDialogMessage() handle this for all
1942 // buttons except the owner-drawn ones which it
1943 // just seems to ignore
1944 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1945 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1947 // emulate the button click
1948 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1950 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1955 // FIXME: this should be handled by
1956 // wxNavigationKeyEvent handler and not here!!
1960 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1962 if ( btn
&& btn
->IsEnabled() )
1964 // if we do have a default button, do press it
1965 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1969 else // no default button
1970 #endif // wxUSE_BUTTON
1972 // no special function for enter and don't even
1973 // let IsDialogMessage() have it: it seems to
1974 // do something really strange with it
1987 wxNavigationKeyEvent event
;
1988 event
.SetDirection(bForward
);
1989 event
.SetWindowChange(bWindowChange
);
1990 event
.SetEventObject(this);
1992 if ( GetEventHandler()->ProcessEvent(event
) )
1999 // let ::IsDialogMessage() do almost everything and handle just the
2000 // things it doesn't here: Ctrl-TAB for switching notebook pages
2001 if ( msg
->message
== WM_KEYDOWN
)
2003 // don't process system keys here
2004 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
2006 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
2008 // find the first notebook parent and change its page
2009 wxWindow
*win
= this;
2010 wxNotebook
*nbook
= NULL
;
2011 while ( win
&& !nbook
)
2013 nbook
= wxDynamicCast(win
, wxNotebook
);
2014 win
= win
->GetParent();
2019 bool forward
= !wxIsShiftDown();
2021 nbook
->AdvanceSelection(forward
);
2028 if ( ::IsDialogMessage(GetHwnd(), msg
) )
2030 // IsDialogMessage() did something...
2034 #endif // __WXUNIVERSAL__
2039 // relay mouse move events to the tooltip control
2040 MSG
*msg
= (MSG
*)pMsg
;
2041 if ( msg
->message
== WM_MOUSEMOVE
)
2042 m_tooltip
->RelayEvent(pMsg
);
2044 #endif // wxUSE_TOOLTIPS
2049 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
2051 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
2052 return m_acceleratorTable
.Translate(this, pMsg
);
2056 #endif // wxUSE_ACCEL
2059 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
))
2061 // preprocess all messages by default
2065 // ---------------------------------------------------------------------------
2066 // message params unpackers (different for Win16 and Win32)
2067 // ---------------------------------------------------------------------------
2071 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2072 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
2074 *id
= LOWORD(wParam
);
2075 *hwnd
= (WXHWND
)lParam
;
2076 *cmd
= HIWORD(wParam
);
2079 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2080 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2082 *state
= LOWORD(wParam
);
2083 *minimized
= HIWORD(wParam
);
2084 *hwnd
= (WXHWND
)lParam
;
2087 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2088 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2090 *code
= LOWORD(wParam
);
2091 *pos
= HIWORD(wParam
);
2092 *hwnd
= (WXHWND
)lParam
;
2095 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2096 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2098 #ifndef __WXMICROWIN__
2099 *nCtlColor
= CTLCOLOR_BTN
;
2100 *hwnd
= (WXHWND
)lParam
;
2101 *hdc
= (WXHDC
)wParam
;
2105 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2106 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2108 *item
= (WXWORD
)wParam
;
2109 *flags
= HIWORD(wParam
);
2110 *hmenu
= (WXHMENU
)lParam
;
2115 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2116 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2118 *id
= (WXWORD
)wParam
;
2119 *hwnd
= (WXHWND
)LOWORD(lParam
);
2120 *cmd
= HIWORD(lParam
);
2123 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2124 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2126 *state
= (WXWORD
)wParam
;
2127 *minimized
= LOWORD(lParam
);
2128 *hwnd
= (WXHWND
)HIWORD(lParam
);
2131 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2132 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2134 *code
= (WXWORD
)wParam
;
2135 *pos
= LOWORD(lParam
);
2136 *hwnd
= (WXHWND
)HIWORD(lParam
);
2139 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2140 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2142 *hwnd
= (WXHWND
)LOWORD(lParam
);
2143 *nCtlColor
= (int)HIWORD(lParam
);
2144 *hdc
= (WXHDC
)wParam
;
2147 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2148 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2150 *item
= (WXWORD
)wParam
;
2151 *flags
= LOWORD(lParam
);
2152 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2157 // ---------------------------------------------------------------------------
2158 // Main wxWindows window proc and the window proc for wxWindow
2159 // ---------------------------------------------------------------------------
2161 // Hook for new window just as it's being created, when the window isn't yet
2162 // associated with the handle
2163 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2165 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2166 // window being created and insures that it's always unset back later
2167 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2169 gs_winBeingCreated
= winBeingCreated
;
2172 wxWindowCreationHook::~wxWindowCreationHook()
2174 gs_winBeingCreated
= NULL
;
2178 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2180 // trace all messages - useful for the debugging
2182 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2183 wxGetMessageName(message
), wParam
, lParam
);
2184 #endif // __WXDEBUG__
2186 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2188 // when we get the first message for the HWND we just created, we associate
2189 // it with wxWindow stored in gs_winBeingCreated
2190 if ( !wnd
&& gs_winBeingCreated
)
2192 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2193 wnd
= gs_winBeingCreated
;
2194 gs_winBeingCreated
= NULL
;
2195 wnd
->SetHWND((WXHWND
)hWnd
);
2201 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2203 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2208 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2210 // did we process the message?
2211 bool processed
= FALSE
;
2222 // for most messages we should return 0 when we do process the message
2230 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2233 // return 0 to allow window creation
2234 rc
.result
= mayCreate
? 0 : -1;
2240 // never set processed to TRUE and *always* pass WM_DESTROY to
2241 // DefWindowProc() as Windows may do some internal cleanup when
2242 // processing it and failing to pass the message along may cause
2243 // memory and resource leaks!
2244 (void)HandleDestroy();
2248 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2256 // we're not interested in these messages at all
2259 case SIZE_MINIMIZED
:
2260 // we shouldn't send sizev events for these messages as the
2261 // client size may be negative which breaks existing code
2263 // OTOH we might send another (wxMinimizedEvent?) one or
2264 // add an additional parameter to wxSizeEvent if this is
2265 // useful to anybody
2269 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2270 // fall through nevertheless
2272 case SIZE_MAXIMIZED
:
2274 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2279 #ifndef __WXMICROWIN__
2280 case WM_ACTIVATEAPP
:
2281 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2287 WXWORD state
, minimized
;
2289 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2291 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2296 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2300 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2304 processed
= HandlePaint();
2308 // don't let the DefWindowProc() destroy our window - we'll do it
2309 // ourselves in ~wxWindow
2315 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2319 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2320 GET_Y_LPARAM(lParam
),
2324 #if wxUSE_MOUSEWHEEL
2326 processed
= HandleMouseWheel(wParam
, lParam
);
2330 case WM_LBUTTONDOWN
:
2332 case WM_LBUTTONDBLCLK
:
2333 case WM_RBUTTONDOWN
:
2335 case WM_RBUTTONDBLCLK
:
2336 case WM_MBUTTONDOWN
:
2338 case WM_MBUTTONDBLCLK
:
2341 #ifdef __WXMICROWIN__
2342 // MicroWindows seems to ignore the fact that a window is
2343 // disabled. So catch mouse events and throw them away if
2345 wxWindowMSW
* win
= this;
2348 if (!win
->IsEnabled())
2353 win
= win
->GetParent();
2354 if (win
&& win
->IsTopLevel())
2357 #endif // __WXMICROWIN__
2360 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2362 processed
= HandleMouseEvent(message
,
2363 GET_X_LPARAM(lParam
),
2364 GET_Y_LPARAM(lParam
),
2370 #ifdef __WXMICROWIN__
2371 case WM_NCLBUTTONDOWN
:
2372 case WM_NCLBUTTONUP
:
2373 case WM_NCLBUTTONDBLCLK
:
2374 case WM_NCRBUTTONDOWN
:
2375 case WM_NCRBUTTONUP
:
2376 case WM_NCRBUTTONDBLCLK
:
2378 case WM_NCMBUTTONDOWN
:
2379 case WM_NCMBUTTONUP
:
2380 case WM_NCMBUTTONDBLCLK
:
2383 // MicroWindows seems to ignore the fact that a window
2384 // is disabled. So catch mouse events and throw them away if necessary.
2386 wxWindowMSW
* win
= this;
2389 if (!win
->IsEnabled())
2394 win
= win
->GetParent();
2395 if (win
&& win
->IsTopLevel())
2400 #endif // __WXMICROWIN__
2407 case MM_JOY1BUTTONDOWN
:
2408 case MM_JOY2BUTTONDOWN
:
2409 case MM_JOY1BUTTONUP
:
2410 case MM_JOY2BUTTONUP
:
2411 processed
= HandleJoystickEvent(message
,
2412 GET_X_LPARAM(lParam
),
2413 GET_Y_LPARAM(lParam
),
2416 #endif // __WXMICROWIN__
2419 processed
= HandleSysCommand(wParam
, lParam
);
2426 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2428 processed
= HandleCommand(id
, cmd
, hwnd
);
2434 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2438 // for these messages we must return TRUE if process the message
2441 case WM_MEASUREITEM
:
2443 int idCtrl
= (UINT
)wParam
;
2444 if ( message
== WM_DRAWITEM
)
2446 processed
= MSWOnDrawItem(idCtrl
,
2447 (WXDRAWITEMSTRUCT
*)lParam
);
2451 processed
= MSWOnMeasureItem(idCtrl
,
2452 (WXMEASUREITEMSTRUCT
*)lParam
);
2459 #endif // defined(WM_DRAWITEM)
2462 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
2464 // want everything: i.e. all keys and WM_CHAR message
2465 rc
.result
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
2466 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
2469 //else: get the dlg code from the DefWindowProc()
2474 // If this has been processed by an event handler,
2475 // return 0 now (we've handled it).
2476 if ( HandleKeyDown((WORD
) wParam
, lParam
) )
2483 // we consider these message "not interesting" to OnChar
2484 if ( wParam
== VK_SHIFT
|| wParam
== VK_CONTROL
)
2493 // avoid duplicate messages to OnChar for these ASCII keys: they
2494 // will be translated by TranslateMessage() and received in WM_CHAR
2502 // but set processed to FALSE, not TRUE to still pass them to
2503 // the control's default window proc - otherwise built-in
2504 // keyboard handling won't work
2510 // special case of VK_APPS: treat it the same as right mouse
2511 // click because both usually pop up a context menu
2517 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2518 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2528 processed
= HandleChar((WORD
)wParam
, lParam
);
2535 // special case of VK_APPS: treat it the same as right mouse button
2536 if ( wParam
== VK_APPS
)
2541 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2542 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2547 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2552 case WM_CHAR
: // Always an ASCII character
2553 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2561 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2563 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2569 // CTLCOLOR messages are sent by children to query the parent for their
2570 // colors#ifndef __WXMICROWIN__
2571 #ifndef __WXMICROWIN__
2573 case WM_CTLCOLORMSGBOX
:
2574 case WM_CTLCOLOREDIT
:
2575 case WM_CTLCOLORLISTBOX
:
2576 case WM_CTLCOLORBTN
:
2577 case WM_CTLCOLORDLG
:
2578 case WM_CTLCOLORSCROLLBAR
:
2579 case WM_CTLCOLORSTATIC
:
2587 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2589 processed
= HandleCtlColor(&rc
.hBrush
,
2598 #endif // !__WXMICROWIN__
2600 case WM_SYSCOLORCHANGE
:
2601 // the return value for this message is ignored
2602 processed
= HandleSysColorChange();
2605 case WM_DISPLAYCHANGE
:
2606 processed
= HandleDisplayChange();
2609 case WM_PALETTECHANGED
:
2610 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2613 case WM_QUERYNEWPALETTE
:
2614 processed
= HandleQueryNewPalette();
2618 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2621 // we processed the message, i.e. erased the background
2627 processed
= HandleDropFiles(wParam
);
2631 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2635 // we never set focus from here
2640 case WM_QUERYENDSESSION
:
2641 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2645 processed
= HandleEndSession(wParam
!= 0, lParam
);
2648 case WM_GETMINMAXINFO
:
2649 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2653 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2654 LOWORD(lParam
), // hit test
2655 HIWORD(lParam
)); // mouse msg
2659 // returning TRUE stops the DefWindowProc() from further
2660 // processing this message - exactly what we need because we've
2661 // just set the cursor.
2666 #if defined(__WIN32__) && defined(WM_HELP)
2669 HELPINFO
* info
= (HELPINFO
*) lParam
;
2670 // Don't yet process menu help events, just windows
2671 if (info
->iContextType
== HELPINFO_WINDOW
)
2673 wxWindowMSW
* subjectOfHelp
= this;
2674 bool eventProcessed
= FALSE
;
2675 while (subjectOfHelp
&& !eventProcessed
)
2677 wxHelpEvent
helpEvent(wxEVT_HELP
,
2678 subjectOfHelp
->GetId(),
2679 wxPoint(info
->MousePos
.x
,
2680 info
->MousePos
.y
) );
2681 helpEvent
.SetEventObject(this);
2683 GetEventHandler()->ProcessEvent(helpEvent
);
2685 // Go up the window hierarchy until the event is
2687 subjectOfHelp
= subjectOfHelp
->GetParent();
2690 processed
= eventProcessed
;
2692 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2694 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2695 helpEvent
.SetEventObject(this);
2696 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2699 //else: processed is already FALSE
2703 case WM_CONTEXTMENU
:
2705 // we don't convert from screen to client coordinates as
2706 // the event may be handled by a parent window
2707 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2709 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2710 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2719 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2720 wxGetMessageName(message
));
2721 #endif // __WXDEBUG__
2722 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2728 // ----------------------------------------------------------------------------
2729 // wxWindow <-> HWND map
2730 // ----------------------------------------------------------------------------
2732 wxWinHashTable
*wxWinHandleHash
= NULL
;
2734 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2736 return wxWinHandleHash
->Get((long)hWnd
);
2739 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2741 // adding NULL hWnd is (first) surely a result of an error and
2742 // (secondly) breaks menu command processing
2743 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2744 wxT("attempt to add a NULL hWnd to window list ignored") );
2746 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2748 if ( oldWin
&& (oldWin
!= win
) )
2750 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2751 hWnd
, win
->GetClassInfo()->GetClassName());
2754 #endif // __WXDEBUG__
2757 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2761 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2763 wxWinHandleHash
->Delete((long)win
->GetHWND());
2766 // ----------------------------------------------------------------------------
2767 // various MSW speciic class dependent functions
2768 // ----------------------------------------------------------------------------
2770 // Default destroyer - override if you destroy it in some other way
2771 // (e.g. with MDI child windows)
2772 void wxWindowMSW::MSWDestroyWindow()
2776 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2779 int& w
, int& h
) const
2781 bool nonDefault
= FALSE
;
2785 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2786 // just as well set it to CW_USEDEFAULT as well
2793 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2799 NB: there used to be some code here which set the initial size of the
2800 window to the client size of the parent if no explicit size was
2801 specified. This was wrong because wxWindows programs often assume
2802 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2803 it. To see why, you should understand that Windows sends WM_SIZE from
2804 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2805 from some base class ctor and so this WM_SIZE is not processed in the
2806 real class' OnSize() (because it's not fully constructed yet and the
2807 event goes to some base class OnSize() instead). So the WM_SIZE we
2808 rely on is the one sent when the parent frame resizes its children
2809 but here is the problem: if the child already has just the right
2810 size, nothing will happen as both wxWindows and Windows check for
2811 this and ignore any attempts to change the window size to the size it
2812 already has - so no WM_SIZE would be sent.
2816 // as abobe, h is not used at all in this case anyhow
2823 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2831 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2832 const wxChar
*title
,
2836 WXDWORD extendedStyle
)
2838 // choose the position/size for the new window
2840 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2842 // find the correct parent HWND
2843 wxWindow
*parent
= GetParent();
2844 bool isChild
= (style
& WS_CHILD
) != 0;
2846 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2848 // popup windows should have desktop as parent because they shouldn't
2849 // be limited to the parents client area as child windows usually are
2850 hParent
= ::GetDesktopWindow();
2854 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2856 // this is either a normal child window or a top level window with
2857 // wxFRAME_TOOL_WINDOW style (see below)
2858 hParent
= GetHwndOf(parent
);
2862 // this is either a window for which no parent was specified (not
2863 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2864 // style: we should use NULL parent HWND for it or it would be
2865 // always on top of its parent which is not what we usually want
2866 // (in fact, we only want it for frames with the special
2867 // wxFRAME_TOOL_WINDOW as above)
2873 // controlId is menu handle for the top level windows, so set it to 0
2874 // unless we're creating a child window
2878 controlId
= GetId();
2880 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2882 style
|= WS_CLIPSIBLINGS
;
2890 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2891 // which is the same but without CS_[HV]REDRAW class styles so using it
2892 // ensures that the window is not fully repainted on each resize
2893 wxString
className(wclass
);
2894 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2896 className
+= wxT("NR");
2899 // do create the window
2900 wxWindowCreationHook
hook(this);
2902 m_hWnd
= (WXHWND
)::CreateWindowEx
2906 title
? title
: wxT(""),
2912 NULL
// no extra data
2917 wxLogSysError(_("Can't create window of class %s"), wclass
);
2922 SubclassWin(m_hWnd
);
2924 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2929 // ===========================================================================
2930 // MSW message handlers
2931 // ===========================================================================
2933 // ---------------------------------------------------------------------------
2935 // ---------------------------------------------------------------------------
2938 // FIXME: VZ: I'm not sure at all that the order of processing is correct
2939 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2941 #ifndef __WXMICROWIN__
2942 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2943 HWND hWnd
= hdr
->hwndFrom
;
2944 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2946 // is this one of our windows?
2949 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2952 // try all our children
2953 wxWindowList::Node
*node
= GetChildren().GetFirst();
2956 wxWindow
*child
= node
->GetData();
2957 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2962 node
= node
->GetNext();
2965 // finally try this window too (catches toolbar case)
2966 return MSWOnNotify(idCtrl
, lParam
, result
);
2967 #else // __WXMICROWIN__
2972 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
2974 WXLPARAM
* WXUNUSED(result
))
2977 NMHDR
* hdr
= (NMHDR
*)lParam
;
2978 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
2980 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
2981 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
2986 #endif // wxUSE_TOOLTIPS
2992 // ---------------------------------------------------------------------------
2993 // end session messages
2994 // ---------------------------------------------------------------------------
2996 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
2998 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
2999 event
.SetEventObject(wxTheApp
);
3000 event
.SetCanVeto(TRUE
);
3001 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
3003 bool rc
= wxTheApp
->ProcessEvent(event
);
3007 // we may end only if the app didn't veto session closing (double
3009 *mayEnd
= !event
.GetVeto();
3015 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
3017 // do nothing if the session isn't ending
3022 if ( (this != wxTheApp
->GetTopWindow()) )
3025 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
3026 event
.SetEventObject(wxTheApp
);
3027 event
.SetCanVeto(FALSE
);
3028 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
3030 return wxTheApp
->ProcessEvent(event
);
3033 // ---------------------------------------------------------------------------
3034 // window creation/destruction
3035 // ---------------------------------------------------------------------------
3037 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
3039 // TODO: should generate this event from WM_NCCREATE
3040 wxWindowCreateEvent
event((wxWindow
*)this);
3041 (void)GetEventHandler()->ProcessEvent(event
);
3048 bool wxWindowMSW::HandleDestroy()
3050 wxWindowDestroyEvent
event((wxWindow
*)this);
3051 (void)GetEventHandler()->ProcessEvent(event
);
3053 // delete our drop target if we've got one
3054 #if wxUSE_DRAG_AND_DROP
3055 if ( m_dropTarget
!= NULL
)
3057 m_dropTarget
->Revoke(m_hWnd
);
3059 delete m_dropTarget
;
3060 m_dropTarget
= NULL
;
3062 #endif // wxUSE_DRAG_AND_DROP
3064 // WM_DESTROY handled
3068 // ---------------------------------------------------------------------------
3070 // ---------------------------------------------------------------------------
3072 bool wxWindowMSW::HandleActivate(int state
,
3073 bool WXUNUSED(minimized
),
3074 WXHWND
WXUNUSED(activate
))
3076 wxActivateEvent
event(wxEVT_ACTIVATE
,
3077 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3079 event
.SetEventObject(this);
3081 return GetEventHandler()->ProcessEvent(event
);
3084 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3086 // notify the parent keeping track of focus for the kbd navigation
3087 // purposes that we got it
3088 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3089 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3095 m_caret
->OnSetFocus();
3097 #endif // wxUSE_CARET
3100 // If it's a wxTextCtrl don't send the event as it will be done
3101 // after the control gets to process it from EN_FOCUS handler
3102 if ( wxDynamicCastThis(wxTextCtrl
) )
3106 #endif // wxUSE_TEXTCTRL
3108 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3109 event
.SetEventObject(this);
3111 // wxFindWinFromHandle() may return NULL, it is ok
3112 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3114 return GetEventHandler()->ProcessEvent(event
);
3117 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3123 m_caret
->OnKillFocus();
3125 #endif // wxUSE_CARET
3128 // If it's a wxTextCtrl don't send the event as it will be done
3129 // after the control gets to process it.
3130 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3137 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3138 event
.SetEventObject(this);
3140 // wxFindWinFromHandle() may return NULL, it is ok
3141 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3143 return GetEventHandler()->ProcessEvent(event
);
3146 // ---------------------------------------------------------------------------
3148 // ---------------------------------------------------------------------------
3150 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3152 wxShowEvent
event(GetId(), show
);
3153 event
.m_eventObject
= this;
3155 return GetEventHandler()->ProcessEvent(event
);
3158 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3160 wxInitDialogEvent
event(GetId());
3161 event
.m_eventObject
= this;
3163 return GetEventHandler()->ProcessEvent(event
);
3166 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3168 #ifndef __WXMICROWIN__
3169 HDROP hFilesInfo
= (HDROP
) wParam
;
3171 // Get the total number of files dropped
3172 UINT gwFilesDropped
= ::DragQueryFile
3180 wxString
*files
= new wxString
[gwFilesDropped
];
3181 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3183 // first get the needed buffer length (+1 for terminating NUL)
3184 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3186 // and now get the file name
3187 ::DragQueryFile(hFilesInfo
, wIndex
,
3188 files
[wIndex
].GetWriteBuf(len
), len
);
3190 files
[wIndex
].UngetWriteBuf();
3192 DragFinish (hFilesInfo
);
3194 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3195 event
.m_eventObject
= this;
3198 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3199 event
.m_pos
.x
= dropPoint
.x
;
3200 event
.m_pos
.y
= dropPoint
.y
;
3202 return GetEventHandler()->ProcessEvent(event
);
3203 #else // __WXMICROWIN__
3208 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3210 int WXUNUSED(mouseMsg
))
3212 #ifndef __WXMICROWIN__
3213 // the logic is as follows:
3214 // -1. don't set cursor for non client area, including but not limited to
3215 // the title bar, scrollbars, &c
3216 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3217 // 1. if we have the cursor set it unless wxIsBusy()
3218 // 2. if we're a top level window, set some cursor anyhow
3219 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3221 if ( nHitTest
!= HTCLIENT
)
3226 HCURSOR hcursor
= 0;
3228 // first ask the user code - it may wish to set the cursor in some very
3229 // specific way (for example, depending on the current position)
3232 if ( !::GetCursorPos(&pt
) )
3234 wxLogLastError(wxT("GetCursorPos"));
3237 // In WIN16 it doesn't return a value.
3238 ::GetCursorPos(&pt
);
3243 ScreenToClient(&x
, &y
);
3244 wxSetCursorEvent
event(x
, y
);
3246 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3247 if ( processedEvtSetCursor
&& event
.HasCursor() )
3249 hcursor
= GetHcursorOf(event
.GetCursor());
3254 bool isBusy
= wxIsBusy();
3256 // the test for processedEvtSetCursor is here to prevent using m_cursor
3257 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3258 // it - this is a way to say that our cursor shouldn't be used for this
3260 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3262 hcursor
= GetHcursorOf(m_cursor
);
3269 hcursor
= wxGetCurrentBusyCursor();
3271 else if ( !hcursor
)
3273 const wxCursor
*cursor
= wxGetGlobalCursor();
3274 if ( cursor
&& cursor
->Ok() )
3276 hcursor
= GetHcursorOf(*cursor
);
3284 ::SetCursor(hcursor
);
3286 // cursor set, stop here
3289 #endif // __WXMICROWIN__
3291 // pass up the window chain
3295 // ---------------------------------------------------------------------------
3296 // owner drawn stuff
3297 // ---------------------------------------------------------------------------
3299 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3301 #if wxUSE_OWNER_DRAWN
3303 #if wxUSE_MENUS_NATIVE
3304 // is it a menu item?
3305 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3306 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3308 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3310 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3312 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3313 // the DC from being released
3314 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3315 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3316 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3317 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3319 return pMenuItem
->OnDrawItem
3323 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3324 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3327 #endif // wxUSE_MENUS_NATIVE
3330 wxWindow
*item
= FindItem(id
);
3331 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3333 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3335 #endif // wxUSE_CONTROLS
3337 #endif // USE_OWNER_DRAWN
3342 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3344 #if wxUSE_OWNER_DRAWN
3345 // is it a menu item?
3346 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3347 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3349 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3351 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3353 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3354 &pMeasureStruct
->itemHeight
);
3357 wxWindow
*item
= FindItem(id
);
3358 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3360 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3362 #endif // owner-drawn menus
3366 // ---------------------------------------------------------------------------
3367 // colours and palettes
3368 // ---------------------------------------------------------------------------
3370 bool wxWindowMSW::HandleSysColorChange()
3372 wxSysColourChangedEvent event
;
3373 event
.SetEventObject(this);
3375 (void)GetEventHandler()->ProcessEvent(event
);
3377 // always let the system carry on the default processing to allow the
3378 // native controls to react to the colours update
3382 bool wxWindowMSW::HandleDisplayChange()
3384 wxDisplayChangedEvent event
;
3385 event
.SetEventObject(this);
3387 return GetEventHandler()->ProcessEvent(event
);
3390 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3398 #ifndef __WXMICROWIN__
3399 WXHBRUSH hBrush
= 0;
3401 if ( nCtlColor
== CTLCOLOR_DLG
)
3403 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3408 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3410 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3412 #endif // wxUSE_CONTROLS
3418 #else // __WXMICROWIN__
3423 // Define for each class of dialog and control
3424 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3425 WXHWND
WXUNUSED(hWnd
),
3426 WXUINT
WXUNUSED(nCtlColor
),
3427 WXUINT
WXUNUSED(message
),
3428 WXWPARAM
WXUNUSED(wParam
),
3429 WXLPARAM
WXUNUSED(lParam
))
3434 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3437 // same as below except we don't respond to our own messages
3438 if ( hWndPalChange
!= GetHWND() )
3440 // check to see if we our our parents have a custom palette
3441 wxWindow
*win
= this;
3442 while ( win
&& !win
->HasCustomPalette() )
3444 win
= win
->GetParent();
3447 if ( win
&& win
->HasCustomPalette() )
3449 // realize the palette to see whether redrawing is needed
3450 HDC hdc
= ::GetDC((HWND
) hWndPalChange
);
3451 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3452 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3454 int result
= ::RealizePalette(hdc
);
3456 // restore the palette (before releasing the DC)
3457 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3458 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3459 ::RealizePalette(hdc
);
3460 ::ReleaseDC((HWND
) hWndPalChange
, hdc
);
3462 // now check for the need to redraw
3464 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
);
3468 #endif // wxUSE_PALETTE
3470 wxPaletteChangedEvent
event(GetId());
3471 event
.SetEventObject(this);
3472 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3474 return GetEventHandler()->ProcessEvent(event
);
3477 bool wxWindowMSW::HandleQueryNewPalette()
3481 // check to see if we our our parents have a custom palette
3482 wxWindow
*win
= this;
3483 while (!win
->HasCustomPalette() && win
->GetParent()) win
= win
->GetParent();
3484 if (win
->HasCustomPalette()) {
3485 /* realize the palette to see whether redrawing is needed */
3486 HDC hdc
= GetDC((HWND
) GetHWND());
3487 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3488 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) );
3490 int result
= ::RealizePalette(hdc
);
3491 /* restore the palette (before releasing the DC) */
3492 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3493 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) );
3494 ::RealizePalette(hdc
);
3495 ::ReleaseDC((HWND
) GetHWND(), hdc
);
3496 /* now check for the need to redraw */
3498 ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
);
3500 #endif // wxUSE_PALETTE
3502 wxQueryNewPaletteEvent
event(GetId());
3503 event
.SetEventObject(this);
3505 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3508 // Responds to colour changes: passes event on to children.
3509 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
))
3511 // the top level window also reset the standard colour map as it might have
3512 // changed (there is no need to do it for the non top level windows as we
3513 // only have to do it once)
3517 gs_hasStdCmap
= FALSE
;
3519 wxWindowList::Node
*node
= GetChildren().GetFirst();
3522 // Only propagate to non-top-level windows because Windows already
3523 // sends this event to all top-level ones
3524 wxWindow
*win
= node
->GetData();
3525 if ( !win
->IsTopLevel() )
3527 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3528 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3529 // the standard controls
3530 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3533 node
= node
->GetNext();
3536 // update the colours we use if they were not set explicitly by the user:
3537 // this must be done or OnCtlColor() would continue to use the old colours
3540 m_foregroundColour
= wxSystemSettings::
3541 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3546 m_backgroundColour
= wxSystemSettings::
3547 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3551 extern wxCOLORMAP
*wxGetStdColourMap()
3553 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3554 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3556 if ( !gs_hasStdCmap
)
3558 static bool s_coloursInit
= FALSE
;
3560 if ( !s_coloursInit
)
3562 // When a bitmap is loaded, the RGB values can change (apparently
3563 // because Windows adjusts them to care for the old programs always
3564 // using 0xc0c0c0 while the transparent colour for the new Windows
3565 // versions is different). But we do this adjustment ourselves so
3566 // we want to avoid Windows' "help" and for this we need to have a
3567 // reference bitmap which can tell us what the RGB values change
3569 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3570 if ( stdColourBitmap
.Ok() )
3572 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3573 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3574 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3577 memDC
.SelectObject(stdColourBitmap
);
3580 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3582 memDC
.GetPixel(i
, 0, &colour
);
3583 s_stdColours
[i
] = wxColourToRGB(colour
);
3586 else // wxBITMAP_STD_COLOURS couldn't be loaded
3588 s_stdColours
[0] = RGB(000,000,000); // black
3589 s_stdColours
[1] = RGB(128,128,128); // dark grey
3590 s_stdColours
[2] = RGB(192,192,192); // light grey
3591 s_stdColours
[3] = RGB(255,255,255); // white
3592 //s_stdColours[4] = RGB(000,000,255); // blue
3593 //s_stdColours[5] = RGB(255,000,255); // magenta
3596 s_coloursInit
= TRUE
;
3599 gs_hasStdCmap
= TRUE
;
3601 // create the colour map
3602 #define INIT_CMAP_ENTRY(col) \
3603 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3604 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3606 INIT_CMAP_ENTRY(BTNTEXT
);
3607 INIT_CMAP_ENTRY(BTNSHADOW
);
3608 INIT_CMAP_ENTRY(BTNFACE
);
3609 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3611 #undef INIT_CMAP_ENTRY
3617 // ---------------------------------------------------------------------------
3619 // ---------------------------------------------------------------------------
3621 bool wxWindowMSW::HandlePaint()
3624 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3626 wxLogLastError(wxT("CreateRectRgn"));
3627 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3628 wxLogLastError(wxT("GetUpdateRgn"));
3630 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3633 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3635 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3636 updateRect
.right
- updateRect
.left
,
3637 updateRect
.bottom
- updateRect
.top
);
3640 wxPaintEvent
event(m_windowId
);
3641 event
.SetEventObject(this);
3643 bool processed
= GetEventHandler()->ProcessEvent(event
);
3645 // note that we must generate NC event after the normal one as otherwise
3646 // BeginPaint() will happily overwrite our decorations with the background
3648 wxNcPaintEvent
eventNc(m_windowId
);
3649 eventNc
.SetEventObject(this);
3650 GetEventHandler()->ProcessEvent(eventNc
);
3655 // Can be called from an application's OnPaint handler
3656 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3658 #ifdef __WXUNIVERSAL__
3661 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3664 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3669 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3671 // Prevents flicker when dragging
3672 if ( ::IsIconic(GetHwnd()) )
3678 dc
.SetWindow((wxWindow
*)this);
3681 wxEraseEvent
event(m_windowId
, &dc
);
3682 event
.SetEventObject(this);
3683 bool rc
= GetEventHandler()->ProcessEvent(event
);
3687 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3688 dc
.SelectOldObjects(hdc
);
3693 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3696 ::GetClientRect(GetHwnd(), &rect
);
3698 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3699 m_backgroundColour
.Green(),
3700 m_backgroundColour
.Blue());
3701 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3703 wxLogLastError(wxT("CreateSolidBrush"));
3705 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3707 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3709 ::FillRect(hdc
, &rect
, hBrush
);
3710 ::DeleteObject(hBrush
);
3711 ::SetMapMode(hdc
, mode
);
3714 // ---------------------------------------------------------------------------
3715 // moving and resizing
3716 // ---------------------------------------------------------------------------
3718 bool wxWindowMSW::HandleMinimize()
3720 wxIconizeEvent
event(m_windowId
);
3721 event
.SetEventObject(this);
3723 return GetEventHandler()->ProcessEvent(event
);
3726 bool wxWindowMSW::HandleMaximize()
3728 wxMaximizeEvent
event(m_windowId
);
3729 event
.SetEventObject(this);
3731 return GetEventHandler()->ProcessEvent(event
);
3734 bool wxWindowMSW::HandleMove(int x
, int y
)
3736 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3737 event
.SetEventObject(this);
3739 return GetEventHandler()->ProcessEvent(event
);
3742 bool wxWindowMSW::HandleSize(int w
, int h
, WXUINT
WXUNUSED(flag
))
3744 wxSizeEvent
event(wxSize(w
, h
), m_windowId
);
3745 event
.SetEventObject(this);
3747 return GetEventHandler()->ProcessEvent(event
);
3750 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3752 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3756 int minWidth
= GetMinWidth(),
3757 minHeight
= GetMinHeight(),
3758 maxWidth
= GetMaxWidth(),
3759 maxHeight
= GetMaxHeight();
3761 if ( minWidth
!= -1 )
3763 info
->ptMinTrackSize
.x
= minWidth
;
3767 if ( minHeight
!= -1 )
3769 info
->ptMinTrackSize
.y
= minHeight
;
3773 if ( maxWidth
!= -1 )
3775 info
->ptMaxTrackSize
.x
= maxWidth
;
3779 if ( maxHeight
!= -1 )
3781 info
->ptMaxTrackSize
.y
= maxHeight
;
3788 // ---------------------------------------------------------------------------
3790 // ---------------------------------------------------------------------------
3792 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3794 #if wxUSE_MENUS_NATIVE
3795 if ( !cmd
&& wxCurrentPopupMenu
)
3797 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3798 wxCurrentPopupMenu
= NULL
;
3800 return popupMenu
->MSWCommand(cmd
, id
);
3802 #endif // wxUSE_MENUS_NATIVE
3804 wxWindow
*win
= NULL
;
3806 // first try to find it from HWND - this works even with the broken
3807 // programs using the same ids for different controls
3810 win
= wxFindWinFromHandle(control
);
3816 // must cast to a signed type before comparing with other ids!
3817 win
= FindItem((signed short)id
);
3822 return win
->MSWCommand(cmd
, id
);
3825 // the messages sent from the in-place edit control used by the treectrl
3826 // for label editing have id == 0, but they should _not_ be treated as menu
3827 // messages (they are EN_XXX ones, in fact) so don't translate anything
3828 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3831 // If no child window, it may be an accelerator, e.g. for a popup menu
3834 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3835 event
.SetEventObject(this);
3839 return GetEventHandler()->ProcessEvent(event
);
3841 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3844 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3845 // notifications to its parent which we want to reflect back to
3847 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3848 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3851 #endif // wxUSE_SPINCTRL
3856 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3858 // 4 bits are reserved
3859 switch ( wParam
& 0xFFFFFFF0 )
3862 return HandleMaximize();
3865 return HandleMinimize();
3871 // ---------------------------------------------------------------------------
3873 // ---------------------------------------------------------------------------
3875 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3879 // our client coords are not quite the same as Windows ones
3880 wxPoint pt
= GetClientAreaOrigin();
3881 event
.m_x
= x
- pt
.x
;
3882 event
.m_y
= y
- pt
.y
;
3884 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3885 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3886 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3887 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3888 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3889 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3891 event
.SetTimestamp(s_currentMsg
.time
);
3892 event
.m_eventObject
= this;
3894 #if wxUSE_MOUSEEVENT_HACK
3897 m_lastMouseEvent
= event
.GetEventType();
3898 #endif // wxUSE_MOUSEEVENT_HACK
3901 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3903 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3904 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3905 // from the message id and take the value in the table to get wxWin event
3907 static const wxEventType eventsMouse
[] =
3921 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3922 InitMouseEvent(event
, x
, y
, flags
);
3924 return GetEventHandler()->ProcessEvent(event
);
3927 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
3929 if ( !m_mouseInWindow
)
3931 // it would be wrong to assume that just because we get a mouse move
3932 // event that the mouse is inside the window: although this is usually
3933 // true, it is not if we had captured the mouse, so we need to check
3934 // the mouse coordinates here
3935 if ( !HasCapture() || IsMouseInWindow() )
3937 // Generate an ENTER event
3938 m_mouseInWindow
= TRUE
;
3940 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
3941 InitMouseEvent(event
, x
, y
, flags
);
3943 (void)GetEventHandler()->ProcessEvent(event
);
3947 #if wxUSE_MOUSEEVENT_HACK
3948 // Window gets a click down message followed by a mouse move message even
3949 // if position isn't changed! We want to discard the trailing move event
3950 // if x and y are the same.
3951 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
3952 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
3953 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
3954 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
3956 m_lastMouseEvent
= wxEVT_MOTION
;
3960 #endif // wxUSE_MOUSEEVENT_HACK
3962 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
3966 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
3968 #if wxUSE_MOUSEWHEEL
3969 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
3970 InitMouseEvent(event
,
3971 GET_X_LPARAM(lParam
),
3972 GET_Y_LPARAM(lParam
),
3974 event
.m_wheelRotation
= (short)HIWORD(wParam
);
3975 event
.m_wheelDelta
= WHEEL_DELTA
;
3978 static int s_linesPerRotation
= -1;
3979 if ( s_linesPerRotation
== -1 )
3981 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
3982 &s_linesPerRotation
, 0))
3984 // this is not supposed to happen
3985 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
3987 // the default is 3, so use it if SystemParametersInfo() failed
3988 s_linesPerRotation
= 3;
3992 // no SystemParametersInfo() under Win16
3993 static const int s_linesPerRotation
= 3;
3996 event
.m_linesPerAction
= s_linesPerRotation
;
3997 return GetEventHandler()->ProcessEvent(event
);
4008 // ---------------------------------------------------------------------------
4009 // keyboard handling
4010 // ---------------------------------------------------------------------------
4012 // create the key event of the given type for the given key - used by
4013 // HandleChar and HandleKeyDown/Up
4014 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
4016 WXLPARAM lParam
) const
4018 wxKeyEvent
event(evType
);
4019 event
.SetId(GetId());
4020 event
.m_shiftDown
= wxIsShiftDown();
4021 event
.m_controlDown
= wxIsCtrlDown();
4022 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
4024 event
.m_eventObject
= (wxWindow
*)this; // const_cast
4025 event
.m_keyCode
= id
;
4026 event
.SetTimestamp(s_currentMsg
.time
);
4028 // translate the position to client coords
4032 GetWindowRect(GetHwnd(),&rect
);
4042 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
4044 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
4046 bool ctrlDown
= FALSE
;
4051 // If 1 -> 26, translate to CTRL plus a letter.
4053 if ( (id
> 0) && (id
< 27) )
4075 else if ( (id
= wxCharCodeMSWToWX(wParam
)) == 0 )
4077 // it's ASCII and will be processed here only when called from
4078 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
4084 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
));
4087 event
.m_controlDown
= TRUE
;
4090 if ( GetEventHandler()->ProcessEvent(event
) )
4097 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
4099 int id
= wxCharCodeMSWToWX(wParam
);
4103 // normal ASCII char
4107 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4109 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
));
4110 if ( GetEventHandler()->ProcessEvent(event
) )
4119 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
4121 int id
= wxCharCodeMSWToWX(wParam
);
4125 // normal ASCII char
4129 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4131 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
));
4132 if ( GetEventHandler()->ProcessEvent(event
) )
4139 // ---------------------------------------------------------------------------
4141 // ---------------------------------------------------------------------------
4143 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4147 if ( flags
& JOY_BUTTON1CHG
)
4148 change
= wxJOY_BUTTON1
;
4149 if ( flags
& JOY_BUTTON2CHG
)
4150 change
= wxJOY_BUTTON2
;
4151 if ( flags
& JOY_BUTTON3CHG
)
4152 change
= wxJOY_BUTTON3
;
4153 if ( flags
& JOY_BUTTON4CHG
)
4154 change
= wxJOY_BUTTON4
;
4157 if ( flags
& JOY_BUTTON1
)
4158 buttons
|= wxJOY_BUTTON1
;
4159 if ( flags
& JOY_BUTTON2
)
4160 buttons
|= wxJOY_BUTTON2
;
4161 if ( flags
& JOY_BUTTON3
)
4162 buttons
|= wxJOY_BUTTON3
;
4163 if ( flags
& JOY_BUTTON4
)
4164 buttons
|= wxJOY_BUTTON4
;
4166 // the event ids aren't consecutive so we can't use table based lookup
4168 wxEventType eventType
;
4173 eventType
= wxEVT_JOY_MOVE
;
4178 eventType
= wxEVT_JOY_MOVE
;
4183 eventType
= wxEVT_JOY_ZMOVE
;
4188 eventType
= wxEVT_JOY_ZMOVE
;
4191 case MM_JOY1BUTTONDOWN
:
4193 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4196 case MM_JOY2BUTTONDOWN
:
4198 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4201 case MM_JOY1BUTTONUP
:
4203 eventType
= wxEVT_JOY_BUTTON_UP
;
4206 case MM_JOY2BUTTONUP
:
4208 eventType
= wxEVT_JOY_BUTTON_UP
;
4212 wxFAIL_MSG(wxT("no such joystick event"));
4217 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4218 event
.SetPosition(wxPoint(x
, y
));
4219 event
.SetEventObject(this);
4221 return GetEventHandler()->ProcessEvent(event
);
4227 // ---------------------------------------------------------------------------
4229 // ---------------------------------------------------------------------------
4231 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4232 WXWORD pos
, WXHWND control
)
4236 wxWindow
*child
= wxFindWinFromHandle(control
);
4238 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4241 wxScrollWinEvent event
;
4242 event
.SetPosition(pos
);
4243 event
.SetOrientation(orientation
);
4244 event
.m_eventObject
= this;
4249 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4253 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4257 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4261 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4265 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4269 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4272 case SB_THUMBPOSITION
:
4275 // under Win32, the scrollbar range and position are 32 bit integers,
4276 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4277 // explicitly query the scrollbar for the correct position (this must
4278 // be done only for these two SB_ events as they are the only one
4279 // carrying the scrollbar position)
4281 SCROLLINFO scrollInfo
;
4282 wxZeroMemory(scrollInfo
);
4283 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4284 scrollInfo
.fMask
= SIF_TRACKPOS
;
4286 if ( !::GetScrollInfo(GetHwnd(),
4287 orientation
== wxHORIZONTAL
? SB_HORZ
4291 wxLogLastError(_T("GetScrollInfo"));
4294 event
.SetPosition(scrollInfo
.nTrackPos
);
4298 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4299 ? wxEVT_SCROLLWIN_THUMBRELEASE
4300 : wxEVT_SCROLLWIN_THUMBTRACK
;
4307 return GetEventHandler()->ProcessEvent(event
);
4310 // ===========================================================================
4312 // ===========================================================================
4314 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4317 HDC dc
= ::GetDC((HWND
) wnd
);
4322 // the_font->UseResource();
4323 // the_font->RealizeResource();
4324 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4326 was
= (HFONT
) SelectObject(dc
,fnt
);
4328 GetTextMetrics(dc
, &tm
);
4329 if ( the_font
&& fnt
&& was
)
4331 SelectObject(dc
,was
);
4333 ReleaseDC((HWND
)wnd
, dc
);
4336 *x
= tm
.tmAveCharWidth
;
4338 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4341 // the_font->ReleaseResource();
4344 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4345 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4346 int wxCharCodeMSWToWX(int keySym
)
4351 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4352 case VK_BACK
: id
= WXK_BACK
; break;
4353 case VK_TAB
: id
= WXK_TAB
; break;
4354 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4355 case VK_RETURN
: id
= WXK_RETURN
; break;
4356 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4357 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4358 case VK_MENU
: id
= WXK_MENU
; break;
4359 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4360 case VK_SPACE
: id
= WXK_SPACE
; break;
4361 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4362 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4363 case VK_NEXT
: id
= WXK_NEXT
; break;
4364 case VK_END
: id
= WXK_END
; break;
4365 case VK_HOME
: id
= WXK_HOME
; break;
4366 case VK_LEFT
: id
= WXK_LEFT
; break;
4367 case VK_UP
: id
= WXK_UP
; break;
4368 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4369 case VK_DOWN
: id
= WXK_DOWN
; break;
4370 case VK_SELECT
: id
= WXK_SELECT
; break;
4371 case VK_PRINT
: id
= WXK_PRINT
; break;
4372 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4373 case VK_INSERT
: id
= WXK_INSERT
; break;
4374 case VK_DELETE
: id
= WXK_DELETE
; break;
4375 case VK_HELP
: id
= WXK_HELP
; break;
4376 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4377 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4378 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4379 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4380 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4381 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4382 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4383 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4384 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4385 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4386 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4387 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4388 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4389 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4390 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4391 case VK_F1
: id
= WXK_F1
; break;
4392 case VK_F2
: id
= WXK_F2
; break;
4393 case VK_F3
: id
= WXK_F3
; break;
4394 case VK_F4
: id
= WXK_F4
; break;
4395 case VK_F5
: id
= WXK_F5
; break;
4396 case VK_F6
: id
= WXK_F6
; break;
4397 case VK_F7
: id
= WXK_F7
; break;
4398 case VK_F8
: id
= WXK_F8
; break;
4399 case VK_F9
: id
= WXK_F9
; break;
4400 case VK_F10
: id
= WXK_F10
; break;
4401 case VK_F11
: id
= WXK_F11
; break;
4402 case VK_F12
: id
= WXK_F12
; break;
4403 case VK_F13
: id
= WXK_F13
; break;
4404 case VK_F14
: id
= WXK_F14
; break;
4405 case VK_F15
: id
= WXK_F15
; break;
4406 case VK_F16
: id
= WXK_F16
; break;
4407 case VK_F17
: id
= WXK_F17
; break;
4408 case VK_F18
: id
= WXK_F18
; break;
4409 case VK_F19
: id
= WXK_F19
; break;
4410 case VK_F20
: id
= WXK_F20
; break;
4411 case VK_F21
: id
= WXK_F21
; break;
4412 case VK_F22
: id
= WXK_F22
; break;
4413 case VK_F23
: id
= WXK_F23
; break;
4414 case VK_F24
: id
= WXK_F24
; break;
4415 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4416 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4424 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4430 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4431 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4432 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4433 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4434 case WXK_MENU
: keySym
= VK_MENU
; break;
4435 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4436 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4437 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4438 case WXK_END
: keySym
= VK_END
; break;
4439 case WXK_HOME
: keySym
= VK_HOME
; break;
4440 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4441 case WXK_UP
: keySym
= VK_UP
; break;
4442 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4443 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4444 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4445 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4446 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4447 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4448 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4449 case WXK_HELP
: keySym
= VK_HELP
; break;
4450 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4451 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4452 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4453 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4454 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4455 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4456 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4457 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4458 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4459 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4460 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4461 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4462 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4463 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4464 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4465 case WXK_F1
: keySym
= VK_F1
; break;
4466 case WXK_F2
: keySym
= VK_F2
; break;
4467 case WXK_F3
: keySym
= VK_F3
; break;
4468 case WXK_F4
: keySym
= VK_F4
; break;
4469 case WXK_F5
: keySym
= VK_F5
; break;
4470 case WXK_F6
: keySym
= VK_F6
; break;
4471 case WXK_F7
: keySym
= VK_F7
; break;
4472 case WXK_F8
: keySym
= VK_F8
; break;
4473 case WXK_F9
: keySym
= VK_F9
; break;
4474 case WXK_F10
: keySym
= VK_F10
; break;
4475 case WXK_F11
: keySym
= VK_F11
; break;
4476 case WXK_F12
: keySym
= VK_F12
; break;
4477 case WXK_F13
: keySym
= VK_F13
; break;
4478 case WXK_F14
: keySym
= VK_F14
; break;
4479 case WXK_F15
: keySym
= VK_F15
; break;
4480 case WXK_F16
: keySym
= VK_F16
; break;
4481 case WXK_F17
: keySym
= VK_F17
; break;
4482 case WXK_F18
: keySym
= VK_F18
; break;
4483 case WXK_F19
: keySym
= VK_F19
; break;
4484 case WXK_F20
: keySym
= VK_F20
; break;
4485 case WXK_F21
: keySym
= VK_F21
; break;
4486 case WXK_F22
: keySym
= VK_F22
; break;
4487 case WXK_F23
: keySym
= VK_F23
; break;
4488 case WXK_F24
: keySym
= VK_F24
; break;
4489 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4490 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4501 wxWindow
*wxGetActiveWindow()
4503 HWND hWnd
= GetActiveWindow();
4506 return wxFindWinFromHandle((WXHWND
) hWnd
);
4511 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4513 HWND hwnd
= (HWND
)hWnd
;
4515 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4516 // by code in msw/radiobox.cpp), for all the others we just search up the
4518 wxWindow
*win
= (wxWindow
*)NULL
;
4521 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4524 // all these hacks only work under Win32 anyhow
4528 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4529 // wxWindow class which overrides WM_GETDLGCODE processing to
4530 // do it as well, win would be already non NULL
4531 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4533 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4535 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4536 #endif // wxUSE_RADIOBOX
4538 // spin control text buddy window should be mapped to spin ctrl
4539 // itself so try it too
4540 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4543 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4545 #endif // wxUSE_SPINCTRL
4551 while ( hwnd
&& !win
)
4553 // this is a really ugly hack needed to avoid mistakenly returning the
4554 // parent frame wxWindow for the find/replace modeless dialog HWND -
4555 // this, in turn, is needed to call IsDialogMessage() from
4556 // wxApp::ProcessMessage() as for this we must return NULL from here
4558 // FIXME: this is clearly not the best way to do it but I think we'll
4559 // need to change HWND <-> wxWindow code more heavily than I can
4560 // do it now to fix it
4561 #ifndef __WXMICROWIN__
4562 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4564 // it's a dialog box, don't go upwards
4569 hwnd
= ::GetParent(hwnd
);
4570 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4576 #ifndef __WXMICROWIN__
4578 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4579 // in active frames and dialogs, regardless of where the focus is.
4580 static HHOOK wxTheKeyboardHook
= 0;
4581 static FARPROC wxTheKeyboardHookProc
= 0;
4582 int APIENTRY _EXPORT
4583 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4585 void wxSetKeyboardHook(bool doIt
)
4589 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4590 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4592 #if defined(__WIN32__) && !defined(__TWIN32__)
4593 GetCurrentThreadId()
4594 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4602 UnhookWindowsHookEx(wxTheKeyboardHook
);
4604 // avoids warning about statement with no effect (FreeProcInstance
4605 // doesn't do anything under Win32)
4606 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4607 FreeProcInstance(wxTheKeyboardHookProc
);
4612 int APIENTRY _EXPORT
4613 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4615 DWORD hiWord
= HIWORD(lParam
);
4616 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4618 int id
= wxCharCodeMSWToWX(wParam
);
4621 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4622 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4623 event
.m_altDown
= TRUE
;
4625 event
.m_eventObject
= NULL
;
4626 event
.m_keyCode
= id
;
4627 event
.m_shiftDown
= wxIsShiftDown();
4628 event
.m_controlDown
= wxIsCtrlDown();
4629 event
.SetTimestamp(s_currentMsg
.time
);
4631 wxWindow
*win
= wxGetActiveWindow();
4632 wxEvtHandler
*handler
;
4635 handler
= win
->GetEventHandler();
4636 event
.SetId(win
->GetId());
4644 if ( handler
&& handler
->ProcessEvent(event
) )
4652 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4655 #endif // !__WXMICROWIN__
4658 const char *wxGetMessageName(int message
)
4662 case 0x0000: return "WM_NULL";
4663 case 0x0001: return "WM_CREATE";
4664 case 0x0002: return "WM_DESTROY";
4665 case 0x0003: return "WM_MOVE";
4666 case 0x0005: return "WM_SIZE";
4667 case 0x0006: return "WM_ACTIVATE";
4668 case 0x0007: return "WM_SETFOCUS";
4669 case 0x0008: return "WM_KILLFOCUS";
4670 case 0x000A: return "WM_ENABLE";
4671 case 0x000B: return "WM_SETREDRAW";
4672 case 0x000C: return "WM_SETTEXT";
4673 case 0x000D: return "WM_GETTEXT";
4674 case 0x000E: return "WM_GETTEXTLENGTH";
4675 case 0x000F: return "WM_PAINT";
4676 case 0x0010: return "WM_CLOSE";
4677 case 0x0011: return "WM_QUERYENDSESSION";
4678 case 0x0012: return "WM_QUIT";
4679 case 0x0013: return "WM_QUERYOPEN";
4680 case 0x0014: return "WM_ERASEBKGND";
4681 case 0x0015: return "WM_SYSCOLORCHANGE";
4682 case 0x0016: return "WM_ENDSESSION";
4683 case 0x0017: return "WM_SYSTEMERROR";
4684 case 0x0018: return "WM_SHOWWINDOW";
4685 case 0x0019: return "WM_CTLCOLOR";
4686 case 0x001A: return "WM_WININICHANGE";
4687 case 0x001B: return "WM_DEVMODECHANGE";
4688 case 0x001C: return "WM_ACTIVATEAPP";
4689 case 0x001D: return "WM_FONTCHANGE";
4690 case 0x001E: return "WM_TIMECHANGE";
4691 case 0x001F: return "WM_CANCELMODE";
4692 case 0x0020: return "WM_SETCURSOR";
4693 case 0x0021: return "WM_MOUSEACTIVATE";
4694 case 0x0022: return "WM_CHILDACTIVATE";
4695 case 0x0023: return "WM_QUEUESYNC";
4696 case 0x0024: return "WM_GETMINMAXINFO";
4697 case 0x0026: return "WM_PAINTICON";
4698 case 0x0027: return "WM_ICONERASEBKGND";
4699 case 0x0028: return "WM_NEXTDLGCTL";
4700 case 0x002A: return "WM_SPOOLERSTATUS";
4701 case 0x002B: return "WM_DRAWITEM";
4702 case 0x002C: return "WM_MEASUREITEM";
4703 case 0x002D: return "WM_DELETEITEM";
4704 case 0x002E: return "WM_VKEYTOITEM";
4705 case 0x002F: return "WM_CHARTOITEM";
4706 case 0x0030: return "WM_SETFONT";
4707 case 0x0031: return "WM_GETFONT";
4708 case 0x0037: return "WM_QUERYDRAGICON";
4709 case 0x0039: return "WM_COMPAREITEM";
4710 case 0x0041: return "WM_COMPACTING";
4711 case 0x0044: return "WM_COMMNOTIFY";
4712 case 0x0046: return "WM_WINDOWPOSCHANGING";
4713 case 0x0047: return "WM_WINDOWPOSCHANGED";
4714 case 0x0048: return "WM_POWER";
4717 case 0x004A: return "WM_COPYDATA";
4718 case 0x004B: return "WM_CANCELJOURNAL";
4719 case 0x004E: return "WM_NOTIFY";
4720 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4721 case 0x0051: return "WM_INPUTLANGCHANGE";
4722 case 0x0052: return "WM_TCARD";
4723 case 0x0053: return "WM_HELP";
4724 case 0x0054: return "WM_USERCHANGED";
4725 case 0x0055: return "WM_NOTIFYFORMAT";
4726 case 0x007B: return "WM_CONTEXTMENU";
4727 case 0x007C: return "WM_STYLECHANGING";
4728 case 0x007D: return "WM_STYLECHANGED";
4729 case 0x007E: return "WM_DISPLAYCHANGE";
4730 case 0x007F: return "WM_GETICON";
4731 case 0x0080: return "WM_SETICON";
4734 case 0x0081: return "WM_NCCREATE";
4735 case 0x0082: return "WM_NCDESTROY";
4736 case 0x0083: return "WM_NCCALCSIZE";
4737 case 0x0084: return "WM_NCHITTEST";
4738 case 0x0085: return "WM_NCPAINT";
4739 case 0x0086: return "WM_NCACTIVATE";
4740 case 0x0087: return "WM_GETDLGCODE";
4741 case 0x00A0: return "WM_NCMOUSEMOVE";
4742 case 0x00A1: return "WM_NCLBUTTONDOWN";
4743 case 0x00A2: return "WM_NCLBUTTONUP";
4744 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4745 case 0x00A4: return "WM_NCRBUTTONDOWN";
4746 case 0x00A5: return "WM_NCRBUTTONUP";
4747 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4748 case 0x00A7: return "WM_NCMBUTTONDOWN";
4749 case 0x00A8: return "WM_NCMBUTTONUP";
4750 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4751 case 0x0100: return "WM_KEYDOWN";
4752 case 0x0101: return "WM_KEYUP";
4753 case 0x0102: return "WM_CHAR";
4754 case 0x0103: return "WM_DEADCHAR";
4755 case 0x0104: return "WM_SYSKEYDOWN";
4756 case 0x0105: return "WM_SYSKEYUP";
4757 case 0x0106: return "WM_SYSCHAR";
4758 case 0x0107: return "WM_SYSDEADCHAR";
4759 case 0x0108: return "WM_KEYLAST";
4762 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4763 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4764 case 0x010F: return "WM_IME_COMPOSITION";
4767 case 0x0110: return "WM_INITDIALOG";
4768 case 0x0111: return "WM_COMMAND";
4769 case 0x0112: return "WM_SYSCOMMAND";
4770 case 0x0113: return "WM_TIMER";
4771 case 0x0114: return "WM_HSCROLL";
4772 case 0x0115: return "WM_VSCROLL";
4773 case 0x0116: return "WM_INITMENU";
4774 case 0x0117: return "WM_INITMENUPOPUP";
4775 case 0x011F: return "WM_MENUSELECT";
4776 case 0x0120: return "WM_MENUCHAR";
4777 case 0x0121: return "WM_ENTERIDLE";
4778 case 0x0200: return "WM_MOUSEMOVE";
4779 case 0x0201: return "WM_LBUTTONDOWN";
4780 case 0x0202: return "WM_LBUTTONUP";
4781 case 0x0203: return "WM_LBUTTONDBLCLK";
4782 case 0x0204: return "WM_RBUTTONDOWN";
4783 case 0x0205: return "WM_RBUTTONUP";
4784 case 0x0206: return "WM_RBUTTONDBLCLK";
4785 case 0x0207: return "WM_MBUTTONDOWN";
4786 case 0x0208: return "WM_MBUTTONUP";
4787 case 0x0209: return "WM_MBUTTONDBLCLK";
4788 case 0x020A: return "WM_MOUSEWHEEL";
4789 case 0x0210: return "WM_PARENTNOTIFY";
4790 case 0x0211: return "WM_ENTERMENULOOP";
4791 case 0x0212: return "WM_EXITMENULOOP";
4794 case 0x0213: return "WM_NEXTMENU";
4795 case 0x0214: return "WM_SIZING";
4796 case 0x0215: return "WM_CAPTURECHANGED";
4797 case 0x0216: return "WM_MOVING";
4798 case 0x0218: return "WM_POWERBROADCAST";
4799 case 0x0219: return "WM_DEVICECHANGE";
4802 case 0x0220: return "WM_MDICREATE";
4803 case 0x0221: return "WM_MDIDESTROY";
4804 case 0x0222: return "WM_MDIACTIVATE";
4805 case 0x0223: return "WM_MDIRESTORE";
4806 case 0x0224: return "WM_MDINEXT";
4807 case 0x0225: return "WM_MDIMAXIMIZE";
4808 case 0x0226: return "WM_MDITILE";
4809 case 0x0227: return "WM_MDICASCADE";
4810 case 0x0228: return "WM_MDIICONARRANGE";
4811 case 0x0229: return "WM_MDIGETACTIVE";
4812 case 0x0230: return "WM_MDISETMENU";
4813 case 0x0233: return "WM_DROPFILES";
4816 case 0x0281: return "WM_IME_SETCONTEXT";
4817 case 0x0282: return "WM_IME_NOTIFY";
4818 case 0x0283: return "WM_IME_CONTROL";
4819 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4820 case 0x0285: return "WM_IME_SELECT";
4821 case 0x0286: return "WM_IME_CHAR";
4822 case 0x0290: return "WM_IME_KEYDOWN";
4823 case 0x0291: return "WM_IME_KEYUP";
4826 case 0x0300: return "WM_CUT";
4827 case 0x0301: return "WM_COPY";
4828 case 0x0302: return "WM_PASTE";
4829 case 0x0303: return "WM_CLEAR";
4830 case 0x0304: return "WM_UNDO";
4831 case 0x0305: return "WM_RENDERFORMAT";
4832 case 0x0306: return "WM_RENDERALLFORMATS";
4833 case 0x0307: return "WM_DESTROYCLIPBOARD";
4834 case 0x0308: return "WM_DRAWCLIPBOARD";
4835 case 0x0309: return "WM_PAINTCLIPBOARD";
4836 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4837 case 0x030B: return "WM_SIZECLIPBOARD";
4838 case 0x030C: return "WM_ASKCBFORMATNAME";
4839 case 0x030D: return "WM_CHANGECBCHAIN";
4840 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4841 case 0x030F: return "WM_QUERYNEWPALETTE";
4842 case 0x0310: return "WM_PALETTEISCHANGING";
4843 case 0x0311: return "WM_PALETTECHANGED";
4846 // common controls messages - although they're not strictly speaking
4847 // standard, it's nice to decode them nevertheless
4850 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4851 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4852 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4853 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4854 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4855 case 0x1000 + 5: return "LVM_GETITEMA";
4856 case 0x1000 + 75: return "LVM_GETITEMW";
4857 case 0x1000 + 6: return "LVM_SETITEMA";
4858 case 0x1000 + 76: return "LVM_SETITEMW";
4859 case 0x1000 + 7: return "LVM_INSERTITEMA";
4860 case 0x1000 + 77: return "LVM_INSERTITEMW";
4861 case 0x1000 + 8: return "LVM_DELETEITEM";
4862 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4863 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4864 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4865 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4866 case 0x1000 + 13: return "LVM_FINDITEMA";
4867 case 0x1000 + 83: return "LVM_FINDITEMW";
4868 case 0x1000 + 14: return "LVM_GETITEMRECT";
4869 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4870 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4871 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4872 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4873 case 0x1000 + 18: return "LVM_HITTEST";
4874 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4875 case 0x1000 + 20: return "LVM_SCROLL";
4876 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4877 case 0x1000 + 22: return "LVM_ARRANGE";
4878 case 0x1000 + 23: return "LVM_EDITLABELA";
4879 case 0x1000 + 118: return "LVM_EDITLABELW";
4880 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4881 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4882 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4883 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4884 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4885 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4886 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4887 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4888 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4889 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4890 case 0x1000 + 31: return "LVM_GETHEADER";
4891 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4892 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4893 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4894 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4895 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4896 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4897 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4898 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4899 case 0x1000 + 41: return "LVM_GETORIGIN";
4900 case 0x1000 + 42: return "LVM_UPDATE";
4901 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4902 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4903 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4904 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4905 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4906 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4907 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4908 case 0x1000 + 48: return "LVM_SORTITEMS";
4909 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
4910 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
4911 case 0x1000 + 51: return "LVM_GETITEMSPACING";
4912 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
4913 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
4914 case 0x1000 + 53: return "LVM_SETICONSPACING";
4915 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
4916 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
4917 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
4918 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
4919 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
4920 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
4921 case 0x1000 + 60: return "LVM_SETHOTITEM";
4922 case 0x1000 + 61: return "LVM_GETHOTITEM";
4923 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
4924 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
4925 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
4926 case 0x1000 + 65: return "LVM_SETWORKAREA";
4929 case 0x1100 + 0: return "TVM_INSERTITEMA";
4930 case 0x1100 + 50: return "TVM_INSERTITEMW";
4931 case 0x1100 + 1: return "TVM_DELETEITEM";
4932 case 0x1100 + 2: return "TVM_EXPAND";
4933 case 0x1100 + 4: return "TVM_GETITEMRECT";
4934 case 0x1100 + 5: return "TVM_GETCOUNT";
4935 case 0x1100 + 6: return "TVM_GETINDENT";
4936 case 0x1100 + 7: return "TVM_SETINDENT";
4937 case 0x1100 + 8: return "TVM_GETIMAGELIST";
4938 case 0x1100 + 9: return "TVM_SETIMAGELIST";
4939 case 0x1100 + 10: return "TVM_GETNEXTITEM";
4940 case 0x1100 + 11: return "TVM_SELECTITEM";
4941 case 0x1100 + 12: return "TVM_GETITEMA";
4942 case 0x1100 + 62: return "TVM_GETITEMW";
4943 case 0x1100 + 13: return "TVM_SETITEMA";
4944 case 0x1100 + 63: return "TVM_SETITEMW";
4945 case 0x1100 + 14: return "TVM_EDITLABELA";
4946 case 0x1100 + 65: return "TVM_EDITLABELW";
4947 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
4948 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
4949 case 0x1100 + 17: return "TVM_HITTEST";
4950 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
4951 case 0x1100 + 19: return "TVM_SORTCHILDREN";
4952 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
4953 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
4954 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
4955 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
4956 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
4957 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
4958 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
4961 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
4962 case 0x1200 + 1: return "HDM_INSERTITEMA";
4963 case 0x1200 + 10: return "HDM_INSERTITEMW";
4964 case 0x1200 + 2: return "HDM_DELETEITEM";
4965 case 0x1200 + 3: return "HDM_GETITEMA";
4966 case 0x1200 + 11: return "HDM_GETITEMW";
4967 case 0x1200 + 4: return "HDM_SETITEMA";
4968 case 0x1200 + 12: return "HDM_SETITEMW";
4969 case 0x1200 + 5: return "HDM_LAYOUT";
4970 case 0x1200 + 6: return "HDM_HITTEST";
4971 case 0x1200 + 7: return "HDM_GETITEMRECT";
4972 case 0x1200 + 8: return "HDM_SETIMAGELIST";
4973 case 0x1200 + 9: return "HDM_GETIMAGELIST";
4974 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
4975 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
4976 case 0x1200 + 17: return "HDM_GETORDERARRAY";
4977 case 0x1200 + 18: return "HDM_SETORDERARRAY";
4978 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
4981 case 0x1300 + 2: return "TCM_GETIMAGELIST";
4982 case 0x1300 + 3: return "TCM_SETIMAGELIST";
4983 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
4984 case 0x1300 + 5: return "TCM_GETITEMA";
4985 case 0x1300 + 60: return "TCM_GETITEMW";
4986 case 0x1300 + 6: return "TCM_SETITEMA";
4987 case 0x1300 + 61: return "TCM_SETITEMW";
4988 case 0x1300 + 7: return "TCM_INSERTITEMA";
4989 case 0x1300 + 62: return "TCM_INSERTITEMW";
4990 case 0x1300 + 8: return "TCM_DELETEITEM";
4991 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
4992 case 0x1300 + 10: return "TCM_GETITEMRECT";
4993 case 0x1300 + 11: return "TCM_GETCURSEL";
4994 case 0x1300 + 12: return "TCM_SETCURSEL";
4995 case 0x1300 + 13: return "TCM_HITTEST";
4996 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
4997 case 0x1300 + 40: return "TCM_ADJUSTRECT";
4998 case 0x1300 + 41: return "TCM_SETITEMSIZE";
4999 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
5000 case 0x1300 + 43: return "TCM_SETPADDING";
5001 case 0x1300 + 44: return "TCM_GETROWCOUNT";
5002 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
5003 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
5004 case 0x1300 + 47: return "TCM_GETCURFOCUS";
5005 case 0x1300 + 48: return "TCM_SETCURFOCUS";
5006 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
5007 case 0x1300 + 50: return "TCM_DESELECTALL";
5010 case WM_USER
+1: return "TB_ENABLEBUTTON";
5011 case WM_USER
+2: return "TB_CHECKBUTTON";
5012 case WM_USER
+3: return "TB_PRESSBUTTON";
5013 case WM_USER
+4: return "TB_HIDEBUTTON";
5014 case WM_USER
+5: return "TB_INDETERMINATE";
5015 case WM_USER
+9: return "TB_ISBUTTONENABLED";
5016 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
5017 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
5018 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
5019 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
5020 case WM_USER
+17: return "TB_SETSTATE";
5021 case WM_USER
+18: return "TB_GETSTATE";
5022 case WM_USER
+19: return "TB_ADDBITMAP";
5023 case WM_USER
+20: return "TB_ADDBUTTONS";
5024 case WM_USER
+21: return "TB_INSERTBUTTON";
5025 case WM_USER
+22: return "TB_DELETEBUTTON";
5026 case WM_USER
+23: return "TB_GETBUTTON";
5027 case WM_USER
+24: return "TB_BUTTONCOUNT";
5028 case WM_USER
+25: return "TB_COMMANDTOINDEX";
5029 case WM_USER
+26: return "TB_SAVERESTOREA";
5030 case WM_USER
+76: return "TB_SAVERESTOREW";
5031 case WM_USER
+27: return "TB_CUSTOMIZE";
5032 case WM_USER
+28: return "TB_ADDSTRINGA";
5033 case WM_USER
+77: return "TB_ADDSTRINGW";
5034 case WM_USER
+29: return "TB_GETITEMRECT";
5035 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
5036 case WM_USER
+31: return "TB_SETBUTTONSIZE";
5037 case WM_USER
+32: return "TB_SETBITMAPSIZE";
5038 case WM_USER
+33: return "TB_AUTOSIZE";
5039 case WM_USER
+35: return "TB_GETTOOLTIPS";
5040 case WM_USER
+36: return "TB_SETTOOLTIPS";
5041 case WM_USER
+37: return "TB_SETPARENT";
5042 case WM_USER
+39: return "TB_SETROWS";
5043 case WM_USER
+40: return "TB_GETROWS";
5044 case WM_USER
+42: return "TB_SETCMDID";
5045 case WM_USER
+43: return "TB_CHANGEBITMAP";
5046 case WM_USER
+44: return "TB_GETBITMAP";
5047 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
5048 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
5049 case WM_USER
+46: return "TB_REPLACEBITMAP";
5050 case WM_USER
+47: return "TB_SETINDENT";
5051 case WM_USER
+48: return "TB_SETIMAGELIST";
5052 case WM_USER
+49: return "TB_GETIMAGELIST";
5053 case WM_USER
+50: return "TB_LOADIMAGES";
5054 case WM_USER
+51: return "TB_GETRECT";
5055 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
5056 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
5057 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
5058 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
5059 case WM_USER
+56: return "TB_SETSTYLE";
5060 case WM_USER
+57: return "TB_GETSTYLE";
5061 case WM_USER
+58: return "TB_GETBUTTONSIZE";
5062 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
5063 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
5064 case WM_USER
+61: return "TB_GETTEXTROWS";
5065 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
5070 static char s_szBuf
[128];
5071 sprintf(s_szBuf
, "<unknown message = %d>", message
);
5075 #endif //__WXDEBUG__
5077 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
5078 int *x
, int *y
, WPARAM
*flags
)
5080 // construct the key mask
5081 WPARAM
& fwKeys
= *flags
;
5083 fwKeys
= MK_RBUTTON
;
5084 if ( wxIsCtrlDown() )
5085 fwKeys
|= MK_CONTROL
;
5086 if ( wxIsShiftDown() )
5089 // simulate right mouse button click
5090 DWORD dwPos
= ::GetMessagePos();
5091 *x
= GET_X_LPARAM(dwPos
);
5092 *y
= GET_Y_LPARAM(dwPos
);
5094 win
->ScreenToClient(x
, y
);
5097 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
5101 HWND hwnd
= GetHwndOf(win
);
5102 HDC hdc
= ::GetDC(hwnd
);
5104 #if !wxDIALOG_UNIT_COMPATIBILITY
5105 // and select the current font into it
5106 HFONT hfont
= GetHfontOf(win
->GetFont());
5109 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
5113 // finally retrieve the text metrics from it
5114 GetTextMetrics(hdc
, &tm
);
5116 #if !wxDIALOG_UNIT_COMPATIBILITY
5120 (void)::SelectObject(hdc
, hfont
);
5124 ::ReleaseDC(hwnd
, hdc
);
5129 // Find the wxWindow at the current mouse position, returning the mouse
5131 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
5133 return wxFindWindowAtPoint(wxGetMousePosition());
5136 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
5141 HWND hWndHit
= ::WindowFromPoint(pt2
);
5143 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
5144 HWND hWnd
= hWndHit
;
5146 // Try to find a window with a wxWindow associated with it
5147 while (!win
&& (hWnd
!= 0))
5149 hWnd
= ::GetParent(hWnd
);
5150 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
5155 // Get the current mouse position.
5156 wxPoint
wxGetMousePosition()
5159 GetCursorPos( & pt
);
5160 return wxPoint(pt
.x
, pt
.y
);