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 // ----------------------------------------------------------------------------
106 // standard constants not available with all compilers/headers
107 // ----------------------------------------------------------------------------
109 // This didn't appear in mingw until 2.95.2
111 #define SIF_TRACKPOS 16
115 #ifndef WM_MOUSEWHEEL
116 #define WM_MOUSEWHEEL 0x020A
119 #define WHEEL_DELTA 120
121 #ifndef SPI_GETWHEELSCROLLLINES
122 #define SPI_GETWHEELSCROLLLINES 104
124 #endif // wxUSE_MOUSEWHEEL
127 #define VK_OEM_1 0xBA
128 #define VK_OEM_PLUS 0xBB
129 #define VK_OEM_COMMA 0xBC
130 #define VK_OEM_MINUS 0xBD
131 #define VK_OEM_PERIOD 0xBE
132 #define VK_OEM_2 0xBF
133 #define VK_OEM_3 0xC0
134 #define VK_OEM_4 0xDB
135 #define VK_OEM_5 0xDC
136 #define VK_OEM_6 0xDD
137 #define VK_OEM_7 0xDE
140 // ---------------------------------------------------------------------------
142 // ---------------------------------------------------------------------------
144 // the last Windows message we got (FIXME-MT)
145 extern MSG s_currentMsg
;
147 #if wxUSE_MENUS_NATIVE
148 wxMenu
*wxCurrentPopupMenu
= NULL
;
149 #endif // wxUSE_MENUS_NATIVE
151 extern const wxChar
*wxCanvasClassName
;
153 // true if we had already created the std colour map, used by
154 // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
155 static bool gs_hasStdCmap
= FALSE
;
157 // ---------------------------------------------------------------------------
159 // ---------------------------------------------------------------------------
161 // the window proc for all our windows
162 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
163 WPARAM wParam
, LPARAM lParam
);
166 const char *wxGetMessageName(int message
);
169 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
170 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
171 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
173 // this magical function is used to translate VK_APPS key presses to right
175 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
176 int *x
, int *y
, WPARAM
*flags
);
178 // get the text metrics for the current font
179 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
181 // wrapper around BringWindowToTop() API
182 static inline void wxBringWindowToTop(HWND hwnd
)
184 #ifdef __WXMICROWIN__
185 // It seems that MicroWindows brings the _parent_ of the window to the top,
186 // which can be the wrong one.
188 // activate (set focus to) specified window
191 // raise top level parent to top of z order
192 ::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
193 #else // !__WXMICROWIN__
194 if ( !::BringWindowToTop(hwnd
) )
196 wxLogLastError(_T("BringWindowToTop"));
198 #endif // __WXMICROWIN__/!__WXMICROWIN__
201 // ---------------------------------------------------------------------------
203 // ---------------------------------------------------------------------------
205 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
207 #ifdef __WXUNIVERSAL__
208 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
210 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
211 #endif // __WXUNIVERSAL__/__WXMSW__
213 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
214 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
215 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
216 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
217 EVT_IDLE(wxWindowMSW::OnIdle
)
220 // ===========================================================================
222 // ===========================================================================
224 // ---------------------------------------------------------------------------
225 // wxWindow utility functions
226 // ---------------------------------------------------------------------------
228 // Find an item given the MS Windows id
229 wxWindow
*wxWindowMSW::FindItem(long id
) const
232 wxControl
*item
= wxDynamicCastThis(wxControl
);
235 // is it we or one of our "internal" children?
236 if ( item
->GetId() == id
237 #ifndef __WXUNIVERSAL__
238 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
239 #endif // __WXUNIVERSAL__
245 #endif // wxUSE_CONTROLS
247 wxWindowList::Node
*current
= GetChildren().GetFirst();
250 wxWindow
*childWin
= current
->GetData();
252 wxWindow
*wnd
= childWin
->FindItem(id
);
256 current
= current
->GetNext();
262 // Find an item given the MS Windows handle
263 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
265 wxWindowList::Node
*current
= GetChildren().GetFirst();
268 wxWindow
*parent
= current
->GetData();
270 // Do a recursive search.
271 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
277 || parent
->IsKindOf(CLASSINFO(wxControl
))
278 #endif // wxUSE_CONTROLS
281 wxWindow
*item
= current
->GetData();
282 if ( item
->GetHWND() == hWnd
)
286 if ( item
->ContainsHWND(hWnd
) )
291 current
= current
->GetNext();
296 // Default command handler
297 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
302 // ----------------------------------------------------------------------------
303 // constructors and such
304 // ----------------------------------------------------------------------------
306 void wxWindowMSW::Init()
312 m_doubleClickAllowed
= 0;
314 m_isBeingDeleted
= FALSE
;
317 m_mouseInWindow
= FALSE
;
318 m_lastKeydownProcessed
= FALSE
;
327 m_backgroundTransparent
= FALSE
;
329 // as all windows are created with WS_VISIBLE style...
332 #if wxUSE_MOUSEEVENT_HACK
335 m_lastMouseEvent
= -1;
336 #endif // wxUSE_MOUSEEVENT_HACK
340 wxWindowMSW::~wxWindowMSW()
342 m_isBeingDeleted
= TRUE
;
344 #ifndef __WXUNIVERSAL__
345 // VS: make sure there's no wxFrame with last focus set to us:
346 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
348 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
351 if ( frame
->GetLastFocus() == this )
353 frame
->SetLastFocus((wxWindow
*)NULL
);
358 #endif // __WXUNIVERSAL__
360 // VS: destroy children first and _then_ detach *this from its parent.
361 // If we'd do it the other way around, children wouldn't be able
362 // find their parent frame (see above).
366 m_parent
->RemoveChild(this);
370 // VZ: test temp removed to understand what really happens here
371 //if (::IsWindow(GetHwnd()))
373 if ( !::DestroyWindow(GetHwnd()) )
374 wxLogLastError(wxT("DestroyWindow"));
377 // remove hWnd <-> wxWindow association
378 wxRemoveHandleAssociation(this);
382 // real construction (Init() must have been called before!)
383 bool wxWindowMSW::Create(wxWindow
*parent
,
388 const wxString
& name
)
390 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
393 // wxGTK doesn't allow to create controls with static box as the parent so
394 // this will result in a crash when the program is ported to wxGTK - warn
397 // the correct solution is to create the controls as siblings of the
399 wxASSERT_MSG( !wxDynamicCast(parent
, wxStaticBox
),
400 _T("wxStaticBox can't be used as a window parent!") );
401 #endif // wxUSE_STATBOX
403 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
406 parent
->AddChild(this);
408 // note that all windows are created visible by default
410 DWORD msflags
= WS_VISIBLE
| MSWGetCreateWindowFlags(&exstyle
);
412 #ifdef __WXUNIVERSAL__
413 // no borders, we draw them ourselves
415 msflags
&= ~WS_BORDER
;
416 #endif // wxUniversal
418 if ( style
& wxPOPUP_WINDOW
)
420 // a popup window floats on top of everything
421 exstyle
|= WS_EX_TOPMOST
| WS_EX_TOOLWINDOW
;
423 // it is also created hidden as other top level windows
424 msflags
&= ~WS_VISIBLE
;
428 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
);
431 // ---------------------------------------------------------------------------
433 // ---------------------------------------------------------------------------
435 void wxWindowMSW::SetFocus()
437 HWND hWnd
= GetHwnd();
438 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
440 #ifndef __WXMICROWIN__
444 if ( !::SetFocus(hWnd
) )
446 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
447 // was there really an error?
448 DWORD dwRes
= ::GetLastError();
451 HWND hwndFocus
= ::GetFocus();
452 if ( hwndFocus
!= hWnd
)
454 wxLogApiError(_T("SetFocus"), dwRes
);
461 void wxWindowMSW::SetFocusFromKbd()
463 wxWindowBase::SetFocusFromKbd();
465 // when the focus is given to the control with DLGC_HASSETSEL style from
466 // keyboard its contents should be entirely selected: this is what
467 // ::IsDialogMessage() does and so we should do it as well to provide the
468 // same LNF as the native programs
469 if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL
)
471 ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1);
475 // Get the window with the focus
476 wxWindow
*wxWindowBase::FindFocus()
478 HWND hWnd
= ::GetFocus();
481 return wxGetWindowFromHWND((WXHWND
)hWnd
);
487 bool wxWindowMSW::Enable(bool enable
)
489 if ( !wxWindowBase::Enable(enable
) )
492 HWND hWnd
= GetHwnd();
494 ::EnableWindow(hWnd
, (BOOL
)enable
);
496 // VZ: no, this is a bad idea: imagine that you have a dialog with some
497 // disabled controls and disable it - you really wouldn't like the
498 // disabled controls be reenabled too when you reenable the dialog!
500 wxWindowList::Node
*node
= GetChildren().GetFirst();
503 wxWindow
*child
= node
->GetData();
504 child
->Enable(enable
);
506 node
= node
->GetNext();
513 bool wxWindowMSW::Show(bool show
)
515 if ( !wxWindowBase::Show(show
) )
518 HWND hWnd
= GetHwnd();
519 int cshow
= show
? SW_SHOW
: SW_HIDE
;
520 ::ShowWindow(hWnd
, cshow
);
524 wxBringWindowToTop(hWnd
);
530 // Raise the window to the top of the Z order
531 void wxWindowMSW::Raise()
533 wxBringWindowToTop(GetHwnd());
536 // Lower the window to the bottom of the Z order
537 void wxWindowMSW::Lower()
539 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
540 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
543 void wxWindowMSW::SetTitle( const wxString
& title
)
545 SetWindowText(GetHwnd(), title
.c_str());
548 wxString
wxWindowMSW::GetTitle() const
550 return wxGetWindowText(GetHWND());
553 void wxWindowMSW::DoCaptureMouse()
555 HWND hWnd
= GetHwnd();
562 void wxWindowMSW::DoReleaseMouse()
564 if ( !::ReleaseCapture() )
566 wxLogLastError(_T("ReleaseCapture"));
570 /* static */ wxWindow
*wxWindowBase::GetCapture()
572 HWND hwnd
= ::GetCapture();
573 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
576 bool wxWindowMSW::SetFont(const wxFont
& font
)
578 if ( !wxWindowBase::SetFont(font
) )
584 HWND hWnd
= GetHwnd();
587 WXHANDLE hFont
= m_font
.GetResourceHandle();
589 wxASSERT_MSG( hFont
, wxT("should have valid font") );
591 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
596 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
598 if ( !wxWindowBase::SetCursor(cursor
) )
606 HWND hWnd
= GetHwnd();
608 // Change the cursor NOW if we're within the correct window
610 ::GetCursorPos(&point
);
612 RECT rect
= wxGetWindowRect(hWnd
);
614 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
615 ::SetCursor(GetHcursorOf(m_cursor
));
621 void wxWindowMSW::WarpPointer (int x
, int y
)
623 ClientToScreen(&x
, &y
);
625 if ( !::SetCursorPos(x
, y
) )
627 wxLogLastError(_T("SetCursorPos"));
631 #if WXWIN_COMPATIBILITY
632 void wxWindowMSW::MSWDeviceToLogical (float *x
, float *y
) const
635 #endif // WXWIN_COMPATIBILITY
637 // ---------------------------------------------------------------------------
639 // ---------------------------------------------------------------------------
641 #if WXWIN_COMPATIBILITY
642 void wxWindowMSW::SetScrollRange(int orient
, int range
, bool refresh
)
644 #if defined(__WIN95__)
648 // Try to adjust the range to cope with page size > 1
649 // - a Windows API quirk
650 int pageSize
= GetScrollPage(orient
);
651 if ( pageSize
> 1 && range
> 0)
653 range1
+= (pageSize
- 1);
659 if ( orient
== wxHORIZONTAL
) {
665 info
.cbSize
= sizeof(SCROLLINFO
);
666 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
670 info
.fMask
= SIF_RANGE
| SIF_PAGE
;
672 HWND hWnd
= GetHwnd();
674 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
677 if ( orient
== wxHORIZONTAL
)
682 HWND hWnd
= GetHwnd();
684 ::SetScrollRange(hWnd
, wOrient
, 0, range
, refresh
);
688 void wxWindowMSW::SetScrollPage(int orient
, int page
, bool refresh
)
690 #if defined(__WIN95__)
694 if ( orient
== wxHORIZONTAL
) {
702 info
.cbSize
= sizeof(SCROLLINFO
);
705 info
.fMask
= SIF_PAGE
;
707 HWND hWnd
= GetHwnd();
709 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
711 if ( orient
== wxHORIZONTAL
)
718 int wxWindowMSW::OldGetScrollRange(int orient
) const
721 if ( orient
== wxHORIZONTAL
)
726 #if __WATCOMC__ && defined(__WINDOWS_386__)
727 short minPos
, maxPos
;
731 HWND hWnd
= GetHwnd();
734 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
735 #if defined(__WIN95__)
736 // Try to adjust the range to cope with page size > 1
737 // - a Windows API quirk
738 int pageSize
= GetScrollPage(orient
);
741 maxPos
-= (pageSize
- 1);
750 int wxWindowMSW::GetScrollPage(int orient
) const
752 if ( orient
== wxHORIZONTAL
)
758 #endif // WXWIN_COMPATIBILITY
760 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
762 #ifdef __WXMICROWIN__
763 return ::GetScrollPosWX(hWnd
, wOrient
);
765 return ::GetScrollPos(hWnd
, wOrient
);
769 int wxWindowMSW::GetScrollPos(int orient
) const
772 if ( orient
== wxHORIZONTAL
)
777 HWND hWnd
= GetHwnd();
778 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
780 return GetScrollPosition(hWnd
, wOrient
);
783 // This now returns the whole range, not just the number
784 // of positions that we can scroll.
785 int wxWindowMSW::GetScrollRange(int orient
) const
788 if ( orient
== wxHORIZONTAL
)
793 #if __WATCOMC__ && defined(__WINDOWS_386__)
794 short minPos
, maxPos
;
798 HWND hWnd
= GetHwnd();
801 ::GetScrollRange(hWnd
, wOrient
, &minPos
, &maxPos
);
802 #if defined(__WIN95__)
803 // Try to adjust the range to cope with page size > 1
804 // - a Windows API quirk
805 int pageSize
= GetScrollThumb(orient
);
808 maxPos
-= (pageSize
- 1);
810 // October 10th: new range concept.
820 int wxWindowMSW::GetScrollThumb(int orient
) const
822 if ( orient
== wxHORIZONTAL
)
828 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
830 HWND hWnd
= GetHwnd();
831 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
833 int dir
= orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
835 #if defined(__WIN95__)
837 info
.cbSize
= sizeof(SCROLLINFO
);
841 info
.fMask
= SIF_POS
;
843 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
845 ::SetScrollPos(hWnd
, dir
, pos
, refresh
);
846 #endif // __WIN95__/!__WIN95__
849 // New function that will replace some of the above.
850 void wxWindowMSW::SetScrollbar(int orient
, int pos
, int thumbVisible
,
851 int range
, bool refresh
)
853 #if defined(__WIN95__)
854 int oldRange
= range
- thumbVisible
;
856 int range1
= oldRange
;
858 // Try to adjust the range to cope with page size > 1
859 // - a Windows API quirk
860 int pageSize
= thumbVisible
;
861 if ( pageSize
> 1 && range
> 0)
863 range1
+= (pageSize
- 1);
869 if ( orient
== wxHORIZONTAL
) {
875 info
.cbSize
= sizeof(SCROLLINFO
);
876 info
.nPage
= pageSize
; // Have to set this, or scrollbar goes awry
880 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
882 HWND hWnd
= GetHwnd();
884 ::SetScrollInfo(hWnd
, dir
, &info
, refresh
);
887 if ( orient
== wxHORIZONTAL
)
892 HWND hWnd
= GetHwnd();
895 ::SetScrollRange(hWnd
, wOrient
, 0, range
, FALSE
);
896 ::SetScrollPos(hWnd
, wOrient
, pos
, refresh
);
899 if ( orient
== wxHORIZONTAL
) {
900 m_xThumbSize
= thumbVisible
;
902 m_yThumbSize
= thumbVisible
;
906 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
912 rect
.left
= prect
->x
;
914 rect
.right
= prect
->x
+ prect
->width
;
915 rect
.bottom
= prect
->y
+ prect
->height
;
923 ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
);
926 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
928 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
931 for ( int n
= 0; n
< count
; n
++ )
933 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
935 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
938 // don't bother to continue, we're already at top/bottom
945 return pos
!= posStart
;
948 bool wxWindowMSW::ScrollLines(int lines
)
950 bool down
= lines
> 0;
952 return ScrollVertically(GetHwnd(),
953 down
? SB_LINEDOWN
: SB_LINEUP
,
954 down
? lines
: -lines
);
957 bool wxWindowMSW::ScrollPages(int pages
)
959 bool down
= pages
> 0;
961 return ScrollVertically(GetHwnd(),
962 down
? SB_PAGEDOWN
: SB_PAGEUP
,
963 down
? pages
: -pages
);
966 // ---------------------------------------------------------------------------
968 // ---------------------------------------------------------------------------
970 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
972 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
974 HWND hwnd
= (HWND
)hWnd
;
975 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
977 wxAssociateWinWithHandle(hwnd
, this);
979 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
981 // we don't need to subclass the window of our own class (in the Windows
982 // sense of the word)
983 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
985 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
989 // don't bother restoring it neither
994 void wxWindowMSW::UnsubclassWin()
996 wxRemoveHandleAssociation(this);
998 // Restore old Window proc
999 HWND hwnd
= GetHwnd();
1004 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
1008 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
1010 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
1013 m_oldWndProc
= NULL
;
1018 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
1020 #if wxUSE_UNICODE_MSLU
1021 // VS: We can't use GetWindowLong(hwnd, GWL_WNDPROC) together with unicows.dll
1022 // because it doesn't return pointer to the real wnd proc but rather a handle
1023 // of a fake proc that does Unicode<->ANSI translation.
1025 // The hack bellow works, because WNDCLASS contains original window handler
1026 // rather that the unicows fake one. This may not be on purpose, though; if
1027 // it stops working with future versions of unicows.dll, we can override
1028 // unicows hooks by setting Unicows_{Set,Get}WindowLong and
1029 // Unicows_RegisterClass to our own versions that keep track of
1030 // fake<->real wnd proc mapping.
1032 // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set
1033 // with RegisterClass!!
1035 if ( wxUsingUnicowsDll() )
1037 static wxChar buffer
[512];
1040 ::GetClassName((HWND
)hWnd
, buffer
, 512);
1041 ::GetClassInfo(wxGetInstance(), buffer
, &cls
);
1042 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1047 return wndProc
== (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
1051 // ----------------------------------------------------------------------------
1053 // ----------------------------------------------------------------------------
1055 void wxWindowMSW::SetWindowStyleFlag(long flags
)
1057 long flagsOld
= GetWindowStyleFlag();
1058 if ( flags
== flagsOld
)
1061 // update the internal variable
1062 wxWindowBase::SetWindowStyleFlag(flags
);
1064 // now update the Windows style as well if needed - and if the window had
1065 // been already created
1069 WXDWORD exstyle
, exstyleOld
;
1070 long style
= MSWGetStyle(flags
, &exstyle
),
1071 styleOld
= MSWGetStyle(flagsOld
, &exstyleOld
);
1073 if ( style
!= styleOld
)
1075 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1076 // this function so instead of simply setting the style to the new
1077 // value we clear the bits which were set in styleOld but are set in
1078 // the new one and set the ones which were not set before
1079 long styleReal
= ::GetWindowLong(GetHwnd(), GWL_STYLE
);
1080 styleReal
&= ~styleOld
;
1083 ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
);
1086 // and the extended style
1087 if ( exstyle
!= exstyleOld
)
1089 long exstyleReal
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
);
1090 exstyleReal
&= ~exstyleOld
;
1091 exstyleReal
|= exstyle
;
1093 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
);
1095 // we must call SetWindowPos() to flash the cached extended style and
1096 // also to make the change to wxSTAY_ON_TOP style take effect: just
1097 // setting the style simply doesn't work
1098 if ( !::SetWindowPos(GetHwnd(),
1099 exstyleReal
& WS_EX_TOPMOST
? HWND_TOPMOST
1102 SWP_NOMOVE
| SWP_NOSIZE
) )
1104 wxLogLastError(_T("SetWindowPos"));
1109 WXDWORD
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD
*exstyle
) const
1111 // translate the style
1112 WXDWORD style
= WS_CHILD
;
1114 if ( flags
& wxCLIP_CHILDREN
)
1115 style
|= WS_CLIPCHILDREN
;
1117 if ( flags
& wxCLIP_SIBLINGS
)
1118 style
|= WS_CLIPSIBLINGS
;
1120 wxBorder border
= (wxBorder
)(flags
& wxBORDER_MASK
);
1121 if ( border
!= wxBORDER_NONE
&& border
!= wxBORDER_DEFAULT
)
1124 // now deal with ext style if the caller wants it
1129 if ( flags
& wxTRANSPARENT_WINDOW
)
1130 *exstyle
|= WS_EX_TRANSPARENT
;
1132 switch ( flags
& wxBORDER_MASK
)
1135 wxFAIL_MSG( _T("unknown border style") );
1139 case wxBORDER_SIMPLE
:
1140 case wxBORDER_DEFAULT
:
1143 case wxBORDER_STATIC
:
1144 *exstyle
|= WS_EX_STATICEDGE
;
1147 case wxBORDER_RAISED
:
1148 *exstyle
|= WS_EX_WINDOWEDGE
;
1151 case wxBORDER_SUNKEN
:
1152 *exstyle
|= WS_EX_CLIENTEDGE
;
1155 case wxBORDER_DOUBLE
:
1156 *exstyle
|= WS_EX_DLGMODALFRAME
;
1164 // Make a Windows extended style from the given wxWindows window style
1165 WXDWORD
wxWindowMSW::MakeExtendedStyle(long style
, bool eliminateBorders
)
1167 WXDWORD exStyle
= 0;
1168 if ( style
& wxTRANSPARENT_WINDOW
)
1169 exStyle
|= WS_EX_TRANSPARENT
;
1171 if ( !eliminateBorders
)
1173 if ( style
& wxSUNKEN_BORDER
)
1174 exStyle
|= WS_EX_CLIENTEDGE
;
1175 if ( style
& wxDOUBLE_BORDER
)
1176 exStyle
|= WS_EX_DLGMODALFRAME
;
1177 #if defined(__WIN95__)
1178 if ( style
& wxRAISED_BORDER
)
1179 // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does
1180 exStyle
|= WS_EX_DLGMODALFRAME
; /* WS_EX_WINDOWEDGE */;
1181 if ( style
& wxSTATIC_BORDER
)
1182 exStyle
|= WS_EX_STATICEDGE
;
1189 // Determines whether native 3D effects or CTL3D should be used,
1190 // applying a default border style if required, and returning an extended
1191 // style to pass to CreateWindowEx.
1192 WXDWORD
wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle
,
1195 // If matches certain criteria, then assume no 3D effects
1196 // unless specifically requested (dealt with in MakeExtendedStyle)
1199 || !IsKindOf(CLASSINFO(wxControl
))
1200 #endif // wxUSE_CONTROLS
1201 || (m_windowStyle
& wxNO_BORDER
) )
1204 return MakeExtendedStyle(m_windowStyle
);
1207 // Determine whether we should be using 3D effects or not.
1208 bool nativeBorder
= FALSE
; // by default, we don't want a Win95 effect
1210 // 1) App can specify global 3D effects
1211 *want3D
= wxTheApp
->GetAuto3D();
1213 // 2) If the parent is being drawn with user colours, or simple border specified,
1214 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
1215 if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS
) || (m_windowStyle
& wxSIMPLE_BORDER
) )
1218 // 3) Control can override this global setting by defining
1219 // a border style, e.g. wxSUNKEN_BORDER
1220 if ( m_windowStyle
& wxSUNKEN_BORDER
)
1223 // 4) If it's a special border, CTL3D can't cope so we want a native border
1224 if ( (m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1225 (m_windowStyle
& wxSTATIC_BORDER
) )
1228 nativeBorder
= TRUE
;
1231 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
1232 // effects from extended style
1235 nativeBorder
= FALSE
;
1238 DWORD exStyle
= MakeExtendedStyle(m_windowStyle
, !nativeBorder
);
1240 // If we want 3D, but haven't specified a border here,
1241 // apply the default border style specified.
1242 // TODO what about non-Win95 WIN32? Does it have borders?
1243 #if defined(__WIN95__) && !wxUSE_CTL3D
1244 if ( defaultBorderStyle
&& (*want3D
) && ! ((m_windowStyle
& wxDOUBLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
1245 (m_windowStyle
& wxSTATIC_BORDER
) || (m_windowStyle
& wxSIMPLE_BORDER
) ))
1246 exStyle
|= defaultBorderStyle
; // WS_EX_CLIENTEDGE;
1252 #if WXWIN_COMPATIBILITY
1253 // If nothing defined for this, try the parent.
1254 // E.g. we may be a button loaded from a resource, with no callback function
1256 void wxWindowMSW::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1258 if ( GetEventHandler()->ProcessEvent(event
) )
1261 m_parent
->GetEventHandler()->OnCommand(win
, event
);
1263 #endif // WXWIN_COMPATIBILITY_2
1265 #if WXWIN_COMPATIBILITY
1266 wxObject
* wxWindowMSW::GetChild(int number
) const
1268 // Return a pointer to the Nth object in the Panel
1269 wxNode
*node
= GetChildren().First();
1272 node
= node
->Next();
1275 wxObject
*obj
= (wxObject
*)node
->Data();
1281 #endif // WXWIN_COMPATIBILITY
1283 // Setup background and foreground colours correctly
1284 void wxWindowMSW::SetupColours()
1287 SetBackgroundColour(GetParent()->GetBackgroundColour());
1290 bool wxWindowMSW::IsMouseInWindow() const
1292 // get the mouse position
1294 ::GetCursorPos(&pt
);
1296 // find the window which currently has the cursor and go up the window
1297 // chain until we find this window - or exhaust it
1298 HWND hwnd
= ::WindowFromPoint(pt
);
1299 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1300 hwnd
= ::GetParent(hwnd
);
1302 return hwnd
!= NULL
;
1305 void wxWindowMSW::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1307 // Check if we need to send a LEAVE event
1308 if ( m_mouseInWindow
)
1310 // note that we should generate the leave event whether the window has
1311 // or doesn't have mouse capture
1312 if ( !IsMouseInWindow() )
1314 // Generate a LEAVE event
1315 m_mouseInWindow
= FALSE
;
1317 // Unfortunately the mouse button and keyboard state may have
1318 // changed by the time the OnIdle function is called, so 'state'
1319 // may be meaningless.
1321 if ( wxIsShiftDown() )
1323 if ( wxIsCtrlDown() )
1324 state
|= MK_CONTROL
;
1325 if ( GetKeyState( VK_LBUTTON
) )
1326 state
|= MK_LBUTTON
;
1327 if ( GetKeyState( VK_MBUTTON
) )
1328 state
|= MK_MBUTTON
;
1329 if ( GetKeyState( VK_RBUTTON
) )
1330 state
|= MK_RBUTTON
;
1333 if ( !::GetCursorPos(&pt
) )
1335 wxLogLastError(_T("GetCursorPos"));
1338 // we need to have client coordinates here for symmetry with
1339 // wxEVT_ENTER_WINDOW
1340 RECT rect
= wxGetWindowRect(GetHwnd());
1344 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1345 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1347 (void)GetEventHandler()->ProcessEvent(event2
);
1354 // Set this window to be the child of 'parent'.
1355 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1357 if ( !wxWindowBase::Reparent(parent
) )
1360 HWND hWndChild
= GetHwnd();
1361 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1363 ::SetParent(hWndChild
, hWndParent
);
1368 void wxWindowMSW::Clear()
1370 wxClientDC
dc((wxWindow
*)this);
1371 wxBrush
brush(GetBackgroundColour(), wxSOLID
);
1372 dc
.SetBackground(brush
);
1376 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1378 #ifndef __WXMICROWIN__
1379 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1383 void wxWindowMSW::Freeze()
1385 SendSetRedraw(GetHwnd(), FALSE
);
1388 void wxWindowMSW::Thaw()
1390 SendSetRedraw(GetHwnd(), TRUE
);
1392 // we need to refresh everything or otherwise he invalidated area is not
1397 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1399 HWND hWnd
= GetHwnd();
1405 mswRect
.left
= rect
->x
;
1406 mswRect
.top
= rect
->y
;
1407 mswRect
.right
= rect
->x
+ rect
->width
;
1408 mswRect
.bottom
= rect
->y
+ rect
->height
;
1410 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1413 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1417 void wxWindowMSW::Update()
1419 if ( !::UpdateWindow(GetHwnd()) )
1421 wxLogLastError(_T("UpdateWindow"));
1424 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
1425 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1426 // handler needs to be really drawn right now
1431 // ---------------------------------------------------------------------------
1433 // ---------------------------------------------------------------------------
1435 #if wxUSE_DRAG_AND_DROP
1437 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1439 if ( m_dropTarget
!= 0 ) {
1440 m_dropTarget
->Revoke(m_hWnd
);
1441 delete m_dropTarget
;
1444 m_dropTarget
= pDropTarget
;
1445 if ( m_dropTarget
!= 0 )
1446 m_dropTarget
->Register(m_hWnd
);
1449 #endif // wxUSE_DRAG_AND_DROP
1451 // old style file-manager drag&drop support: we retain the old-style
1452 // DragAcceptFiles in parallel with SetDropTarget.
1453 void wxWindowMSW::DragAcceptFiles(bool accept
)
1455 HWND hWnd
= GetHwnd();
1457 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1460 // ----------------------------------------------------------------------------
1462 // ----------------------------------------------------------------------------
1466 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1468 wxWindowBase::DoSetToolTip(tooltip
);
1471 m_tooltip
->SetWindow(this);
1474 #endif // wxUSE_TOOLTIPS
1476 // ---------------------------------------------------------------------------
1477 // moving and resizing
1478 // ---------------------------------------------------------------------------
1481 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1483 RECT rect
= wxGetWindowRect(GetHwnd());
1486 *x
= rect
.right
- rect
.left
;
1488 *y
= rect
.bottom
- rect
.top
;
1491 // Get size *available for subwindows* i.e. excluding menu bar etc.
1492 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1494 RECT rect
= wxGetClientRect(GetHwnd());
1502 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1504 RECT rect
= wxGetWindowRect(GetHwnd());
1507 point
.x
= rect
.left
;
1510 // we do the adjustments with respect to the parent only for the "real"
1511 // children, not for the dialogs/frames
1512 if ( !IsTopLevel() )
1514 HWND hParentWnd
= 0;
1515 wxWindow
*parent
= GetParent();
1517 hParentWnd
= GetWinHwnd(parent
);
1519 // Since we now have the absolute screen coords, if there's a parent we
1520 // must subtract its top left corner
1523 ::ScreenToClient(hParentWnd
, &point
);
1528 // We may be faking the client origin. So a window that's really at (0,
1529 // 30) may appear (to wxWin apps) to be at (0, 0).
1530 wxPoint
pt(parent
->GetClientAreaOrigin());
1542 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1550 ::ScreenToClient(GetHwnd(), &pt
);
1558 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1566 ::ClientToScreen(GetHwnd(), &pt
);
1574 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1576 // TODO: is this consistent with other platforms?
1577 // Still, negative width or height shouldn't be allowed
1582 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1584 wxLogLastError(wxT("MoveWindow"));
1588 // set the size of the window: if the dimensions are positive, just use them,
1589 // but if any of them is equal to -1, it means that we must find the value for
1590 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1591 // which case -1 is a valid value for x and y)
1593 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1594 // the width/height to best suit our contents, otherwise we reuse the current
1596 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1598 // get the current size and position...
1599 int currentX
, currentY
;
1600 GetPosition(¤tX
, ¤tY
);
1601 int currentW
,currentH
;
1602 GetSize(¤tW
, ¤tH
);
1604 // ... and don't do anything (avoiding flicker) if it's already ok
1605 if ( x
== currentX
&& y
== currentY
&&
1606 width
== currentW
&& height
== currentH
)
1611 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1613 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1616 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1618 wxSize
size(-1, -1);
1621 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1623 size
= DoGetBestSize();
1628 // just take the current one
1635 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1639 size
= DoGetBestSize();
1641 //else: already called DoGetBestSize() above
1647 // just take the current one
1652 DoMoveWindow(x
, y
, width
, height
);
1655 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1657 // setting the client size is less obvious than it it could have been
1658 // because in the result of changing the total size the window scrollbar
1659 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1660 // will not be correct as the difference between the total and client size
1661 // changes - so we keep changing it until we get it right
1663 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1664 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1665 // may become 3 if the window had 0 size originally and so we didn't
1666 // calculate the scrollbar correction correctly during the first iteration)
1667 // but just to be on the safe side we check for it instead of making it an
1668 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1669 for ( int i
= 0; i
< 4; i
++ )
1672 ::GetClientRect(GetHwnd(), &rectClient
);
1674 // if the size is already ok, stop here (rectClient.left = top = 0)
1675 if ( (rectClient
.right
== width
|| width
== -1) &&
1676 (rectClient
.bottom
== height
|| height
== -1) )
1681 int widthClient
= width
,
1682 heightClient
= height
;
1684 // Find the difference between the entire window (title bar and all)
1685 // and the client area; add this to the new client size to move the
1688 ::GetWindowRect(GetHwnd(), &rectWin
);
1690 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1691 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1694 point
.x
= rectWin
.left
;
1695 point
.y
= rectWin
.top
;
1697 // MoveWindow positions the child windows relative to the parent, so
1698 // adjust if necessary
1699 if ( !IsTopLevel() )
1701 wxWindow
*parent
= GetParent();
1704 ::ScreenToClient(GetHwndOf(parent
), &point
);
1708 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1712 // For implementation purposes - sometimes decorations make the client area
1714 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1716 return wxPoint(0, 0);
1719 // ---------------------------------------------------------------------------
1721 // ---------------------------------------------------------------------------
1723 int wxWindowMSW::GetCharHeight() const
1725 return wxGetTextMetrics(this).tmHeight
;
1728 int wxWindowMSW::GetCharWidth() const
1730 // +1 is needed because Windows apparently adds it when calculating the
1731 // dialog units size in pixels
1732 #if wxDIALOG_UNIT_COMPATIBILITY
1733 return wxGetTextMetrics(this).tmAveCharWidth
;
1735 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1739 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1741 int *descent
, int *externalLeading
,
1742 const wxFont
*theFont
) const
1744 const wxFont
*fontToUse
= theFont
;
1746 fontToUse
= &m_font
;
1748 HWND hWnd
= GetHwnd();
1749 HDC dc
= ::GetDC(hWnd
);
1753 if ( fontToUse
&& fontToUse
->Ok() )
1755 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1757 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1762 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1763 GetTextMetrics(dc
, &tm
);
1765 if ( fontToUse
&& fnt
&& hfontOld
)
1766 SelectObject(dc
, hfontOld
);
1768 ReleaseDC(hWnd
, dc
);
1775 *descent
= tm
.tmDescent
;
1776 if ( externalLeading
)
1777 *externalLeading
= tm
.tmExternalLeading
;
1780 #if wxUSE_CARET && WXWIN_COMPATIBILITY
1781 // ---------------------------------------------------------------------------
1782 // Caret manipulation
1783 // ---------------------------------------------------------------------------
1785 void wxWindowMSW::CreateCaret(int w
, int h
)
1787 SetCaret(new wxCaret(this, w
, h
));
1790 void wxWindowMSW::CreateCaret(const wxBitmap
*WXUNUSED(bitmap
))
1792 wxFAIL_MSG("not implemented");
1795 void wxWindowMSW::ShowCaret(bool show
)
1797 wxCHECK_RET( m_caret
, "no caret to show" );
1799 m_caret
->Show(show
);
1802 void wxWindowMSW::DestroyCaret()
1807 void wxWindowMSW::SetCaretPos(int x
, int y
)
1809 wxCHECK_RET( m_caret
, "no caret to move" );
1811 m_caret
->Move(x
, y
);
1814 void wxWindowMSW::GetCaretPos(int *x
, int *y
) const
1816 wxCHECK_RET( m_caret
, "no caret to get position of" );
1818 m_caret
->GetPosition(x
, y
);
1820 #endif // wxUSE_CARET
1822 // ---------------------------------------------------------------------------
1824 // ---------------------------------------------------------------------------
1826 #if wxUSE_MENUS_NATIVE
1828 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1829 // immediately, without waiting for the next event loop iteration
1831 // NB: this function should probably be made public later as it can almost
1832 // surely replace wxYield() elsewhere as well
1833 static void wxYieldForCommandsOnly()
1835 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1836 // want to process it here)
1838 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1839 && msg
.message
!= WM_QUIT
)
1841 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1845 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1847 menu
->SetInvokingWindow(this);
1850 HWND hWnd
= GetHwnd();
1851 HMENU hMenu
= GetHmenuOf(menu
);
1855 ::ClientToScreen(hWnd
, &point
);
1856 wxCurrentPopupMenu
= menu
;
1857 ::TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1859 // we need to do it righ now as otherwise the events are never going to be
1860 // sent to wxCurrentPopupMenu from HandleCommand()
1862 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1863 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1864 // destroyed as soon as we return (it can be a local variable in the caller
1865 // for example) and so we do need to process the event immediately
1866 wxYieldForCommandsOnly();
1868 wxCurrentPopupMenu
= NULL
;
1870 menu
->SetInvokingWindow(NULL
);
1875 #endif // wxUSE_MENUS_NATIVE
1877 // ===========================================================================
1878 // pre/post message processing
1879 // ===========================================================================
1881 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1884 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1886 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1889 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1891 // wxUniversal implements tab traversal itself
1892 #ifndef __WXUNIVERSAL__
1893 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1895 // intercept dialog navigation keys
1896 MSG
*msg
= (MSG
*)pMsg
;
1898 // here we try to do all the job which ::IsDialogMessage() usually does
1901 bool bProcess
= TRUE
;
1902 if ( msg
->message
!= WM_KEYDOWN
)
1905 if ( bProcess
&& (HIWORD(msg
->lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
1910 bool bCtrlDown
= wxIsCtrlDown();
1911 bool bShiftDown
= wxIsShiftDown();
1913 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1914 // don't process it if it's the case (except for Ctrl-Tab/Enter
1915 // combinations which are always processed)
1919 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1922 bool bForward
= TRUE
,
1923 bWindowChange
= FALSE
;
1925 switch ( msg
->wParam
)
1928 // assume that nobody wants Shift-TAB for himself - if we
1929 // don't do it there is no easy way for a control to grab
1930 // TABs but still let Shift-TAB work as navugation key
1931 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1935 // Ctrl-Tab cycles thru notebook pages
1936 bWindowChange
= bCtrlDown
;
1937 bForward
= !bShiftDown
;
1943 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1951 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1957 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1959 // control wants to process Enter itself, don't
1960 // call IsDialogMessage() which would interpret
1964 else if ( lDlgCode
& DLGC_BUTTON
)
1966 // let IsDialogMessage() handle this for all
1967 // buttons except the owner-drawn ones which it
1968 // just seems to ignore
1969 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1970 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1972 // emulate the button click
1973 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1975 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1980 // FIXME: this should be handled by
1981 // wxNavigationKeyEvent handler and not here!!
1985 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1987 if ( btn
&& btn
->IsEnabled() )
1989 // if we do have a default button, do press it
1990 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1994 else // no default button
1995 #endif // wxUSE_BUTTON
1997 // no special function for enter and don't even
1998 // let IsDialogMessage() have it: it seems to
1999 // do something really strange with it
2012 wxNavigationKeyEvent event
;
2013 event
.SetDirection(bForward
);
2014 event
.SetWindowChange(bWindowChange
);
2015 event
.SetEventObject(this);
2017 if ( GetEventHandler()->ProcessEvent(event
) )
2024 // let ::IsDialogMessage() do almost everything and handle just the
2025 // things it doesn't here: Ctrl-TAB for switching notebook pages
2026 if ( msg
->message
== WM_KEYDOWN
)
2028 // don't process system keys here
2029 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
2031 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
2033 // find the first notebook parent and change its page
2034 wxWindow
*win
= this;
2035 wxNotebook
*nbook
= NULL
;
2036 while ( win
&& !nbook
)
2038 nbook
= wxDynamicCast(win
, wxNotebook
);
2039 win
= win
->GetParent();
2044 bool forward
= !wxIsShiftDown();
2046 nbook
->AdvanceSelection(forward
);
2053 // we handle VK_ESCAPE ourselves in wxDialog::OnCharHook() and we
2054 // shouldn't let IsDialogMessage() get it as it _always_ eats the
2055 // message even when there is no cancel button and when the message is
2056 // needed by the control itself: in particular, it prevents the tree in
2057 // place edit control from being closed with Escape in a dialog
2058 if ( msg
->message
!= WM_KEYDOWN
|| msg
->wParam
!= VK_ESCAPE
)
2060 if ( ::IsDialogMessage(GetHwnd(), msg
) )
2062 // IsDialogMessage() did something...
2067 #endif // __WXUNIVERSAL__
2072 // relay mouse move events to the tooltip control
2073 MSG
*msg
= (MSG
*)pMsg
;
2074 if ( msg
->message
== WM_MOUSEMOVE
)
2075 m_tooltip
->RelayEvent(pMsg
);
2077 #endif // wxUSE_TOOLTIPS
2082 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
2084 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
2085 return m_acceleratorTable
.Translate(this, pMsg
);
2089 #endif // wxUSE_ACCEL
2092 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
))
2094 // preprocess all messages by default
2098 // ---------------------------------------------------------------------------
2099 // message params unpackers (different for Win16 and Win32)
2100 // ---------------------------------------------------------------------------
2104 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2105 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
2107 *id
= LOWORD(wParam
);
2108 *hwnd
= (WXHWND
)lParam
;
2109 *cmd
= HIWORD(wParam
);
2112 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2113 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2115 *state
= LOWORD(wParam
);
2116 *minimized
= HIWORD(wParam
);
2117 *hwnd
= (WXHWND
)lParam
;
2120 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2121 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2123 *code
= LOWORD(wParam
);
2124 *pos
= HIWORD(wParam
);
2125 *hwnd
= (WXHWND
)lParam
;
2128 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2129 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2131 #ifndef __WXMICROWIN__
2132 *nCtlColor
= CTLCOLOR_BTN
;
2133 *hwnd
= (WXHWND
)lParam
;
2134 *hdc
= (WXHDC
)wParam
;
2138 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2139 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2141 *item
= (WXWORD
)wParam
;
2142 *flags
= HIWORD(wParam
);
2143 *hmenu
= (WXHMENU
)lParam
;
2148 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2149 WXWORD
*id
, WXHWND
*hwnd
, WXWORD
*cmd
)
2151 *id
= (WXWORD
)wParam
;
2152 *hwnd
= (WXHWND
)LOWORD(lParam
);
2153 *cmd
= HIWORD(lParam
);
2156 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2157 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2159 *state
= (WXWORD
)wParam
;
2160 *minimized
= LOWORD(lParam
);
2161 *hwnd
= (WXHWND
)HIWORD(lParam
);
2164 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2165 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2167 *code
= (WXWORD
)wParam
;
2168 *pos
= LOWORD(lParam
);
2169 *hwnd
= (WXHWND
)HIWORD(lParam
);
2172 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2173 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2175 *hwnd
= (WXHWND
)LOWORD(lParam
);
2176 *nCtlColor
= (int)HIWORD(lParam
);
2177 *hdc
= (WXHDC
)wParam
;
2180 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2181 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2183 *item
= (WXWORD
)wParam
;
2184 *flags
= LOWORD(lParam
);
2185 *hmenu
= (WXHMENU
)HIWORD(lParam
);
2190 // ---------------------------------------------------------------------------
2191 // Main wxWindows window proc and the window proc for wxWindow
2192 // ---------------------------------------------------------------------------
2194 // Hook for new window just as it's being created, when the window isn't yet
2195 // associated with the handle
2196 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2198 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2199 // window being created and insures that it's always unset back later
2200 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2202 gs_winBeingCreated
= winBeingCreated
;
2205 wxWindowCreationHook::~wxWindowCreationHook()
2207 gs_winBeingCreated
= NULL
;
2211 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2213 // trace all messages - useful for the debugging
2215 wxLogTrace(wxTraceMessages
, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"),
2216 wxGetMessageName(message
), wParam
, lParam
);
2217 #endif // __WXDEBUG__
2219 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2221 // when we get the first message for the HWND we just created, we associate
2222 // it with wxWindow stored in gs_winBeingCreated
2223 if ( !wnd
&& gs_winBeingCreated
)
2225 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2226 wnd
= gs_winBeingCreated
;
2227 gs_winBeingCreated
= NULL
;
2228 wnd
->SetHWND((WXHWND
)hWnd
);
2234 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2236 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2241 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2243 // did we process the message?
2244 bool processed
= FALSE
;
2255 // for most messages we should return 0 when we do process the message
2263 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2266 // return 0 to allow window creation
2267 rc
.result
= mayCreate
? 0 : -1;
2273 // never set processed to TRUE and *always* pass WM_DESTROY to
2274 // DefWindowProc() as Windows may do some internal cleanup when
2275 // processing it and failing to pass the message along may cause
2276 // memory and resource leaks!
2277 (void)HandleDestroy();
2281 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2289 // we're not interested in these messages at all
2292 case SIZE_MINIMIZED
:
2293 // we shouldn't send sizev events for these messages as the
2294 // client size may be negative which breaks existing code
2296 // OTOH we might send another (wxMinimizedEvent?) one or
2297 // add an additional parameter to wxSizeEvent if this is
2298 // useful to anybody
2302 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2303 // fall through nevertheless
2305 case SIZE_MAXIMIZED
:
2307 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2312 #ifndef __WXMICROWIN__
2313 case WM_ACTIVATEAPP
:
2314 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2320 WXWORD state
, minimized
;
2322 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2324 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2329 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2333 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2337 processed
= HandlePaint();
2341 // don't let the DefWindowProc() destroy our window - we'll do it
2342 // ourselves in ~wxWindow
2348 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2352 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2353 GET_Y_LPARAM(lParam
),
2357 #if wxUSE_MOUSEWHEEL
2359 processed
= HandleMouseWheel(wParam
, lParam
);
2363 case WM_LBUTTONDOWN
:
2365 case WM_LBUTTONDBLCLK
:
2366 case WM_RBUTTONDOWN
:
2368 case WM_RBUTTONDBLCLK
:
2369 case WM_MBUTTONDOWN
:
2371 case WM_MBUTTONDBLCLK
:
2374 #ifdef __WXMICROWIN__
2375 // MicroWindows seems to ignore the fact that a window is
2376 // disabled. So catch mouse events and throw them away if
2378 wxWindowMSW
* win
= this;
2381 if (!win
->IsEnabled())
2386 win
= win
->GetParent();
2387 if (win
&& win
->IsTopLevel())
2390 #endif // __WXMICROWIN__
2393 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2395 processed
= HandleMouseEvent(message
,
2396 GET_X_LPARAM(lParam
),
2397 GET_Y_LPARAM(lParam
),
2403 #ifdef __WXMICROWIN__
2404 case WM_NCLBUTTONDOWN
:
2405 case WM_NCLBUTTONUP
:
2406 case WM_NCLBUTTONDBLCLK
:
2407 case WM_NCRBUTTONDOWN
:
2408 case WM_NCRBUTTONUP
:
2409 case WM_NCRBUTTONDBLCLK
:
2411 case WM_NCMBUTTONDOWN
:
2412 case WM_NCMBUTTONUP
:
2413 case WM_NCMBUTTONDBLCLK
:
2416 // MicroWindows seems to ignore the fact that a window
2417 // is disabled. So catch mouse events and throw them away if necessary.
2419 wxWindowMSW
* win
= this;
2422 if (!win
->IsEnabled())
2427 win
= win
->GetParent();
2428 if (win
&& win
->IsTopLevel())
2433 #endif // __WXMICROWIN__
2440 case MM_JOY1BUTTONDOWN
:
2441 case MM_JOY2BUTTONDOWN
:
2442 case MM_JOY1BUTTONUP
:
2443 case MM_JOY2BUTTONUP
:
2444 processed
= HandleJoystickEvent(message
,
2445 GET_X_LPARAM(lParam
),
2446 GET_Y_LPARAM(lParam
),
2449 #endif // __WXMICROWIN__
2452 processed
= HandleSysCommand(wParam
, lParam
);
2459 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2461 processed
= HandleCommand(id
, cmd
, hwnd
);
2467 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2471 // for these messages we must return TRUE if process the message
2474 case WM_MEASUREITEM
:
2476 int idCtrl
= (UINT
)wParam
;
2477 if ( message
== WM_DRAWITEM
)
2479 processed
= MSWOnDrawItem(idCtrl
,
2480 (WXDRAWITEMSTRUCT
*)lParam
);
2484 processed
= MSWOnMeasureItem(idCtrl
,
2485 (WXMEASUREITEMSTRUCT
*)lParam
);
2492 #endif // defined(WM_DRAWITEM)
2495 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
2497 // want everything: i.e. all keys and WM_CHAR message
2498 rc
.result
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
2499 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
2502 //else: get the dlg code from the DefWindowProc()
2507 // If this has been processed by an event handler, return 0 now
2508 // (we've handled it).
2509 m_lastKeydownProcessed
= HandleKeyDown((WORD
) wParam
, lParam
);
2510 if ( m_lastKeydownProcessed
)
2518 // we consider these message "not interesting" to OnChar, so
2519 // just don't do anything more with them
2529 // avoid duplicate messages to OnChar for these ASCII keys:
2530 // they will be translated by TranslateMessage() and received
2552 // but set processed to FALSE, not TRUE to still pass them
2553 // to the control's default window proc - otherwise
2554 // built-in keyboard handling won't work
2560 // special case of VK_APPS: treat it the same as right mouse
2561 // click because both usually pop up a context menu
2567 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2568 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2574 // do generate a CHAR event
2575 processed
= HandleChar((WORD
)wParam
, lParam
);
2583 // special case of VK_APPS: treat it the same as right mouse button
2584 if ( wParam
== VK_APPS
)
2589 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2590 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2595 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2600 case WM_CHAR
: // Always an ASCII character
2601 if ( m_lastKeydownProcessed
)
2603 // The key was handled in the EVT_KEY_DOWN and handling
2604 // a key in an EVT_KEY_DOWN handler is meant, by
2605 // design, to prevent EVT_CHARs from happening
2606 m_lastKeydownProcessed
= FALSE
;
2611 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2620 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2622 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2628 // CTLCOLOR messages are sent by children to query the parent for their
2629 // colors#ifndef __WXMICROWIN__
2630 #ifndef __WXMICROWIN__
2632 case WM_CTLCOLORMSGBOX
:
2633 case WM_CTLCOLOREDIT
:
2634 case WM_CTLCOLORLISTBOX
:
2635 case WM_CTLCOLORBTN
:
2636 case WM_CTLCOLORDLG
:
2637 case WM_CTLCOLORSCROLLBAR
:
2638 case WM_CTLCOLORSTATIC
:
2646 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2648 processed
= HandleCtlColor(&rc
.hBrush
,
2657 #endif // !__WXMICROWIN__
2659 case WM_SYSCOLORCHANGE
:
2660 // the return value for this message is ignored
2661 processed
= HandleSysColorChange();
2664 case WM_DISPLAYCHANGE
:
2665 processed
= HandleDisplayChange();
2668 case WM_PALETTECHANGED
:
2669 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2672 case WM_CAPTURECHANGED
:
2673 processed
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
);
2676 case WM_QUERYNEWPALETTE
:
2677 processed
= HandleQueryNewPalette();
2681 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2684 // we processed the message, i.e. erased the background
2690 processed
= HandleDropFiles(wParam
);
2694 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2698 // we never set focus from here
2703 case WM_QUERYENDSESSION
:
2704 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2708 processed
= HandleEndSession(wParam
!= 0, lParam
);
2711 case WM_GETMINMAXINFO
:
2712 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2716 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2717 LOWORD(lParam
), // hit test
2718 HIWORD(lParam
)); // mouse msg
2722 // returning TRUE stops the DefWindowProc() from further
2723 // processing this message - exactly what we need because we've
2724 // just set the cursor.
2729 #if defined(__WIN32__) && defined(WM_HELP)
2732 HELPINFO
* info
= (HELPINFO
*) lParam
;
2733 // Don't yet process menu help events, just windows
2734 if (info
->iContextType
== HELPINFO_WINDOW
)
2736 wxWindowMSW
* subjectOfHelp
= this;
2737 bool eventProcessed
= FALSE
;
2738 while (subjectOfHelp
&& !eventProcessed
)
2740 wxHelpEvent
helpEvent(wxEVT_HELP
,
2741 subjectOfHelp
->GetId(),
2742 wxPoint(info
->MousePos
.x
,
2743 info
->MousePos
.y
) );
2744 helpEvent
.SetEventObject(this);
2746 GetEventHandler()->ProcessEvent(helpEvent
);
2748 // Go up the window hierarchy until the event is
2750 subjectOfHelp
= subjectOfHelp
->GetParent();
2753 processed
= eventProcessed
;
2755 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2757 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2758 helpEvent
.SetEventObject(this);
2759 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2762 //else: processed is already FALSE
2766 case WM_CONTEXTMENU
:
2768 // we don't convert from screen to client coordinates as
2769 // the event may be handled by a parent window
2770 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2772 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2773 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2782 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2783 wxGetMessageName(message
));
2784 #endif // __WXDEBUG__
2785 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2791 // ----------------------------------------------------------------------------
2792 // wxWindow <-> HWND map
2793 // ----------------------------------------------------------------------------
2795 wxWinHashTable
*wxWinHandleHash
= NULL
;
2797 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2799 return wxWinHandleHash
->Get((long)hWnd
);
2802 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2804 // adding NULL hWnd is (first) surely a result of an error and
2805 // (secondly) breaks menu command processing
2806 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2807 wxT("attempt to add a NULL hWnd to window list ignored") );
2809 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2811 if ( oldWin
&& (oldWin
!= win
) )
2813 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2814 hWnd
, win
->GetClassInfo()->GetClassName());
2817 #endif // __WXDEBUG__
2820 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2824 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2826 wxWinHandleHash
->Delete((long)win
->GetHWND());
2829 // ----------------------------------------------------------------------------
2830 // various MSW speciic class dependent functions
2831 // ----------------------------------------------------------------------------
2833 // Default destroyer - override if you destroy it in some other way
2834 // (e.g. with MDI child windows)
2835 void wxWindowMSW::MSWDestroyWindow()
2839 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2842 int& w
, int& h
) const
2844 bool nonDefault
= FALSE
;
2848 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2849 // just as well set it to CW_USEDEFAULT as well
2856 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2862 NB: there used to be some code here which set the initial size of the
2863 window to the client size of the parent if no explicit size was
2864 specified. This was wrong because wxWindows programs often assume
2865 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2866 it. To see why, you should understand that Windows sends WM_SIZE from
2867 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2868 from some base class ctor and so this WM_SIZE is not processed in the
2869 real class' OnSize() (because it's not fully constructed yet and the
2870 event goes to some base class OnSize() instead). So the WM_SIZE we
2871 rely on is the one sent when the parent frame resizes its children
2872 but here is the problem: if the child already has just the right
2873 size, nothing will happen as both wxWindows and Windows check for
2874 this and ignore any attempts to change the window size to the size it
2875 already has - so no WM_SIZE would be sent.
2879 // as abobe, h is not used at all in this case anyhow
2886 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2894 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2895 const wxChar
*title
,
2899 WXDWORD extendedStyle
)
2901 // choose the position/size for the new window
2903 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2905 // find the correct parent HWND
2906 wxWindow
*parent
= GetParent();
2907 bool isChild
= (style
& WS_CHILD
) != 0;
2909 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2911 // popup windows should have desktop as parent because they shouldn't
2912 // be limited to the parents client area as child windows usually are
2913 hParent
= ::GetDesktopWindow();
2917 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2919 // this is either a normal child window or a top level window with
2920 // wxFRAME_TOOL_WINDOW style (see below)
2921 hParent
= GetHwndOf(parent
);
2925 // this is either a window for which no parent was specified (not
2926 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2927 // style: we should use NULL parent HWND for it or it would be
2928 // always on top of its parent which is not what we usually want
2929 // (in fact, we only want it for frames with the special
2930 // wxFRAME_TOOL_WINDOW as above)
2936 // controlId is menu handle for the top level windows, so set it to 0
2937 // unless we're creating a child window
2941 controlId
= GetId();
2943 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2945 style
|= WS_CLIPSIBLINGS
;
2953 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2954 // which is the same but without CS_[HV]REDRAW class styles so using it
2955 // ensures that the window is not fully repainted on each resize
2956 wxString
className(wclass
);
2957 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2959 className
+= wxT("NR");
2962 // do create the window
2963 wxWindowCreationHook
hook(this);
2965 m_hWnd
= (WXHWND
)::CreateWindowEx
2969 title
? title
: wxT(""),
2975 NULL
// no extra data
2980 wxLogSysError(_("Can't create window of class %s"), wclass
);
2985 SubclassWin(m_hWnd
);
2987 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2992 // ===========================================================================
2993 // MSW message handlers
2994 // ===========================================================================
2996 // ---------------------------------------------------------------------------
2998 // ---------------------------------------------------------------------------
3001 // FIXME: VZ: I'm not sure at all that the order of processing is correct
3002 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
3004 #ifndef __WXMICROWIN__
3005 LPNMHDR hdr
= (LPNMHDR
)lParam
;
3006 HWND hWnd
= hdr
->hwndFrom
;
3007 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
3009 // is this one of our windows?
3012 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
3015 // try all our children
3016 wxWindowList::Node
*node
= GetChildren().GetFirst();
3019 wxWindow
*child
= node
->GetData();
3020 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
3025 node
= node
->GetNext();
3028 // finally try this window too (catches toolbar case)
3029 return MSWOnNotify(idCtrl
, lParam
, result
);
3030 #else // __WXMICROWIN__
3035 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
3037 WXLPARAM
* WXUNUSED(result
))
3040 NMHDR
* hdr
= (NMHDR
*)lParam
;
3041 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
3043 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
3044 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
3049 #endif // wxUSE_TOOLTIPS
3055 // ---------------------------------------------------------------------------
3056 // end session messages
3057 // ---------------------------------------------------------------------------
3059 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
3061 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
3062 event
.SetEventObject(wxTheApp
);
3063 event
.SetCanVeto(TRUE
);
3064 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
3066 bool rc
= wxTheApp
->ProcessEvent(event
);
3070 // we may end only if the app didn't veto session closing (double
3072 *mayEnd
= !event
.GetVeto();
3078 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
3080 // do nothing if the session isn't ending
3085 if ( (this != wxTheApp
->GetTopWindow()) )
3088 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
3089 event
.SetEventObject(wxTheApp
);
3090 event
.SetCanVeto(FALSE
);
3091 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
3093 return wxTheApp
->ProcessEvent(event
);
3096 // ---------------------------------------------------------------------------
3097 // window creation/destruction
3098 // ---------------------------------------------------------------------------
3100 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
3102 // TODO: should generate this event from WM_NCCREATE
3103 wxWindowCreateEvent
event((wxWindow
*)this);
3104 (void)GetEventHandler()->ProcessEvent(event
);
3111 bool wxWindowMSW::HandleDestroy()
3113 wxWindowDestroyEvent
event((wxWindow
*)this);
3114 (void)GetEventHandler()->ProcessEvent(event
);
3116 // delete our drop target if we've got one
3117 #if wxUSE_DRAG_AND_DROP
3118 if ( m_dropTarget
!= NULL
)
3120 m_dropTarget
->Revoke(m_hWnd
);
3122 delete m_dropTarget
;
3123 m_dropTarget
= NULL
;
3125 #endif // wxUSE_DRAG_AND_DROP
3127 // WM_DESTROY handled
3131 // ---------------------------------------------------------------------------
3133 // ---------------------------------------------------------------------------
3135 bool wxWindowMSW::HandleActivate(int state
,
3136 bool WXUNUSED(minimized
),
3137 WXHWND
WXUNUSED(activate
))
3139 wxActivateEvent
event(wxEVT_ACTIVATE
,
3140 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3142 event
.SetEventObject(this);
3144 return GetEventHandler()->ProcessEvent(event
);
3147 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3149 // notify the parent keeping track of focus for the kbd navigation
3150 // purposes that we got it
3151 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3152 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3158 m_caret
->OnSetFocus();
3160 #endif // wxUSE_CARET
3163 // If it's a wxTextCtrl don't send the event as it will be done
3164 // after the control gets to process it from EN_FOCUS handler
3165 if ( wxDynamicCastThis(wxTextCtrl
) )
3169 #endif // wxUSE_TEXTCTRL
3171 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3172 event
.SetEventObject(this);
3174 // wxFindWinFromHandle() may return NULL, it is ok
3175 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3177 return GetEventHandler()->ProcessEvent(event
);
3180 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3186 m_caret
->OnKillFocus();
3188 #endif // wxUSE_CARET
3191 // If it's a wxTextCtrl don't send the event as it will be done
3192 // after the control gets to process it.
3193 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3200 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3201 event
.SetEventObject(this);
3203 // wxFindWinFromHandle() may return NULL, it is ok
3204 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3206 return GetEventHandler()->ProcessEvent(event
);
3209 // ---------------------------------------------------------------------------
3211 // ---------------------------------------------------------------------------
3213 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3215 wxShowEvent
event(GetId(), show
);
3216 event
.m_eventObject
= this;
3218 return GetEventHandler()->ProcessEvent(event
);
3221 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3223 wxInitDialogEvent
event(GetId());
3224 event
.m_eventObject
= this;
3226 return GetEventHandler()->ProcessEvent(event
);
3229 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3231 #ifndef __WXMICROWIN__
3232 HDROP hFilesInfo
= (HDROP
) wParam
;
3234 // Get the total number of files dropped
3235 UINT gwFilesDropped
= ::DragQueryFile
3243 wxString
*files
= new wxString
[gwFilesDropped
];
3244 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3246 // first get the needed buffer length (+1 for terminating NUL)
3247 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3249 // and now get the file name
3250 ::DragQueryFile(hFilesInfo
, wIndex
,
3251 files
[wIndex
].GetWriteBuf(len
), len
);
3253 files
[wIndex
].UngetWriteBuf();
3255 DragFinish (hFilesInfo
);
3257 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3258 event
.m_eventObject
= this;
3261 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3262 event
.m_pos
.x
= dropPoint
.x
;
3263 event
.m_pos
.y
= dropPoint
.y
;
3265 return GetEventHandler()->ProcessEvent(event
);
3266 #else // __WXMICROWIN__
3271 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3273 int WXUNUSED(mouseMsg
))
3275 #ifndef __WXMICROWIN__
3276 // the logic is as follows:
3277 // -1. don't set cursor for non client area, including but not limited to
3278 // the title bar, scrollbars, &c
3279 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3280 // 1. if we have the cursor set it unless wxIsBusy()
3281 // 2. if we're a top level window, set some cursor anyhow
3282 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3284 if ( nHitTest
!= HTCLIENT
)
3289 HCURSOR hcursor
= 0;
3291 // first ask the user code - it may wish to set the cursor in some very
3292 // specific way (for example, depending on the current position)
3295 if ( !::GetCursorPos(&pt
) )
3297 wxLogLastError(wxT("GetCursorPos"));
3300 // In WIN16 it doesn't return a value.
3301 ::GetCursorPos(&pt
);
3306 ScreenToClient(&x
, &y
);
3307 wxSetCursorEvent
event(x
, y
);
3309 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3310 if ( processedEvtSetCursor
&& event
.HasCursor() )
3312 hcursor
= GetHcursorOf(event
.GetCursor());
3317 bool isBusy
= wxIsBusy();
3319 // the test for processedEvtSetCursor is here to prevent using m_cursor
3320 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3321 // it - this is a way to say that our cursor shouldn't be used for this
3323 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3325 hcursor
= GetHcursorOf(m_cursor
);
3332 hcursor
= wxGetCurrentBusyCursor();
3334 else if ( !hcursor
)
3336 const wxCursor
*cursor
= wxGetGlobalCursor();
3337 if ( cursor
&& cursor
->Ok() )
3339 hcursor
= GetHcursorOf(*cursor
);
3347 ::SetCursor(hcursor
);
3349 // cursor set, stop here
3352 #endif // __WXMICROWIN__
3354 // pass up the window chain
3358 // ---------------------------------------------------------------------------
3359 // owner drawn stuff
3360 // ---------------------------------------------------------------------------
3362 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3364 #if wxUSE_OWNER_DRAWN
3366 #if wxUSE_MENUS_NATIVE
3367 // is it a menu item?
3368 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3369 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3371 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3373 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3375 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3376 // the DC from being released
3377 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3378 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3379 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3380 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3382 return pMenuItem
->OnDrawItem
3386 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3387 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3390 #endif // wxUSE_MENUS_NATIVE
3393 wxWindow
*item
= FindItem(id
);
3394 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3396 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3398 #endif // wxUSE_CONTROLS
3400 #endif // USE_OWNER_DRAWN
3405 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3407 #if wxUSE_OWNER_DRAWN
3408 // is it a menu item?
3409 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3410 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3412 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3414 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3416 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3417 &pMeasureStruct
->itemHeight
);
3420 wxWindow
*item
= FindItem(id
);
3421 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3423 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3425 #endif // owner-drawn menus
3429 // ---------------------------------------------------------------------------
3430 // colours and palettes
3431 // ---------------------------------------------------------------------------
3433 bool wxWindowMSW::HandleSysColorChange()
3435 wxSysColourChangedEvent event
;
3436 event
.SetEventObject(this);
3438 (void)GetEventHandler()->ProcessEvent(event
);
3440 // always let the system carry on the default processing to allow the
3441 // native controls to react to the colours update
3445 bool wxWindowMSW::HandleDisplayChange()
3447 wxDisplayChangedEvent event
;
3448 event
.SetEventObject(this);
3450 return GetEventHandler()->ProcessEvent(event
);
3453 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3461 #ifndef __WXMICROWIN__
3462 WXHBRUSH hBrush
= 0;
3464 if ( nCtlColor
== CTLCOLOR_DLG
)
3466 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3471 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3473 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3475 #endif // wxUSE_CONTROLS
3481 #else // __WXMICROWIN__
3486 // Define for each class of dialog and control
3487 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3488 WXHWND
WXUNUSED(hWnd
),
3489 WXUINT
WXUNUSED(nCtlColor
),
3490 WXUINT
WXUNUSED(message
),
3491 WXWPARAM
WXUNUSED(wParam
),
3492 WXLPARAM
WXUNUSED(lParam
))
3497 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3500 // same as below except we don't respond to our own messages
3501 if ( hWndPalChange
!= GetHWND() )
3503 // check to see if we our our parents have a custom palette
3504 wxWindow
*win
= this;
3505 while ( win
&& !win
->HasCustomPalette() )
3507 win
= win
->GetParent();
3510 if ( win
&& win
->HasCustomPalette() )
3512 // realize the palette to see whether redrawing is needed
3513 HDC hdc
= ::GetDC((HWND
) hWndPalChange
);
3514 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3515 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3517 int result
= ::RealizePalette(hdc
);
3519 // restore the palette (before releasing the DC)
3520 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3521 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3522 ::RealizePalette(hdc
);
3523 ::ReleaseDC((HWND
) hWndPalChange
, hdc
);
3525 // now check for the need to redraw
3527 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
);
3531 #endif // wxUSE_PALETTE
3533 wxPaletteChangedEvent
event(GetId());
3534 event
.SetEventObject(this);
3535 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3537 return GetEventHandler()->ProcessEvent(event
);
3540 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
)
3542 wxMouseCaptureChangedEvent
event(GetId(), wxFindWinFromHandle(hWndGainedCapture
));
3543 event
.SetEventObject(this);
3545 return GetEventHandler()->ProcessEvent(event
);
3548 bool wxWindowMSW::HandleQueryNewPalette()
3552 // check to see if we our our parents have a custom palette
3553 wxWindow
*win
= this;
3554 while (!win
->HasCustomPalette() && win
->GetParent()) win
= win
->GetParent();
3555 if (win
->HasCustomPalette()) {
3556 /* realize the palette to see whether redrawing is needed */
3557 HDC hdc
= GetDC((HWND
) GetHWND());
3558 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3559 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) );
3561 int result
= ::RealizePalette(hdc
);
3562 /* restore the palette (before releasing the DC) */
3563 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3564 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) );
3565 ::RealizePalette(hdc
);
3566 ::ReleaseDC((HWND
) GetHWND(), hdc
);
3567 /* now check for the need to redraw */
3569 ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
);
3571 #endif // wxUSE_PALETTE
3573 wxQueryNewPaletteEvent
event(GetId());
3574 event
.SetEventObject(this);
3576 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3579 // Responds to colour changes: passes event on to children.
3580 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
))
3582 // the top level window also reset the standard colour map as it might have
3583 // changed (there is no need to do it for the non top level windows as we
3584 // only have to do it once)
3588 gs_hasStdCmap
= FALSE
;
3590 wxWindowList::Node
*node
= GetChildren().GetFirst();
3593 // Only propagate to non-top-level windows because Windows already
3594 // sends this event to all top-level ones
3595 wxWindow
*win
= node
->GetData();
3596 if ( !win
->IsTopLevel() )
3598 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3599 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3600 // the standard controls
3601 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3604 node
= node
->GetNext();
3607 // update the colours we use if they were not set explicitly by the user:
3608 // this must be done or OnCtlColor() would continue to use the old colours
3611 m_foregroundColour
= wxSystemSettings::
3612 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3617 m_backgroundColour
= wxSystemSettings::
3618 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3622 extern wxCOLORMAP
*wxGetStdColourMap()
3624 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3625 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3627 if ( !gs_hasStdCmap
)
3629 static bool s_coloursInit
= FALSE
;
3631 if ( !s_coloursInit
)
3633 // When a bitmap is loaded, the RGB values can change (apparently
3634 // because Windows adjusts them to care for the old programs always
3635 // using 0xc0c0c0 while the transparent colour for the new Windows
3636 // versions is different). But we do this adjustment ourselves so
3637 // we want to avoid Windows' "help" and for this we need to have a
3638 // reference bitmap which can tell us what the RGB values change
3640 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3641 if ( stdColourBitmap
.Ok() )
3643 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3644 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3645 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3648 memDC
.SelectObject(stdColourBitmap
);
3651 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3653 memDC
.GetPixel(i
, 0, &colour
);
3654 s_stdColours
[i
] = wxColourToRGB(colour
);
3657 else // wxBITMAP_STD_COLOURS couldn't be loaded
3659 s_stdColours
[0] = RGB(000,000,000); // black
3660 s_stdColours
[1] = RGB(128,128,128); // dark grey
3661 s_stdColours
[2] = RGB(192,192,192); // light grey
3662 s_stdColours
[3] = RGB(255,255,255); // white
3663 //s_stdColours[4] = RGB(000,000,255); // blue
3664 //s_stdColours[5] = RGB(255,000,255); // magenta
3667 s_coloursInit
= TRUE
;
3670 gs_hasStdCmap
= TRUE
;
3672 // create the colour map
3673 #define INIT_CMAP_ENTRY(col) \
3674 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3675 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3677 INIT_CMAP_ENTRY(BTNTEXT
);
3678 INIT_CMAP_ENTRY(BTNSHADOW
);
3679 INIT_CMAP_ENTRY(BTNFACE
);
3680 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3682 #undef INIT_CMAP_ENTRY
3688 // ---------------------------------------------------------------------------
3690 // ---------------------------------------------------------------------------
3692 bool wxWindowMSW::HandlePaint()
3695 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3697 wxLogLastError(wxT("CreateRectRgn"));
3698 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3699 wxLogLastError(wxT("GetUpdateRgn"));
3701 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3704 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3706 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3707 updateRect
.right
- updateRect
.left
,
3708 updateRect
.bottom
- updateRect
.top
);
3711 wxPaintEvent
event(m_windowId
);
3712 event
.SetEventObject(this);
3714 bool processed
= GetEventHandler()->ProcessEvent(event
);
3716 // note that we must generate NC event after the normal one as otherwise
3717 // BeginPaint() will happily overwrite our decorations with the background
3719 wxNcPaintEvent
eventNc(m_windowId
);
3720 eventNc
.SetEventObject(this);
3721 GetEventHandler()->ProcessEvent(eventNc
);
3726 // Can be called from an application's OnPaint handler
3727 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3729 #ifdef __WXUNIVERSAL__
3732 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3735 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3740 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3742 // Prevents flicker when dragging
3743 if ( ::IsIconic(GetHwnd()) )
3749 dc
.SetWindow((wxWindow
*)this);
3752 wxEraseEvent
event(m_windowId
, &dc
);
3753 event
.SetEventObject(this);
3754 bool rc
= GetEventHandler()->ProcessEvent(event
);
3758 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3759 dc
.SelectOldObjects(hdc
);
3764 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3767 ::GetClientRect(GetHwnd(), &rect
);
3769 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3770 m_backgroundColour
.Green(),
3771 m_backgroundColour
.Blue());
3772 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3774 wxLogLastError(wxT("CreateSolidBrush"));
3776 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3778 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3780 ::FillRect(hdc
, &rect
, hBrush
);
3781 ::DeleteObject(hBrush
);
3782 ::SetMapMode(hdc
, mode
);
3785 // ---------------------------------------------------------------------------
3786 // moving and resizing
3787 // ---------------------------------------------------------------------------
3789 bool wxWindowMSW::HandleMinimize()
3791 wxIconizeEvent
event(m_windowId
);
3792 event
.SetEventObject(this);
3794 return GetEventHandler()->ProcessEvent(event
);
3797 bool wxWindowMSW::HandleMaximize()
3799 wxMaximizeEvent
event(m_windowId
);
3800 event
.SetEventObject(this);
3802 return GetEventHandler()->ProcessEvent(event
);
3805 bool wxWindowMSW::HandleMove(int x
, int y
)
3807 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3808 event
.SetEventObject(this);
3810 return GetEventHandler()->ProcessEvent(event
);
3813 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
),
3814 WXUINT
WXUNUSED(flag
))
3816 // don't use w and h parameters as they specify the client size while
3817 // according to the docs EVT_SIZE handler is supposed to receive the total
3819 wxSizeEvent
event(GetSize(), m_windowId
);
3820 event
.SetEventObject(this);
3822 return GetEventHandler()->ProcessEvent(event
);
3825 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3827 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3831 int minWidth
= GetMinWidth(),
3832 minHeight
= GetMinHeight(),
3833 maxWidth
= GetMaxWidth(),
3834 maxHeight
= GetMaxHeight();
3836 if ( minWidth
!= -1 )
3838 info
->ptMinTrackSize
.x
= minWidth
;
3842 if ( minHeight
!= -1 )
3844 info
->ptMinTrackSize
.y
= minHeight
;
3848 if ( maxWidth
!= -1 )
3850 info
->ptMaxTrackSize
.x
= maxWidth
;
3854 if ( maxHeight
!= -1 )
3856 info
->ptMaxTrackSize
.y
= maxHeight
;
3863 // ---------------------------------------------------------------------------
3865 // ---------------------------------------------------------------------------
3867 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3869 #if wxUSE_MENUS_NATIVE
3870 if ( !cmd
&& wxCurrentPopupMenu
)
3872 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3873 wxCurrentPopupMenu
= NULL
;
3875 return popupMenu
->MSWCommand(cmd
, id
);
3877 #endif // wxUSE_MENUS_NATIVE
3879 wxWindow
*win
= NULL
;
3881 // first try to find it from HWND - this works even with the broken
3882 // programs using the same ids for different controls
3885 win
= wxFindWinFromHandle(control
);
3891 // must cast to a signed type before comparing with other ids!
3892 win
= FindItem((signed short)id
);
3897 return win
->MSWCommand(cmd
, id
);
3900 // the messages sent from the in-place edit control used by the treectrl
3901 // for label editing have id == 0, but they should _not_ be treated as menu
3902 // messages (they are EN_XXX ones, in fact) so don't translate anything
3903 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3906 // If no child window, it may be an accelerator, e.g. for a popup menu
3909 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3910 event
.SetEventObject(this);
3914 return GetEventHandler()->ProcessEvent(event
);
3916 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3919 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3920 // notifications to its parent which we want to reflect back to
3922 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3923 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3926 #endif // wxUSE_SPINCTRL
3931 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3933 // 4 bits are reserved
3934 switch ( wParam
& 0xFFFFFFF0 )
3937 return HandleMaximize();
3940 return HandleMinimize();
3946 // ---------------------------------------------------------------------------
3948 // ---------------------------------------------------------------------------
3950 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3954 // our client coords are not quite the same as Windows ones
3955 wxPoint pt
= GetClientAreaOrigin();
3956 event
.m_x
= x
- pt
.x
;
3957 event
.m_y
= y
- pt
.y
;
3959 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3960 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3961 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3962 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3963 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3964 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3966 event
.SetTimestamp(s_currentMsg
.time
);
3967 event
.m_eventObject
= this;
3969 #if wxUSE_MOUSEEVENT_HACK
3972 m_lastMouseEvent
= event
.GetEventType();
3973 #endif // wxUSE_MOUSEEVENT_HACK
3976 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3978 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3979 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3980 // from the message id and take the value in the table to get wxWin event
3982 static const wxEventType eventsMouse
[] =
3996 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
3997 InitMouseEvent(event
, x
, y
, flags
);
3999 return GetEventHandler()->ProcessEvent(event
);
4002 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
4004 if ( !m_mouseInWindow
)
4006 // it would be wrong to assume that just because we get a mouse move
4007 // event that the mouse is inside the window: although this is usually
4008 // true, it is not if we had captured the mouse, so we need to check
4009 // the mouse coordinates here
4010 if ( !HasCapture() || IsMouseInWindow() )
4012 // Generate an ENTER event
4013 m_mouseInWindow
= TRUE
;
4015 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
4016 InitMouseEvent(event
, x
, y
, flags
);
4018 (void)GetEventHandler()->ProcessEvent(event
);
4022 #if wxUSE_MOUSEEVENT_HACK
4023 // Window gets a click down message followed by a mouse move message even
4024 // if position isn't changed! We want to discard the trailing move event
4025 // if x and y are the same.
4026 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
4027 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
4028 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
4029 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
4031 m_lastMouseEvent
= wxEVT_MOTION
;
4035 #endif // wxUSE_MOUSEEVENT_HACK
4037 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
4041 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
4043 #if wxUSE_MOUSEWHEEL
4044 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
4045 InitMouseEvent(event
,
4046 GET_X_LPARAM(lParam
),
4047 GET_Y_LPARAM(lParam
),
4049 event
.m_wheelRotation
= (short)HIWORD(wParam
);
4050 event
.m_wheelDelta
= WHEEL_DELTA
;
4053 static int s_linesPerRotation
= -1;
4054 if ( s_linesPerRotation
== -1 )
4056 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
4057 &s_linesPerRotation
, 0))
4059 // this is not supposed to happen
4060 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
4062 // the default is 3, so use it if SystemParametersInfo() failed
4063 s_linesPerRotation
= 3;
4067 // no SystemParametersInfo() under Win16
4068 static const int s_linesPerRotation
= 3;
4071 event
.m_linesPerAction
= s_linesPerRotation
;
4072 return GetEventHandler()->ProcessEvent(event
);
4083 // ---------------------------------------------------------------------------
4084 // keyboard handling
4085 // ---------------------------------------------------------------------------
4087 // create the key event of the given type for the given key - used by
4088 // HandleChar and HandleKeyDown/Up
4089 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
4092 WXWPARAM wParam
) const
4094 wxKeyEvent
event(evType
);
4095 event
.SetId(GetId());
4096 event
.m_shiftDown
= wxIsShiftDown();
4097 event
.m_controlDown
= wxIsCtrlDown();
4098 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
4100 event
.m_eventObject
= (wxWindow
*)this; // const_cast
4101 event
.m_keyCode
= id
;
4102 event
.m_rawCode
= (wxUint32
) wParam
;
4103 event
.m_rawFlags
= (wxUint32
) lParam
;
4104 event
.SetTimestamp(s_currentMsg
.time
);
4106 // translate the position to client coords
4110 GetWindowRect(GetHwnd(),&rect
);
4120 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
4122 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
4124 bool ctrlDown
= FALSE
;
4129 // If 1 -> 26, translate to CTRL plus a letter.
4131 if ( (id
> 0) && (id
< 27) )
4153 else // we're called from WM_KEYDOWN
4155 id
= wxCharCodeMSWToWX(wParam
);
4158 // it's ASCII and will be processed here only when called from
4159 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
4164 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
));
4167 event
.m_controlDown
= TRUE
;
4170 return GetEventHandler()->ProcessEvent(event
);
4173 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
4175 int id
= wxCharCodeMSWToWX(wParam
);
4179 // normal ASCII char
4183 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4185 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
));
4186 if ( GetEventHandler()->ProcessEvent(event
) )
4195 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
4197 int id
= wxCharCodeMSWToWX(wParam
);
4201 // normal ASCII char
4205 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4207 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
));
4208 if ( GetEventHandler()->ProcessEvent(event
) )
4215 // ---------------------------------------------------------------------------
4217 // ---------------------------------------------------------------------------
4219 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4223 if ( flags
& JOY_BUTTON1CHG
)
4224 change
= wxJOY_BUTTON1
;
4225 if ( flags
& JOY_BUTTON2CHG
)
4226 change
= wxJOY_BUTTON2
;
4227 if ( flags
& JOY_BUTTON3CHG
)
4228 change
= wxJOY_BUTTON3
;
4229 if ( flags
& JOY_BUTTON4CHG
)
4230 change
= wxJOY_BUTTON4
;
4233 if ( flags
& JOY_BUTTON1
)
4234 buttons
|= wxJOY_BUTTON1
;
4235 if ( flags
& JOY_BUTTON2
)
4236 buttons
|= wxJOY_BUTTON2
;
4237 if ( flags
& JOY_BUTTON3
)
4238 buttons
|= wxJOY_BUTTON3
;
4239 if ( flags
& JOY_BUTTON4
)
4240 buttons
|= wxJOY_BUTTON4
;
4242 // the event ids aren't consecutive so we can't use table based lookup
4244 wxEventType eventType
;
4249 eventType
= wxEVT_JOY_MOVE
;
4254 eventType
= wxEVT_JOY_MOVE
;
4259 eventType
= wxEVT_JOY_ZMOVE
;
4264 eventType
= wxEVT_JOY_ZMOVE
;
4267 case MM_JOY1BUTTONDOWN
:
4269 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4272 case MM_JOY2BUTTONDOWN
:
4274 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4277 case MM_JOY1BUTTONUP
:
4279 eventType
= wxEVT_JOY_BUTTON_UP
;
4282 case MM_JOY2BUTTONUP
:
4284 eventType
= wxEVT_JOY_BUTTON_UP
;
4288 wxFAIL_MSG(wxT("no such joystick event"));
4293 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4294 event
.SetPosition(wxPoint(x
, y
));
4295 event
.SetEventObject(this);
4297 return GetEventHandler()->ProcessEvent(event
);
4303 // ---------------------------------------------------------------------------
4305 // ---------------------------------------------------------------------------
4307 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4308 WXWORD pos
, WXHWND control
)
4312 wxWindow
*child
= wxFindWinFromHandle(control
);
4314 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4317 wxScrollWinEvent event
;
4318 event
.SetPosition(pos
);
4319 event
.SetOrientation(orientation
);
4320 event
.m_eventObject
= this;
4325 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4329 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4333 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4337 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4341 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4345 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4348 case SB_THUMBPOSITION
:
4351 // under Win32, the scrollbar range and position are 32 bit integers,
4352 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4353 // explicitly query the scrollbar for the correct position (this must
4354 // be done only for these two SB_ events as they are the only one
4355 // carrying the scrollbar position)
4357 SCROLLINFO scrollInfo
;
4358 wxZeroMemory(scrollInfo
);
4359 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4360 scrollInfo
.fMask
= SIF_TRACKPOS
;
4362 if ( !::GetScrollInfo(GetHwnd(),
4363 orientation
== wxHORIZONTAL
? SB_HORZ
4367 wxLogLastError(_T("GetScrollInfo"));
4370 event
.SetPosition(scrollInfo
.nTrackPos
);
4374 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4375 ? wxEVT_SCROLLWIN_THUMBRELEASE
4376 : wxEVT_SCROLLWIN_THUMBTRACK
;
4383 return GetEventHandler()->ProcessEvent(event
);
4386 // ===========================================================================
4388 // ===========================================================================
4390 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4393 HDC dc
= ::GetDC((HWND
) wnd
);
4398 // the_font->UseResource();
4399 // the_font->RealizeResource();
4400 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4402 was
= (HFONT
) SelectObject(dc
,fnt
);
4404 GetTextMetrics(dc
, &tm
);
4405 if ( the_font
&& fnt
&& was
)
4407 SelectObject(dc
,was
);
4409 ReleaseDC((HWND
)wnd
, dc
);
4412 *x
= tm
.tmAveCharWidth
;
4414 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4417 // the_font->ReleaseResource();
4420 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4421 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4422 int wxCharCodeMSWToWX(int keySym
)
4427 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4428 case VK_BACK
: id
= WXK_BACK
; break;
4429 case VK_TAB
: id
= WXK_TAB
; break;
4430 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4431 case VK_RETURN
: id
= WXK_RETURN
; break;
4432 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4433 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4434 case VK_MENU
: id
= WXK_MENU
; break;
4435 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4436 case VK_CAPITAL
: id
= WXK_CAPITAL
; break;
4437 case VK_SPACE
: id
= WXK_SPACE
; break;
4438 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4439 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4440 case VK_NEXT
: id
= WXK_NEXT
; break;
4441 case VK_END
: id
= WXK_END
; break;
4442 case VK_HOME
: id
= WXK_HOME
; break;
4443 case VK_LEFT
: id
= WXK_LEFT
; break;
4444 case VK_UP
: id
= WXK_UP
; break;
4445 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4446 case VK_DOWN
: id
= WXK_DOWN
; break;
4447 case VK_SELECT
: id
= WXK_SELECT
; break;
4448 case VK_PRINT
: id
= WXK_PRINT
; break;
4449 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4450 case VK_INSERT
: id
= WXK_INSERT
; break;
4451 case VK_DELETE
: id
= WXK_DELETE
; break;
4452 case VK_HELP
: id
= WXK_HELP
; break;
4453 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4454 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4455 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4456 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4457 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4458 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4459 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4460 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4461 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4462 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4463 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4464 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4465 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4466 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4467 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4468 case VK_F1
: id
= WXK_F1
; break;
4469 case VK_F2
: id
= WXK_F2
; break;
4470 case VK_F3
: id
= WXK_F3
; break;
4471 case VK_F4
: id
= WXK_F4
; break;
4472 case VK_F5
: id
= WXK_F5
; break;
4473 case VK_F6
: id
= WXK_F6
; break;
4474 case VK_F7
: id
= WXK_F7
; break;
4475 case VK_F8
: id
= WXK_F8
; break;
4476 case VK_F9
: id
= WXK_F9
; break;
4477 case VK_F10
: id
= WXK_F10
; break;
4478 case VK_F11
: id
= WXK_F11
; break;
4479 case VK_F12
: id
= WXK_F12
; break;
4480 case VK_F13
: id
= WXK_F13
; break;
4481 case VK_F14
: id
= WXK_F14
; break;
4482 case VK_F15
: id
= WXK_F15
; break;
4483 case VK_F16
: id
= WXK_F16
; break;
4484 case VK_F17
: id
= WXK_F17
; break;
4485 case VK_F18
: id
= WXK_F18
; break;
4486 case VK_F19
: id
= WXK_F19
; break;
4487 case VK_F20
: id
= WXK_F20
; break;
4488 case VK_F21
: id
= WXK_F21
; break;
4489 case VK_F22
: id
= WXK_F22
; break;
4490 case VK_F23
: id
= WXK_F23
; break;
4491 case VK_F24
: id
= WXK_F24
; break;
4492 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4493 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4495 case VK_OEM_1
: id
= ';'; break;
4496 case VK_OEM_PLUS
: id
= '+'; break;
4497 case VK_OEM_COMMA
: id
= ','; break;
4498 case VK_OEM_MINUS
: id
= '-'; break;
4499 case VK_OEM_PERIOD
: id
= '.'; break;
4500 case VK_OEM_2
: id
= '/'; break;
4501 case VK_OEM_3
: id
= '~'; break;
4502 case VK_OEM_4
: id
= '['; break;
4503 case VK_OEM_5
: id
= '\\'; break;
4504 case VK_OEM_6
: id
= ']'; break;
4505 case VK_OEM_7
: id
= '\''; break;
4514 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4520 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4521 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4522 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4523 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4524 case WXK_MENU
: keySym
= VK_MENU
; break;
4525 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4526 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4527 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4528 case WXK_END
: keySym
= VK_END
; break;
4529 case WXK_HOME
: keySym
= VK_HOME
; break;
4530 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4531 case WXK_UP
: keySym
= VK_UP
; break;
4532 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4533 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4534 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4535 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4536 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4537 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4538 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4539 case WXK_HELP
: keySym
= VK_HELP
; break;
4540 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4541 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4542 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4543 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4544 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4545 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4546 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4547 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4548 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4549 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4550 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4551 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4552 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4553 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4554 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4555 case WXK_F1
: keySym
= VK_F1
; break;
4556 case WXK_F2
: keySym
= VK_F2
; break;
4557 case WXK_F3
: keySym
= VK_F3
; break;
4558 case WXK_F4
: keySym
= VK_F4
; break;
4559 case WXK_F5
: keySym
= VK_F5
; break;
4560 case WXK_F6
: keySym
= VK_F6
; break;
4561 case WXK_F7
: keySym
= VK_F7
; break;
4562 case WXK_F8
: keySym
= VK_F8
; break;
4563 case WXK_F9
: keySym
= VK_F9
; break;
4564 case WXK_F10
: keySym
= VK_F10
; break;
4565 case WXK_F11
: keySym
= VK_F11
; break;
4566 case WXK_F12
: keySym
= VK_F12
; break;
4567 case WXK_F13
: keySym
= VK_F13
; break;
4568 case WXK_F14
: keySym
= VK_F14
; break;
4569 case WXK_F15
: keySym
= VK_F15
; break;
4570 case WXK_F16
: keySym
= VK_F16
; break;
4571 case WXK_F17
: keySym
= VK_F17
; break;
4572 case WXK_F18
: keySym
= VK_F18
; break;
4573 case WXK_F19
: keySym
= VK_F19
; break;
4574 case WXK_F20
: keySym
= VK_F20
; break;
4575 case WXK_F21
: keySym
= VK_F21
; break;
4576 case WXK_F22
: keySym
= VK_F22
; break;
4577 case WXK_F23
: keySym
= VK_F23
; break;
4578 case WXK_F24
: keySym
= VK_F24
; break;
4579 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4580 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4591 wxWindow
*wxGetActiveWindow()
4593 HWND hWnd
= GetActiveWindow();
4596 return wxFindWinFromHandle((WXHWND
) hWnd
);
4601 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4603 HWND hwnd
= (HWND
)hWnd
;
4605 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4606 // by code in msw/radiobox.cpp), for all the others we just search up the
4608 wxWindow
*win
= (wxWindow
*)NULL
;
4611 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4614 // all these hacks only work under Win32 anyhow
4618 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4619 // wxWindow class which overrides WM_GETDLGCODE processing to
4620 // do it as well, win would be already non NULL
4621 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4623 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4625 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4626 #endif // wxUSE_RADIOBOX
4628 // spin control text buddy window should be mapped to spin ctrl
4629 // itself so try it too
4630 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4633 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4635 #endif // wxUSE_SPINCTRL
4641 while ( hwnd
&& !win
)
4643 // this is a really ugly hack needed to avoid mistakenly returning the
4644 // parent frame wxWindow for the find/replace modeless dialog HWND -
4645 // this, in turn, is needed to call IsDialogMessage() from
4646 // wxApp::ProcessMessage() as for this we must return NULL from here
4648 // FIXME: this is clearly not the best way to do it but I think we'll
4649 // need to change HWND <-> wxWindow code more heavily than I can
4650 // do it now to fix it
4651 #ifndef __WXMICROWIN__
4652 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4654 // it's a dialog box, don't go upwards
4659 hwnd
= ::GetParent(hwnd
);
4660 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4666 #ifndef __WXMICROWIN__
4668 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4669 // in active frames and dialogs, regardless of where the focus is.
4670 static HHOOK wxTheKeyboardHook
= 0;
4671 static FARPROC wxTheKeyboardHookProc
= 0;
4672 int APIENTRY _EXPORT
4673 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4675 void wxSetKeyboardHook(bool doIt
)
4679 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4680 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4682 #if defined(__WIN32__) && !defined(__TWIN32__)
4683 GetCurrentThreadId()
4684 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4692 UnhookWindowsHookEx(wxTheKeyboardHook
);
4694 // avoids warning about statement with no effect (FreeProcInstance
4695 // doesn't do anything under Win32)
4696 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4697 FreeProcInstance(wxTheKeyboardHookProc
);
4702 int APIENTRY _EXPORT
4703 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4705 DWORD hiWord
= HIWORD(lParam
);
4706 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4708 int id
= wxCharCodeMSWToWX(wParam
);
4711 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4712 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4713 event
.m_altDown
= TRUE
;
4715 event
.m_eventObject
= NULL
;
4716 event
.m_keyCode
= id
;
4717 event
.m_shiftDown
= wxIsShiftDown();
4718 event
.m_controlDown
= wxIsCtrlDown();
4719 event
.SetTimestamp(s_currentMsg
.time
);
4721 wxWindow
*win
= wxGetActiveWindow();
4722 wxEvtHandler
*handler
;
4725 handler
= win
->GetEventHandler();
4726 event
.SetId(win
->GetId());
4734 if ( handler
&& handler
->ProcessEvent(event
) )
4742 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4745 #endif // !__WXMICROWIN__
4748 const char *wxGetMessageName(int message
)
4752 case 0x0000: return "WM_NULL";
4753 case 0x0001: return "WM_CREATE";
4754 case 0x0002: return "WM_DESTROY";
4755 case 0x0003: return "WM_MOVE";
4756 case 0x0005: return "WM_SIZE";
4757 case 0x0006: return "WM_ACTIVATE";
4758 case 0x0007: return "WM_SETFOCUS";
4759 case 0x0008: return "WM_KILLFOCUS";
4760 case 0x000A: return "WM_ENABLE";
4761 case 0x000B: return "WM_SETREDRAW";
4762 case 0x000C: return "WM_SETTEXT";
4763 case 0x000D: return "WM_GETTEXT";
4764 case 0x000E: return "WM_GETTEXTLENGTH";
4765 case 0x000F: return "WM_PAINT";
4766 case 0x0010: return "WM_CLOSE";
4767 case 0x0011: return "WM_QUERYENDSESSION";
4768 case 0x0012: return "WM_QUIT";
4769 case 0x0013: return "WM_QUERYOPEN";
4770 case 0x0014: return "WM_ERASEBKGND";
4771 case 0x0015: return "WM_SYSCOLORCHANGE";
4772 case 0x0016: return "WM_ENDSESSION";
4773 case 0x0017: return "WM_SYSTEMERROR";
4774 case 0x0018: return "WM_SHOWWINDOW";
4775 case 0x0019: return "WM_CTLCOLOR";
4776 case 0x001A: return "WM_WININICHANGE";
4777 case 0x001B: return "WM_DEVMODECHANGE";
4778 case 0x001C: return "WM_ACTIVATEAPP";
4779 case 0x001D: return "WM_FONTCHANGE";
4780 case 0x001E: return "WM_TIMECHANGE";
4781 case 0x001F: return "WM_CANCELMODE";
4782 case 0x0020: return "WM_SETCURSOR";
4783 case 0x0021: return "WM_MOUSEACTIVATE";
4784 case 0x0022: return "WM_CHILDACTIVATE";
4785 case 0x0023: return "WM_QUEUESYNC";
4786 case 0x0024: return "WM_GETMINMAXINFO";
4787 case 0x0026: return "WM_PAINTICON";
4788 case 0x0027: return "WM_ICONERASEBKGND";
4789 case 0x0028: return "WM_NEXTDLGCTL";
4790 case 0x002A: return "WM_SPOOLERSTATUS";
4791 case 0x002B: return "WM_DRAWITEM";
4792 case 0x002C: return "WM_MEASUREITEM";
4793 case 0x002D: return "WM_DELETEITEM";
4794 case 0x002E: return "WM_VKEYTOITEM";
4795 case 0x002F: return "WM_CHARTOITEM";
4796 case 0x0030: return "WM_SETFONT";
4797 case 0x0031: return "WM_GETFONT";
4798 case 0x0037: return "WM_QUERYDRAGICON";
4799 case 0x0039: return "WM_COMPAREITEM";
4800 case 0x0041: return "WM_COMPACTING";
4801 case 0x0044: return "WM_COMMNOTIFY";
4802 case 0x0046: return "WM_WINDOWPOSCHANGING";
4803 case 0x0047: return "WM_WINDOWPOSCHANGED";
4804 case 0x0048: return "WM_POWER";
4807 case 0x004A: return "WM_COPYDATA";
4808 case 0x004B: return "WM_CANCELJOURNAL";
4809 case 0x004E: return "WM_NOTIFY";
4810 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4811 case 0x0051: return "WM_INPUTLANGCHANGE";
4812 case 0x0052: return "WM_TCARD";
4813 case 0x0053: return "WM_HELP";
4814 case 0x0054: return "WM_USERCHANGED";
4815 case 0x0055: return "WM_NOTIFYFORMAT";
4816 case 0x007B: return "WM_CONTEXTMENU";
4817 case 0x007C: return "WM_STYLECHANGING";
4818 case 0x007D: return "WM_STYLECHANGED";
4819 case 0x007E: return "WM_DISPLAYCHANGE";
4820 case 0x007F: return "WM_GETICON";
4821 case 0x0080: return "WM_SETICON";
4824 case 0x0081: return "WM_NCCREATE";
4825 case 0x0082: return "WM_NCDESTROY";
4826 case 0x0083: return "WM_NCCALCSIZE";
4827 case 0x0084: return "WM_NCHITTEST";
4828 case 0x0085: return "WM_NCPAINT";
4829 case 0x0086: return "WM_NCACTIVATE";
4830 case 0x0087: return "WM_GETDLGCODE";
4831 case 0x00A0: return "WM_NCMOUSEMOVE";
4832 case 0x00A1: return "WM_NCLBUTTONDOWN";
4833 case 0x00A2: return "WM_NCLBUTTONUP";
4834 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4835 case 0x00A4: return "WM_NCRBUTTONDOWN";
4836 case 0x00A5: return "WM_NCRBUTTONUP";
4837 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4838 case 0x00A7: return "WM_NCMBUTTONDOWN";
4839 case 0x00A8: return "WM_NCMBUTTONUP";
4840 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4841 case 0x0100: return "WM_KEYDOWN";
4842 case 0x0101: return "WM_KEYUP";
4843 case 0x0102: return "WM_CHAR";
4844 case 0x0103: return "WM_DEADCHAR";
4845 case 0x0104: return "WM_SYSKEYDOWN";
4846 case 0x0105: return "WM_SYSKEYUP";
4847 case 0x0106: return "WM_SYSCHAR";
4848 case 0x0107: return "WM_SYSDEADCHAR";
4849 case 0x0108: return "WM_KEYLAST";
4852 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4853 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4854 case 0x010F: return "WM_IME_COMPOSITION";
4857 case 0x0110: return "WM_INITDIALOG";
4858 case 0x0111: return "WM_COMMAND";
4859 case 0x0112: return "WM_SYSCOMMAND";
4860 case 0x0113: return "WM_TIMER";
4861 case 0x0114: return "WM_HSCROLL";
4862 case 0x0115: return "WM_VSCROLL";
4863 case 0x0116: return "WM_INITMENU";
4864 case 0x0117: return "WM_INITMENUPOPUP";
4865 case 0x011F: return "WM_MENUSELECT";
4866 case 0x0120: return "WM_MENUCHAR";
4867 case 0x0121: return "WM_ENTERIDLE";
4868 case 0x0200: return "WM_MOUSEMOVE";
4869 case 0x0201: return "WM_LBUTTONDOWN";
4870 case 0x0202: return "WM_LBUTTONUP";
4871 case 0x0203: return "WM_LBUTTONDBLCLK";
4872 case 0x0204: return "WM_RBUTTONDOWN";
4873 case 0x0205: return "WM_RBUTTONUP";
4874 case 0x0206: return "WM_RBUTTONDBLCLK";
4875 case 0x0207: return "WM_MBUTTONDOWN";
4876 case 0x0208: return "WM_MBUTTONUP";
4877 case 0x0209: return "WM_MBUTTONDBLCLK";
4878 case 0x020A: return "WM_MOUSEWHEEL";
4879 case 0x0210: return "WM_PARENTNOTIFY";
4880 case 0x0211: return "WM_ENTERMENULOOP";
4881 case 0x0212: return "WM_EXITMENULOOP";
4884 case 0x0213: return "WM_NEXTMENU";
4885 case 0x0214: return "WM_SIZING";
4886 case 0x0215: return "WM_CAPTURECHANGED";
4887 case 0x0216: return "WM_MOVING";
4888 case 0x0218: return "WM_POWERBROADCAST";
4889 case 0x0219: return "WM_DEVICECHANGE";
4892 case 0x0220: return "WM_MDICREATE";
4893 case 0x0221: return "WM_MDIDESTROY";
4894 case 0x0222: return "WM_MDIACTIVATE";
4895 case 0x0223: return "WM_MDIRESTORE";
4896 case 0x0224: return "WM_MDINEXT";
4897 case 0x0225: return "WM_MDIMAXIMIZE";
4898 case 0x0226: return "WM_MDITILE";
4899 case 0x0227: return "WM_MDICASCADE";
4900 case 0x0228: return "WM_MDIICONARRANGE";
4901 case 0x0229: return "WM_MDIGETACTIVE";
4902 case 0x0230: return "WM_MDISETMENU";
4903 case 0x0233: return "WM_DROPFILES";
4906 case 0x0281: return "WM_IME_SETCONTEXT";
4907 case 0x0282: return "WM_IME_NOTIFY";
4908 case 0x0283: return "WM_IME_CONTROL";
4909 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4910 case 0x0285: return "WM_IME_SELECT";
4911 case 0x0286: return "WM_IME_CHAR";
4912 case 0x0290: return "WM_IME_KEYDOWN";
4913 case 0x0291: return "WM_IME_KEYUP";
4916 case 0x0300: return "WM_CUT";
4917 case 0x0301: return "WM_COPY";
4918 case 0x0302: return "WM_PASTE";
4919 case 0x0303: return "WM_CLEAR";
4920 case 0x0304: return "WM_UNDO";
4921 case 0x0305: return "WM_RENDERFORMAT";
4922 case 0x0306: return "WM_RENDERALLFORMATS";
4923 case 0x0307: return "WM_DESTROYCLIPBOARD";
4924 case 0x0308: return "WM_DRAWCLIPBOARD";
4925 case 0x0309: return "WM_PAINTCLIPBOARD";
4926 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4927 case 0x030B: return "WM_SIZECLIPBOARD";
4928 case 0x030C: return "WM_ASKCBFORMATNAME";
4929 case 0x030D: return "WM_CHANGECBCHAIN";
4930 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4931 case 0x030F: return "WM_QUERYNEWPALETTE";
4932 case 0x0310: return "WM_PALETTEISCHANGING";
4933 case 0x0311: return "WM_PALETTECHANGED";
4936 // common controls messages - although they're not strictly speaking
4937 // standard, it's nice to decode them nevertheless
4940 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4941 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4942 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4943 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4944 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4945 case 0x1000 + 5: return "LVM_GETITEMA";
4946 case 0x1000 + 75: return "LVM_GETITEMW";
4947 case 0x1000 + 6: return "LVM_SETITEMA";
4948 case 0x1000 + 76: return "LVM_SETITEMW";
4949 case 0x1000 + 7: return "LVM_INSERTITEMA";
4950 case 0x1000 + 77: return "LVM_INSERTITEMW";
4951 case 0x1000 + 8: return "LVM_DELETEITEM";
4952 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4953 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4954 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4955 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4956 case 0x1000 + 13: return "LVM_FINDITEMA";
4957 case 0x1000 + 83: return "LVM_FINDITEMW";
4958 case 0x1000 + 14: return "LVM_GETITEMRECT";
4959 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4960 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4961 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4962 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4963 case 0x1000 + 18: return "LVM_HITTEST";
4964 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4965 case 0x1000 + 20: return "LVM_SCROLL";
4966 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4967 case 0x1000 + 22: return "LVM_ARRANGE";
4968 case 0x1000 + 23: return "LVM_EDITLABELA";
4969 case 0x1000 + 118: return "LVM_EDITLABELW";
4970 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4971 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4972 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4973 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4974 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4975 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4976 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4977 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4978 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4979 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4980 case 0x1000 + 31: return "LVM_GETHEADER";
4981 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4982 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4983 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4984 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4985 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4986 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4987 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4988 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4989 case 0x1000 + 41: return "LVM_GETORIGIN";
4990 case 0x1000 + 42: return "LVM_UPDATE";
4991 case 0x1000 + 43: return "LVM_SETITEMSTATE";
4992 case 0x1000 + 44: return "LVM_GETITEMSTATE";
4993 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
4994 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
4995 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
4996 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
4997 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
4998 case 0x1000 + 48: return "LVM_SORTITEMS";
4999 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
5000 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
5001 case 0x1000 + 51: return "LVM_GETITEMSPACING";
5002 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
5003 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
5004 case 0x1000 + 53: return "LVM_SETICONSPACING";
5005 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
5006 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
5007 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
5008 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
5009 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
5010 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
5011 case 0x1000 + 60: return "LVM_SETHOTITEM";
5012 case 0x1000 + 61: return "LVM_GETHOTITEM";
5013 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
5014 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
5015 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
5016 case 0x1000 + 65: return "LVM_SETWORKAREA";
5019 case 0x1100 + 0: return "TVM_INSERTITEMA";
5020 case 0x1100 + 50: return "TVM_INSERTITEMW";
5021 case 0x1100 + 1: return "TVM_DELETEITEM";
5022 case 0x1100 + 2: return "TVM_EXPAND";
5023 case 0x1100 + 4: return "TVM_GETITEMRECT";
5024 case 0x1100 + 5: return "TVM_GETCOUNT";
5025 case 0x1100 + 6: return "TVM_GETINDENT";
5026 case 0x1100 + 7: return "TVM_SETINDENT";
5027 case 0x1100 + 8: return "TVM_GETIMAGELIST";
5028 case 0x1100 + 9: return "TVM_SETIMAGELIST";
5029 case 0x1100 + 10: return "TVM_GETNEXTITEM";
5030 case 0x1100 + 11: return "TVM_SELECTITEM";
5031 case 0x1100 + 12: return "TVM_GETITEMA";
5032 case 0x1100 + 62: return "TVM_GETITEMW";
5033 case 0x1100 + 13: return "TVM_SETITEMA";
5034 case 0x1100 + 63: return "TVM_SETITEMW";
5035 case 0x1100 + 14: return "TVM_EDITLABELA";
5036 case 0x1100 + 65: return "TVM_EDITLABELW";
5037 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
5038 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
5039 case 0x1100 + 17: return "TVM_HITTEST";
5040 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
5041 case 0x1100 + 19: return "TVM_SORTCHILDREN";
5042 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
5043 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
5044 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
5045 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
5046 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
5047 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
5048 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
5051 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
5052 case 0x1200 + 1: return "HDM_INSERTITEMA";
5053 case 0x1200 + 10: return "HDM_INSERTITEMW";
5054 case 0x1200 + 2: return "HDM_DELETEITEM";
5055 case 0x1200 + 3: return "HDM_GETITEMA";
5056 case 0x1200 + 11: return "HDM_GETITEMW";
5057 case 0x1200 + 4: return "HDM_SETITEMA";
5058 case 0x1200 + 12: return "HDM_SETITEMW";
5059 case 0x1200 + 5: return "HDM_LAYOUT";
5060 case 0x1200 + 6: return "HDM_HITTEST";
5061 case 0x1200 + 7: return "HDM_GETITEMRECT";
5062 case 0x1200 + 8: return "HDM_SETIMAGELIST";
5063 case 0x1200 + 9: return "HDM_GETIMAGELIST";
5064 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
5065 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
5066 case 0x1200 + 17: return "HDM_GETORDERARRAY";
5067 case 0x1200 + 18: return "HDM_SETORDERARRAY";
5068 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
5071 case 0x1300 + 2: return "TCM_GETIMAGELIST";
5072 case 0x1300 + 3: return "TCM_SETIMAGELIST";
5073 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
5074 case 0x1300 + 5: return "TCM_GETITEMA";
5075 case 0x1300 + 60: return "TCM_GETITEMW";
5076 case 0x1300 + 6: return "TCM_SETITEMA";
5077 case 0x1300 + 61: return "TCM_SETITEMW";
5078 case 0x1300 + 7: return "TCM_INSERTITEMA";
5079 case 0x1300 + 62: return "TCM_INSERTITEMW";
5080 case 0x1300 + 8: return "TCM_DELETEITEM";
5081 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
5082 case 0x1300 + 10: return "TCM_GETITEMRECT";
5083 case 0x1300 + 11: return "TCM_GETCURSEL";
5084 case 0x1300 + 12: return "TCM_SETCURSEL";
5085 case 0x1300 + 13: return "TCM_HITTEST";
5086 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
5087 case 0x1300 + 40: return "TCM_ADJUSTRECT";
5088 case 0x1300 + 41: return "TCM_SETITEMSIZE";
5089 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
5090 case 0x1300 + 43: return "TCM_SETPADDING";
5091 case 0x1300 + 44: return "TCM_GETROWCOUNT";
5092 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
5093 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
5094 case 0x1300 + 47: return "TCM_GETCURFOCUS";
5095 case 0x1300 + 48: return "TCM_SETCURFOCUS";
5096 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
5097 case 0x1300 + 50: return "TCM_DESELECTALL";
5100 case WM_USER
+1: return "TB_ENABLEBUTTON";
5101 case WM_USER
+2: return "TB_CHECKBUTTON";
5102 case WM_USER
+3: return "TB_PRESSBUTTON";
5103 case WM_USER
+4: return "TB_HIDEBUTTON";
5104 case WM_USER
+5: return "TB_INDETERMINATE";
5105 case WM_USER
+9: return "TB_ISBUTTONENABLED";
5106 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
5107 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
5108 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
5109 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
5110 case WM_USER
+17: return "TB_SETSTATE";
5111 case WM_USER
+18: return "TB_GETSTATE";
5112 case WM_USER
+19: return "TB_ADDBITMAP";
5113 case WM_USER
+20: return "TB_ADDBUTTONS";
5114 case WM_USER
+21: return "TB_INSERTBUTTON";
5115 case WM_USER
+22: return "TB_DELETEBUTTON";
5116 case WM_USER
+23: return "TB_GETBUTTON";
5117 case WM_USER
+24: return "TB_BUTTONCOUNT";
5118 case WM_USER
+25: return "TB_COMMANDTOINDEX";
5119 case WM_USER
+26: return "TB_SAVERESTOREA";
5120 case WM_USER
+76: return "TB_SAVERESTOREW";
5121 case WM_USER
+27: return "TB_CUSTOMIZE";
5122 case WM_USER
+28: return "TB_ADDSTRINGA";
5123 case WM_USER
+77: return "TB_ADDSTRINGW";
5124 case WM_USER
+29: return "TB_GETITEMRECT";
5125 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
5126 case WM_USER
+31: return "TB_SETBUTTONSIZE";
5127 case WM_USER
+32: return "TB_SETBITMAPSIZE";
5128 case WM_USER
+33: return "TB_AUTOSIZE";
5129 case WM_USER
+35: return "TB_GETTOOLTIPS";
5130 case WM_USER
+36: return "TB_SETTOOLTIPS";
5131 case WM_USER
+37: return "TB_SETPARENT";
5132 case WM_USER
+39: return "TB_SETROWS";
5133 case WM_USER
+40: return "TB_GETROWS";
5134 case WM_USER
+42: return "TB_SETCMDID";
5135 case WM_USER
+43: return "TB_CHANGEBITMAP";
5136 case WM_USER
+44: return "TB_GETBITMAP";
5137 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
5138 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
5139 case WM_USER
+46: return "TB_REPLACEBITMAP";
5140 case WM_USER
+47: return "TB_SETINDENT";
5141 case WM_USER
+48: return "TB_SETIMAGELIST";
5142 case WM_USER
+49: return "TB_GETIMAGELIST";
5143 case WM_USER
+50: return "TB_LOADIMAGES";
5144 case WM_USER
+51: return "TB_GETRECT";
5145 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
5146 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
5147 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
5148 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
5149 case WM_USER
+56: return "TB_SETSTYLE";
5150 case WM_USER
+57: return "TB_GETSTYLE";
5151 case WM_USER
+58: return "TB_GETBUTTONSIZE";
5152 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
5153 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
5154 case WM_USER
+61: return "TB_GETTEXTROWS";
5155 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
5160 static char s_szBuf
[128];
5161 sprintf(s_szBuf
, "<unknown message = %d>", message
);
5165 #endif //__WXDEBUG__
5167 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
5168 int *x
, int *y
, WPARAM
*flags
)
5170 // construct the key mask
5171 WPARAM
& fwKeys
= *flags
;
5173 fwKeys
= MK_RBUTTON
;
5174 if ( wxIsCtrlDown() )
5175 fwKeys
|= MK_CONTROL
;
5176 if ( wxIsShiftDown() )
5179 // simulate right mouse button click
5180 DWORD dwPos
= ::GetMessagePos();
5181 *x
= GET_X_LPARAM(dwPos
);
5182 *y
= GET_Y_LPARAM(dwPos
);
5184 win
->ScreenToClient(x
, y
);
5187 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
5191 HWND hwnd
= GetHwndOf(win
);
5192 HDC hdc
= ::GetDC(hwnd
);
5194 #if !wxDIALOG_UNIT_COMPATIBILITY
5195 // and select the current font into it
5196 HFONT hfont
= GetHfontOf(win
->GetFont());
5199 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
5203 // finally retrieve the text metrics from it
5204 GetTextMetrics(hdc
, &tm
);
5206 #if !wxDIALOG_UNIT_COMPATIBILITY
5210 (void)::SelectObject(hdc
, hfont
);
5214 ::ReleaseDC(hwnd
, hdc
);
5219 // Find the wxWindow at the current mouse position, returning the mouse
5221 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
5223 return wxFindWindowAtPoint(wxGetMousePosition());
5226 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
5231 HWND hWndHit
= ::WindowFromPoint(pt2
);
5233 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
5234 HWND hWnd
= hWndHit
;
5236 // Try to find a window with a wxWindow associated with it
5237 while (!win
&& (hWnd
!= 0))
5239 hWnd
= ::GetParent(hWnd
);
5240 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
5245 // Get the current mouse position.
5246 wxPoint
wxGetMousePosition()
5249 GetCursorPos( & pt
);
5251 return wxPoint(pt
.x
, pt
.y
);