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 #ifdef __WXUNIVERSAL__
2342 // Universal uses its own wxFrame/wxDialog, so we don't receive
2343 // close events unless we have this.
2348 // don't let the DefWindowProc() destroy our window - we'll do it
2349 // ourselves in ~wxWindow
2356 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2360 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2361 GET_Y_LPARAM(lParam
),
2365 #if wxUSE_MOUSEWHEEL
2367 processed
= HandleMouseWheel(wParam
, lParam
);
2371 case WM_LBUTTONDOWN
:
2373 case WM_LBUTTONDBLCLK
:
2374 case WM_RBUTTONDOWN
:
2376 case WM_RBUTTONDBLCLK
:
2377 case WM_MBUTTONDOWN
:
2379 case WM_MBUTTONDBLCLK
:
2382 #ifdef __WXMICROWIN__
2383 // MicroWindows seems to ignore the fact that a window is
2384 // disabled. So catch mouse events and throw them away if
2386 wxWindowMSW
* win
= this;
2389 if (!win
->IsEnabled())
2394 win
= win
->GetParent();
2395 if (win
&& win
->IsTopLevel())
2398 #endif // __WXMICROWIN__
2401 if (message
== WM_LBUTTONDOWN
&& AcceptsFocus())
2403 processed
= HandleMouseEvent(message
,
2404 GET_X_LPARAM(lParam
),
2405 GET_Y_LPARAM(lParam
),
2411 #ifdef __WXMICROWIN__
2412 case WM_NCLBUTTONDOWN
:
2413 case WM_NCLBUTTONUP
:
2414 case WM_NCLBUTTONDBLCLK
:
2415 case WM_NCRBUTTONDOWN
:
2416 case WM_NCRBUTTONUP
:
2417 case WM_NCRBUTTONDBLCLK
:
2419 case WM_NCMBUTTONDOWN
:
2420 case WM_NCMBUTTONUP
:
2421 case WM_NCMBUTTONDBLCLK
:
2424 // MicroWindows seems to ignore the fact that a window
2425 // is disabled. So catch mouse events and throw them away if necessary.
2427 wxWindowMSW
* win
= this;
2430 if (!win
->IsEnabled())
2435 win
= win
->GetParent();
2436 if (win
&& win
->IsTopLevel())
2441 #endif // __WXMICROWIN__
2448 case MM_JOY1BUTTONDOWN
:
2449 case MM_JOY2BUTTONDOWN
:
2450 case MM_JOY1BUTTONUP
:
2451 case MM_JOY2BUTTONUP
:
2452 processed
= HandleJoystickEvent(message
,
2453 GET_X_LPARAM(lParam
),
2454 GET_Y_LPARAM(lParam
),
2457 #endif // __WXMICROWIN__
2460 processed
= HandleSysCommand(wParam
, lParam
);
2467 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2469 processed
= HandleCommand(id
, cmd
, hwnd
);
2475 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2479 // for these messages we must return TRUE if process the message
2482 case WM_MEASUREITEM
:
2484 int idCtrl
= (UINT
)wParam
;
2485 if ( message
== WM_DRAWITEM
)
2487 processed
= MSWOnDrawItem(idCtrl
,
2488 (WXDRAWITEMSTRUCT
*)lParam
);
2492 processed
= MSWOnMeasureItem(idCtrl
,
2493 (WXMEASUREITEMSTRUCT
*)lParam
);
2500 #endif // defined(WM_DRAWITEM)
2503 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
2505 // want everything: i.e. all keys and WM_CHAR message
2506 rc
.result
= DLGC_WANTARROWS
| DLGC_WANTCHARS
|
2507 DLGC_WANTTAB
| DLGC_WANTMESSAGE
;
2510 //else: get the dlg code from the DefWindowProc()
2515 // If this has been processed by an event handler, return 0 now
2516 // (we've handled it).
2517 m_lastKeydownProcessed
= HandleKeyDown((WORD
) wParam
, lParam
);
2518 if ( m_lastKeydownProcessed
)
2526 // we consider these message "not interesting" to OnChar, so
2527 // just don't do anything more with them
2537 // avoid duplicate messages to OnChar for these ASCII keys:
2538 // they will be translated by TranslateMessage() and received
2560 // but set processed to FALSE, not TRUE to still pass them
2561 // to the control's default window proc - otherwise
2562 // built-in keyboard handling won't work
2568 // special case of VK_APPS: treat it the same as right mouse
2569 // click because both usually pop up a context menu
2575 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2576 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2582 // do generate a CHAR event
2583 processed
= HandleChar((WORD
)wParam
, lParam
);
2591 // special case of VK_APPS: treat it the same as right mouse button
2592 if ( wParam
== VK_APPS
)
2597 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2598 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2603 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2608 case WM_CHAR
: // Always an ASCII character
2609 if ( m_lastKeydownProcessed
)
2611 // The key was handled in the EVT_KEY_DOWN and handling
2612 // a key in an EVT_KEY_DOWN handler is meant, by
2613 // design, to prevent EVT_CHARs from happening
2614 m_lastKeydownProcessed
= FALSE
;
2619 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2628 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2630 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2636 // CTLCOLOR messages are sent by children to query the parent for their
2637 // colors#ifndef __WXMICROWIN__
2638 #ifndef __WXMICROWIN__
2640 case WM_CTLCOLORMSGBOX
:
2641 case WM_CTLCOLOREDIT
:
2642 case WM_CTLCOLORLISTBOX
:
2643 case WM_CTLCOLORBTN
:
2644 case WM_CTLCOLORDLG
:
2645 case WM_CTLCOLORSCROLLBAR
:
2646 case WM_CTLCOLORSTATIC
:
2654 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2656 processed
= HandleCtlColor(&rc
.hBrush
,
2665 #endif // !__WXMICROWIN__
2667 case WM_SYSCOLORCHANGE
:
2668 // the return value for this message is ignored
2669 processed
= HandleSysColorChange();
2672 case WM_DISPLAYCHANGE
:
2673 processed
= HandleDisplayChange();
2676 case WM_PALETTECHANGED
:
2677 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2680 case WM_CAPTURECHANGED
:
2681 processed
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
);
2684 case WM_QUERYNEWPALETTE
:
2685 processed
= HandleQueryNewPalette();
2689 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2692 // we processed the message, i.e. erased the background
2698 processed
= HandleDropFiles(wParam
);
2702 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2706 // we never set focus from here
2711 case WM_QUERYENDSESSION
:
2712 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2716 processed
= HandleEndSession(wParam
!= 0, lParam
);
2719 case WM_GETMINMAXINFO
:
2720 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2724 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2725 LOWORD(lParam
), // hit test
2726 HIWORD(lParam
)); // mouse msg
2730 // returning TRUE stops the DefWindowProc() from further
2731 // processing this message - exactly what we need because we've
2732 // just set the cursor.
2737 #if defined(__WIN32__) && defined(WM_HELP)
2740 HELPINFO
* info
= (HELPINFO
*) lParam
;
2741 // Don't yet process menu help events, just windows
2742 if (info
->iContextType
== HELPINFO_WINDOW
)
2744 wxWindowMSW
* subjectOfHelp
= this;
2745 bool eventProcessed
= FALSE
;
2746 while (subjectOfHelp
&& !eventProcessed
)
2748 wxHelpEvent
helpEvent(wxEVT_HELP
,
2749 subjectOfHelp
->GetId(),
2750 wxPoint(info
->MousePos
.x
,
2751 info
->MousePos
.y
) );
2752 helpEvent
.SetEventObject(this);
2754 GetEventHandler()->ProcessEvent(helpEvent
);
2756 // Go up the window hierarchy until the event is
2758 subjectOfHelp
= subjectOfHelp
->GetParent();
2761 processed
= eventProcessed
;
2763 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2765 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2766 helpEvent
.SetEventObject(this);
2767 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2770 //else: processed is already FALSE
2774 case WM_CONTEXTMENU
:
2776 // we don't convert from screen to client coordinates as
2777 // the event may be handled by a parent window
2778 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2780 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2781 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2790 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2791 wxGetMessageName(message
));
2792 #endif // __WXDEBUG__
2793 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2799 // ----------------------------------------------------------------------------
2800 // wxWindow <-> HWND map
2801 // ----------------------------------------------------------------------------
2803 wxWinHashTable
*wxWinHandleHash
= NULL
;
2805 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2807 return wxWinHandleHash
->Get((long)hWnd
);
2810 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2812 // adding NULL hWnd is (first) surely a result of an error and
2813 // (secondly) breaks menu command processing
2814 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2815 wxT("attempt to add a NULL hWnd to window list ignored") );
2817 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2819 if ( oldWin
&& (oldWin
!= win
) )
2821 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2822 hWnd
, win
->GetClassInfo()->GetClassName());
2825 #endif // __WXDEBUG__
2828 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2832 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2834 wxWinHandleHash
->Delete((long)win
->GetHWND());
2837 // ----------------------------------------------------------------------------
2838 // various MSW speciic class dependent functions
2839 // ----------------------------------------------------------------------------
2841 // Default destroyer - override if you destroy it in some other way
2842 // (e.g. with MDI child windows)
2843 void wxWindowMSW::MSWDestroyWindow()
2847 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2850 int& w
, int& h
) const
2852 bool nonDefault
= FALSE
;
2856 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2857 // just as well set it to CW_USEDEFAULT as well
2864 y
= pos
.y
== -1 ? CW_USEDEFAULT
: pos
.y
;
2870 NB: there used to be some code here which set the initial size of the
2871 window to the client size of the parent if no explicit size was
2872 specified. This was wrong because wxWindows programs often assume
2873 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2874 it. To see why, you should understand that Windows sends WM_SIZE from
2875 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2876 from some base class ctor and so this WM_SIZE is not processed in the
2877 real class' OnSize() (because it's not fully constructed yet and the
2878 event goes to some base class OnSize() instead). So the WM_SIZE we
2879 rely on is the one sent when the parent frame resizes its children
2880 but here is the problem: if the child already has just the right
2881 size, nothing will happen as both wxWindows and Windows check for
2882 this and ignore any attempts to change the window size to the size it
2883 already has - so no WM_SIZE would be sent.
2887 // as abobe, h is not used at all in this case anyhow
2894 h
= size
.y
== -1 ? CW_USEDEFAULT
: size
.y
;
2902 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2903 const wxChar
*title
,
2907 WXDWORD extendedStyle
)
2909 // choose the position/size for the new window
2911 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2913 // find the correct parent HWND
2914 wxWindow
*parent
= GetParent();
2915 bool isChild
= (style
& WS_CHILD
) != 0;
2917 if ( GetWindowStyleFlag() & wxPOPUP_WINDOW
)
2919 // popup windows should have desktop as parent because they shouldn't
2920 // be limited to the parents client area as child windows usually are
2921 hParent
= ::GetDesktopWindow();
2925 if ( (isChild
|| HasFlag(wxFRAME_TOOL_WINDOW
)) && parent
)
2927 // this is either a normal child window or a top level window with
2928 // wxFRAME_TOOL_WINDOW style (see below)
2929 hParent
= GetHwndOf(parent
);
2933 // this is either a window for which no parent was specified (not
2934 // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
2935 // style: we should use NULL parent HWND for it or it would be
2936 // always on top of its parent which is not what we usually want
2937 // (in fact, we only want it for frames with the special
2938 // wxFRAME_TOOL_WINDOW as above)
2944 // controlId is menu handle for the top level windows, so set it to 0
2945 // unless we're creating a child window
2949 controlId
= GetId();
2951 if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
2953 style
|= WS_CLIPSIBLINGS
;
2961 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2962 // which is the same but without CS_[HV]REDRAW class styles so using it
2963 // ensures that the window is not fully repainted on each resize
2964 wxString
className(wclass
);
2965 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2967 className
+= wxT("NR");
2970 // do create the window
2971 wxWindowCreationHook
hook(this);
2973 m_hWnd
= (WXHWND
)::CreateWindowEx
2977 title
? title
: wxT(""),
2983 NULL
// no extra data
2988 wxLogSysError(_("Can't create window of class %s"), wclass
);
2993 SubclassWin(m_hWnd
);
2995 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
3000 // ===========================================================================
3001 // MSW message handlers
3002 // ===========================================================================
3004 // ---------------------------------------------------------------------------
3006 // ---------------------------------------------------------------------------
3009 // FIXME: VZ: I'm not sure at all that the order of processing is correct
3010 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
3012 #ifndef __WXMICROWIN__
3013 LPNMHDR hdr
= (LPNMHDR
)lParam
;
3014 HWND hWnd
= hdr
->hwndFrom
;
3015 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
3017 // is this one of our windows?
3020 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
3023 // try all our children
3024 wxWindowList::Node
*node
= GetChildren().GetFirst();
3027 wxWindow
*child
= node
->GetData();
3028 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
3033 node
= node
->GetNext();
3036 // finally try this window too (catches toolbar case)
3037 return MSWOnNotify(idCtrl
, lParam
, result
);
3038 #else // __WXMICROWIN__
3043 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
3045 WXLPARAM
* WXUNUSED(result
))
3048 NMHDR
* hdr
= (NMHDR
*)lParam
;
3049 if ( (int)hdr
->code
== TTN_NEEDTEXT
&& m_tooltip
)
3051 TOOLTIPTEXT
*ttt
= (TOOLTIPTEXT
*)lParam
;
3052 ttt
->lpszText
= (wxChar
*)m_tooltip
->GetTip().c_str();
3057 #endif // wxUSE_TOOLTIPS
3063 // ---------------------------------------------------------------------------
3064 // end session messages
3065 // ---------------------------------------------------------------------------
3067 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
3069 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
3070 event
.SetEventObject(wxTheApp
);
3071 event
.SetCanVeto(TRUE
);
3072 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
3074 bool rc
= wxTheApp
->ProcessEvent(event
);
3078 // we may end only if the app didn't veto session closing (double
3080 *mayEnd
= !event
.GetVeto();
3086 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
3088 // do nothing if the session isn't ending
3093 if ( (this != wxTheApp
->GetTopWindow()) )
3096 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
3097 event
.SetEventObject(wxTheApp
);
3098 event
.SetCanVeto(FALSE
);
3099 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
3101 return wxTheApp
->ProcessEvent(event
);
3104 // ---------------------------------------------------------------------------
3105 // window creation/destruction
3106 // ---------------------------------------------------------------------------
3108 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED(cs
), bool *mayCreate
)
3110 // TODO: should generate this event from WM_NCCREATE
3111 wxWindowCreateEvent
event((wxWindow
*)this);
3112 (void)GetEventHandler()->ProcessEvent(event
);
3119 bool wxWindowMSW::HandleDestroy()
3121 wxWindowDestroyEvent
event((wxWindow
*)this);
3122 (void)GetEventHandler()->ProcessEvent(event
);
3124 // delete our drop target if we've got one
3125 #if wxUSE_DRAG_AND_DROP
3126 if ( m_dropTarget
!= NULL
)
3128 m_dropTarget
->Revoke(m_hWnd
);
3130 delete m_dropTarget
;
3131 m_dropTarget
= NULL
;
3133 #endif // wxUSE_DRAG_AND_DROP
3135 // WM_DESTROY handled
3139 // ---------------------------------------------------------------------------
3141 // ---------------------------------------------------------------------------
3143 bool wxWindowMSW::HandleActivate(int state
,
3144 bool WXUNUSED(minimized
),
3145 WXHWND
WXUNUSED(activate
))
3147 wxActivateEvent
event(wxEVT_ACTIVATE
,
3148 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3150 event
.SetEventObject(this);
3152 return GetEventHandler()->ProcessEvent(event
);
3155 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3157 // notify the parent keeping track of focus for the kbd navigation
3158 // purposes that we got it
3159 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3160 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3166 m_caret
->OnSetFocus();
3168 #endif // wxUSE_CARET
3171 // If it's a wxTextCtrl don't send the event as it will be done
3172 // after the control gets to process it from EN_FOCUS handler
3173 if ( wxDynamicCastThis(wxTextCtrl
) )
3177 #endif // wxUSE_TEXTCTRL
3179 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3180 event
.SetEventObject(this);
3182 // wxFindWinFromHandle() may return NULL, it is ok
3183 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3185 return GetEventHandler()->ProcessEvent(event
);
3188 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3194 m_caret
->OnKillFocus();
3196 #endif // wxUSE_CARET
3199 // If it's a wxTextCtrl don't send the event as it will be done
3200 // after the control gets to process it.
3201 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3208 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3209 event
.SetEventObject(this);
3211 // wxFindWinFromHandle() may return NULL, it is ok
3212 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3214 return GetEventHandler()->ProcessEvent(event
);
3217 // ---------------------------------------------------------------------------
3219 // ---------------------------------------------------------------------------
3221 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3223 wxShowEvent
event(GetId(), show
);
3224 event
.m_eventObject
= this;
3226 return GetEventHandler()->ProcessEvent(event
);
3229 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3231 wxInitDialogEvent
event(GetId());
3232 event
.m_eventObject
= this;
3234 return GetEventHandler()->ProcessEvent(event
);
3237 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3239 #ifndef __WXMICROWIN__
3240 HDROP hFilesInfo
= (HDROP
) wParam
;
3242 // Get the total number of files dropped
3243 UINT gwFilesDropped
= ::DragQueryFile
3251 wxString
*files
= new wxString
[gwFilesDropped
];
3252 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3254 // first get the needed buffer length (+1 for terminating NUL)
3255 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3257 // and now get the file name
3258 ::DragQueryFile(hFilesInfo
, wIndex
,
3259 files
[wIndex
].GetWriteBuf(len
), len
);
3261 files
[wIndex
].UngetWriteBuf();
3263 DragFinish (hFilesInfo
);
3265 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3266 event
.m_eventObject
= this;
3269 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3270 event
.m_pos
.x
= dropPoint
.x
;
3271 event
.m_pos
.y
= dropPoint
.y
;
3273 return GetEventHandler()->ProcessEvent(event
);
3274 #else // __WXMICROWIN__
3279 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3281 int WXUNUSED(mouseMsg
))
3283 #ifndef __WXMICROWIN__
3284 // the logic is as follows:
3285 // -1. don't set cursor for non client area, including but not limited to
3286 // the title bar, scrollbars, &c
3287 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3288 // 1. if we have the cursor set it unless wxIsBusy()
3289 // 2. if we're a top level window, set some cursor anyhow
3290 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3292 if ( nHitTest
!= HTCLIENT
)
3297 HCURSOR hcursor
= 0;
3299 // first ask the user code - it may wish to set the cursor in some very
3300 // specific way (for example, depending on the current position)
3303 if ( !::GetCursorPos(&pt
) )
3305 wxLogLastError(wxT("GetCursorPos"));
3308 // In WIN16 it doesn't return a value.
3309 ::GetCursorPos(&pt
);
3314 ScreenToClient(&x
, &y
);
3315 wxSetCursorEvent
event(x
, y
);
3317 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3318 if ( processedEvtSetCursor
&& event
.HasCursor() )
3320 hcursor
= GetHcursorOf(event
.GetCursor());
3325 bool isBusy
= wxIsBusy();
3327 // the test for processedEvtSetCursor is here to prevent using m_cursor
3328 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3329 // it - this is a way to say that our cursor shouldn't be used for this
3331 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3333 hcursor
= GetHcursorOf(m_cursor
);
3340 hcursor
= wxGetCurrentBusyCursor();
3342 else if ( !hcursor
)
3344 const wxCursor
*cursor
= wxGetGlobalCursor();
3345 if ( cursor
&& cursor
->Ok() )
3347 hcursor
= GetHcursorOf(*cursor
);
3355 ::SetCursor(hcursor
);
3357 // cursor set, stop here
3360 #endif // __WXMICROWIN__
3362 // pass up the window chain
3366 // ---------------------------------------------------------------------------
3367 // owner drawn stuff
3368 // ---------------------------------------------------------------------------
3370 bool wxWindowMSW::MSWOnDrawItem(int id
, WXDRAWITEMSTRUCT
*itemStruct
)
3372 #if wxUSE_OWNER_DRAWN
3374 #if wxUSE_MENUS_NATIVE
3375 // is it a menu item?
3376 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3377 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3379 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3381 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3383 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3384 // the DC from being released
3385 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3386 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3387 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3388 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3390 return pMenuItem
->OnDrawItem
3394 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3395 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3398 #endif // wxUSE_MENUS_NATIVE
3401 wxWindow
*item
= FindItem(id
);
3402 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3404 return ((wxControl
*)item
)->MSWOnDraw(itemStruct
);
3406 #endif // wxUSE_CONTROLS
3408 #endif // USE_OWNER_DRAWN
3413 bool wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3415 #if wxUSE_OWNER_DRAWN
3416 // is it a menu item?
3417 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3418 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3420 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3422 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3424 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3425 &pMeasureStruct
->itemHeight
);
3428 wxWindow
*item
= FindItem(id
);
3429 if ( item
&& item
->IsKindOf(CLASSINFO(wxControl
)) )
3431 return ((wxControl
*)item
)->MSWOnMeasure(itemStruct
);
3433 #endif // owner-drawn menus
3437 // ---------------------------------------------------------------------------
3438 // colours and palettes
3439 // ---------------------------------------------------------------------------
3441 bool wxWindowMSW::HandleSysColorChange()
3443 wxSysColourChangedEvent event
;
3444 event
.SetEventObject(this);
3446 (void)GetEventHandler()->ProcessEvent(event
);
3448 // always let the system carry on the default processing to allow the
3449 // native controls to react to the colours update
3453 bool wxWindowMSW::HandleDisplayChange()
3455 wxDisplayChangedEvent event
;
3456 event
.SetEventObject(this);
3458 return GetEventHandler()->ProcessEvent(event
);
3461 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3469 #ifndef __WXMICROWIN__
3470 WXHBRUSH hBrush
= 0;
3472 if ( nCtlColor
== CTLCOLOR_DLG
)
3474 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3479 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3481 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3483 #endif // wxUSE_CONTROLS
3489 #else // __WXMICROWIN__
3494 // Define for each class of dialog and control
3495 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3496 WXHWND
WXUNUSED(hWnd
),
3497 WXUINT
WXUNUSED(nCtlColor
),
3498 WXUINT
WXUNUSED(message
),
3499 WXWPARAM
WXUNUSED(wParam
),
3500 WXLPARAM
WXUNUSED(lParam
))
3505 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3508 // same as below except we don't respond to our own messages
3509 if ( hWndPalChange
!= GetHWND() )
3511 // check to see if we our our parents have a custom palette
3512 wxWindow
*win
= this;
3513 while ( win
&& !win
->HasCustomPalette() )
3515 win
= win
->GetParent();
3518 if ( win
&& win
->HasCustomPalette() )
3520 // realize the palette to see whether redrawing is needed
3521 HDC hdc
= ::GetDC((HWND
) hWndPalChange
);
3522 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3523 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3525 int result
= ::RealizePalette(hdc
);
3527 // restore the palette (before releasing the DC)
3528 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3529 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3530 ::RealizePalette(hdc
);
3531 ::ReleaseDC((HWND
) hWndPalChange
, hdc
);
3533 // now check for the need to redraw
3535 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
);
3539 #endif // wxUSE_PALETTE
3541 wxPaletteChangedEvent
event(GetId());
3542 event
.SetEventObject(this);
3543 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3545 return GetEventHandler()->ProcessEvent(event
);
3548 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
)
3550 wxMouseCaptureChangedEvent
event(GetId(), wxFindWinFromHandle(hWndGainedCapture
));
3551 event
.SetEventObject(this);
3553 return GetEventHandler()->ProcessEvent(event
);
3556 bool wxWindowMSW::HandleQueryNewPalette()
3560 // check to see if we our our parents have a custom palette
3561 wxWindow
*win
= this;
3562 while (!win
->HasCustomPalette() && win
->GetParent()) win
= win
->GetParent();
3563 if (win
->HasCustomPalette()) {
3564 /* realize the palette to see whether redrawing is needed */
3565 HDC hdc
= GetDC((HWND
) GetHWND());
3566 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3567 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) );
3569 int result
= ::RealizePalette(hdc
);
3570 /* restore the palette (before releasing the DC) */
3571 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3572 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) );
3573 ::RealizePalette(hdc
);
3574 ::ReleaseDC((HWND
) GetHWND(), hdc
);
3575 /* now check for the need to redraw */
3577 ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
);
3579 #endif // wxUSE_PALETTE
3581 wxQueryNewPaletteEvent
event(GetId());
3582 event
.SetEventObject(this);
3584 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3587 // Responds to colour changes: passes event on to children.
3588 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
))
3590 // the top level window also reset the standard colour map as it might have
3591 // changed (there is no need to do it for the non top level windows as we
3592 // only have to do it once)
3596 gs_hasStdCmap
= FALSE
;
3598 wxWindowList::Node
*node
= GetChildren().GetFirst();
3601 // Only propagate to non-top-level windows because Windows already
3602 // sends this event to all top-level ones
3603 wxWindow
*win
= node
->GetData();
3604 if ( !win
->IsTopLevel() )
3606 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3607 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3608 // the standard controls
3609 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3612 node
= node
->GetNext();
3615 // update the colours we use if they were not set explicitly by the user:
3616 // this must be done or OnCtlColor() would continue to use the old colours
3619 m_foregroundColour
= wxSystemSettings::
3620 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3625 m_backgroundColour
= wxSystemSettings::
3626 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3630 extern wxCOLORMAP
*wxGetStdColourMap()
3632 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3633 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3635 if ( !gs_hasStdCmap
)
3637 static bool s_coloursInit
= FALSE
;
3639 if ( !s_coloursInit
)
3641 // When a bitmap is loaded, the RGB values can change (apparently
3642 // because Windows adjusts them to care for the old programs always
3643 // using 0xc0c0c0 while the transparent colour for the new Windows
3644 // versions is different). But we do this adjustment ourselves so
3645 // we want to avoid Windows' "help" and for this we need to have a
3646 // reference bitmap which can tell us what the RGB values change
3648 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3649 if ( stdColourBitmap
.Ok() )
3651 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3652 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3653 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3656 memDC
.SelectObject(stdColourBitmap
);
3659 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3661 memDC
.GetPixel(i
, 0, &colour
);
3662 s_stdColours
[i
] = wxColourToRGB(colour
);
3665 else // wxBITMAP_STD_COLOURS couldn't be loaded
3667 s_stdColours
[0] = RGB(000,000,000); // black
3668 s_stdColours
[1] = RGB(128,128,128); // dark grey
3669 s_stdColours
[2] = RGB(192,192,192); // light grey
3670 s_stdColours
[3] = RGB(255,255,255); // white
3671 //s_stdColours[4] = RGB(000,000,255); // blue
3672 //s_stdColours[5] = RGB(255,000,255); // magenta
3675 s_coloursInit
= TRUE
;
3678 gs_hasStdCmap
= TRUE
;
3680 // create the colour map
3681 #define INIT_CMAP_ENTRY(col) \
3682 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3683 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3685 INIT_CMAP_ENTRY(BTNTEXT
);
3686 INIT_CMAP_ENTRY(BTNSHADOW
);
3687 INIT_CMAP_ENTRY(BTNFACE
);
3688 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3690 #undef INIT_CMAP_ENTRY
3696 // ---------------------------------------------------------------------------
3698 // ---------------------------------------------------------------------------
3700 bool wxWindowMSW::HandlePaint()
3703 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3705 wxLogLastError(wxT("CreateRectRgn"));
3706 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3707 wxLogLastError(wxT("GetUpdateRgn"));
3709 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3712 ::GetUpdateRect(GetHwnd(), &updateRect
, FALSE
);
3714 m_updateRegion
= wxRegion(updateRect
.left
, updateRect
.top
,
3715 updateRect
.right
- updateRect
.left
,
3716 updateRect
.bottom
- updateRect
.top
);
3719 wxPaintEvent
event(m_windowId
);
3720 event
.SetEventObject(this);
3722 bool processed
= GetEventHandler()->ProcessEvent(event
);
3724 // note that we must generate NC event after the normal one as otherwise
3725 // BeginPaint() will happily overwrite our decorations with the background
3727 wxNcPaintEvent
eventNc(m_windowId
);
3728 eventNc
.SetEventObject(this);
3729 GetEventHandler()->ProcessEvent(eventNc
);
3734 // Can be called from an application's OnPaint handler
3735 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3737 #ifdef __WXUNIVERSAL__
3740 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3743 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3748 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3750 // Prevents flicker when dragging
3751 if ( ::IsIconic(GetHwnd()) )
3757 dc
.SetWindow((wxWindow
*)this);
3760 wxEraseEvent
event(m_windowId
, &dc
);
3761 event
.SetEventObject(this);
3762 bool rc
= GetEventHandler()->ProcessEvent(event
);
3766 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3767 dc
.SelectOldObjects(hdc
);
3772 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3775 ::GetClientRect(GetHwnd(), &rect
);
3777 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3778 m_backgroundColour
.Green(),
3779 m_backgroundColour
.Blue());
3780 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3782 wxLogLastError(wxT("CreateSolidBrush"));
3784 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3786 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3788 ::FillRect(hdc
, &rect
, hBrush
);
3789 ::DeleteObject(hBrush
);
3790 ::SetMapMode(hdc
, mode
);
3793 // ---------------------------------------------------------------------------
3794 // moving and resizing
3795 // ---------------------------------------------------------------------------
3797 bool wxWindowMSW::HandleMinimize()
3799 wxIconizeEvent
event(m_windowId
);
3800 event
.SetEventObject(this);
3802 return GetEventHandler()->ProcessEvent(event
);
3805 bool wxWindowMSW::HandleMaximize()
3807 wxMaximizeEvent
event(m_windowId
);
3808 event
.SetEventObject(this);
3810 return GetEventHandler()->ProcessEvent(event
);
3813 bool wxWindowMSW::HandleMove(int x
, int y
)
3815 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3816 event
.SetEventObject(this);
3818 return GetEventHandler()->ProcessEvent(event
);
3821 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
),
3822 WXUINT
WXUNUSED(flag
))
3824 // don't use w and h parameters as they specify the client size while
3825 // according to the docs EVT_SIZE handler is supposed to receive the total
3827 wxSizeEvent
event(GetSize(), m_windowId
);
3828 event
.SetEventObject(this);
3830 return GetEventHandler()->ProcessEvent(event
);
3833 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3835 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3839 int minWidth
= GetMinWidth(),
3840 minHeight
= GetMinHeight(),
3841 maxWidth
= GetMaxWidth(),
3842 maxHeight
= GetMaxHeight();
3844 if ( minWidth
!= -1 )
3846 info
->ptMinTrackSize
.x
= minWidth
;
3850 if ( minHeight
!= -1 )
3852 info
->ptMinTrackSize
.y
= minHeight
;
3856 if ( maxWidth
!= -1 )
3858 info
->ptMaxTrackSize
.x
= maxWidth
;
3862 if ( maxHeight
!= -1 )
3864 info
->ptMaxTrackSize
.y
= maxHeight
;
3871 // ---------------------------------------------------------------------------
3873 // ---------------------------------------------------------------------------
3875 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
3877 #if wxUSE_MENUS_NATIVE
3878 if ( !cmd
&& wxCurrentPopupMenu
)
3880 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
3881 wxCurrentPopupMenu
= NULL
;
3883 return popupMenu
->MSWCommand(cmd
, id
);
3885 #endif // wxUSE_MENUS_NATIVE
3887 wxWindow
*win
= NULL
;
3889 // first try to find it from HWND - this works even with the broken
3890 // programs using the same ids for different controls
3893 win
= wxFindWinFromHandle(control
);
3899 // must cast to a signed type before comparing with other ids!
3900 win
= FindItem((signed short)id
);
3905 return win
->MSWCommand(cmd
, id
);
3908 // the messages sent from the in-place edit control used by the treectrl
3909 // for label editing have id == 0, but they should _not_ be treated as menu
3910 // messages (they are EN_XXX ones, in fact) so don't translate anything
3911 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
3914 // If no child window, it may be an accelerator, e.g. for a popup menu
3917 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
3918 event
.SetEventObject(this);
3922 return GetEventHandler()->ProcessEvent(event
);
3924 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
3927 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
3928 // notifications to its parent which we want to reflect back to
3930 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
3931 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
3934 #endif // wxUSE_SPINCTRL
3939 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
3941 // 4 bits are reserved
3942 switch ( wParam
& 0xFFFFFFF0 )
3945 return HandleMaximize();
3948 return HandleMinimize();
3954 // ---------------------------------------------------------------------------
3956 // ---------------------------------------------------------------------------
3958 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
3962 // our client coords are not quite the same as Windows ones
3963 wxPoint pt
= GetClientAreaOrigin();
3964 event
.m_x
= x
- pt
.x
;
3965 event
.m_y
= y
- pt
.y
;
3967 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
3968 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
3969 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
3970 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
3971 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
3972 event
.m_altDown
= (::GetKeyState(VK_MENU
) & 0x80000000) != 0;
3974 event
.SetTimestamp(s_currentMsg
.time
);
3975 event
.m_eventObject
= this;
3977 #if wxUSE_MOUSEEVENT_HACK
3980 m_lastMouseEvent
= event
.GetEventType();
3981 #endif // wxUSE_MOUSEEVENT_HACK
3984 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
3986 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
3987 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
3988 // from the message id and take the value in the table to get wxWin event
3990 static const wxEventType eventsMouse
[] =
4004 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
4005 InitMouseEvent(event
, x
, y
, flags
);
4007 return GetEventHandler()->ProcessEvent(event
);
4010 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
4012 if ( !m_mouseInWindow
)
4014 // it would be wrong to assume that just because we get a mouse move
4015 // event that the mouse is inside the window: although this is usually
4016 // true, it is not if we had captured the mouse, so we need to check
4017 // the mouse coordinates here
4018 if ( !HasCapture() || IsMouseInWindow() )
4020 // Generate an ENTER event
4021 m_mouseInWindow
= TRUE
;
4023 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
4024 InitMouseEvent(event
, x
, y
, flags
);
4026 (void)GetEventHandler()->ProcessEvent(event
);
4030 #if wxUSE_MOUSEEVENT_HACK
4031 // Window gets a click down message followed by a mouse move message even
4032 // if position isn't changed! We want to discard the trailing move event
4033 // if x and y are the same.
4034 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
4035 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
4036 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
4037 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
4039 m_lastMouseEvent
= wxEVT_MOTION
;
4043 #endif // wxUSE_MOUSEEVENT_HACK
4045 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
4049 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
4051 #if wxUSE_MOUSEWHEEL
4052 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
4053 InitMouseEvent(event
,
4054 GET_X_LPARAM(lParam
),
4055 GET_Y_LPARAM(lParam
),
4057 event
.m_wheelRotation
= (short)HIWORD(wParam
);
4058 event
.m_wheelDelta
= WHEEL_DELTA
;
4061 static int s_linesPerRotation
= -1;
4062 if ( s_linesPerRotation
== -1 )
4064 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
4065 &s_linesPerRotation
, 0))
4067 // this is not supposed to happen
4068 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
4070 // the default is 3, so use it if SystemParametersInfo() failed
4071 s_linesPerRotation
= 3;
4075 // no SystemParametersInfo() under Win16
4076 static const int s_linesPerRotation
= 3;
4079 event
.m_linesPerAction
= s_linesPerRotation
;
4080 return GetEventHandler()->ProcessEvent(event
);
4091 // ---------------------------------------------------------------------------
4092 // keyboard handling
4093 // ---------------------------------------------------------------------------
4095 // create the key event of the given type for the given key - used by
4096 // HandleChar and HandleKeyDown/Up
4097 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
4100 WXWPARAM wParam
) const
4102 wxKeyEvent
event(evType
);
4103 event
.SetId(GetId());
4104 event
.m_shiftDown
= wxIsShiftDown();
4105 event
.m_controlDown
= wxIsCtrlDown();
4106 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
4108 event
.m_eventObject
= (wxWindow
*)this; // const_cast
4109 event
.m_keyCode
= id
;
4110 event
.m_rawCode
= (wxUint32
) wParam
;
4111 event
.m_rawFlags
= (wxUint32
) lParam
;
4112 event
.SetTimestamp(s_currentMsg
.time
);
4114 // translate the position to client coords
4118 GetWindowRect(GetHwnd(),&rect
);
4128 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
4130 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
4132 bool ctrlDown
= FALSE
;
4137 // If 1 -> 26, translate to CTRL plus a letter.
4139 if ( (id
> 0) && (id
< 27) )
4161 else // we're called from WM_KEYDOWN
4163 id
= wxCharCodeMSWToWX(wParam
);
4166 // it's ASCII and will be processed here only when called from
4167 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
4172 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
));
4175 event
.m_controlDown
= TRUE
;
4178 return GetEventHandler()->ProcessEvent(event
);
4181 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
4183 int id
= wxCharCodeMSWToWX(wParam
);
4187 // normal ASCII char
4191 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4193 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
));
4194 if ( GetEventHandler()->ProcessEvent(event
) )
4203 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
4205 int id
= wxCharCodeMSWToWX(wParam
);
4209 // normal ASCII char
4213 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4215 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
));
4216 if ( GetEventHandler()->ProcessEvent(event
) )
4223 // ---------------------------------------------------------------------------
4225 // ---------------------------------------------------------------------------
4227 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4231 if ( flags
& JOY_BUTTON1CHG
)
4232 change
= wxJOY_BUTTON1
;
4233 if ( flags
& JOY_BUTTON2CHG
)
4234 change
= wxJOY_BUTTON2
;
4235 if ( flags
& JOY_BUTTON3CHG
)
4236 change
= wxJOY_BUTTON3
;
4237 if ( flags
& JOY_BUTTON4CHG
)
4238 change
= wxJOY_BUTTON4
;
4241 if ( flags
& JOY_BUTTON1
)
4242 buttons
|= wxJOY_BUTTON1
;
4243 if ( flags
& JOY_BUTTON2
)
4244 buttons
|= wxJOY_BUTTON2
;
4245 if ( flags
& JOY_BUTTON3
)
4246 buttons
|= wxJOY_BUTTON3
;
4247 if ( flags
& JOY_BUTTON4
)
4248 buttons
|= wxJOY_BUTTON4
;
4250 // the event ids aren't consecutive so we can't use table based lookup
4252 wxEventType eventType
;
4257 eventType
= wxEVT_JOY_MOVE
;
4262 eventType
= wxEVT_JOY_MOVE
;
4267 eventType
= wxEVT_JOY_ZMOVE
;
4272 eventType
= wxEVT_JOY_ZMOVE
;
4275 case MM_JOY1BUTTONDOWN
:
4277 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4280 case MM_JOY2BUTTONDOWN
:
4282 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4285 case MM_JOY1BUTTONUP
:
4287 eventType
= wxEVT_JOY_BUTTON_UP
;
4290 case MM_JOY2BUTTONUP
:
4292 eventType
= wxEVT_JOY_BUTTON_UP
;
4296 wxFAIL_MSG(wxT("no such joystick event"));
4301 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4302 event
.SetPosition(wxPoint(x
, y
));
4303 event
.SetEventObject(this);
4305 return GetEventHandler()->ProcessEvent(event
);
4311 // ---------------------------------------------------------------------------
4313 // ---------------------------------------------------------------------------
4315 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4316 WXWORD pos
, WXHWND control
)
4320 wxWindow
*child
= wxFindWinFromHandle(control
);
4322 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4325 wxScrollWinEvent event
;
4326 event
.SetPosition(pos
);
4327 event
.SetOrientation(orientation
);
4328 event
.m_eventObject
= this;
4333 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4337 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4341 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4345 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4349 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4353 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4356 case SB_THUMBPOSITION
:
4359 // under Win32, the scrollbar range and position are 32 bit integers,
4360 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4361 // explicitly query the scrollbar for the correct position (this must
4362 // be done only for these two SB_ events as they are the only one
4363 // carrying the scrollbar position)
4365 SCROLLINFO scrollInfo
;
4366 wxZeroMemory(scrollInfo
);
4367 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
4368 scrollInfo
.fMask
= SIF_TRACKPOS
;
4370 if ( !::GetScrollInfo(GetHwnd(),
4371 orientation
== wxHORIZONTAL
? SB_HORZ
4375 wxLogLastError(_T("GetScrollInfo"));
4378 event
.SetPosition(scrollInfo
.nTrackPos
);
4382 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4383 ? wxEVT_SCROLLWIN_THUMBRELEASE
4384 : wxEVT_SCROLLWIN_THUMBTRACK
;
4391 return GetEventHandler()->ProcessEvent(event
);
4394 // ===========================================================================
4396 // ===========================================================================
4398 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4401 HDC dc
= ::GetDC((HWND
) wnd
);
4406 // the_font->UseResource();
4407 // the_font->RealizeResource();
4408 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4410 was
= (HFONT
) SelectObject(dc
,fnt
);
4412 GetTextMetrics(dc
, &tm
);
4413 if ( the_font
&& fnt
&& was
)
4415 SelectObject(dc
,was
);
4417 ReleaseDC((HWND
)wnd
, dc
);
4420 *x
= tm
.tmAveCharWidth
;
4422 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4425 // the_font->ReleaseResource();
4428 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4429 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4430 int wxCharCodeMSWToWX(int keySym
)
4435 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4436 case VK_BACK
: id
= WXK_BACK
; break;
4437 case VK_TAB
: id
= WXK_TAB
; break;
4438 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4439 case VK_RETURN
: id
= WXK_RETURN
; break;
4440 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4441 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4442 case VK_MENU
: id
= WXK_MENU
; break;
4443 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4444 case VK_CAPITAL
: id
= WXK_CAPITAL
; break;
4445 case VK_SPACE
: id
= WXK_SPACE
; break;
4446 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4447 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4448 case VK_NEXT
: id
= WXK_NEXT
; break;
4449 case VK_END
: id
= WXK_END
; break;
4450 case VK_HOME
: id
= WXK_HOME
; break;
4451 case VK_LEFT
: id
= WXK_LEFT
; break;
4452 case VK_UP
: id
= WXK_UP
; break;
4453 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4454 case VK_DOWN
: id
= WXK_DOWN
; break;
4455 case VK_SELECT
: id
= WXK_SELECT
; break;
4456 case VK_PRINT
: id
= WXK_PRINT
; break;
4457 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4458 case VK_INSERT
: id
= WXK_INSERT
; break;
4459 case VK_DELETE
: id
= WXK_DELETE
; break;
4460 case VK_HELP
: id
= WXK_HELP
; break;
4461 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4462 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4463 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4464 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4465 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4466 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4467 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4468 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4469 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4470 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4471 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4472 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4473 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4474 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4475 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4476 case VK_F1
: id
= WXK_F1
; break;
4477 case VK_F2
: id
= WXK_F2
; break;
4478 case VK_F3
: id
= WXK_F3
; break;
4479 case VK_F4
: id
= WXK_F4
; break;
4480 case VK_F5
: id
= WXK_F5
; break;
4481 case VK_F6
: id
= WXK_F6
; break;
4482 case VK_F7
: id
= WXK_F7
; break;
4483 case VK_F8
: id
= WXK_F8
; break;
4484 case VK_F9
: id
= WXK_F9
; break;
4485 case VK_F10
: id
= WXK_F10
; break;
4486 case VK_F11
: id
= WXK_F11
; break;
4487 case VK_F12
: id
= WXK_F12
; break;
4488 case VK_F13
: id
= WXK_F13
; break;
4489 case VK_F14
: id
= WXK_F14
; break;
4490 case VK_F15
: id
= WXK_F15
; break;
4491 case VK_F16
: id
= WXK_F16
; break;
4492 case VK_F17
: id
= WXK_F17
; break;
4493 case VK_F18
: id
= WXK_F18
; break;
4494 case VK_F19
: id
= WXK_F19
; break;
4495 case VK_F20
: id
= WXK_F20
; break;
4496 case VK_F21
: id
= WXK_F21
; break;
4497 case VK_F22
: id
= WXK_F22
; break;
4498 case VK_F23
: id
= WXK_F23
; break;
4499 case VK_F24
: id
= WXK_F24
; break;
4500 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4501 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4503 case VK_OEM_1
: id
= ';'; break;
4504 case VK_OEM_PLUS
: id
= '+'; break;
4505 case VK_OEM_COMMA
: id
= ','; break;
4506 case VK_OEM_MINUS
: id
= '-'; break;
4507 case VK_OEM_PERIOD
: id
= '.'; break;
4508 case VK_OEM_2
: id
= '/'; break;
4509 case VK_OEM_3
: id
= '~'; break;
4510 case VK_OEM_4
: id
= '['; break;
4511 case VK_OEM_5
: id
= '\\'; break;
4512 case VK_OEM_6
: id
= ']'; break;
4513 case VK_OEM_7
: id
= '\''; break;
4522 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4528 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4529 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4530 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4531 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4532 case WXK_MENU
: keySym
= VK_MENU
; break;
4533 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4534 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4535 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4536 case WXK_END
: keySym
= VK_END
; break;
4537 case WXK_HOME
: keySym
= VK_HOME
; break;
4538 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4539 case WXK_UP
: keySym
= VK_UP
; break;
4540 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4541 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4542 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4543 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4544 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4545 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4546 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4547 case WXK_HELP
: keySym
= VK_HELP
; break;
4548 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4549 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4550 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4551 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4552 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4553 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4554 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4555 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4556 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4557 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4558 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4559 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4560 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4561 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4562 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4563 case WXK_F1
: keySym
= VK_F1
; break;
4564 case WXK_F2
: keySym
= VK_F2
; break;
4565 case WXK_F3
: keySym
= VK_F3
; break;
4566 case WXK_F4
: keySym
= VK_F4
; break;
4567 case WXK_F5
: keySym
= VK_F5
; break;
4568 case WXK_F6
: keySym
= VK_F6
; break;
4569 case WXK_F7
: keySym
= VK_F7
; break;
4570 case WXK_F8
: keySym
= VK_F8
; break;
4571 case WXK_F9
: keySym
= VK_F9
; break;
4572 case WXK_F10
: keySym
= VK_F10
; break;
4573 case WXK_F11
: keySym
= VK_F11
; break;
4574 case WXK_F12
: keySym
= VK_F12
; break;
4575 case WXK_F13
: keySym
= VK_F13
; break;
4576 case WXK_F14
: keySym
= VK_F14
; break;
4577 case WXK_F15
: keySym
= VK_F15
; break;
4578 case WXK_F16
: keySym
= VK_F16
; break;
4579 case WXK_F17
: keySym
= VK_F17
; break;
4580 case WXK_F18
: keySym
= VK_F18
; break;
4581 case WXK_F19
: keySym
= VK_F19
; break;
4582 case WXK_F20
: keySym
= VK_F20
; break;
4583 case WXK_F21
: keySym
= VK_F21
; break;
4584 case WXK_F22
: keySym
= VK_F22
; break;
4585 case WXK_F23
: keySym
= VK_F23
; break;
4586 case WXK_F24
: keySym
= VK_F24
; break;
4587 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4588 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4599 wxWindow
*wxGetActiveWindow()
4601 HWND hWnd
= GetActiveWindow();
4604 return wxFindWinFromHandle((WXHWND
) hWnd
);
4609 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4611 HWND hwnd
= (HWND
)hWnd
;
4613 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4614 // by code in msw/radiobox.cpp), for all the others we just search up the
4616 wxWindow
*win
= (wxWindow
*)NULL
;
4619 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4622 // all these hacks only work under Win32 anyhow
4626 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4627 // wxWindow class which overrides WM_GETDLGCODE processing to
4628 // do it as well, win would be already non NULL
4629 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4631 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4633 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4634 #endif // wxUSE_RADIOBOX
4636 // spin control text buddy window should be mapped to spin ctrl
4637 // itself so try it too
4638 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4641 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4643 #endif // wxUSE_SPINCTRL
4649 while ( hwnd
&& !win
)
4651 // this is a really ugly hack needed to avoid mistakenly returning the
4652 // parent frame wxWindow for the find/replace modeless dialog HWND -
4653 // this, in turn, is needed to call IsDialogMessage() from
4654 // wxApp::ProcessMessage() as for this we must return NULL from here
4656 // FIXME: this is clearly not the best way to do it but I think we'll
4657 // need to change HWND <-> wxWindow code more heavily than I can
4658 // do it now to fix it
4659 #ifndef __WXMICROWIN__
4660 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4662 // it's a dialog box, don't go upwards
4667 hwnd
= ::GetParent(hwnd
);
4668 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4674 #ifndef __WXMICROWIN__
4676 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4677 // in active frames and dialogs, regardless of where the focus is.
4678 static HHOOK wxTheKeyboardHook
= 0;
4679 static FARPROC wxTheKeyboardHookProc
= 0;
4680 int APIENTRY _EXPORT
4681 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4683 void wxSetKeyboardHook(bool doIt
)
4687 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4688 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4690 #if defined(__WIN32__) && !defined(__TWIN32__)
4691 GetCurrentThreadId()
4692 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4700 UnhookWindowsHookEx(wxTheKeyboardHook
);
4702 // avoids warning about statement with no effect (FreeProcInstance
4703 // doesn't do anything under Win32)
4704 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
4705 FreeProcInstance(wxTheKeyboardHookProc
);
4710 int APIENTRY _EXPORT
4711 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4713 DWORD hiWord
= HIWORD(lParam
);
4714 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4716 int id
= wxCharCodeMSWToWX(wParam
);
4719 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4720 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4721 event
.m_altDown
= TRUE
;
4723 event
.m_eventObject
= NULL
;
4724 event
.m_keyCode
= id
;
4725 event
.m_shiftDown
= wxIsShiftDown();
4726 event
.m_controlDown
= wxIsCtrlDown();
4727 event
.SetTimestamp(s_currentMsg
.time
);
4729 wxWindow
*win
= wxGetActiveWindow();
4730 wxEvtHandler
*handler
;
4733 handler
= win
->GetEventHandler();
4734 event
.SetId(win
->GetId());
4742 if ( handler
&& handler
->ProcessEvent(event
) )
4750 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
4753 #endif // !__WXMICROWIN__
4756 const char *wxGetMessageName(int message
)
4760 case 0x0000: return "WM_NULL";
4761 case 0x0001: return "WM_CREATE";
4762 case 0x0002: return "WM_DESTROY";
4763 case 0x0003: return "WM_MOVE";
4764 case 0x0005: return "WM_SIZE";
4765 case 0x0006: return "WM_ACTIVATE";
4766 case 0x0007: return "WM_SETFOCUS";
4767 case 0x0008: return "WM_KILLFOCUS";
4768 case 0x000A: return "WM_ENABLE";
4769 case 0x000B: return "WM_SETREDRAW";
4770 case 0x000C: return "WM_SETTEXT";
4771 case 0x000D: return "WM_GETTEXT";
4772 case 0x000E: return "WM_GETTEXTLENGTH";
4773 case 0x000F: return "WM_PAINT";
4774 case 0x0010: return "WM_CLOSE";
4775 case 0x0011: return "WM_QUERYENDSESSION";
4776 case 0x0012: return "WM_QUIT";
4777 case 0x0013: return "WM_QUERYOPEN";
4778 case 0x0014: return "WM_ERASEBKGND";
4779 case 0x0015: return "WM_SYSCOLORCHANGE";
4780 case 0x0016: return "WM_ENDSESSION";
4781 case 0x0017: return "WM_SYSTEMERROR";
4782 case 0x0018: return "WM_SHOWWINDOW";
4783 case 0x0019: return "WM_CTLCOLOR";
4784 case 0x001A: return "WM_WININICHANGE";
4785 case 0x001B: return "WM_DEVMODECHANGE";
4786 case 0x001C: return "WM_ACTIVATEAPP";
4787 case 0x001D: return "WM_FONTCHANGE";
4788 case 0x001E: return "WM_TIMECHANGE";
4789 case 0x001F: return "WM_CANCELMODE";
4790 case 0x0020: return "WM_SETCURSOR";
4791 case 0x0021: return "WM_MOUSEACTIVATE";
4792 case 0x0022: return "WM_CHILDACTIVATE";
4793 case 0x0023: return "WM_QUEUESYNC";
4794 case 0x0024: return "WM_GETMINMAXINFO";
4795 case 0x0026: return "WM_PAINTICON";
4796 case 0x0027: return "WM_ICONERASEBKGND";
4797 case 0x0028: return "WM_NEXTDLGCTL";
4798 case 0x002A: return "WM_SPOOLERSTATUS";
4799 case 0x002B: return "WM_DRAWITEM";
4800 case 0x002C: return "WM_MEASUREITEM";
4801 case 0x002D: return "WM_DELETEITEM";
4802 case 0x002E: return "WM_VKEYTOITEM";
4803 case 0x002F: return "WM_CHARTOITEM";
4804 case 0x0030: return "WM_SETFONT";
4805 case 0x0031: return "WM_GETFONT";
4806 case 0x0037: return "WM_QUERYDRAGICON";
4807 case 0x0039: return "WM_COMPAREITEM";
4808 case 0x0041: return "WM_COMPACTING";
4809 case 0x0044: return "WM_COMMNOTIFY";
4810 case 0x0046: return "WM_WINDOWPOSCHANGING";
4811 case 0x0047: return "WM_WINDOWPOSCHANGED";
4812 case 0x0048: return "WM_POWER";
4815 case 0x004A: return "WM_COPYDATA";
4816 case 0x004B: return "WM_CANCELJOURNAL";
4817 case 0x004E: return "WM_NOTIFY";
4818 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
4819 case 0x0051: return "WM_INPUTLANGCHANGE";
4820 case 0x0052: return "WM_TCARD";
4821 case 0x0053: return "WM_HELP";
4822 case 0x0054: return "WM_USERCHANGED";
4823 case 0x0055: return "WM_NOTIFYFORMAT";
4824 case 0x007B: return "WM_CONTEXTMENU";
4825 case 0x007C: return "WM_STYLECHANGING";
4826 case 0x007D: return "WM_STYLECHANGED";
4827 case 0x007E: return "WM_DISPLAYCHANGE";
4828 case 0x007F: return "WM_GETICON";
4829 case 0x0080: return "WM_SETICON";
4832 case 0x0081: return "WM_NCCREATE";
4833 case 0x0082: return "WM_NCDESTROY";
4834 case 0x0083: return "WM_NCCALCSIZE";
4835 case 0x0084: return "WM_NCHITTEST";
4836 case 0x0085: return "WM_NCPAINT";
4837 case 0x0086: return "WM_NCACTIVATE";
4838 case 0x0087: return "WM_GETDLGCODE";
4839 case 0x00A0: return "WM_NCMOUSEMOVE";
4840 case 0x00A1: return "WM_NCLBUTTONDOWN";
4841 case 0x00A2: return "WM_NCLBUTTONUP";
4842 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
4843 case 0x00A4: return "WM_NCRBUTTONDOWN";
4844 case 0x00A5: return "WM_NCRBUTTONUP";
4845 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
4846 case 0x00A7: return "WM_NCMBUTTONDOWN";
4847 case 0x00A8: return "WM_NCMBUTTONUP";
4848 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
4849 case 0x0100: return "WM_KEYDOWN";
4850 case 0x0101: return "WM_KEYUP";
4851 case 0x0102: return "WM_CHAR";
4852 case 0x0103: return "WM_DEADCHAR";
4853 case 0x0104: return "WM_SYSKEYDOWN";
4854 case 0x0105: return "WM_SYSKEYUP";
4855 case 0x0106: return "WM_SYSCHAR";
4856 case 0x0107: return "WM_SYSDEADCHAR";
4857 case 0x0108: return "WM_KEYLAST";
4860 case 0x010D: return "WM_IME_STARTCOMPOSITION";
4861 case 0x010E: return "WM_IME_ENDCOMPOSITION";
4862 case 0x010F: return "WM_IME_COMPOSITION";
4865 case 0x0110: return "WM_INITDIALOG";
4866 case 0x0111: return "WM_COMMAND";
4867 case 0x0112: return "WM_SYSCOMMAND";
4868 case 0x0113: return "WM_TIMER";
4869 case 0x0114: return "WM_HSCROLL";
4870 case 0x0115: return "WM_VSCROLL";
4871 case 0x0116: return "WM_INITMENU";
4872 case 0x0117: return "WM_INITMENUPOPUP";
4873 case 0x011F: return "WM_MENUSELECT";
4874 case 0x0120: return "WM_MENUCHAR";
4875 case 0x0121: return "WM_ENTERIDLE";
4876 case 0x0200: return "WM_MOUSEMOVE";
4877 case 0x0201: return "WM_LBUTTONDOWN";
4878 case 0x0202: return "WM_LBUTTONUP";
4879 case 0x0203: return "WM_LBUTTONDBLCLK";
4880 case 0x0204: return "WM_RBUTTONDOWN";
4881 case 0x0205: return "WM_RBUTTONUP";
4882 case 0x0206: return "WM_RBUTTONDBLCLK";
4883 case 0x0207: return "WM_MBUTTONDOWN";
4884 case 0x0208: return "WM_MBUTTONUP";
4885 case 0x0209: return "WM_MBUTTONDBLCLK";
4886 case 0x020A: return "WM_MOUSEWHEEL";
4887 case 0x0210: return "WM_PARENTNOTIFY";
4888 case 0x0211: return "WM_ENTERMENULOOP";
4889 case 0x0212: return "WM_EXITMENULOOP";
4892 case 0x0213: return "WM_NEXTMENU";
4893 case 0x0214: return "WM_SIZING";
4894 case 0x0215: return "WM_CAPTURECHANGED";
4895 case 0x0216: return "WM_MOVING";
4896 case 0x0218: return "WM_POWERBROADCAST";
4897 case 0x0219: return "WM_DEVICECHANGE";
4900 case 0x0220: return "WM_MDICREATE";
4901 case 0x0221: return "WM_MDIDESTROY";
4902 case 0x0222: return "WM_MDIACTIVATE";
4903 case 0x0223: return "WM_MDIRESTORE";
4904 case 0x0224: return "WM_MDINEXT";
4905 case 0x0225: return "WM_MDIMAXIMIZE";
4906 case 0x0226: return "WM_MDITILE";
4907 case 0x0227: return "WM_MDICASCADE";
4908 case 0x0228: return "WM_MDIICONARRANGE";
4909 case 0x0229: return "WM_MDIGETACTIVE";
4910 case 0x0230: return "WM_MDISETMENU";
4911 case 0x0233: return "WM_DROPFILES";
4914 case 0x0281: return "WM_IME_SETCONTEXT";
4915 case 0x0282: return "WM_IME_NOTIFY";
4916 case 0x0283: return "WM_IME_CONTROL";
4917 case 0x0284: return "WM_IME_COMPOSITIONFULL";
4918 case 0x0285: return "WM_IME_SELECT";
4919 case 0x0286: return "WM_IME_CHAR";
4920 case 0x0290: return "WM_IME_KEYDOWN";
4921 case 0x0291: return "WM_IME_KEYUP";
4924 case 0x0300: return "WM_CUT";
4925 case 0x0301: return "WM_COPY";
4926 case 0x0302: return "WM_PASTE";
4927 case 0x0303: return "WM_CLEAR";
4928 case 0x0304: return "WM_UNDO";
4929 case 0x0305: return "WM_RENDERFORMAT";
4930 case 0x0306: return "WM_RENDERALLFORMATS";
4931 case 0x0307: return "WM_DESTROYCLIPBOARD";
4932 case 0x0308: return "WM_DRAWCLIPBOARD";
4933 case 0x0309: return "WM_PAINTCLIPBOARD";
4934 case 0x030A: return "WM_VSCROLLCLIPBOARD";
4935 case 0x030B: return "WM_SIZECLIPBOARD";
4936 case 0x030C: return "WM_ASKCBFORMATNAME";
4937 case 0x030D: return "WM_CHANGECBCHAIN";
4938 case 0x030E: return "WM_HSCROLLCLIPBOARD";
4939 case 0x030F: return "WM_QUERYNEWPALETTE";
4940 case 0x0310: return "WM_PALETTEISCHANGING";
4941 case 0x0311: return "WM_PALETTECHANGED";
4944 // common controls messages - although they're not strictly speaking
4945 // standard, it's nice to decode them nevertheless
4948 case 0x1000 + 0: return "LVM_GETBKCOLOR";
4949 case 0x1000 + 1: return "LVM_SETBKCOLOR";
4950 case 0x1000 + 2: return "LVM_GETIMAGELIST";
4951 case 0x1000 + 3: return "LVM_SETIMAGELIST";
4952 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
4953 case 0x1000 + 5: return "LVM_GETITEMA";
4954 case 0x1000 + 75: return "LVM_GETITEMW";
4955 case 0x1000 + 6: return "LVM_SETITEMA";
4956 case 0x1000 + 76: return "LVM_SETITEMW";
4957 case 0x1000 + 7: return "LVM_INSERTITEMA";
4958 case 0x1000 + 77: return "LVM_INSERTITEMW";
4959 case 0x1000 + 8: return "LVM_DELETEITEM";
4960 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
4961 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
4962 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
4963 case 0x1000 + 12: return "LVM_GETNEXTITEM";
4964 case 0x1000 + 13: return "LVM_FINDITEMA";
4965 case 0x1000 + 83: return "LVM_FINDITEMW";
4966 case 0x1000 + 14: return "LVM_GETITEMRECT";
4967 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
4968 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
4969 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
4970 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
4971 case 0x1000 + 18: return "LVM_HITTEST";
4972 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
4973 case 0x1000 + 20: return "LVM_SCROLL";
4974 case 0x1000 + 21: return "LVM_REDRAWITEMS";
4975 case 0x1000 + 22: return "LVM_ARRANGE";
4976 case 0x1000 + 23: return "LVM_EDITLABELA";
4977 case 0x1000 + 118: return "LVM_EDITLABELW";
4978 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
4979 case 0x1000 + 25: return "LVM_GETCOLUMNA";
4980 case 0x1000 + 95: return "LVM_GETCOLUMNW";
4981 case 0x1000 + 26: return "LVM_SETCOLUMNA";
4982 case 0x1000 + 96: return "LVM_SETCOLUMNW";
4983 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
4984 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
4985 case 0x1000 + 28: return "LVM_DELETECOLUMN";
4986 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
4987 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
4988 case 0x1000 + 31: return "LVM_GETHEADER";
4989 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
4990 case 0x1000 + 34: return "LVM_GETVIEWRECT";
4991 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
4992 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
4993 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
4994 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
4995 case 0x1000 + 39: return "LVM_GETTOPINDEX";
4996 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
4997 case 0x1000 + 41: return "LVM_GETORIGIN";
4998 case 0x1000 + 42: return "LVM_UPDATE";
4999 case 0x1000 + 43: return "LVM_SETITEMSTATE";
5000 case 0x1000 + 44: return "LVM_GETITEMSTATE";
5001 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
5002 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
5003 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
5004 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
5005 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
5006 case 0x1000 + 48: return "LVM_SORTITEMS";
5007 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
5008 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
5009 case 0x1000 + 51: return "LVM_GETITEMSPACING";
5010 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
5011 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
5012 case 0x1000 + 53: return "LVM_SETICONSPACING";
5013 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
5014 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
5015 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
5016 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
5017 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
5018 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
5019 case 0x1000 + 60: return "LVM_SETHOTITEM";
5020 case 0x1000 + 61: return "LVM_GETHOTITEM";
5021 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
5022 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
5023 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
5024 case 0x1000 + 65: return "LVM_SETWORKAREA";
5027 case 0x1100 + 0: return "TVM_INSERTITEMA";
5028 case 0x1100 + 50: return "TVM_INSERTITEMW";
5029 case 0x1100 + 1: return "TVM_DELETEITEM";
5030 case 0x1100 + 2: return "TVM_EXPAND";
5031 case 0x1100 + 4: return "TVM_GETITEMRECT";
5032 case 0x1100 + 5: return "TVM_GETCOUNT";
5033 case 0x1100 + 6: return "TVM_GETINDENT";
5034 case 0x1100 + 7: return "TVM_SETINDENT";
5035 case 0x1100 + 8: return "TVM_GETIMAGELIST";
5036 case 0x1100 + 9: return "TVM_SETIMAGELIST";
5037 case 0x1100 + 10: return "TVM_GETNEXTITEM";
5038 case 0x1100 + 11: return "TVM_SELECTITEM";
5039 case 0x1100 + 12: return "TVM_GETITEMA";
5040 case 0x1100 + 62: return "TVM_GETITEMW";
5041 case 0x1100 + 13: return "TVM_SETITEMA";
5042 case 0x1100 + 63: return "TVM_SETITEMW";
5043 case 0x1100 + 14: return "TVM_EDITLABELA";
5044 case 0x1100 + 65: return "TVM_EDITLABELW";
5045 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
5046 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
5047 case 0x1100 + 17: return "TVM_HITTEST";
5048 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
5049 case 0x1100 + 19: return "TVM_SORTCHILDREN";
5050 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
5051 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
5052 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
5053 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
5054 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
5055 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
5056 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
5059 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
5060 case 0x1200 + 1: return "HDM_INSERTITEMA";
5061 case 0x1200 + 10: return "HDM_INSERTITEMW";
5062 case 0x1200 + 2: return "HDM_DELETEITEM";
5063 case 0x1200 + 3: return "HDM_GETITEMA";
5064 case 0x1200 + 11: return "HDM_GETITEMW";
5065 case 0x1200 + 4: return "HDM_SETITEMA";
5066 case 0x1200 + 12: return "HDM_SETITEMW";
5067 case 0x1200 + 5: return "HDM_LAYOUT";
5068 case 0x1200 + 6: return "HDM_HITTEST";
5069 case 0x1200 + 7: return "HDM_GETITEMRECT";
5070 case 0x1200 + 8: return "HDM_SETIMAGELIST";
5071 case 0x1200 + 9: return "HDM_GETIMAGELIST";
5072 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
5073 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
5074 case 0x1200 + 17: return "HDM_GETORDERARRAY";
5075 case 0x1200 + 18: return "HDM_SETORDERARRAY";
5076 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
5079 case 0x1300 + 2: return "TCM_GETIMAGELIST";
5080 case 0x1300 + 3: return "TCM_SETIMAGELIST";
5081 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
5082 case 0x1300 + 5: return "TCM_GETITEMA";
5083 case 0x1300 + 60: return "TCM_GETITEMW";
5084 case 0x1300 + 6: return "TCM_SETITEMA";
5085 case 0x1300 + 61: return "TCM_SETITEMW";
5086 case 0x1300 + 7: return "TCM_INSERTITEMA";
5087 case 0x1300 + 62: return "TCM_INSERTITEMW";
5088 case 0x1300 + 8: return "TCM_DELETEITEM";
5089 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
5090 case 0x1300 + 10: return "TCM_GETITEMRECT";
5091 case 0x1300 + 11: return "TCM_GETCURSEL";
5092 case 0x1300 + 12: return "TCM_SETCURSEL";
5093 case 0x1300 + 13: return "TCM_HITTEST";
5094 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
5095 case 0x1300 + 40: return "TCM_ADJUSTRECT";
5096 case 0x1300 + 41: return "TCM_SETITEMSIZE";
5097 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
5098 case 0x1300 + 43: return "TCM_SETPADDING";
5099 case 0x1300 + 44: return "TCM_GETROWCOUNT";
5100 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
5101 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
5102 case 0x1300 + 47: return "TCM_GETCURFOCUS";
5103 case 0x1300 + 48: return "TCM_SETCURFOCUS";
5104 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
5105 case 0x1300 + 50: return "TCM_DESELECTALL";
5108 case WM_USER
+1: return "TB_ENABLEBUTTON";
5109 case WM_USER
+2: return "TB_CHECKBUTTON";
5110 case WM_USER
+3: return "TB_PRESSBUTTON";
5111 case WM_USER
+4: return "TB_HIDEBUTTON";
5112 case WM_USER
+5: return "TB_INDETERMINATE";
5113 case WM_USER
+9: return "TB_ISBUTTONENABLED";
5114 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
5115 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
5116 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
5117 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
5118 case WM_USER
+17: return "TB_SETSTATE";
5119 case WM_USER
+18: return "TB_GETSTATE";
5120 case WM_USER
+19: return "TB_ADDBITMAP";
5121 case WM_USER
+20: return "TB_ADDBUTTONS";
5122 case WM_USER
+21: return "TB_INSERTBUTTON";
5123 case WM_USER
+22: return "TB_DELETEBUTTON";
5124 case WM_USER
+23: return "TB_GETBUTTON";
5125 case WM_USER
+24: return "TB_BUTTONCOUNT";
5126 case WM_USER
+25: return "TB_COMMANDTOINDEX";
5127 case WM_USER
+26: return "TB_SAVERESTOREA";
5128 case WM_USER
+76: return "TB_SAVERESTOREW";
5129 case WM_USER
+27: return "TB_CUSTOMIZE";
5130 case WM_USER
+28: return "TB_ADDSTRINGA";
5131 case WM_USER
+77: return "TB_ADDSTRINGW";
5132 case WM_USER
+29: return "TB_GETITEMRECT";
5133 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
5134 case WM_USER
+31: return "TB_SETBUTTONSIZE";
5135 case WM_USER
+32: return "TB_SETBITMAPSIZE";
5136 case WM_USER
+33: return "TB_AUTOSIZE";
5137 case WM_USER
+35: return "TB_GETTOOLTIPS";
5138 case WM_USER
+36: return "TB_SETTOOLTIPS";
5139 case WM_USER
+37: return "TB_SETPARENT";
5140 case WM_USER
+39: return "TB_SETROWS";
5141 case WM_USER
+40: return "TB_GETROWS";
5142 case WM_USER
+42: return "TB_SETCMDID";
5143 case WM_USER
+43: return "TB_CHANGEBITMAP";
5144 case WM_USER
+44: return "TB_GETBITMAP";
5145 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
5146 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
5147 case WM_USER
+46: return "TB_REPLACEBITMAP";
5148 case WM_USER
+47: return "TB_SETINDENT";
5149 case WM_USER
+48: return "TB_SETIMAGELIST";
5150 case WM_USER
+49: return "TB_GETIMAGELIST";
5151 case WM_USER
+50: return "TB_LOADIMAGES";
5152 case WM_USER
+51: return "TB_GETRECT";
5153 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
5154 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
5155 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
5156 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
5157 case WM_USER
+56: return "TB_SETSTYLE";
5158 case WM_USER
+57: return "TB_GETSTYLE";
5159 case WM_USER
+58: return "TB_GETBUTTONSIZE";
5160 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
5161 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
5162 case WM_USER
+61: return "TB_GETTEXTROWS";
5163 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
5168 static char s_szBuf
[128];
5169 sprintf(s_szBuf
, "<unknown message = %d>", message
);
5173 #endif //__WXDEBUG__
5175 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
5176 int *x
, int *y
, WPARAM
*flags
)
5178 // construct the key mask
5179 WPARAM
& fwKeys
= *flags
;
5181 fwKeys
= MK_RBUTTON
;
5182 if ( wxIsCtrlDown() )
5183 fwKeys
|= MK_CONTROL
;
5184 if ( wxIsShiftDown() )
5187 // simulate right mouse button click
5188 DWORD dwPos
= ::GetMessagePos();
5189 *x
= GET_X_LPARAM(dwPos
);
5190 *y
= GET_Y_LPARAM(dwPos
);
5192 win
->ScreenToClient(x
, y
);
5195 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
5199 HWND hwnd
= GetHwndOf(win
);
5200 HDC hdc
= ::GetDC(hwnd
);
5202 #if !wxDIALOG_UNIT_COMPATIBILITY
5203 // and select the current font into it
5204 HFONT hfont
= GetHfontOf(win
->GetFont());
5207 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
5211 // finally retrieve the text metrics from it
5212 GetTextMetrics(hdc
, &tm
);
5214 #if !wxDIALOG_UNIT_COMPATIBILITY
5218 (void)::SelectObject(hdc
, hfont
);
5222 ::ReleaseDC(hwnd
, hdc
);
5227 // Find the wxWindow at the current mouse position, returning the mouse
5229 wxWindow
* wxFindWindowAtPointer(wxPoint
& WXUNUSED(pt
))
5231 return wxFindWindowAtPoint(wxGetMousePosition());
5234 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
5239 HWND hWndHit
= ::WindowFromPoint(pt2
);
5241 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
5242 HWND hWnd
= hWndHit
;
5244 // Try to find a window with a wxWindow associated with it
5245 while (!win
&& (hWnd
!= 0))
5247 hWnd
= ::GetParent(hWnd
);
5248 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
5253 // Get the current mouse position.
5254 wxPoint
wxGetMousePosition()
5257 GetCursorPos( & pt
);
5259 return wxPoint(pt
.x
, pt
.y
);