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
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "window.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
32 #include "wx/msw/wrapwin.h"
33 #include "wx/window.h"
38 #include "wx/dcclient.h"
39 #include "wx/dcmemory.h"
42 #include "wx/layout.h"
43 #include "wx/dialog.h"
45 #include "wx/listbox.h"
46 #include "wx/button.h"
47 #include "wx/msgdlg.h"
48 #include "wx/settings.h"
49 #include "wx/statbox.h"
52 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
53 #include "wx/ownerdrw.h"
56 #if wxUSE_DRAG_AND_DROP
60 #if wxUSE_ACCESSIBILITY
61 #include "wx/access.h"
65 #define WM_GETOBJECT 0x003D
68 #define OBJID_CLIENT 0xFFFFFFFC
72 #include "wx/menuitem.h"
75 #include "wx/msw/private.h"
78 #include "wx/tooltip.h"
86 #include "wx/spinctrl.h"
87 #endif // wxUSE_SPINCTRL
92 #include "wx/textctrl.h"
93 #include "wx/notebook.h"
97 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__)
103 #include <windowsx.h>
106 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__)
108 #include <commctrl.h>
110 #elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler
111 #include "wx/msw/gnuwin32/extra.h"
114 #if defined(__GNUG__)
115 #include "wx/msw/missing.h"
118 #if defined(__WXWINCE__)
119 #include "wx/msw/wince/missing.h"
122 // ----------------------------------------------------------------------------
123 // standard constants not available with all compilers/headers
124 // ----------------------------------------------------------------------------
126 // This didn't appear in mingw until 2.95.2
128 #define SIF_TRACKPOS 16
132 #ifndef WM_MOUSEWHEEL
133 #define WM_MOUSEWHEEL 0x020A
136 #define WHEEL_DELTA 120
138 #ifndef SPI_GETWHEELSCROLLLINES
139 #define SPI_GETWHEELSCROLLLINES 104
141 #endif // wxUSE_MOUSEWHEEL
144 #define VK_OEM_1 0xBA
145 #define VK_OEM_2 0xBF
146 #define VK_OEM_3 0xC0
147 #define VK_OEM_4 0xDB
148 #define VK_OEM_5 0xDC
149 #define VK_OEM_6 0xDD
150 #define VK_OEM_7 0xDE
154 #define VK_OEM_PLUS 0xBB
155 #define VK_OEM_COMMA 0xBC
156 #define VK_OEM_MINUS 0xBD
157 #define VK_OEM_PERIOD 0xBE
160 // ---------------------------------------------------------------------------
162 // ---------------------------------------------------------------------------
164 // the last Windows message we got (FIXME-MT)
165 extern MSG s_currentMsg
;
167 #if wxUSE_MENUS_NATIVE
168 wxMenu
*wxCurrentPopupMenu
= NULL
;
169 #endif // wxUSE_MENUS_NATIVE
171 extern const wxChar
*wxCanvasClassName
;
173 // true if we had already created the std colour map, used by
174 // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
175 static bool gs_hasStdCmap
= FALSE
;
177 // ---------------------------------------------------------------------------
179 // ---------------------------------------------------------------------------
181 // the window proc for all our windows
182 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
183 WPARAM wParam
, LPARAM lParam
);
187 const char *wxGetMessageName(int message
);
190 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
191 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
192 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
194 // this magical function is used to translate VK_APPS key presses to right
196 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
197 int *x
, int *y
, WPARAM
*flags
);
199 // get the text metrics for the current font
200 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
202 // find the window for the mouse event at the specified position
203 static wxWindowMSW
*FindWindowForMouseEvent(wxWindowMSW
*win
, int *x
, int *y
); //TW:REQ:Univ
205 // wrapper around BringWindowToTop() API
206 static inline void wxBringWindowToTop(HWND hwnd
)
208 #ifdef __WXMICROWIN__
209 // It seems that MicroWindows brings the _parent_ of the window to the top,
210 // which can be the wrong one.
212 // activate (set focus to) specified window
216 // raise top level parent to top of z order
217 if (!::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
))
219 wxLogLastError(_T("SetWindowPos"));
223 // ---------------------------------------------------------------------------
225 // ---------------------------------------------------------------------------
227 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
229 #ifdef __WXUNIVERSAL__
230 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
232 #if wxUSE_EXTENDED_RTTI
233 IMPLEMENT_DYNAMIC_CLASS_XTI(wxWindow
, wxWindowBase
,"wx/window.h")
235 WX_BEGIN_PROPERTIES_TABLE(wxWindow
)
236 // Always constructor Properties first
238 WX_READONLY_PROPERTY( Parent
,wxWindow
*, GetParent
, )
239 WX_PROPERTY( Id
,wxWindowID
, SetId
, GetId
, -1 )
240 WX_PROPERTY_SET_BY_REF( Position
,wxPoint
, SetPosition
, GetPosition
, wxPoint(-1,-1) ) // pos
241 WX_PROPERTY_SET_BY_REF( Size
,wxSize
, SetSize
, GetSize
, wxSize(-1,-1) ) // size
242 WX_PROPERTY( WindowStyle
, long , SetWindowStyle
, GetWindowStyle
, ) // style
244 // Then all relations of the object graph
246 WX_READONLY_PROPERTY_COLLECTION( Children
, wxWindowList
, wxWindowBase
* , GetChildren
)
248 // and finally all other properties
250 WX_PROPERTY( ExtraStyle
, long , SetExtraStyle
, GetExtraStyle
, ) // extstyle
251 WX_PROPERTY_SET_BY_REF_RET_BOOL( BackgroundColour
, wxColour
, SetBackgroundColour
, GetBackgroundColour
, ) // bg
252 WX_PROPERTY_SET_BY_REF_RET_BOOL( ForegroundColour
, wxColour
, SetForegroundColour
, GetForegroundColour
, ) // fg
253 WX_PROPERTY_SET_RET_BOOL( Enabled
, bool , Enable
, IsEnabled
, wxxVariant((bool)true) )
254 WX_PROPERTY_SET_RET_BOOL( Shown
, bool , Show
, IsShown
, wxxVariant((bool)true) )
256 // possible property candidates (not in xrc) or not valid in all subclasses
257 WX_PROPERTY_SET_BY_REF( Title
,wxString
, SetTitle
, GetTitle
, wxT("") )
258 WX_PROPERTY_SET_AND_GET_BY_REF_RET_BOOL( Font
, wxFont
, SetFont
, GetFont
, )
259 WX_PROPERTY_SET_BY_REF( Label
,wxString
, SetLabel
, GetLabel
, wxT("") )
260 // MaxHeight, Width , MinHeight , Width
261 // TODO switch label to control and title to toplevels
263 WX_PROPERTY( ThemeEnabled
, bool , SetThemeEnabled
, GetThemeEnabled
, )
264 //WX_PROPERTY_SET_BY_REF( Cursor , wxCursor , SetCursor , GetCursor , )
265 // WX_PROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , )
266 WX_PROPERTY( AutoLayout
, bool , SetAutoLayout
, GetAutoLayout
, )
268 WX_END_PROPERTIES_TABLE()
270 WX_BEGIN_HANDLERS_TABLE(wxWindow
)
271 WX_END_HANDLERS_TABLE()
273 WX_CONSTRUCTOR_DUMMY(wxWindow
)
275 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
277 #endif // __WXUNIVERSAL__/__WXMSW__
279 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
280 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
281 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
282 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
285 // ===========================================================================
287 // ===========================================================================
289 // ---------------------------------------------------------------------------
290 // wxWindow utility functions
291 // ---------------------------------------------------------------------------
293 // Find an item given the MS Windows id
294 wxWindow
*wxWindowMSW::FindItem(long id
) const
297 wxControl
*item
= wxDynamicCastThis(wxControl
);
300 // is it we or one of our "internal" children?
301 if ( item
->GetId() == id
302 #ifndef __WXUNIVERSAL__
303 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
304 #endif // __WXUNIVERSAL__
310 #endif // wxUSE_CONTROLS
312 wxWindowList::compatibility_iterator current
= GetChildren().GetFirst();
315 wxWindow
*childWin
= current
->GetData();
317 wxWindow
*wnd
= childWin
->FindItem(id
);
321 current
= current
->GetNext();
327 // Find an item given the MS Windows handle
328 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
330 wxWindowList::compatibility_iterator current
= GetChildren().GetFirst();
333 wxWindow
*parent
= current
->GetData();
335 // Do a recursive search.
336 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
342 || parent
->IsKindOf(CLASSINFO(wxControl
))
343 #endif // wxUSE_CONTROLS
346 wxWindow
*item
= current
->GetData();
347 if ( item
->GetHWND() == hWnd
)
351 if ( item
->ContainsHWND(hWnd
) )
356 current
= current
->GetNext();
361 // Default command handler
362 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
367 // ----------------------------------------------------------------------------
368 // constructors and such
369 // ----------------------------------------------------------------------------
371 void wxWindowMSW::Init()
377 m_isBeingDeleted
= FALSE
;
379 m_mouseInWindow
= FALSE
;
380 m_lastKeydownProcessed
= FALSE
;
382 m_childrenDisabled
= NULL
;
392 // as all windows are created with WS_VISIBLE style...
395 #if wxUSE_MOUSEEVENT_HACK
398 m_lastMouseEvent
= -1;
399 #endif // wxUSE_MOUSEEVENT_HACK
403 wxWindowMSW::~wxWindowMSW()
405 m_isBeingDeleted
= TRUE
;
407 #ifndef __WXUNIVERSAL__
408 // VS: make sure there's no wxFrame with last focus set to us:
409 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
411 wxTopLevelWindow
*frame
= wxDynamicCast(win
, wxTopLevelWindow
);
414 if ( frame
->GetLastFocus() == this )
416 frame
->SetLastFocus(NULL
);
421 #endif // __WXUNIVERSAL__
423 // VS: destroy children first and _then_ detach *this from its parent.
424 // If we'd do it the other way around, children wouldn't be able
425 // find their parent frame (see above).
429 m_parent
->RemoveChild(this);
433 // VZ: test temp removed to understand what really happens here
434 //if (::IsWindow(GetHwnd()))
436 if ( !::DestroyWindow(GetHwnd()) )
437 wxLogLastError(wxT("DestroyWindow"));
440 // remove hWnd <-> wxWindow association
441 wxRemoveHandleAssociation(this);
444 delete m_childrenDisabled
;
447 // real construction (Init() must have been called before!)
448 bool wxWindowMSW::Create(wxWindow
*parent
,
453 const wxString
& name
)
455 wxCHECK_MSG( parent
, FALSE
, wxT("can't create wxWindow without parent") );
457 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
460 parent
->AddChild(this);
463 DWORD msflags
= MSWGetCreateWindowFlags(&exstyle
);
465 #ifdef __WXUNIVERSAL__
466 // no borders, we draw them ourselves
467 exstyle
&= ~(WS_EX_DLGMODALFRAME
|
471 msflags
&= ~WS_BORDER
;
472 #endif // wxUniversal
474 // all windows are created visible by default except popup ones (which are
475 // like the wxTopLevelWindows in this aspect)
476 if ( style
& wxPOPUP_WINDOW
)
478 msflags
&= ~WS_VISIBLE
;
483 msflags
|= WS_VISIBLE
;
486 return MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
);
489 // ---------------------------------------------------------------------------
491 // ---------------------------------------------------------------------------
493 void wxWindowMSW::SetFocus()
495 HWND hWnd
= GetHwnd();
496 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
498 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
502 if ( !::SetFocus(hWnd
) )
504 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
505 // was there really an error?
506 DWORD dwRes
= ::GetLastError();
509 HWND hwndFocus
= ::GetFocus();
510 if ( hwndFocus
!= hWnd
)
512 wxLogApiError(_T("SetFocus"), dwRes
);
519 void wxWindowMSW::SetFocusFromKbd()
521 // when the focus is given to the control with DLGC_HASSETSEL style from
522 // keyboard its contents should be entirely selected: this is what
523 // ::IsDialogMessage() does and so we should do it as well to provide the
524 // same LNF as the native programs
525 if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL
)
527 ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1);
530 // do this after (maybe) setting the selection as like this when
531 // wxEVT_SET_FOCUS handler is called, the selection would have been already
532 // set correctly -- this may be important
533 wxWindowBase::SetFocusFromKbd();
536 // Get the window with the focus
537 wxWindow
*wxWindowBase::FindFocus()
539 HWND hWnd
= ::GetFocus();
542 return wxGetWindowFromHWND((WXHWND
)hWnd
);
548 bool wxWindowMSW::Enable(bool enable
)
550 if ( !wxWindowBase::Enable(enable
) )
553 HWND hWnd
= GetHwnd();
555 ::EnableWindow(hWnd
, (BOOL
)enable
);
557 // the logic below doesn't apply to the top level windows -- otherwise
558 // showing a modal dialog would result in total greying out (and ungreying
559 // out later) of everything which would be really ugly
563 // when the parent is disabled, all of its children should be disabled as
564 // well but when it is enabled back, only those of the children which
565 // hadn't been already disabled in the beginning should be enabled again,
566 // so we have to keep the list of those children
567 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
569 node
= node
->GetNext() )
571 wxWindow
*child
= node
->GetData();
572 if ( child
->IsTopLevel() )
574 // the logic below doesn't apply to top level children
580 // enable the child back unless it had been disabled before us
581 if ( !m_childrenDisabled
|| !m_childrenDisabled
->Find(child
) )
584 else // we're being disabled
586 if ( child
->IsEnabled() )
588 // disable it as children shouldn't stay enabled while the
592 else // child already disabled, remember it
594 // have we created the list of disabled children already?
595 if ( !m_childrenDisabled
)
596 m_childrenDisabled
= new wxWindowList
;
598 m_childrenDisabled
->Append(child
);
603 if ( enable
&& m_childrenDisabled
)
605 // we don't need this list any more, don't keep unused memory
606 delete m_childrenDisabled
;
607 m_childrenDisabled
= NULL
;
613 bool wxWindowMSW::Show(bool show
)
615 if ( !wxWindowBase::Show(show
) )
618 HWND hWnd
= GetHwnd();
619 int cshow
= show
? SW_SHOW
: SW_HIDE
;
620 ::ShowWindow(hWnd
, cshow
);
622 if ( show
&& IsTopLevel() )
624 wxBringWindowToTop(hWnd
);
630 // Raise the window to the top of the Z order
631 void wxWindowMSW::Raise()
633 wxBringWindowToTop(GetHwnd());
636 // Lower the window to the bottom of the Z order
637 void wxWindowMSW::Lower()
639 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
640 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
643 void wxWindowMSW::SetTitle( const wxString
& title
)
645 SetWindowText(GetHwnd(), title
.c_str());
648 wxString
wxWindowMSW::GetTitle() const
650 return wxGetWindowText(GetHWND());
653 void wxWindowMSW::DoCaptureMouse()
655 HWND hWnd
= GetHwnd();
662 void wxWindowMSW::DoReleaseMouse()
664 if ( !::ReleaseCapture() )
666 wxLogLastError(_T("ReleaseCapture"));
670 /* static */ wxWindow
*wxWindowBase::GetCapture()
672 HWND hwnd
= ::GetCapture();
673 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
676 bool wxWindowMSW::SetFont(const wxFont
& font
)
678 if ( !wxWindowBase::SetFont(font
) )
684 HWND hWnd
= GetHwnd();
687 WXHANDLE hFont
= m_font
.GetResourceHandle();
689 wxASSERT_MSG( hFont
, wxT("should have valid font") );
691 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
696 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
698 if ( !wxWindowBase::SetCursor(cursor
) )
706 HWND hWnd
= GetHwnd();
708 // Change the cursor NOW if we're within the correct window
710 ::GetCursorPos(&point
);
712 RECT rect
= wxGetWindowRect(hWnd
);
714 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
715 ::SetCursor(GetHcursorOf(m_cursor
));
721 void wxWindowMSW::WarpPointer (int x
, int y
)
723 ClientToScreen(&x
, &y
);
725 if ( !::SetCursorPos(x
, y
) )
727 wxLogLastError(_T("SetCursorPos"));
731 // ---------------------------------------------------------------------------
733 // ---------------------------------------------------------------------------
735 // convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT
736 static inline int wxDirToWinStyle(int orient
)
738 return orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
;
741 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
743 #ifdef __WXMICROWIN__
744 return ::GetScrollPosWX(hWnd
, wOrient
);
746 WinStruct
<SCROLLINFO
> scrollInfo
;
747 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
748 scrollInfo
.fMask
= SIF_POS
;
749 if ( !::GetScrollInfo(hWnd
,
753 // Not neccessarily an error, if there are no scrollbars yet.
754 // wxLogLastError(_T("GetScrollInfo"));
756 return scrollInfo
.nPos
;
757 // return ::GetScrollPos(hWnd, wOrient);
761 int wxWindowMSW::GetScrollPos(int orient
) const
763 HWND hWnd
= GetHwnd();
764 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
766 return GetScrollPosition(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
);
769 // This now returns the whole range, not just the number
770 // of positions that we can scroll.
771 int wxWindowMSW::GetScrollRange(int orient
) const
774 HWND hWnd
= GetHwnd();
778 ::GetScrollRange(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
781 WinStruct
<SCROLLINFO
> scrollInfo
;
782 scrollInfo
.fMask
= SIF_RANGE
;
783 if ( !::GetScrollInfo(hWnd
,
784 orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
787 // Most of the time this is not really an error, since the return
788 // value can also be zero when there is no scrollbar yet.
789 // wxLogLastError(_T("GetScrollInfo"));
791 maxPos
= scrollInfo
.nMax
;
793 // undo "range - 1" done in SetScrollbar()
797 int wxWindowMSW::GetScrollThumb(int orient
) const
799 return orient
== wxHORIZONTAL
? m_xThumbSize
: m_yThumbSize
;
802 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
804 HWND hWnd
= GetHwnd();
805 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
807 WinStruct
<SCROLLINFO
> info
;
811 info
.fMask
= SIF_POS
;
812 if ( HasFlag(wxALWAYS_SHOW_SB
) )
814 // disable scrollbar instead of removing it then
815 info
.fMask
|= SIF_DISABLENOSCROLL
;
818 ::SetScrollInfo(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
822 // New function that will replace some of the above.
823 void wxWindowMSW::SetScrollbar(int orient
,
829 WinStruct
<SCROLLINFO
> info
;
830 info
.nPage
= pageSize
;
831 info
.nMin
= 0; // range is nMax - nMin + 1
832 info
.nMax
= range
- 1; // as both nMax and nMax are inclusive
834 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
835 if ( HasFlag(wxALWAYS_SHOW_SB
) )
837 // disable scrollbar instead of removing it then
838 info
.fMask
|= SIF_DISABLENOSCROLL
;
841 HWND hWnd
= GetHwnd();
844 ::SetScrollInfo(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
848 *(orient
== wxHORIZONTAL
? &m_xThumbSize
: &m_yThumbSize
) = pageSize
;
851 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
857 rect
.left
= prect
->x
;
859 rect
.right
= prect
->x
+ prect
->width
;
860 rect
.bottom
= prect
->y
+ prect
->height
;
869 // FIXME: is this the exact equivalent of the line below?
870 ::ScrollWindowEx(GetHwnd(), dx
, dy
, pr
, pr
, 0, 0, SW_ERASE
|SW_INVALIDATE
);
872 ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
);
876 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
878 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
881 for ( int n
= 0; n
< count
; n
++ )
883 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
885 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
888 // don't bother to continue, we're already at top/bottom
895 return pos
!= posStart
;
898 bool wxWindowMSW::ScrollLines(int lines
)
900 bool down
= lines
> 0;
902 return ScrollVertically(GetHwnd(),
903 down
? SB_LINEDOWN
: SB_LINEUP
,
904 down
? lines
: -lines
);
907 bool wxWindowMSW::ScrollPages(int pages
)
909 bool down
= pages
> 0;
911 return ScrollVertically(GetHwnd(),
912 down
? SB_PAGEDOWN
: SB_PAGEUP
,
913 down
? pages
: -pages
);
916 // ---------------------------------------------------------------------------
918 // ---------------------------------------------------------------------------
920 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
922 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
924 HWND hwnd
= (HWND
)hWnd
;
925 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
927 wxAssociateWinWithHandle(hwnd
, this);
929 m_oldWndProc
= (WXFARPROC
)::GetWindowLong((HWND
)hWnd
, GWL_WNDPROC
);
931 // we don't need to subclass the window of our own class (in the Windows
932 // sense of the word)
933 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
935 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) wxWndProc
);
939 // don't bother restoring it neither: this also makes it easy to
940 // implement IsOfStandardClass() method which returns TRUE for the
941 // standard controls and FALSE for the wxWindows own windows as it can
942 // simply check m_oldWndProc
947 void wxWindowMSW::UnsubclassWin()
949 wxRemoveHandleAssociation(this);
951 // Restore old Window proc
952 HWND hwnd
= GetHwnd();
957 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
961 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
963 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) m_oldWndProc
);
971 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
973 // Unicows note: the code below works, but only because WNDCLASS contains
974 // original window handler rather that the unicows fake one. This may not
975 // be on purpose, though; if it stops working with future versions of
976 // unicows.dll, we can override unicows hooks by setting
977 // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own
978 // versions that keep track of fake<->real wnd proc mapping.
980 // On WinCE (at least), the wndproc comparison doesn't work,
981 // so have to use something like this.
983 extern const wxChar
*wxCanvasClassName
;
984 extern const wxChar
*wxCanvasClassNameNR
;
985 extern const wxChar
*wxMDIFrameClassName
;
986 extern const wxChar
*wxMDIFrameClassNameNoRedraw
;
987 extern const wxChar
*wxMDIChildFrameClassName
;
988 extern const wxChar
*wxMDIChildFrameClassNameNoRedraw
;
989 wxString
str(wxGetWindowClass(hWnd
));
990 if (str
== wxCanvasClassName
||
991 str
== wxCanvasClassNameNR
||
992 str
== wxMDIFrameClassName
||
993 str
== wxMDIFrameClassNameNoRedraw
||
994 str
== wxMDIChildFrameClassName
||
995 str
== wxMDIChildFrameClassNameNoRedraw
||
996 str
== _T("wxTLWHiddenParent"))
997 return TRUE
; // Effectively means don't subclass
1002 if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd
), &cls
) )
1004 wxLogLastError(_T("GetClassInfo"));
1009 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1013 // ----------------------------------------------------------------------------
1015 // ----------------------------------------------------------------------------
1017 void wxWindowMSW::SetWindowStyleFlag(long flags
)
1019 long flagsOld
= GetWindowStyleFlag();
1020 if ( flags
== flagsOld
)
1023 // update the internal variable
1024 wxWindowBase::SetWindowStyleFlag(flags
);
1026 // now update the Windows style as well if needed - and if the window had
1027 // been already created
1031 WXDWORD exstyle
, exstyleOld
;
1032 long style
= MSWGetStyle(flags
, &exstyle
),
1033 styleOld
= MSWGetStyle(flagsOld
, &exstyleOld
);
1035 if ( style
!= styleOld
)
1037 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1038 // this function so instead of simply setting the style to the new
1039 // value we clear the bits which were set in styleOld but are set in
1040 // the new one and set the ones which were not set before
1041 long styleReal
= ::GetWindowLong(GetHwnd(), GWL_STYLE
);
1042 styleReal
&= ~styleOld
;
1045 ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
);
1048 // and the extended style
1049 if ( exstyle
!= exstyleOld
)
1051 long exstyleReal
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
);
1052 exstyleReal
&= ~exstyleOld
;
1053 exstyleReal
|= exstyle
;
1055 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
);
1057 // we must call SetWindowPos() to flash the cached extended style and
1058 // also to make the change to wxSTAY_ON_TOP style take effect: just
1059 // setting the style simply doesn't work
1060 if ( !::SetWindowPos(GetHwnd(),
1061 exstyleReal
& WS_EX_TOPMOST
? HWND_TOPMOST
1064 SWP_NOMOVE
| SWP_NOSIZE
) )
1066 wxLogLastError(_T("SetWindowPos"));
1071 WXDWORD
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD
*exstyle
) const
1073 // translate the style
1074 WXDWORD style
= WS_CHILD
| WS_VISIBLE
;
1076 if ( flags
& wxCLIP_CHILDREN
)
1077 style
|= WS_CLIPCHILDREN
;
1079 if ( flags
& wxCLIP_SIBLINGS
)
1080 style
|= WS_CLIPSIBLINGS
;
1082 if ( flags
& wxVSCROLL
)
1083 style
|= WS_VSCROLL
;
1085 if ( flags
& wxHSCROLL
)
1086 style
|= WS_HSCROLL
;
1088 const wxBorder border
= GetBorder(flags
);
1090 // WS_BORDER is only required for wxBORDER_SIMPLE
1091 if ( border
== wxBORDER_SIMPLE
)
1094 // now deal with ext style if the caller wants it
1100 if ( flags
& wxTRANSPARENT_WINDOW
)
1101 *exstyle
|= WS_EX_TRANSPARENT
;
1107 case wxBORDER_DEFAULT
:
1108 wxFAIL_MSG( _T("unknown border style") );
1112 case wxBORDER_SIMPLE
:
1115 case wxBORDER_STATIC
:
1116 *exstyle
|= WS_EX_STATICEDGE
;
1119 case wxBORDER_RAISED
:
1120 *exstyle
|= WS_EX_DLGMODALFRAME
;
1123 case wxBORDER_SUNKEN
:
1124 *exstyle
|= WS_EX_CLIENTEDGE
;
1125 style
&= ~WS_BORDER
;
1128 case wxBORDER_DOUBLE
:
1129 *exstyle
|= WS_EX_DLGMODALFRAME
;
1133 // wxUniv doesn't use Windows dialog navigation functions at all
1134 #if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
1135 // to make the dialog navigation work with the nested panels we must
1136 // use this style (top level windows such as dialogs don't need it)
1137 if ( (flags
& wxTAB_TRAVERSAL
) && !IsTopLevel() )
1139 *exstyle
|= WS_EX_CONTROLPARENT
;
1141 #endif // __WXUNIVERSAL__
1147 // Setup background and foreground colours correctly
1148 void wxWindowMSW::SetupColours()
1151 SetBackgroundColour(GetParent()->GetBackgroundColour());
1154 bool wxWindowMSW::IsMouseInWindow() const
1156 // get the mouse position
1158 ::GetCursorPos(&pt
);
1160 // find the window which currently has the cursor and go up the window
1161 // chain until we find this window - or exhaust it
1162 HWND hwnd
= ::WindowFromPoint(pt
);
1163 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1164 hwnd
= ::GetParent(hwnd
);
1166 return hwnd
!= NULL
;
1169 void wxWindowMSW::OnInternalIdle()
1171 // Check if we need to send a LEAVE event
1172 if ( m_mouseInWindow
)
1174 // note that we should generate the leave event whether the window has
1175 // or doesn't have mouse capture
1176 if ( !IsMouseInWindow() )
1178 // Generate a LEAVE event
1179 m_mouseInWindow
= FALSE
;
1181 // Unfortunately the mouse button and keyboard state may have
1182 // changed by the time the OnInternalIdle function is called, so 'state'
1183 // may be meaningless.
1185 if ( wxIsShiftDown() )
1187 if ( wxIsCtrlDown() )
1188 state
|= MK_CONTROL
;
1189 if ( GetKeyState( VK_LBUTTON
) )
1190 state
|= MK_LBUTTON
;
1191 if ( GetKeyState( VK_MBUTTON
) )
1192 state
|= MK_MBUTTON
;
1193 if ( GetKeyState( VK_RBUTTON
) )
1194 state
|= MK_RBUTTON
;
1197 if ( !::GetCursorPos(&pt
) )
1199 wxLogLastError(_T("GetCursorPos"));
1202 // we need to have client coordinates here for symmetry with
1203 // wxEVT_ENTER_WINDOW
1204 RECT rect
= wxGetWindowRect(GetHwnd());
1208 wxMouseEvent
event2(wxEVT_LEAVE_WINDOW
);
1209 InitMouseEvent(event2
, pt
.x
, pt
.y
, state
);
1211 (void)GetEventHandler()->ProcessEvent(event2
);
1215 if (wxUpdateUIEvent::CanUpdate(this))
1216 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
1219 // Set this window to be the child of 'parent'.
1220 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1222 if ( !wxWindowBase::Reparent(parent
) )
1225 HWND hWndChild
= GetHwnd();
1226 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1228 ::SetParent(hWndChild
, hWndParent
);
1233 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1235 #ifndef __WXMICROWIN__
1236 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1240 void wxWindowMSW::Freeze()
1242 SendSetRedraw(GetHwnd(), FALSE
);
1245 void wxWindowMSW::Thaw()
1247 SendSetRedraw(GetHwnd(), TRUE
);
1249 // we need to refresh everything or otherwise he invalidated area is not
1254 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1256 HWND hWnd
= GetHwnd();
1262 mswRect
.left
= rect
->x
;
1263 mswRect
.top
= rect
->y
;
1264 mswRect
.right
= rect
->x
+ rect
->width
;
1265 mswRect
.bottom
= rect
->y
+ rect
->height
;
1267 ::InvalidateRect(hWnd
, &mswRect
, eraseBack
);
1270 ::InvalidateRect(hWnd
, NULL
, eraseBack
);
1274 void wxWindowMSW::Update()
1276 if ( !::UpdateWindow(GetHwnd()) )
1278 wxLogLastError(_T("UpdateWindow"));
1281 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1282 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1283 // handler needs to be really drawn right now
1288 // ---------------------------------------------------------------------------
1290 // ---------------------------------------------------------------------------
1293 #if wxUSE_DRAG_AND_DROP
1294 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1296 if ( m_dropTarget
!= 0 ) {
1297 m_dropTarget
->Revoke(m_hWnd
);
1298 delete m_dropTarget
;
1301 m_dropTarget
= pDropTarget
;
1302 if ( m_dropTarget
!= 0 )
1303 m_dropTarget
->Register(m_hWnd
);
1305 #endif // wxUSE_DRAG_AND_DROP
1307 // old style file-manager drag&drop support: we retain the old-style
1308 // DragAcceptFiles in parallel with SetDropTarget.
1309 void wxWindowMSW::DragAcceptFiles(bool accept
)
1311 #if !defined(__WXWINCE__)
1312 HWND hWnd
= GetHwnd();
1314 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1318 // ----------------------------------------------------------------------------
1320 // ----------------------------------------------------------------------------
1324 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1326 wxWindowBase::DoSetToolTip(tooltip
);
1329 m_tooltip
->SetWindow((wxWindow
*)this);
1332 #endif // wxUSE_TOOLTIPS
1334 // ---------------------------------------------------------------------------
1335 // moving and resizing
1336 // ---------------------------------------------------------------------------
1339 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1341 RECT rect
= wxGetWindowRect(GetHwnd());
1344 *x
= rect
.right
- rect
.left
;
1346 *y
= rect
.bottom
- rect
.top
;
1349 // Get size *available for subwindows* i.e. excluding menu bar etc.
1350 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1352 RECT rect
= wxGetClientRect(GetHwnd());
1360 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1362 RECT rect
= wxGetWindowRect(GetHwnd());
1365 point
.x
= rect
.left
;
1368 // we do the adjustments with respect to the parent only for the "real"
1369 // children, not for the dialogs/frames
1370 if ( !IsTopLevel() )
1372 HWND hParentWnd
= 0;
1373 wxWindow
*parent
= GetParent();
1375 hParentWnd
= GetWinHwnd(parent
);
1377 // Since we now have the absolute screen coords, if there's a parent we
1378 // must subtract its top left corner
1381 ::ScreenToClient(hParentWnd
, &point
);
1386 // We may be faking the client origin. So a window that's really at (0,
1387 // 30) may appear (to wxWin apps) to be at (0, 0).
1388 wxPoint
pt(parent
->GetClientAreaOrigin());
1400 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1408 ::ScreenToClient(GetHwnd(), &pt
);
1416 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1424 ::ClientToScreen(GetHwnd(), &pt
);
1432 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1434 // TODO: is this consistent with other platforms?
1435 // Still, negative width or height shouldn't be allowed
1440 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, TRUE
) )
1442 wxLogLastError(wxT("MoveWindow"));
1446 // set the size of the window: if the dimensions are positive, just use them,
1447 // but if any of them is equal to -1, it means that we must find the value for
1448 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1449 // which case -1 is a valid value for x and y)
1451 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1452 // the width/height to best suit our contents, otherwise we reuse the current
1454 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1456 // get the current size and position...
1457 int currentX
, currentY
;
1458 GetPosition(¤tX
, ¤tY
);
1459 int currentW
,currentH
;
1460 GetSize(¤tW
, ¤tH
);
1462 // ... and don't do anything (avoiding flicker) if it's already ok
1463 if ( x
== currentX
&& y
== currentY
&&
1464 width
== currentW
&& height
== currentH
)
1469 if ( x
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1471 if ( y
== -1 && !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1474 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1476 wxSize
size(-1, -1);
1479 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1481 size
= DoGetBestSize();
1486 // just take the current one
1493 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1497 size
= DoGetBestSize();
1499 //else: already called DoGetBestSize() above
1505 // just take the current one
1510 DoMoveWindow(x
, y
, width
, height
);
1513 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1515 // setting the client size is less obvious than it it could have been
1516 // because in the result of changing the total size the window scrollbar
1517 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1518 // will not be correct as the difference between the total and client size
1519 // changes - so we keep changing it until we get it right
1521 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1522 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1523 // may become 3 if the window had 0 size originally and so we didn't
1524 // calculate the scrollbar correction correctly during the first iteration)
1525 // but just to be on the safe side we check for it instead of making it an
1526 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1527 for ( int i
= 0; i
< 4; i
++ )
1530 ::GetClientRect(GetHwnd(), &rectClient
);
1532 // if the size is already ok, stop here (rectClient.left = top = 0)
1533 if ( (rectClient
.right
== width
|| width
== -1) &&
1534 (rectClient
.bottom
== height
|| height
== -1) )
1539 int widthClient
= width
,
1540 heightClient
= height
;
1542 // Find the difference between the entire window (title bar and all)
1543 // and the client area; add this to the new client size to move the
1546 ::GetWindowRect(GetHwnd(), &rectWin
);
1548 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1549 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1552 point
.x
= rectWin
.left
;
1553 point
.y
= rectWin
.top
;
1555 // MoveWindow positions the child windows relative to the parent, so
1556 // adjust if necessary
1557 if ( !IsTopLevel() )
1559 wxWindow
*parent
= GetParent();
1562 ::ScreenToClient(GetHwndOf(parent
), &point
);
1566 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1570 // For implementation purposes - sometimes decorations make the client area
1572 wxPoint
wxWindowMSW::GetClientAreaOrigin() const
1574 return wxPoint(0, 0);
1577 // ---------------------------------------------------------------------------
1579 // ---------------------------------------------------------------------------
1581 int wxWindowMSW::GetCharHeight() const
1583 return wxGetTextMetrics(this).tmHeight
;
1586 int wxWindowMSW::GetCharWidth() const
1588 // +1 is needed because Windows apparently adds it when calculating the
1589 // dialog units size in pixels
1590 #if wxDIALOG_UNIT_COMPATIBILITY
1591 return wxGetTextMetrics(this).tmAveCharWidth
;
1593 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1597 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1599 int *descent
, int *externalLeading
,
1600 const wxFont
*theFont
) const
1602 const wxFont
*fontToUse
= theFont
;
1604 fontToUse
= &m_font
;
1606 HWND hWnd
= GetHwnd();
1607 HDC dc
= ::GetDC(hWnd
);
1611 if ( fontToUse
&& fontToUse
->Ok() )
1613 fnt
= (HFONT
)((wxFont
*)fontToUse
)->GetResourceHandle(); // const_cast
1615 hfontOld
= (HFONT
)SelectObject(dc
,fnt
);
1620 GetTextExtentPoint(dc
, string
, (int)string
.Length(), &sizeRect
);
1621 GetTextMetrics(dc
, &tm
);
1623 if ( fontToUse
&& fnt
&& hfontOld
)
1624 SelectObject(dc
, hfontOld
);
1626 ReleaseDC(hWnd
, dc
);
1633 *descent
= tm
.tmDescent
;
1634 if ( externalLeading
)
1635 *externalLeading
= tm
.tmExternalLeading
;
1638 // ---------------------------------------------------------------------------
1640 // ---------------------------------------------------------------------------
1642 #if wxUSE_MENUS_NATIVE
1644 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1645 // immediately, without waiting for the next event loop iteration
1647 // NB: this function should probably be made public later as it can almost
1648 // surely replace wxYield() elsewhere as well
1649 static void wxYieldForCommandsOnly()
1651 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1652 // want to process it here)
1654 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
)
1655 && msg
.message
!= WM_QUIT
)
1657 wxTheApp
->DoMessage((WXMSG
*)&msg
);
1660 // If we retrieved a WM_QUIT, insert back into the message queue.
1661 if (msg
.message
== WM_QUIT
)
1662 ::PostQuitMessage(0);
1665 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1667 menu
->SetInvokingWindow(this);
1670 HWND hWnd
= GetHwnd();
1671 HMENU hMenu
= GetHmenuOf(menu
);
1675 ::ClientToScreen(hWnd
, &point
);
1676 wxCurrentPopupMenu
= menu
;
1678 #if !defined(__WXWINCE__)
1679 flags
= TPM_RIGHTBUTTON
;
1681 ::TrackPopupMenu(hMenu
, flags
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1683 // we need to do it righ now as otherwise the events are never going to be
1684 // sent to wxCurrentPopupMenu from HandleCommand()
1686 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1687 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1688 // destroyed as soon as we return (it can be a local variable in the caller
1689 // for example) and so we do need to process the event immediately
1690 wxYieldForCommandsOnly();
1692 wxCurrentPopupMenu
= NULL
;
1694 menu
->SetInvokingWindow(NULL
);
1699 #endif // wxUSE_MENUS_NATIVE
1701 // ===========================================================================
1702 // pre/post message processing
1703 // ===========================================================================
1705 long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1708 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1710 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1713 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1715 // wxUniversal implements tab traversal itself
1716 #ifndef __WXUNIVERSAL__
1717 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1719 // intercept dialog navigation keys
1720 MSG
*msg
= (MSG
*)pMsg
;
1722 // here we try to do all the job which ::IsDialogMessage() usually does
1725 if ( msg
->message
== WM_KEYDOWN
)
1727 bool bCtrlDown
= wxIsCtrlDown();
1728 bool bShiftDown
= wxIsShiftDown();
1730 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1731 // don't process it if it's the case (except for Ctrl-Tab/Enter
1732 // combinations which are always processed)
1736 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1738 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
1739 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
1740 // it, of course, implies them
1741 if ( lDlgCode
& DLGC_WANTALLKEYS
)
1743 lDlgCode
|= DLGC_WANTTAB
| DLGC_WANTARROWS
;
1747 bool bForward
= TRUE
,
1748 bWindowChange
= FALSE
;
1750 // should we process this message specially?
1751 bool bProcess
= TRUE
;
1752 switch ( msg
->wParam
)
1755 // assume that nobody wants Shift-TAB for himself - if we
1756 // don't do it there is no easy way for a control to grab
1757 // TABs but still let Shift-TAB work as navugation key
1758 if ( (lDlgCode
& DLGC_WANTTAB
) && !bShiftDown
) {
1762 // Ctrl-Tab cycles thru notebook pages
1763 bWindowChange
= bCtrlDown
;
1764 bForward
= !bShiftDown
;
1770 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1778 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1784 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1786 // control wants to process Enter itself, don't
1787 // call IsDialogMessage() which would interpret
1791 else if ( lDlgCode
& DLGC_BUTTON
)
1793 // let IsDialogMessage() handle this for all
1794 // buttons except the owner-drawn ones which it
1795 // just seems to ignore
1796 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1797 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1799 // emulate the button click
1800 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1802 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1807 // FIXME: this should be handled by
1808 // wxNavigationKeyEvent handler and not here!!
1812 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1814 if ( btn
&& btn
->IsEnabled() )
1816 // if we do have a default button, do press it
1817 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1821 else // no default button
1823 #endif // wxUSE_BUTTON
1824 // this is a quick and dirty test for a text
1826 if ( !(lDlgCode
& DLGC_HASSETSEL
) )
1828 // don't process Enter, the control might
1829 // need it for itself and don't let
1830 // ::IsDialogMessage() have it as it can
1831 // eat the Enter events sometimes
1834 else if (!IsTopLevel())
1836 // if not a top level window, let parent
1840 //else: treat Enter as TAB: pass to the next
1841 // control as this is the best thing to do
1842 // if the text doesn't handle Enter itself
1854 wxNavigationKeyEvent event
;
1855 event
.SetDirection(bForward
);
1856 event
.SetWindowChange(bWindowChange
);
1857 event
.SetEventObject(this);
1859 if ( GetEventHandler()->ProcessEvent(event
) )
1866 // let ::IsDialogMessage() do almost everything and handle just the
1867 // things it doesn't here: Ctrl-TAB for switching notebook pages
1868 if ( msg
->message
== WM_KEYDOWN
)
1870 // don't process system keys here
1871 if ( !(HIWORD(msg
->lParam
) & KF_ALTDOWN
) )
1873 if ( (msg
->wParam
== VK_TAB
) && wxIsCtrlDown() )
1875 // find the first notebook parent and change its page
1876 wxWindow
*win
= this;
1877 wxNotebook
*nbook
= NULL
;
1878 while ( win
&& !nbook
)
1880 nbook
= wxDynamicCast(win
, wxNotebook
);
1881 win
= win
->GetParent();
1886 bool forward
= !wxIsShiftDown();
1888 nbook
->AdvanceSelection(forward
);
1895 // we handle VK_ESCAPE ourselves in wxDialog::OnCharHook() and we
1896 // shouldn't let IsDialogMessage() get it as it _always_ eats the
1897 // message even when there is no cancel button and when the message is
1898 // needed by the control itself: in particular, it prevents the tree in
1899 // place edit control from being closed with Escape in a dialog
1900 if ( msg
->message
!= WM_KEYDOWN
|| msg
->wParam
!= VK_ESCAPE
)
1902 // ::IsDialogMessage() is broken and may sometimes hang the
1903 // application by going into an infinite loop, so we try to detect
1904 // [some of] the situatations when this may happen and not call it
1907 // assume we can call it by default
1908 bool canSafelyCallIsDlgMsg
= TRUE
;
1910 HWND hwndFocus
= ::GetFocus();
1912 // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter
1913 // an infinite loop, because it will recursively check the child
1914 // windows but not the window itself and so if none of the children
1915 // accepts focus it loops forever (as it only stops when it gets
1916 // back to the window it started from)
1918 // while it is very unusual that a window with WS_EX_CONTROLPARENT
1919 // style has the focus, it can happen. One such possibility is if
1920 // all windows are either toplevel, wxDialog, wxPanel or static
1921 // controls and no window can actually accept keyboard input.
1922 #if !defined(__WXWINCE__)
1923 if ( ::GetWindowLong(hwndFocus
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT
)
1925 // passimistic by default
1926 canSafelyCallIsDlgMsg
= FALSE
;
1927 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
1929 node
= node
->GetNext() )
1931 wxWindow
* const win
= node
->GetData();
1932 if ( win
->AcceptsFocus() &&
1933 !(::GetWindowLong(GetHwndOf(win
), GWL_EXSTYLE
) &
1934 WS_EX_CONTROLPARENT
) )
1936 // it shouldn't hang...
1937 canSafelyCallIsDlgMsg
= TRUE
;
1943 #endif // !__WXWINCE__
1945 if ( canSafelyCallIsDlgMsg
)
1947 // ::IsDialogMessage() can enter in an infinite loop when the
1948 // currently focused window is disabled or hidden and its
1949 // parent has WS_EX_CONTROLPARENT style, so don't call it in
1953 if ( !::IsWindowEnabled(hwndFocus
) ||
1954 !::IsWindowVisible(hwndFocus
) )
1956 // it would enter an infinite loop if we do this!
1957 canSafelyCallIsDlgMsg
= FALSE
;
1962 if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) )
1964 // it's a top level window, don't go further -- e.g. even
1965 // if the parent of a dialog is disabled, this doesn't
1966 // break navigation inside the dialog
1970 hwndFocus
= ::GetParent(hwndFocus
);
1974 // let IsDialogMessage() have the message if it's safe to call it
1975 if ( canSafelyCallIsDlgMsg
&& ::IsDialogMessage(GetHwnd(), msg
) )
1977 // IsDialogMessage() did something...
1982 #endif // __WXUNIVERSAL__
1987 // relay mouse move events to the tooltip control
1988 MSG
*msg
= (MSG
*)pMsg
;
1989 if ( msg
->message
== WM_MOUSEMOVE
)
1990 m_tooltip
->RelayEvent(pMsg
);
1992 #endif // wxUSE_TOOLTIPS
1997 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
1999 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
2000 return m_acceleratorTable
.Translate(this, pMsg
);
2004 #endif // wxUSE_ACCEL
2007 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
))
2009 // preprocess all messages by default
2013 // ---------------------------------------------------------------------------
2014 // message params unpackers
2015 // ---------------------------------------------------------------------------
2017 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2018 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
2020 *id
= LOWORD(wParam
);
2021 *hwnd
= (WXHWND
)lParam
;
2022 *cmd
= HIWORD(wParam
);
2025 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2026 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2028 *state
= LOWORD(wParam
);
2029 *minimized
= HIWORD(wParam
);
2030 *hwnd
= (WXHWND
)lParam
;
2033 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2034 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2036 *code
= LOWORD(wParam
);
2037 *pos
= HIWORD(wParam
);
2038 *hwnd
= (WXHWND
)lParam
;
2041 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2042 WXWORD
*nCtlColor
, WXHDC
*hdc
, WXHWND
*hwnd
)
2044 #ifndef __WXMICROWIN__
2045 *nCtlColor
= CTLCOLOR_BTN
;
2046 *hwnd
= (WXHWND
)lParam
;
2047 *hdc
= (WXHDC
)wParam
;
2051 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2052 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2054 *item
= (WXWORD
)wParam
;
2055 *flags
= HIWORD(wParam
);
2056 *hmenu
= (WXHMENU
)lParam
;
2059 // ---------------------------------------------------------------------------
2060 // Main wxWindows window proc and the window proc for wxWindow
2061 // ---------------------------------------------------------------------------
2063 // Hook for new window just as it's being created, when the window isn't yet
2064 // associated with the handle
2065 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2067 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2068 // window being created and insures that it's always unset back later
2069 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2071 gs_winBeingCreated
= winBeingCreated
;
2074 wxWindowCreationHook::~wxWindowCreationHook()
2076 gs_winBeingCreated
= NULL
;
2080 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2082 // trace all messages - useful for the debugging
2084 wxLogTrace(wxTraceMessages
,
2085 wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
2086 wxGetMessageName(message
), (long)hWnd
, (long)wParam
, lParam
);
2087 #endif // __WXDEBUG__
2089 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2091 // when we get the first message for the HWND we just created, we associate
2092 // it with wxWindow stored in gs_winBeingCreated
2093 if ( !wnd
&& gs_winBeingCreated
)
2095 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2096 wnd
= gs_winBeingCreated
;
2097 gs_winBeingCreated
= NULL
;
2098 wnd
->SetHWND((WXHWND
)hWnd
);
2104 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2106 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2111 long wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2113 // did we process the message?
2114 bool processed
= FALSE
;
2125 // for most messages we should return 0 when we do process the message
2133 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2136 // return 0 to allow window creation
2137 rc
.result
= mayCreate
? 0 : -1;
2143 // never set processed to TRUE and *always* pass WM_DESTROY to
2144 // DefWindowProc() as Windows may do some internal cleanup when
2145 // processing it and failing to pass the message along may cause
2146 // memory and resource leaks!
2147 (void)HandleDestroy();
2151 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2154 #if !defined(__WXWINCE__)
2157 LPRECT pRect
= (LPRECT
)lParam
;
2159 rc
.SetLeft(pRect
->left
);
2160 rc
.SetTop(pRect
->top
);
2161 rc
.SetRight(pRect
->right
);
2162 rc
.SetBottom(pRect
->bottom
);
2163 processed
= HandleMoving(rc
);
2165 pRect
->left
= rc
.GetLeft();
2166 pRect
->top
= rc
.GetTop();
2167 pRect
->right
= rc
.GetRight();
2168 pRect
->bottom
= rc
.GetBottom();
2179 // we're not interested in these messages at all
2182 case SIZE_MINIMIZED
:
2183 // we shouldn't send sizev events for these messages as the
2184 // client size may be negative which breaks existing code
2186 // OTOH we might send another (wxMinimizedEvent?) one or
2187 // add an additional parameter to wxSizeEvent if this is
2188 // useful to anybody
2192 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2193 // fall through nevertheless
2195 case SIZE_MAXIMIZED
:
2197 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
),
2202 #if !defined(__WXWINCE__)
2205 LPRECT pRect
= (LPRECT
)lParam
;
2207 rc
.SetLeft(pRect
->left
);
2208 rc
.SetTop(pRect
->top
);
2209 rc
.SetRight(pRect
->right
);
2210 rc
.SetBottom(pRect
->bottom
);
2211 processed
= HandleSizing(rc
);
2213 pRect
->left
= rc
.GetLeft();
2214 pRect
->top
= rc
.GetTop();
2215 pRect
->right
= rc
.GetRight();
2216 pRect
->bottom
= rc
.GetBottom();
2222 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2223 case WM_ACTIVATEAPP
:
2224 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2230 WXWORD state
, minimized
;
2232 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2234 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2239 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2243 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2250 // cast to wxWindow is needed for wxUniv
2251 wxPaintDCEx
dc((wxWindow
*)this, (WXHDC
)wParam
);
2252 processed
= HandlePaint();
2256 processed
= HandlePaint();
2262 #ifdef __WXUNIVERSAL__
2263 // Universal uses its own wxFrame/wxDialog, so we don't receive
2264 // close events unless we have this.
2269 // don't let the DefWindowProc() destroy our window - we'll do it
2270 // ourselves in ~wxWindow
2277 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2281 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2282 GET_Y_LPARAM(lParam
),
2286 #if wxUSE_MOUSEWHEEL
2288 processed
= HandleMouseWheel(wParam
, lParam
);
2292 case WM_LBUTTONDOWN
:
2294 case WM_LBUTTONDBLCLK
:
2295 case WM_RBUTTONDOWN
:
2297 case WM_RBUTTONDBLCLK
:
2298 case WM_MBUTTONDOWN
:
2300 case WM_MBUTTONDBLCLK
:
2302 #ifdef __WXMICROWIN__
2303 // MicroWindows seems to ignore the fact that a window is
2304 // disabled. So catch mouse events and throw them away if
2306 wxWindowMSW
* win
= this;
2309 if (!win
->IsEnabled())
2315 win
= win
->GetParent();
2316 if ( !win
|| win
->IsTopLevel() )
2323 #endif // __WXMICROWIN__
2324 int x
= GET_X_LPARAM(lParam
),
2325 y
= GET_Y_LPARAM(lParam
);
2327 // redirect the event to a static control if necessary by
2328 // finding one under mouse
2330 if ( GetCapture() == this )
2332 // but don't do it if the mouse is captured by this window
2333 // because then it should really get this event itself
2338 win
= FindWindowForMouseEvent(this, &x
, &y
);
2340 // this should never happen
2341 wxCHECK_MSG( win
, 0,
2342 _T("FindWindowForMouseEvent() returned NULL") );
2344 // for the standard classes their WndProc sets the focus to
2345 // them anyhow and doing it from here results in some weird
2346 // problems, but for our windows we want them to acquire
2347 // focus when clicked
2348 if ( !win
->IsOfStandardClass() )
2350 if ( message
== WM_LBUTTONDOWN
&& win
->AcceptsFocus() )
2355 processed
= win
->HandleMouseEvent(message
, x
, y
, wParam
);
2364 case MM_JOY1BUTTONDOWN
:
2365 case MM_JOY2BUTTONDOWN
:
2366 case MM_JOY1BUTTONUP
:
2367 case MM_JOY2BUTTONUP
:
2368 processed
= HandleJoystickEvent(message
,
2369 GET_X_LPARAM(lParam
),
2370 GET_Y_LPARAM(lParam
),
2373 #endif // __WXMICROWIN__
2376 processed
= HandleSysCommand(wParam
, lParam
);
2383 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2385 processed
= HandleCommand(id
, cmd
, hwnd
);
2390 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2393 // for these messages we must return TRUE if process the message
2396 case WM_MEASUREITEM
:
2398 int idCtrl
= (UINT
)wParam
;
2399 if ( message
== WM_DRAWITEM
)
2401 processed
= MSWOnDrawItem(idCtrl
,
2402 (WXDRAWITEMSTRUCT
*)lParam
);
2406 processed
= MSWOnMeasureItem(idCtrl
,
2407 (WXMEASUREITEMSTRUCT
*)lParam
);
2414 #endif // defined(WM_DRAWITEM)
2417 if ( !IsOfStandardClass() )
2419 // we always want to get the char events
2420 rc
.result
= DLGC_WANTCHARS
;
2422 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
2424 // in fact, we want everything
2425 rc
.result
|= DLGC_WANTARROWS
|
2432 //else: get the dlg code from the DefWindowProc()
2437 // If this has been processed by an event handler, return 0 now
2438 // (we've handled it).
2439 m_lastKeydownProcessed
= HandleKeyDown((WORD
) wParam
, lParam
);
2440 if ( m_lastKeydownProcessed
)
2449 // we consider these message "not interesting" to OnChar, so
2450 // just don't do anything more with them
2460 // avoid duplicate messages to OnChar for these ASCII keys:
2461 // they will be translated by TranslateMessage() and received
2483 // but set processed to FALSE, not TRUE to still pass them
2484 // to the control's default window proc - otherwise
2485 // built-in keyboard handling won't work
2490 // special case of VK_APPS: treat it the same as right mouse
2491 // click because both usually pop up a context menu
2497 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2498 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, x
, y
, flags
);
2504 // do generate a CHAR event
2505 processed
= HandleChar((WORD
)wParam
, lParam
);
2508 if (message
== WM_SYSKEYDOWN
) // Let Windows still handle the SYSKEYs
2515 // special case of VK_APPS: treat it the same as right mouse button
2516 if ( wParam
== VK_APPS
)
2521 TranslateKbdEventToMouse(this, &x
, &y
, &flags
);
2522 processed
= HandleMouseEvent(WM_RBUTTONUP
, x
, y
, flags
);
2527 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2532 case WM_CHAR
: // Always an ASCII character
2533 if ( m_lastKeydownProcessed
)
2535 // The key was handled in the EVT_KEY_DOWN and handling
2536 // a key in an EVT_KEY_DOWN handler is meant, by
2537 // design, to prevent EVT_CHARs from happening
2538 m_lastKeydownProcessed
= FALSE
;
2543 processed
= HandleChar((WORD
)wParam
, lParam
, TRUE
);
2549 processed
= HandleHotKey((WORD
)wParam
, lParam
);
2551 #endif // wxUSE_HOTKEY
2558 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2560 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2566 // CTLCOLOR messages are sent by children to query the parent for their
2567 // colors#ifndef __WXMICROWIN__
2568 #ifndef __WXMICROWIN__
2569 case WM_CTLCOLORMSGBOX
:
2570 case WM_CTLCOLOREDIT
:
2571 case WM_CTLCOLORLISTBOX
:
2572 case WM_CTLCOLORBTN
:
2573 case WM_CTLCOLORDLG
:
2574 case WM_CTLCOLORSCROLLBAR
:
2575 case WM_CTLCOLORSTATIC
:
2580 UnpackCtlColor(wParam
, lParam
, &nCtlColor
, &hdc
, &hwnd
);
2582 processed
= HandleCtlColor(&rc
.hBrush
,
2591 #endif // !__WXMICROWIN__
2593 case WM_SYSCOLORCHANGE
:
2594 // the return value for this message is ignored
2595 processed
= HandleSysColorChange();
2598 #if !defined(__WXWINCE__)
2599 case WM_DISPLAYCHANGE
:
2600 processed
= HandleDisplayChange();
2604 case WM_PALETTECHANGED
:
2605 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2608 case WM_CAPTURECHANGED
:
2609 processed
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
);
2612 case WM_QUERYNEWPALETTE
:
2613 processed
= HandleQueryNewPalette();
2617 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2620 // we processed the message, i.e. erased the background
2625 #if !defined(__WXWINCE__)
2627 processed
= HandleDropFiles(wParam
);
2632 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2636 // we never set focus from here
2641 #if !defined(__WXWINCE__)
2642 case WM_QUERYENDSESSION
:
2643 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2647 processed
= HandleEndSession(wParam
!= 0, lParam
);
2650 case WM_GETMINMAXINFO
:
2651 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2656 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2657 LOWORD(lParam
), // hit test
2658 HIWORD(lParam
)); // mouse msg
2662 // returning TRUE stops the DefWindowProc() from further
2663 // processing this message - exactly what we need because we've
2664 // just set the cursor.
2669 #if wxUSE_ACCESSIBILITY
2672 //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
2673 LPARAM dwObjId
= (LPARAM
) (DWORD
) lParam
;
2675 if (dwObjId
== OBJID_CLIENT
&& GetOrCreateAccessible())
2677 return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible());
2683 #if defined(WM_HELP)
2686 // HELPINFO doesn't seem to be supported on WinCE.
2688 HELPINFO
* info
= (HELPINFO
*) lParam
;
2689 // Don't yet process menu help events, just windows
2690 if (info
->iContextType
== HELPINFO_WINDOW
)
2693 wxWindowMSW
* subjectOfHelp
= this;
2694 bool eventProcessed
= FALSE
;
2695 while (subjectOfHelp
&& !eventProcessed
)
2697 wxHelpEvent
helpEvent(wxEVT_HELP
,
2698 subjectOfHelp
->GetId(),
2702 wxPoint(info
->MousePos
.x
, info
->MousePos
.y
)
2706 helpEvent
.SetEventObject(this);
2708 GetEventHandler()->ProcessEvent(helpEvent
);
2710 // Go up the window hierarchy until the event is
2712 subjectOfHelp
= subjectOfHelp
->GetParent();
2715 processed
= eventProcessed
;
2718 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2720 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2721 helpEvent
.SetEventObject(this);
2722 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2725 //else: processed is already FALSE
2731 #if !defined(__WXWINCE__)
2732 case WM_CONTEXTMENU
:
2734 // we don't convert from screen to client coordinates as
2735 // the event may be handled by a parent window
2736 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2738 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2739 processed
= GetEventHandler()->ProcessEvent(evtCtx
);
2745 // we're only interested in our own menus, not MF_SYSMENU
2746 if ( HIWORD(wParam
) == MF_POPUP
)
2748 // handle menu chars for ownerdrawn menu items
2749 int i
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
);
2750 if ( i
!= wxNOT_FOUND
)
2752 rc
.result
= MAKELRESULT(i
, MNC_EXECUTE
);
2762 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2763 wxGetMessageName(message
));
2764 #endif // __WXDEBUG__
2765 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2771 // ----------------------------------------------------------------------------
2772 // wxWindow <-> HWND map
2773 // ----------------------------------------------------------------------------
2775 wxWinHashTable
*wxWinHandleHash
= NULL
;
2777 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2779 return wxWinHandleHash
->Get((long)hWnd
);
2782 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2784 // adding NULL hWnd is (first) surely a result of an error and
2785 // (secondly) breaks menu command processing
2786 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2787 wxT("attempt to add a NULL hWnd to window list ignored") );
2789 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2791 if ( oldWin
&& (oldWin
!= win
) )
2793 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2794 (int) hWnd
, win
->GetClassInfo()->GetClassName());
2797 #endif // __WXDEBUG__
2800 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2804 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2806 wxWinHandleHash
->Delete((long)win
->GetHWND());
2809 // ----------------------------------------------------------------------------
2810 // various MSW speciic class dependent functions
2811 // ----------------------------------------------------------------------------
2813 // Default destroyer - override if you destroy it in some other way
2814 // (e.g. with MDI child windows)
2815 void wxWindowMSW::MSWDestroyWindow()
2819 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2822 int& w
, int& h
) const
2824 static const int DEFAULT_Y
= 200;
2825 static const int DEFAULT_H
= 250;
2827 bool nonDefault
= FALSE
;
2831 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2832 // just as well set it to CW_USEDEFAULT as well
2838 // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it
2839 // neither because it is not handled as a special value by Windows then
2840 // and so we have to choose some default value for it
2842 y
= pos
.y
== -1 ? DEFAULT_Y
: pos
.y
;
2848 NB: there used to be some code here which set the initial size of the
2849 window to the client size of the parent if no explicit size was
2850 specified. This was wrong because wxWindows programs often assume
2851 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2852 it. To see why, you should understand that Windows sends WM_SIZE from
2853 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2854 from some base class ctor and so this WM_SIZE is not processed in the
2855 real class' OnSize() (because it's not fully constructed yet and the
2856 event goes to some base class OnSize() instead). So the WM_SIZE we
2857 rely on is the one sent when the parent frame resizes its children
2858 but here is the problem: if the child already has just the right
2859 size, nothing will happen as both wxWindows and Windows check for
2860 this and ignore any attempts to change the window size to the size it
2861 already has - so no WM_SIZE would be sent.
2865 // as above, h is not used at all in this case anyhow
2871 // and, again as above, we can't set the height to CW_USEDEFAULT here
2873 h
= size
.y
== -1 ? DEFAULT_H
: size
.y
;
2881 WXHWND
wxWindowMSW::MSWGetParent() const
2883 return m_parent
? m_parent
->GetHWND() : WXHWND(NULL
);
2886 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
2887 const wxChar
*title
,
2891 WXDWORD extendedStyle
)
2893 // choose the position/size for the new window
2895 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
2897 // controlId is menu handle for the top level windows, so set it to 0
2898 // unless we're creating a child window
2899 int controlId
= style
& WS_CHILD
? GetId() : 0;
2901 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2902 // which is the same but without CS_[HV]REDRAW class styles so using it
2903 // ensures that the window is not fully repainted on each resize
2904 wxString
className(wclass
);
2905 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE
)
2907 className
+= wxT("NR");
2910 // do create the window
2911 wxWindowCreationHook
hook(this);
2914 if (extendedStyle
== 0)
2916 m_hWnd
= (WXHWND
)::CreateWindow
2919 title
? title
: wxEmptyString
,
2922 (HWND
)MSWGetParent(),
2925 NULL
// no extra data
2931 m_hWnd
= (WXHWND
)::CreateWindowEx
2935 title
? title
: wxEmptyString
,
2938 (HWND
)MSWGetParent(),
2941 NULL
// no extra data
2947 wxLogSysError(_("Can't create window of class %s"), wclass
);
2952 SubclassWin(m_hWnd
);
2954 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2959 // ===========================================================================
2960 // MSW message handlers
2961 // ===========================================================================
2963 // ---------------------------------------------------------------------------
2965 // ---------------------------------------------------------------------------
2969 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
2971 #ifndef __WXMICROWIN__
2972 LPNMHDR hdr
= (LPNMHDR
)lParam
;
2973 HWND hWnd
= hdr
->hwndFrom
;
2974 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
2976 // if the control is one of our windows, let it handle the message itself
2979 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
2982 // VZ: why did we do it? normally this is unnecessary and, besides, it
2983 // breaks the message processing for the toolbars because the tooltip
2984 // notifications were being forwarded to the toolbar child controls
2985 // (if it had any) before being passed to the toolbar itself, so in my
2986 // example the tooltip for the combobox was always shown instead of the
2987 // correct button tooltips
2989 // try all our children
2990 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
2993 wxWindow
*child
= node
->GetData();
2994 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
2999 node
= node
->GetNext();
3003 // by default, handle it ourselves
3004 return MSWOnNotify(idCtrl
, lParam
, result
);
3005 #else // __WXMICROWIN__
3012 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
,
3014 const wxString
& ttip
)
3016 // I don't know why it happens, but the versions of comctl32.dll starting
3017 // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally,
3018 // this message is supposed to be sent to Unicode programs only) -- hence
3019 // we need to handle it as well, otherwise no tooltips will be shown in
3022 if ( !(code
== (WXUINT
) TTN_NEEDTEXTA
|| code
== (WXUINT
) TTN_NEEDTEXTW
) || ttip
.empty() )
3024 // not a tooltip message or no tooltip to show anyhow
3029 LPTOOLTIPTEXT ttText
= (LPTOOLTIPTEXT
)lParam
;
3032 if ( code
== (WXUINT
) TTN_NEEDTEXTA
)
3034 // we pass just the pointer as we store the string internally anyhow
3035 ttText
->lpszText
= (char *)ttip
.c_str();
3037 else // TTN_NEEDTEXTW
3041 // in Unicode mode this is just what we need
3042 ttText
->lpszText
= (wxChar
*)ttip
.c_str();
3044 MultiByteToWideChar(CP_ACP
, 0, ttip
, ttip
.length()+1,
3045 (wchar_t *)ttText
->szText
,
3046 sizeof(ttText
->szText
) / sizeof(wchar_t));
3047 #endif // Unicode/!Unicode
3053 #endif // wxUSE_TOOLTIPS
3055 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
3057 WXLPARAM
* WXUNUSED(result
))
3062 NMHDR
* hdr
= (NMHDR
*)lParam
;
3063 if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip()))
3069 #endif // wxUSE_TOOLTIPS
3076 // ---------------------------------------------------------------------------
3077 // end session messages
3078 // ---------------------------------------------------------------------------
3080 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
3083 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, -1);
3084 event
.SetEventObject(wxTheApp
);
3085 event
.SetCanVeto(TRUE
);
3086 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
3088 bool rc
= wxTheApp
->ProcessEvent(event
);
3092 // we may end only if the app didn't veto session closing (double
3094 *mayEnd
= !event
.GetVeto();
3103 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
3106 // do nothing if the session isn't ending
3111 if ( (this != wxTheApp
->GetTopWindow()) )
3114 wxCloseEvent
event(wxEVT_END_SESSION
, -1);
3115 event
.SetEventObject(wxTheApp
);
3116 event
.SetCanVeto(FALSE
);
3117 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
3119 return wxTheApp
->ProcessEvent(event
);
3125 // ---------------------------------------------------------------------------
3126 // window creation/destruction
3127 // ---------------------------------------------------------------------------
3129 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs
, bool *mayCreate
)
3131 // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
3132 // parent as well as otherwise several Win32 functions using
3133 // GetNextDlgTabItem() to iterate over all controls such as
3134 // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
3135 // all of them iterate over all the controls starting from the focus and
3136 // stop iterating when they get back to the focus but unless all parents
3137 // have WS_EX_CONTROLPARENT bit set, they would never get back to focus
3139 if ( ((CREATESTRUCT
*)cs
)->dwExStyle
& WS_EX_CONTROLPARENT
)
3141 // there is no need to do anything for the top level windows
3142 const wxWindow
*parent
= GetParent();
3143 while ( parent
&& !parent
->IsTopLevel() )
3145 LONG exStyle
= ::GetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
);
3146 if ( !(exStyle
& WS_EX_CONTROLPARENT
) )
3148 // force the parent to have this style
3149 ::SetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
,
3150 exStyle
| WS_EX_CONTROLPARENT
);
3153 parent
= parent
->GetParent();
3158 // TODO: should generate this event from WM_NCCREATE
3159 wxWindowCreateEvent
event((wxWindow
*)this);
3160 (void)GetEventHandler()->ProcessEvent(event
);
3167 bool wxWindowMSW::HandleDestroy()
3171 // delete our drop target if we've got one
3172 #if wxUSE_DRAG_AND_DROP
3173 if ( m_dropTarget
!= NULL
)
3175 m_dropTarget
->Revoke(m_hWnd
);
3177 delete m_dropTarget
;
3178 m_dropTarget
= NULL
;
3180 #endif // wxUSE_DRAG_AND_DROP
3182 // WM_DESTROY handled
3186 // ---------------------------------------------------------------------------
3188 // ---------------------------------------------------------------------------
3190 bool wxWindowMSW::HandleActivate(int state
,
3191 bool WXUNUSED(minimized
),
3192 WXHWND
WXUNUSED(activate
))
3194 wxActivateEvent
event(wxEVT_ACTIVATE
,
3195 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3197 event
.SetEventObject(this);
3199 return GetEventHandler()->ProcessEvent(event
);
3202 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3204 // notify the parent keeping track of focus for the kbd navigation
3205 // purposes that we got it
3206 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3207 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3213 m_caret
->OnSetFocus();
3215 #endif // wxUSE_CARET
3218 // If it's a wxTextCtrl don't send the event as it will be done
3219 // after the control gets to process it from EN_FOCUS handler
3220 if ( wxDynamicCastThis(wxTextCtrl
) )
3224 #endif // wxUSE_TEXTCTRL
3226 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3227 event
.SetEventObject(this);
3229 // wxFindWinFromHandle() may return NULL, it is ok
3230 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3232 return GetEventHandler()->ProcessEvent(event
);
3235 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3241 m_caret
->OnKillFocus();
3243 #endif // wxUSE_CARET
3246 // If it's a wxTextCtrl don't send the event as it will be done
3247 // after the control gets to process it.
3248 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3255 // Don't send the event when in the process of being deleted. This can
3256 // only cause problems if the event handler tries to access the object.
3257 if ( m_isBeingDeleted
)
3262 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3263 event
.SetEventObject(this);
3265 // wxFindWinFromHandle() may return NULL, it is ok
3266 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3268 return GetEventHandler()->ProcessEvent(event
);
3271 // ---------------------------------------------------------------------------
3273 // ---------------------------------------------------------------------------
3275 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3277 wxShowEvent
event(GetId(), show
);
3278 event
.m_eventObject
= this;
3280 return GetEventHandler()->ProcessEvent(event
);
3283 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3285 wxInitDialogEvent
event(GetId());
3286 event
.m_eventObject
= this;
3288 return GetEventHandler()->ProcessEvent(event
);
3291 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3293 #if defined (__WXMICROWIN__) || defined(__WXWINCE__)
3295 #else // __WXMICROWIN__
3296 HDROP hFilesInfo
= (HDROP
) wParam
;
3298 // Get the total number of files dropped
3299 UINT gwFilesDropped
= ::DragQueryFile
3307 wxString
*files
= new wxString
[gwFilesDropped
];
3308 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3310 // first get the needed buffer length (+1 for terminating NUL)
3311 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3313 // and now get the file name
3314 ::DragQueryFile(hFilesInfo
, wIndex
,
3315 wxStringBuffer(files
[wIndex
], len
), len
);
3317 DragFinish (hFilesInfo
);
3319 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3320 event
.m_eventObject
= this;
3323 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3324 event
.m_pos
.x
= dropPoint
.x
;
3325 event
.m_pos
.y
= dropPoint
.y
;
3327 return GetEventHandler()->ProcessEvent(event
);
3332 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3334 int WXUNUSED(mouseMsg
))
3336 #ifndef __WXMICROWIN__
3337 // the logic is as follows:
3338 // -1. don't set cursor for non client area, including but not limited to
3339 // the title bar, scrollbars, &c
3340 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3341 // 1. if we have the cursor set it unless wxIsBusy()
3342 // 2. if we're a top level window, set some cursor anyhow
3343 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3345 if ( nHitTest
!= HTCLIENT
)
3350 HCURSOR hcursor
= 0;
3352 // first ask the user code - it may wish to set the cursor in some very
3353 // specific way (for example, depending on the current position)
3355 if ( !::GetCursorPos(&pt
) )
3357 wxLogLastError(wxT("GetCursorPos"));
3362 ScreenToClient(&x
, &y
);
3363 wxSetCursorEvent
event(x
, y
);
3365 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3366 if ( processedEvtSetCursor
&& event
.HasCursor() )
3368 hcursor
= GetHcursorOf(event
.GetCursor());
3373 bool isBusy
= wxIsBusy();
3375 // the test for processedEvtSetCursor is here to prevent using m_cursor
3376 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3377 // it - this is a way to say that our cursor shouldn't be used for this
3379 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3381 hcursor
= GetHcursorOf(m_cursor
);
3388 hcursor
= wxGetCurrentBusyCursor();
3390 else if ( !hcursor
)
3392 const wxCursor
*cursor
= wxGetGlobalCursor();
3393 if ( cursor
&& cursor
->Ok() )
3395 hcursor
= GetHcursorOf(*cursor
);
3403 // wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor);
3405 ::SetCursor(hcursor
);
3407 // cursor set, stop here
3410 #endif // __WXMICROWIN__
3412 // pass up the window chain
3416 // ---------------------------------------------------------------------------
3417 // owner drawn stuff
3418 // ---------------------------------------------------------------------------
3420 #if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \
3421 (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__))
3422 #define WXUNUSED_UNLESS_ODRAWN(param) param
3424 #define WXUNUSED_UNLESS_ODRAWN(param)
3428 wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id
),
3429 WXDRAWITEMSTRUCT
* WXUNUSED_UNLESS_ODRAWN(itemStruct
))
3431 #if wxUSE_OWNER_DRAWN
3433 #if wxUSE_MENUS_NATIVE
3434 // is it a menu item?
3435 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3436 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3438 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3440 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3442 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3443 // the DC from being released
3444 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3445 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3446 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3447 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3449 return pMenuItem
->OnDrawItem
3453 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3454 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3457 #endif // wxUSE_MENUS_NATIVE
3459 #endif // USE_OWNER_DRAWN
3461 #if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)
3463 #if wxUSE_OWNER_DRAWN
3464 wxControl
*item
= wxDynamicCast(FindItem(id
), wxControl
);
3465 #else // !wxUSE_OWNER_DRAWN
3466 // we may still have owner-drawn buttons internally because we have to make
3467 // them owner-drawn to support colour change
3468 wxControl
*item
= wxDynamicCast(FindItem(id
), wxButton
);
3469 #endif // USE_OWNER_DRAWN
3473 return item
->MSWOnDraw(itemStruct
);
3476 #endif // wxUSE_CONTROLS
3482 wxWindowMSW::MSWOnMeasureItem(int WXUNUSED_UNLESS_ODRAWN(id
),
3483 WXMEASUREITEMSTRUCT
*
3484 WXUNUSED_UNLESS_ODRAWN(itemStruct
))
3486 #if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
3487 // is it a menu item?
3488 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3489 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3491 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3493 wxCHECK( pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)), FALSE
);
3495 return pMenuItem
->OnMeasureItem(&pMeasureStruct
->itemWidth
,
3496 &pMeasureStruct
->itemHeight
);
3499 wxControl
*item
= wxDynamicCast(FindItem(id
), wxControl
);
3502 return item
->MSWOnMeasure(itemStruct
);
3504 #endif // wxUSE_OWNER_DRAWN
3509 // ---------------------------------------------------------------------------
3510 // colours and palettes
3511 // ---------------------------------------------------------------------------
3513 bool wxWindowMSW::HandleSysColorChange()
3515 wxSysColourChangedEvent event
;
3516 event
.SetEventObject(this);
3518 (void)GetEventHandler()->ProcessEvent(event
);
3520 // always let the system carry on the default processing to allow the
3521 // native controls to react to the colours update
3525 bool wxWindowMSW::HandleDisplayChange()
3527 wxDisplayChangedEvent event
;
3528 event
.SetEventObject(this);
3530 return GetEventHandler()->ProcessEvent(event
);
3533 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
,
3541 #ifndef __WXMICROWIN__
3542 WXHBRUSH hBrush
= 0;
3547 if ( nCtlColor
== CTLCOLOR_DLG
)
3550 hBrush
= OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3555 wxControl
*item
= (wxControl
*)FindItemByHWND(pWnd
, TRUE
);
3557 hBrush
= item
->OnCtlColor(pDC
, pWnd
, nCtlColor
, message
, wParam
, lParam
);
3559 #endif // wxUSE_CONTROLS
3565 #else // __WXMICROWIN__
3570 // Define for each class of dialog and control
3571 WXHBRUSH
wxWindowMSW::OnCtlColor(WXHDC
WXUNUSED(hDC
),
3572 WXHWND
WXUNUSED(hWnd
),
3573 WXUINT
WXUNUSED(nCtlColor
),
3574 WXUINT
WXUNUSED(message
),
3575 WXWPARAM
WXUNUSED(wParam
),
3576 WXLPARAM
WXUNUSED(lParam
))
3581 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3584 // same as below except we don't respond to our own messages
3585 if ( hWndPalChange
!= GetHWND() )
3587 // check to see if we our our parents have a custom palette
3588 wxWindowMSW
*win
= this;
3589 while ( win
&& !win
->HasCustomPalette() )
3591 win
= win
->GetParent();
3594 if ( win
&& win
->HasCustomPalette() )
3596 // realize the palette to see whether redrawing is needed
3597 HDC hdc
= ::GetDC((HWND
) hWndPalChange
);
3598 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3599 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3601 int result
= ::RealizePalette(hdc
);
3603 // restore the palette (before releasing the DC)
3604 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3605 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3606 ::RealizePalette(hdc
);
3607 ::ReleaseDC((HWND
) hWndPalChange
, hdc
);
3609 // now check for the need to redraw
3611 InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
);
3615 #endif // wxUSE_PALETTE
3617 wxPaletteChangedEvent
event(GetId());
3618 event
.SetEventObject(this);
3619 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3621 return GetEventHandler()->ProcessEvent(event
);
3624 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
)
3626 wxMouseCaptureChangedEvent
event(GetId(), wxFindWinFromHandle(hWndGainedCapture
));
3627 event
.SetEventObject(this);
3629 return GetEventHandler()->ProcessEvent(event
);
3632 bool wxWindowMSW::HandleQueryNewPalette()
3636 // check to see if we our our parents have a custom palette
3637 wxWindowMSW
*win
= this;
3638 while (!win
->HasCustomPalette() && win
->GetParent()) win
= win
->GetParent();
3639 if (win
->HasCustomPalette()) {
3640 /* realize the palette to see whether redrawing is needed */
3641 HDC hdc
= GetDC((HWND
) GetHWND());
3642 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3643 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) );
3645 int result
= ::RealizePalette(hdc
);
3646 /* restore the palette (before releasing the DC) */
3647 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3648 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) );
3649 ::RealizePalette(hdc
);
3650 ::ReleaseDC((HWND
) GetHWND(), hdc
);
3651 /* now check for the need to redraw */
3653 ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
);
3655 #endif // wxUSE_PALETTE
3657 wxQueryNewPaletteEvent
event(GetId());
3658 event
.SetEventObject(this);
3660 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3663 // Responds to colour changes: passes event on to children.
3664 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
))
3666 // the top level window also reset the standard colour map as it might have
3667 // changed (there is no need to do it for the non top level windows as we
3668 // only have to do it once)
3672 gs_hasStdCmap
= FALSE
;
3674 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3677 // Only propagate to non-top-level windows because Windows already
3678 // sends this event to all top-level ones
3679 wxWindow
*win
= node
->GetData();
3680 if ( !win
->IsTopLevel() )
3682 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3683 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3684 // the standard controls
3685 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3688 node
= node
->GetNext();
3691 // update the colours we use if they were not set explicitly by the user:
3692 // this must be done or OnCtlColor() would continue to use the old colours
3695 m_foregroundColour
= wxSystemSettings::
3696 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT
);
3701 m_backgroundColour
= wxSystemSettings::
3702 GetSystemColour(wxSYS_COLOUR_BTNFACE
);
3706 extern wxCOLORMAP
*wxGetStdColourMap()
3708 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3709 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3711 if ( !gs_hasStdCmap
)
3713 static bool s_coloursInit
= FALSE
;
3715 if ( !s_coloursInit
)
3717 // When a bitmap is loaded, the RGB values can change (apparently
3718 // because Windows adjusts them to care for the old programs always
3719 // using 0xc0c0c0 while the transparent colour for the new Windows
3720 // versions is different). But we do this adjustment ourselves so
3721 // we want to avoid Windows' "help" and for this we need to have a
3722 // reference bitmap which can tell us what the RGB values change
3724 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3725 if ( stdColourBitmap
.Ok() )
3727 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3728 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3729 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3732 memDC
.SelectObject(stdColourBitmap
);
3735 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3737 memDC
.GetPixel(i
, 0, &colour
);
3738 s_stdColours
[i
] = wxColourToRGB(colour
);
3741 else // wxBITMAP_STD_COLOURS couldn't be loaded
3743 s_stdColours
[0] = RGB(000,000,000); // black
3744 s_stdColours
[1] = RGB(128,128,128); // dark grey
3745 s_stdColours
[2] = RGB(192,192,192); // light grey
3746 s_stdColours
[3] = RGB(255,255,255); // white
3747 //s_stdColours[4] = RGB(000,000,255); // blue
3748 //s_stdColours[5] = RGB(255,000,255); // magenta
3751 s_coloursInit
= TRUE
;
3754 gs_hasStdCmap
= TRUE
;
3756 // create the colour map
3757 #define INIT_CMAP_ENTRY(col) \
3758 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3759 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3761 INIT_CMAP_ENTRY(BTNTEXT
);
3762 INIT_CMAP_ENTRY(BTNSHADOW
);
3763 INIT_CMAP_ENTRY(BTNFACE
);
3764 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3766 #undef INIT_CMAP_ENTRY
3772 // ---------------------------------------------------------------------------
3774 // ---------------------------------------------------------------------------
3776 bool wxWindowMSW::HandlePaint()
3778 // if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
3781 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3783 wxLogLastError(wxT("CreateRectRgn"));
3784 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3785 wxLogLastError(wxT("GetUpdateRgn"));
3787 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3789 wxPaintEvent
event(m_windowId
);
3790 event
.SetEventObject(this);
3792 bool processed
= GetEventHandler()->ProcessEvent(event
);
3794 // note that we must generate NC event after the normal one as otherwise
3795 // BeginPaint() will happily overwrite our decorations with the background
3797 wxNcPaintEvent
eventNc(m_windowId
);
3798 eventNc
.SetEventObject(this);
3799 GetEventHandler()->ProcessEvent(eventNc
);
3804 // Can be called from an application's OnPaint handler
3805 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3807 #ifdef __WXUNIVERSAL__
3810 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3813 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3818 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3820 // Prevents flicker when dragging
3821 if ( ::IsIconic(GetHwnd()) )
3825 if (GetParent() && GetParent()->GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND
)
3830 if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND
)
3832 if (wxUxThemeEngine::Get())
3834 WXHTHEME hTheme
= wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L
"TAB");
3838 ::GetClientRect((HWND
) GetHWND(), (RECT
*) & rect
);
3839 wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme
, hdc
, 10 /* TABP_BODY */, 0, &rect
, &rect
);
3840 wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme
);
3850 dc
.SetWindow((wxWindow
*)this);
3853 wxEraseEvent
event(m_windowId
, &dc
);
3854 event
.SetEventObject(this);
3855 bool rc
= GetEventHandler()->ProcessEvent(event
);
3859 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3860 dc
.SelectOldObjects(hdc
);
3865 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3868 ::GetClientRect(GetHwnd(), &rect
);
3870 COLORREF ref
= PALETTERGB(m_backgroundColour
.Red(),
3871 m_backgroundColour
.Green(),
3872 m_backgroundColour
.Blue());
3873 HBRUSH hBrush
= ::CreateSolidBrush(ref
);
3875 wxLogLastError(wxT("CreateSolidBrush"));
3877 HDC hdc
= (HDC
)event
.GetDC()->GetHDC();
3880 int mode
= ::SetMapMode(hdc
, MM_TEXT
);
3883 ::FillRect(hdc
, &rect
, hBrush
);
3884 ::DeleteObject(hBrush
);
3887 ::SetMapMode(hdc
, mode
);
3891 // ---------------------------------------------------------------------------
3892 // moving and resizing
3893 // ---------------------------------------------------------------------------
3895 bool wxWindowMSW::HandleMinimize()
3897 wxIconizeEvent
event(m_windowId
);
3898 event
.SetEventObject(this);
3900 return GetEventHandler()->ProcessEvent(event
);
3903 bool wxWindowMSW::HandleMaximize()
3905 wxMaximizeEvent
event(m_windowId
);
3906 event
.SetEventObject(this);
3908 return GetEventHandler()->ProcessEvent(event
);
3911 bool wxWindowMSW::HandleMove(int x
, int y
)
3913 wxMoveEvent
event(wxPoint(x
, y
), m_windowId
);
3914 event
.SetEventObject(this);
3916 return GetEventHandler()->ProcessEvent(event
);
3919 bool wxWindowMSW::HandleMoving(wxRect
& rect
)
3921 wxMoveEvent
event(rect
, m_windowId
);
3922 event
.SetEventObject(this);
3924 bool rc
= GetEventHandler()->ProcessEvent(event
);
3926 rect
= event
.GetRect();
3930 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
),
3931 WXUINT
WXUNUSED(flag
))
3933 // don't use w and h parameters as they specify the client size while
3934 // according to the docs EVT_SIZE handler is supposed to receive the total
3936 wxSizeEvent
event(GetSize(), m_windowId
);
3937 event
.SetEventObject(this);
3939 return GetEventHandler()->ProcessEvent(event
);
3942 bool wxWindowMSW::HandleSizing(wxRect
& rect
)
3944 wxSizeEvent
event(rect
, m_windowId
);
3945 event
.SetEventObject(this);
3947 bool rc
= GetEventHandler()->ProcessEvent(event
);
3949 rect
= event
.GetRect();
3953 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
3958 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
3962 int minWidth
= GetMinWidth(),
3963 minHeight
= GetMinHeight(),
3964 maxWidth
= GetMaxWidth(),
3965 maxHeight
= GetMaxHeight();
3967 if ( minWidth
!= -1 )
3969 info
->ptMinTrackSize
.x
= minWidth
;
3973 if ( minHeight
!= -1 )
3975 info
->ptMinTrackSize
.y
= minHeight
;
3979 if ( maxWidth
!= -1 )
3981 info
->ptMaxTrackSize
.x
= maxWidth
;
3985 if ( maxHeight
!= -1 )
3987 info
->ptMaxTrackSize
.y
= maxHeight
;
3995 // ---------------------------------------------------------------------------
3997 // ---------------------------------------------------------------------------
3999 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
4001 #if wxUSE_MENUS_NATIVE
4002 if ( !cmd
&& wxCurrentPopupMenu
)
4004 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
4005 wxCurrentPopupMenu
= NULL
;
4007 return popupMenu
->MSWCommand(cmd
, id
);
4009 #endif // wxUSE_MENUS_NATIVE
4011 wxWindow
*win
= NULL
;
4013 // first try to find it from HWND - this works even with the broken
4014 // programs using the same ids for different controls
4017 win
= wxFindWinFromHandle(control
);
4023 // must cast to a signed type before comparing with other ids!
4024 win
= FindItem((signed short)id
);
4029 return win
->MSWCommand(cmd
, id
);
4032 // the messages sent from the in-place edit control used by the treectrl
4033 // for label editing have id == 0, but they should _not_ be treated as menu
4034 // messages (they are EN_XXX ones, in fact) so don't translate anything
4035 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
4038 // If no child window, it may be an accelerator, e.g. for a popup menu
4041 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
4042 event
.SetEventObject(this);
4046 return GetEventHandler()->ProcessEvent(event
);
4048 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4051 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
4052 // notifications to its parent which we want to reflect back to
4054 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
4055 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
4058 #endif // wxUSE_SPINCTRL
4063 bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam
, WXLPARAM
WXUNUSED(lParam
))
4066 // 4 bits are reserved
4067 switch ( wParam
& 0xFFFFFFF0 )
4070 return HandleMaximize();
4073 return HandleMinimize();
4080 // ---------------------------------------------------------------------------
4082 // ---------------------------------------------------------------------------
4084 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
4088 // our client coords are not quite the same as Windows ones
4089 wxPoint pt
= GetClientAreaOrigin();
4090 event
.m_x
= x
- pt
.x
;
4091 event
.m_y
= y
- pt
.y
;
4093 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
4094 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
4095 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
4096 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
4097 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
4098 // event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0;
4099 // Returns different negative values on WinME and WinNT,
4100 // so simply test for negative value.
4101 event
.m_altDown
= ::GetKeyState(VK_MENU
) < 0;
4103 event
.SetTimestamp(s_currentMsg
.time
);
4104 event
.m_eventObject
= this;
4105 event
.SetId(GetId());
4107 #if wxUSE_MOUSEEVENT_HACK
4110 m_lastMouseEvent
= event
.GetEventType();
4111 #endif // wxUSE_MOUSEEVENT_HACK
4114 // Windows doesn't send the mouse events to the static controls (which are
4115 // transparent in the sense that their WM_NCHITTEST handler returns
4116 // HTTRANSPARENT) at all but we want all controls to receive the mouse events
4117 // and so we manually check if we don't have a child window under mouse and if
4118 // we do, send the event to it instead of the window Windows had sent WM_XXX
4121 // Notice that this is not done for the mouse move events because this could
4122 // (would?) be too slow, but only for clicks which means that the static texts
4123 // still don't get move, enter nor leave events.
4124 static wxWindowMSW
*FindWindowForMouseEvent(wxWindowMSW
*win
, int *x
, int *y
) //TW:REQ:Univ
4126 wxCHECK_MSG( x
&& y
, win
, _T("NULL pointer in FindWindowForMouseEvent") );
4128 // first try to find a non transparent child: this allows us to send events
4129 // to a static text which is inside a static box, for example
4130 POINT pt
= { *x
, *y
};
4131 HWND hwnd
= GetHwndOf(win
),
4135 hwndUnderMouse
= ::ChildWindowFromPoint
4141 hwndUnderMouse
= ::ChildWindowFromPointEx
4151 if ( !hwndUnderMouse
|| hwndUnderMouse
== hwnd
)
4153 // now try any child window at all
4154 hwndUnderMouse
= ::ChildWindowFromPoint(hwnd
, pt
);
4157 // check that we have a child window which is susceptible to receive mouse
4158 // events: for this it must be shown and enabled
4159 if ( hwndUnderMouse
&&
4160 hwndUnderMouse
!= hwnd
&&
4161 ::IsWindowVisible(hwndUnderMouse
) &&
4162 ::IsWindowEnabled(hwndUnderMouse
) )
4164 wxWindow
*winUnderMouse
= wxFindWinFromHandle((WXHWND
)hwndUnderMouse
);
4165 if ( winUnderMouse
)
4167 // translate the mouse coords to the other window coords
4168 win
->ClientToScreen(x
, y
);
4169 winUnderMouse
->ScreenToClient(x
, y
);
4171 win
= winUnderMouse
;
4178 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4180 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
4181 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
4182 // from the message id and take the value in the table to get wxWin event
4184 static const wxEventType eventsMouse
[] =
4198 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
4199 InitMouseEvent(event
, x
, y
, flags
);
4201 return GetEventHandler()->ProcessEvent(event
);
4204 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
4206 if ( !m_mouseInWindow
)
4208 // it would be wrong to assume that just because we get a mouse move
4209 // event that the mouse is inside the window: although this is usually
4210 // true, it is not if we had captured the mouse, so we need to check
4211 // the mouse coordinates here
4212 if ( !HasCapture() || IsMouseInWindow() )
4214 // Generate an ENTER event
4215 m_mouseInWindow
= TRUE
;
4217 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
4218 InitMouseEvent(event
, x
, y
, flags
);
4220 (void)GetEventHandler()->ProcessEvent(event
);
4224 #if wxUSE_MOUSEEVENT_HACK
4225 // Window gets a click down message followed by a mouse move message even
4226 // if position isn't changed! We want to discard the trailing move event
4227 // if x and y are the same.
4228 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
4229 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
4230 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
4231 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
4233 m_lastMouseEvent
= wxEVT_MOTION
;
4237 #endif // wxUSE_MOUSEEVENT_HACK
4239 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
4243 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
4245 #if wxUSE_MOUSEWHEEL
4246 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
4247 InitMouseEvent(event
,
4248 GET_X_LPARAM(lParam
),
4249 GET_Y_LPARAM(lParam
),
4251 event
.m_wheelRotation
= (short)HIWORD(wParam
);
4252 event
.m_wheelDelta
= WHEEL_DELTA
;
4254 static int s_linesPerRotation
= -1;
4255 if ( s_linesPerRotation
== -1 )
4257 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
4258 &s_linesPerRotation
, 0))
4260 // this is not supposed to happen
4261 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
4263 // the default is 3, so use it if SystemParametersInfo() failed
4264 s_linesPerRotation
= 3;
4268 event
.m_linesPerAction
= s_linesPerRotation
;
4269 return GetEventHandler()->ProcessEvent(event
);
4280 // ---------------------------------------------------------------------------
4281 // keyboard handling
4282 // ---------------------------------------------------------------------------
4284 // create the key event of the given type for the given key - used by
4285 // HandleChar and HandleKeyDown/Up
4286 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
4289 WXWPARAM wParam
) const
4291 wxKeyEvent
event(evType
);
4292 event
.SetId(GetId());
4293 event
.m_shiftDown
= wxIsShiftDown();
4294 event
.m_controlDown
= wxIsCtrlDown();
4295 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
4297 event
.m_eventObject
= (wxWindow
*)this; // const_cast
4298 event
.m_keyCode
= id
;
4299 event
.m_rawCode
= (wxUint32
) wParam
;
4300 event
.m_rawFlags
= (wxUint32
) lParam
;
4301 event
.SetTimestamp(s_currentMsg
.time
);
4303 // translate the position to client coords
4307 GetWindowRect(GetHwnd(),&rect
);
4317 // isASCII is TRUE only when we're called from WM_CHAR handler and not from
4319 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
4324 // If 1 -> 26, translate to either special keycode or just set
4325 // ctrlDown. IOW, Ctrl-C should result in keycode == 3 and
4326 // ControlDown() == TRUE.
4328 if ( (id
> 0) && (id
< 27) )
4350 else // we're called from WM_KEYDOWN
4352 id
= wxCharCodeMSWToWX(wParam
);
4355 // it's ASCII and will be processed here only when called from
4356 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
4361 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
));
4363 // the alphanumeric keys produced by pressing AltGr+something on European
4364 // keyboards have both Ctrl and Alt modifiers which may confuse the user
4365 // code as, normally, keys with Ctrl and/or Alt don't result in anything
4366 // alphanumeric, so pretend that there are no modifiers at all (the
4367 // KEY_DOWN event would still have the correct modifiers if they're really
4369 if ( event
.m_controlDown
&& event
.m_altDown
&&
4370 (id
>= 32 && id
< 256) )
4372 event
.m_controlDown
=
4373 event
.m_altDown
= FALSE
;
4376 return GetEventHandler()->ProcessEvent(event
);
4379 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
4381 int id
= wxCharCodeMSWToWX(wParam
);
4385 // normal ASCII char
4389 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4391 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
));
4392 if ( GetEventHandler()->ProcessEvent(event
) )
4401 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
4403 int id
= wxCharCodeMSWToWX(wParam
);
4407 // normal ASCII char
4411 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4413 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
));
4414 if ( GetEventHandler()->ProcessEvent(event
) )
4421 int wxWindowMSW::HandleMenuChar(int chAccel
, WXLPARAM lParam
)
4423 // FIXME: implement GetMenuItemCount for WinCE, possibly
4424 // in terms of GetMenuItemInfo
4426 const HMENU hmenu
= (HMENU
)lParam
;
4430 mii
.cbSize
= sizeof(MENUITEMINFO
);
4431 mii
.fMask
= MIIM_TYPE
| MIIM_DATA
;
4433 // find if we have this letter in any owner drawn item
4434 const int count
= ::GetMenuItemCount(hmenu
);
4435 for ( int i
= 0; i
< count
; i
++ )
4437 if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) )
4439 if ( mii
.fType
== MFT_OWNERDRAW
)
4441 // dwItemData member of the MENUITEMINFO is a
4442 // pointer to the associated wxMenuItem -- see the
4443 // menu creation code
4444 wxMenuItem
*item
= (wxMenuItem
*)mii
.dwItemData
;
4446 const wxChar
*p
= wxStrchr(item
->GetText(), _T('&'));
4449 if ( *p
== _T('&') )
4451 // this is not the accel char, find the real one
4452 p
= wxStrchr(p
+ 1, _T('&'));
4454 else // got the accel char
4456 // FIXME-UNICODE: this comparison doesn't risk to work
4457 // for non ASCII accelerator characters I'm afraid, but
4459 if ( wxToupper(*p
) == chAccel
)
4465 // this one doesn't match
4472 else // failed to get the menu text?
4474 // it's not fatal, so don't show error, but still log
4476 wxLogLastError(_T("GetMenuItemInfo"));
4483 // ---------------------------------------------------------------------------
4485 // ---------------------------------------------------------------------------
4487 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4491 if ( flags
& JOY_BUTTON1CHG
)
4492 change
= wxJOY_BUTTON1
;
4493 if ( flags
& JOY_BUTTON2CHG
)
4494 change
= wxJOY_BUTTON2
;
4495 if ( flags
& JOY_BUTTON3CHG
)
4496 change
= wxJOY_BUTTON3
;
4497 if ( flags
& JOY_BUTTON4CHG
)
4498 change
= wxJOY_BUTTON4
;
4501 if ( flags
& JOY_BUTTON1
)
4502 buttons
|= wxJOY_BUTTON1
;
4503 if ( flags
& JOY_BUTTON2
)
4504 buttons
|= wxJOY_BUTTON2
;
4505 if ( flags
& JOY_BUTTON3
)
4506 buttons
|= wxJOY_BUTTON3
;
4507 if ( flags
& JOY_BUTTON4
)
4508 buttons
|= wxJOY_BUTTON4
;
4510 // the event ids aren't consecutive so we can't use table based lookup
4512 wxEventType eventType
;
4517 eventType
= wxEVT_JOY_MOVE
;
4522 eventType
= wxEVT_JOY_MOVE
;
4527 eventType
= wxEVT_JOY_ZMOVE
;
4532 eventType
= wxEVT_JOY_ZMOVE
;
4535 case MM_JOY1BUTTONDOWN
:
4537 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4540 case MM_JOY2BUTTONDOWN
:
4542 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4545 case MM_JOY1BUTTONUP
:
4547 eventType
= wxEVT_JOY_BUTTON_UP
;
4550 case MM_JOY2BUTTONUP
:
4552 eventType
= wxEVT_JOY_BUTTON_UP
;
4556 wxFAIL_MSG(wxT("no such joystick event"));
4561 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4562 event
.SetPosition(wxPoint(x
, y
));
4563 event
.SetEventObject(this);
4565 return GetEventHandler()->ProcessEvent(event
);
4571 // ---------------------------------------------------------------------------
4573 // ---------------------------------------------------------------------------
4575 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4576 WXWORD pos
, WXHWND control
)
4580 wxWindow
*child
= wxFindWinFromHandle(control
);
4582 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4585 wxScrollWinEvent event
;
4586 event
.SetPosition(pos
);
4587 event
.SetOrientation(orientation
);
4588 event
.m_eventObject
= this;
4593 event
.m_eventType
= wxEVT_SCROLLWIN_TOP
;
4597 event
.m_eventType
= wxEVT_SCROLLWIN_BOTTOM
;
4601 event
.m_eventType
= wxEVT_SCROLLWIN_LINEUP
;
4605 event
.m_eventType
= wxEVT_SCROLLWIN_LINEDOWN
;
4609 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEUP
;
4613 event
.m_eventType
= wxEVT_SCROLLWIN_PAGEDOWN
;
4616 case SB_THUMBPOSITION
:
4618 // under Win32, the scrollbar range and position are 32 bit integers,
4619 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4620 // explicitly query the scrollbar for the correct position (this must
4621 // be done only for these two SB_ events as they are the only one
4622 // carrying the scrollbar position)
4624 WinStruct
<SCROLLINFO
> scrollInfo
;
4625 scrollInfo
.fMask
= SIF_TRACKPOS
;
4627 if ( !::GetScrollInfo(GetHwnd(),
4628 orientation
== wxHORIZONTAL
? SB_HORZ
4632 // Not neccessarily an error, if there are no scrollbars yet.
4633 // wxLogLastError(_T("GetScrollInfo"));
4636 event
.SetPosition(scrollInfo
.nTrackPos
);
4639 event
.m_eventType
= wParam
== SB_THUMBPOSITION
4640 ? wxEVT_SCROLLWIN_THUMBRELEASE
4641 : wxEVT_SCROLLWIN_THUMBTRACK
;
4648 return GetEventHandler()->ProcessEvent(event
);
4651 // ===========================================================================
4653 // ===========================================================================
4655 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
*the_font
)
4658 HDC dc
= ::GetDC((HWND
) wnd
);
4663 // the_font->UseResource();
4664 // the_font->RealizeResource();
4665 fnt
= (HFONT
)((wxFont
*)the_font
)->GetResourceHandle(); // const_cast
4667 was
= (HFONT
) SelectObject(dc
,fnt
);
4669 GetTextMetrics(dc
, &tm
);
4670 if ( the_font
&& fnt
&& was
)
4672 SelectObject(dc
,was
);
4674 ReleaseDC((HWND
)wnd
, dc
);
4677 *x
= tm
.tmAveCharWidth
;
4679 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4682 // the_font->ReleaseResource();
4685 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4686 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4687 int wxCharCodeMSWToWX(int keySym
)
4692 case VK_CANCEL
: id
= WXK_CANCEL
; break;
4693 case VK_BACK
: id
= WXK_BACK
; break;
4694 case VK_TAB
: id
= WXK_TAB
; break;
4695 case VK_CLEAR
: id
= WXK_CLEAR
; break;
4696 case VK_RETURN
: id
= WXK_RETURN
; break;
4697 case VK_SHIFT
: id
= WXK_SHIFT
; break;
4698 case VK_CONTROL
: id
= WXK_CONTROL
; break;
4699 case VK_MENU
: id
= WXK_MENU
; break;
4700 case VK_PAUSE
: id
= WXK_PAUSE
; break;
4701 case VK_CAPITAL
: id
= WXK_CAPITAL
; break;
4702 case VK_SPACE
: id
= WXK_SPACE
; break;
4703 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
4704 case VK_PRIOR
: id
= WXK_PRIOR
; break;
4705 case VK_NEXT
: id
= WXK_NEXT
; break;
4706 case VK_END
: id
= WXK_END
; break;
4707 case VK_HOME
: id
= WXK_HOME
; break;
4708 case VK_LEFT
: id
= WXK_LEFT
; break;
4709 case VK_UP
: id
= WXK_UP
; break;
4710 case VK_RIGHT
: id
= WXK_RIGHT
; break;
4711 case VK_DOWN
: id
= WXK_DOWN
; break;
4712 case VK_SELECT
: id
= WXK_SELECT
; break;
4713 case VK_PRINT
: id
= WXK_PRINT
; break;
4714 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
4715 case VK_INSERT
: id
= WXK_INSERT
; break;
4716 case VK_DELETE
: id
= WXK_DELETE
; break;
4717 case VK_HELP
: id
= WXK_HELP
; break;
4718 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
4719 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
4720 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
4721 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
4722 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
4723 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
4724 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
4725 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
4726 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
4727 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
4728 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
4729 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
4730 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
4731 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
4732 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
4733 case VK_F1
: id
= WXK_F1
; break;
4734 case VK_F2
: id
= WXK_F2
; break;
4735 case VK_F3
: id
= WXK_F3
; break;
4736 case VK_F4
: id
= WXK_F4
; break;
4737 case VK_F5
: id
= WXK_F5
; break;
4738 case VK_F6
: id
= WXK_F6
; break;
4739 case VK_F7
: id
= WXK_F7
; break;
4740 case VK_F8
: id
= WXK_F8
; break;
4741 case VK_F9
: id
= WXK_F9
; break;
4742 case VK_F10
: id
= WXK_F10
; break;
4743 case VK_F11
: id
= WXK_F11
; break;
4744 case VK_F12
: id
= WXK_F12
; break;
4745 case VK_F13
: id
= WXK_F13
; break;
4746 case VK_F14
: id
= WXK_F14
; break;
4747 case VK_F15
: id
= WXK_F15
; break;
4748 case VK_F16
: id
= WXK_F16
; break;
4749 case VK_F17
: id
= WXK_F17
; break;
4750 case VK_F18
: id
= WXK_F18
; break;
4751 case VK_F19
: id
= WXK_F19
; break;
4752 case VK_F20
: id
= WXK_F20
; break;
4753 case VK_F21
: id
= WXK_F21
; break;
4754 case VK_F22
: id
= WXK_F22
; break;
4755 case VK_F23
: id
= WXK_F23
; break;
4756 case VK_F24
: id
= WXK_F24
; break;
4757 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
4758 case VK_SCROLL
: id
= WXK_SCROLL
; break;
4760 case VK_OEM_1
: id
= ';'; break;
4761 case VK_OEM_PLUS
: id
= '+'; break;
4762 case VK_OEM_COMMA
: id
= ','; break;
4763 case VK_OEM_MINUS
: id
= '-'; break;
4764 case VK_OEM_PERIOD
: id
= '.'; break;
4765 case VK_OEM_2
: id
= '/'; break;
4766 case VK_OEM_3
: id
= '~'; break;
4767 case VK_OEM_4
: id
= '['; break;
4768 case VK_OEM_5
: id
= '\\'; break;
4769 case VK_OEM_6
: id
= ']'; break;
4770 case VK_OEM_7
: id
= '\''; break;
4773 case VK_LWIN
: id
= WXK_WINDOWS_LEFT
; break;
4774 case VK_RWIN
: id
= WXK_WINDOWS_RIGHT
; break;
4775 case VK_APPS
: id
= WXK_WINDOWS_MENU
; break;
4776 #endif // VK_APPS defined
4785 int wxCharCodeWXToMSW(int id
, bool *isVirtual
)
4791 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
4792 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
4793 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
4794 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
4795 case WXK_MENU
: keySym
= VK_MENU
; break;
4796 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
4797 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
4798 case WXK_NEXT
: keySym
= VK_NEXT
; break;
4799 case WXK_END
: keySym
= VK_END
; break;
4800 case WXK_HOME
: keySym
= VK_HOME
; break;
4801 case WXK_LEFT
: keySym
= VK_LEFT
; break;
4802 case WXK_UP
: keySym
= VK_UP
; break;
4803 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
4804 case WXK_DOWN
: keySym
= VK_DOWN
; break;
4805 case WXK_SELECT
: keySym
= VK_SELECT
; break;
4806 case WXK_PRINT
: keySym
= VK_PRINT
; break;
4807 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
4808 case WXK_INSERT
: keySym
= VK_INSERT
; break;
4809 case WXK_DELETE
: keySym
= VK_DELETE
; break;
4810 case WXK_HELP
: keySym
= VK_HELP
; break;
4811 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
4812 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
4813 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
4814 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
4815 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
4816 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
4817 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
4818 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
4819 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
4820 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
4821 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
4822 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
4823 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
4824 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
4825 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
4826 case WXK_F1
: keySym
= VK_F1
; break;
4827 case WXK_F2
: keySym
= VK_F2
; break;
4828 case WXK_F3
: keySym
= VK_F3
; break;
4829 case WXK_F4
: keySym
= VK_F4
; break;
4830 case WXK_F5
: keySym
= VK_F5
; break;
4831 case WXK_F6
: keySym
= VK_F6
; break;
4832 case WXK_F7
: keySym
= VK_F7
; break;
4833 case WXK_F8
: keySym
= VK_F8
; break;
4834 case WXK_F9
: keySym
= VK_F9
; break;
4835 case WXK_F10
: keySym
= VK_F10
; break;
4836 case WXK_F11
: keySym
= VK_F11
; break;
4837 case WXK_F12
: keySym
= VK_F12
; break;
4838 case WXK_F13
: keySym
= VK_F13
; break;
4839 case WXK_F14
: keySym
= VK_F14
; break;
4840 case WXK_F15
: keySym
= VK_F15
; break;
4841 case WXK_F16
: keySym
= VK_F16
; break;
4842 case WXK_F17
: keySym
= VK_F17
; break;
4843 case WXK_F18
: keySym
= VK_F18
; break;
4844 case WXK_F19
: keySym
= VK_F19
; break;
4845 case WXK_F20
: keySym
= VK_F20
; break;
4846 case WXK_F21
: keySym
= VK_F21
; break;
4847 case WXK_F22
: keySym
= VK_F22
; break;
4848 case WXK_F23
: keySym
= VK_F23
; break;
4849 case WXK_F24
: keySym
= VK_F24
; break;
4850 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
4851 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
4862 wxWindow
*wxGetActiveWindow()
4864 HWND hWnd
= GetActiveWindow();
4867 return wxFindWinFromHandle((WXHWND
) hWnd
);
4872 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
4874 HWND hwnd
= (HWND
)hWnd
;
4876 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4877 // by code in msw/radiobox.cpp), for all the others we just search up the
4879 wxWindow
*win
= (wxWindow
*)NULL
;
4882 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4886 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4887 // wxWindow class which overrides WM_GETDLGCODE processing to
4888 // do it as well, win would be already non NULL
4889 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
4891 win
= (wxWindow
*)::GetWindowLong(hwnd
, GWL_USERDATA
);
4893 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4894 #endif // wxUSE_RADIOBOX
4896 // spin control text buddy window should be mapped to spin ctrl
4897 // itself so try it too
4898 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4901 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
4903 #endif // wxUSE_SPINCTRL
4907 while ( hwnd
&& !win
)
4909 // this is a really ugly hack needed to avoid mistakenly returning the
4910 // parent frame wxWindow for the find/replace modeless dialog HWND -
4911 // this, in turn, is needed to call IsDialogMessage() from
4912 // wxApp::ProcessMessage() as for this we must return NULL from here
4914 // FIXME: this is clearly not the best way to do it but I think we'll
4915 // need to change HWND <-> wxWindow code more heavily than I can
4916 // do it now to fix it
4917 #ifndef __WXMICROWIN__
4918 if ( ::GetWindow(hwnd
, GW_OWNER
) )
4920 // it's a dialog box, don't go upwards
4925 hwnd
= ::GetParent(hwnd
);
4926 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
4932 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
4934 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4935 // in active frames and dialogs, regardless of where the focus is.
4936 static HHOOK wxTheKeyboardHook
= 0;
4937 static FARPROC wxTheKeyboardHookProc
= 0;
4938 int APIENTRY _EXPORT
4939 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
4941 void wxSetKeyboardHook(bool doIt
)
4945 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
4946 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
4948 GetCurrentThreadId()
4949 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
4954 UnhookWindowsHookEx(wxTheKeyboardHook
);
4958 int APIENTRY _EXPORT
4959 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
4961 DWORD hiWord
= HIWORD(lParam
);
4962 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
4964 int id
= wxCharCodeMSWToWX(wParam
);
4967 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
4968 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
4969 event
.m_altDown
= TRUE
;
4971 event
.m_eventObject
= NULL
;
4972 event
.m_keyCode
= id
;
4973 event
.m_shiftDown
= wxIsShiftDown();
4974 event
.m_controlDown
= wxIsCtrlDown();
4975 event
.SetTimestamp(s_currentMsg
.time
);
4977 wxWindow
*win
= wxGetActiveWindow();
4978 wxEvtHandler
*handler
;
4981 handler
= win
->GetEventHandler();
4982 event
.SetId(win
->GetId());
4990 if ( handler
&& handler
->ProcessEvent(event
) )
4998 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
5001 #endif // !__WXMICROWIN__
5004 const char *wxGetMessageName(int message
)
5008 case 0x0000: return "WM_NULL";
5009 case 0x0001: return "WM_CREATE";
5010 case 0x0002: return "WM_DESTROY";
5011 case 0x0003: return "WM_MOVE";
5012 case 0x0005: return "WM_SIZE";
5013 case 0x0006: return "WM_ACTIVATE";
5014 case 0x0007: return "WM_SETFOCUS";
5015 case 0x0008: return "WM_KILLFOCUS";
5016 case 0x000A: return "WM_ENABLE";
5017 case 0x000B: return "WM_SETREDRAW";
5018 case 0x000C: return "WM_SETTEXT";
5019 case 0x000D: return "WM_GETTEXT";
5020 case 0x000E: return "WM_GETTEXTLENGTH";
5021 case 0x000F: return "WM_PAINT";
5022 case 0x0010: return "WM_CLOSE";
5023 case 0x0011: return "WM_QUERYENDSESSION";
5024 case 0x0012: return "WM_QUIT";
5025 case 0x0013: return "WM_QUERYOPEN";
5026 case 0x0014: return "WM_ERASEBKGND";
5027 case 0x0015: return "WM_SYSCOLORCHANGE";
5028 case 0x0016: return "WM_ENDSESSION";
5029 case 0x0017: return "WM_SYSTEMERROR";
5030 case 0x0018: return "WM_SHOWWINDOW";
5031 case 0x0019: return "WM_CTLCOLOR";
5032 case 0x001A: return "WM_WININICHANGE";
5033 case 0x001B: return "WM_DEVMODECHANGE";
5034 case 0x001C: return "WM_ACTIVATEAPP";
5035 case 0x001D: return "WM_FONTCHANGE";
5036 case 0x001E: return "WM_TIMECHANGE";
5037 case 0x001F: return "WM_CANCELMODE";
5038 case 0x0020: return "WM_SETCURSOR";
5039 case 0x0021: return "WM_MOUSEACTIVATE";
5040 case 0x0022: return "WM_CHILDACTIVATE";
5041 case 0x0023: return "WM_QUEUESYNC";
5042 case 0x0024: return "WM_GETMINMAXINFO";
5043 case 0x0026: return "WM_PAINTICON";
5044 case 0x0027: return "WM_ICONERASEBKGND";
5045 case 0x0028: return "WM_NEXTDLGCTL";
5046 case 0x002A: return "WM_SPOOLERSTATUS";
5047 case 0x002B: return "WM_DRAWITEM";
5048 case 0x002C: return "WM_MEASUREITEM";
5049 case 0x002D: return "WM_DELETEITEM";
5050 case 0x002E: return "WM_VKEYTOITEM";
5051 case 0x002F: return "WM_CHARTOITEM";
5052 case 0x0030: return "WM_SETFONT";
5053 case 0x0031: return "WM_GETFONT";
5054 case 0x0037: return "WM_QUERYDRAGICON";
5055 case 0x0039: return "WM_COMPAREITEM";
5056 case 0x0041: return "WM_COMPACTING";
5057 case 0x0044: return "WM_COMMNOTIFY";
5058 case 0x0046: return "WM_WINDOWPOSCHANGING";
5059 case 0x0047: return "WM_WINDOWPOSCHANGED";
5060 case 0x0048: return "WM_POWER";
5062 case 0x004A: return "WM_COPYDATA";
5063 case 0x004B: return "WM_CANCELJOURNAL";
5064 case 0x004E: return "WM_NOTIFY";
5065 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
5066 case 0x0051: return "WM_INPUTLANGCHANGE";
5067 case 0x0052: return "WM_TCARD";
5068 case 0x0053: return "WM_HELP";
5069 case 0x0054: return "WM_USERCHANGED";
5070 case 0x0055: return "WM_NOTIFYFORMAT";
5071 case 0x007B: return "WM_CONTEXTMENU";
5072 case 0x007C: return "WM_STYLECHANGING";
5073 case 0x007D: return "WM_STYLECHANGED";
5074 case 0x007E: return "WM_DISPLAYCHANGE";
5075 case 0x007F: return "WM_GETICON";
5076 case 0x0080: return "WM_SETICON";
5078 case 0x0081: return "WM_NCCREATE";
5079 case 0x0082: return "WM_NCDESTROY";
5080 case 0x0083: return "WM_NCCALCSIZE";
5081 case 0x0084: return "WM_NCHITTEST";
5082 case 0x0085: return "WM_NCPAINT";
5083 case 0x0086: return "WM_NCACTIVATE";
5084 case 0x0087: return "WM_GETDLGCODE";
5085 case 0x00A0: return "WM_NCMOUSEMOVE";
5086 case 0x00A1: return "WM_NCLBUTTONDOWN";
5087 case 0x00A2: return "WM_NCLBUTTONUP";
5088 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
5089 case 0x00A4: return "WM_NCRBUTTONDOWN";
5090 case 0x00A5: return "WM_NCRBUTTONUP";
5091 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
5092 case 0x00A7: return "WM_NCMBUTTONDOWN";
5093 case 0x00A8: return "WM_NCMBUTTONUP";
5094 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
5095 case 0x0100: return "WM_KEYDOWN";
5096 case 0x0101: return "WM_KEYUP";
5097 case 0x0102: return "WM_CHAR";
5098 case 0x0103: return "WM_DEADCHAR";
5099 case 0x0104: return "WM_SYSKEYDOWN";
5100 case 0x0105: return "WM_SYSKEYUP";
5101 case 0x0106: return "WM_SYSCHAR";
5102 case 0x0107: return "WM_SYSDEADCHAR";
5103 case 0x0108: return "WM_KEYLAST";
5105 case 0x010D: return "WM_IME_STARTCOMPOSITION";
5106 case 0x010E: return "WM_IME_ENDCOMPOSITION";
5107 case 0x010F: return "WM_IME_COMPOSITION";
5109 case 0x0110: return "WM_INITDIALOG";
5110 case 0x0111: return "WM_COMMAND";
5111 case 0x0112: return "WM_SYSCOMMAND";
5112 case 0x0113: return "WM_TIMER";
5113 case 0x0114: return "WM_HSCROLL";
5114 case 0x0115: return "WM_VSCROLL";
5115 case 0x0116: return "WM_INITMENU";
5116 case 0x0117: return "WM_INITMENUPOPUP";
5117 case 0x011F: return "WM_MENUSELECT";
5118 case 0x0120: return "WM_MENUCHAR";
5119 case 0x0121: return "WM_ENTERIDLE";
5120 case 0x0200: return "WM_MOUSEMOVE";
5121 case 0x0201: return "WM_LBUTTONDOWN";
5122 case 0x0202: return "WM_LBUTTONUP";
5123 case 0x0203: return "WM_LBUTTONDBLCLK";
5124 case 0x0204: return "WM_RBUTTONDOWN";
5125 case 0x0205: return "WM_RBUTTONUP";
5126 case 0x0206: return "WM_RBUTTONDBLCLK";
5127 case 0x0207: return "WM_MBUTTONDOWN";
5128 case 0x0208: return "WM_MBUTTONUP";
5129 case 0x0209: return "WM_MBUTTONDBLCLK";
5130 case 0x020A: return "WM_MOUSEWHEEL";
5131 case 0x0210: return "WM_PARENTNOTIFY";
5132 case 0x0211: return "WM_ENTERMENULOOP";
5133 case 0x0212: return "WM_EXITMENULOOP";
5135 case 0x0213: return "WM_NEXTMENU";
5136 case 0x0214: return "WM_SIZING";
5137 case 0x0215: return "WM_CAPTURECHANGED";
5138 case 0x0216: return "WM_MOVING";
5139 case 0x0218: return "WM_POWERBROADCAST";
5140 case 0x0219: return "WM_DEVICECHANGE";
5142 case 0x0220: return "WM_MDICREATE";
5143 case 0x0221: return "WM_MDIDESTROY";
5144 case 0x0222: return "WM_MDIACTIVATE";
5145 case 0x0223: return "WM_MDIRESTORE";
5146 case 0x0224: return "WM_MDINEXT";
5147 case 0x0225: return "WM_MDIMAXIMIZE";
5148 case 0x0226: return "WM_MDITILE";
5149 case 0x0227: return "WM_MDICASCADE";
5150 case 0x0228: return "WM_MDIICONARRANGE";
5151 case 0x0229: return "WM_MDIGETACTIVE";
5152 case 0x0230: return "WM_MDISETMENU";
5153 case 0x0233: return "WM_DROPFILES";
5155 case 0x0281: return "WM_IME_SETCONTEXT";
5156 case 0x0282: return "WM_IME_NOTIFY";
5157 case 0x0283: return "WM_IME_CONTROL";
5158 case 0x0284: return "WM_IME_COMPOSITIONFULL";
5159 case 0x0285: return "WM_IME_SELECT";
5160 case 0x0286: return "WM_IME_CHAR";
5161 case 0x0290: return "WM_IME_KEYDOWN";
5162 case 0x0291: return "WM_IME_KEYUP";
5164 case 0x0300: return "WM_CUT";
5165 case 0x0301: return "WM_COPY";
5166 case 0x0302: return "WM_PASTE";
5167 case 0x0303: return "WM_CLEAR";
5168 case 0x0304: return "WM_UNDO";
5169 case 0x0305: return "WM_RENDERFORMAT";
5170 case 0x0306: return "WM_RENDERALLFORMATS";
5171 case 0x0307: return "WM_DESTROYCLIPBOARD";
5172 case 0x0308: return "WM_DRAWCLIPBOARD";
5173 case 0x0309: return "WM_PAINTCLIPBOARD";
5174 case 0x030A: return "WM_VSCROLLCLIPBOARD";
5175 case 0x030B: return "WM_SIZECLIPBOARD";
5176 case 0x030C: return "WM_ASKCBFORMATNAME";
5177 case 0x030D: return "WM_CHANGECBCHAIN";
5178 case 0x030E: return "WM_HSCROLLCLIPBOARD";
5179 case 0x030F: return "WM_QUERYNEWPALETTE";
5180 case 0x0310: return "WM_PALETTEISCHANGING";
5181 case 0x0311: return "WM_PALETTECHANGED";
5183 case 0x0312: return "WM_HOTKEY";
5186 // common controls messages - although they're not strictly speaking
5187 // standard, it's nice to decode them nevertheless
5190 case 0x1000 + 0: return "LVM_GETBKCOLOR";
5191 case 0x1000 + 1: return "LVM_SETBKCOLOR";
5192 case 0x1000 + 2: return "LVM_GETIMAGELIST";
5193 case 0x1000 + 3: return "LVM_SETIMAGELIST";
5194 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
5195 case 0x1000 + 5: return "LVM_GETITEMA";
5196 case 0x1000 + 75: return "LVM_GETITEMW";
5197 case 0x1000 + 6: return "LVM_SETITEMA";
5198 case 0x1000 + 76: return "LVM_SETITEMW";
5199 case 0x1000 + 7: return "LVM_INSERTITEMA";
5200 case 0x1000 + 77: return "LVM_INSERTITEMW";
5201 case 0x1000 + 8: return "LVM_DELETEITEM";
5202 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
5203 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
5204 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
5205 case 0x1000 + 12: return "LVM_GETNEXTITEM";
5206 case 0x1000 + 13: return "LVM_FINDITEMA";
5207 case 0x1000 + 83: return "LVM_FINDITEMW";
5208 case 0x1000 + 14: return "LVM_GETITEMRECT";
5209 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
5210 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
5211 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
5212 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
5213 case 0x1000 + 18: return "LVM_HITTEST";
5214 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
5215 case 0x1000 + 20: return "LVM_SCROLL";
5216 case 0x1000 + 21: return "LVM_REDRAWITEMS";
5217 case 0x1000 + 22: return "LVM_ARRANGE";
5218 case 0x1000 + 23: return "LVM_EDITLABELA";
5219 case 0x1000 + 118: return "LVM_EDITLABELW";
5220 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
5221 case 0x1000 + 25: return "LVM_GETCOLUMNA";
5222 case 0x1000 + 95: return "LVM_GETCOLUMNW";
5223 case 0x1000 + 26: return "LVM_SETCOLUMNA";
5224 case 0x1000 + 96: return "LVM_SETCOLUMNW";
5225 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
5226 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
5227 case 0x1000 + 28: return "LVM_DELETECOLUMN";
5228 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
5229 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
5230 case 0x1000 + 31: return "LVM_GETHEADER";
5231 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
5232 case 0x1000 + 34: return "LVM_GETVIEWRECT";
5233 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
5234 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
5235 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
5236 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
5237 case 0x1000 + 39: return "LVM_GETTOPINDEX";
5238 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
5239 case 0x1000 + 41: return "LVM_GETORIGIN";
5240 case 0x1000 + 42: return "LVM_UPDATE";
5241 case 0x1000 + 43: return "LVM_SETITEMSTATE";
5242 case 0x1000 + 44: return "LVM_GETITEMSTATE";
5243 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
5244 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
5245 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
5246 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
5247 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
5248 case 0x1000 + 48: return "LVM_SORTITEMS";
5249 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
5250 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
5251 case 0x1000 + 51: return "LVM_GETITEMSPACING";
5252 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
5253 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
5254 case 0x1000 + 53: return "LVM_SETICONSPACING";
5255 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
5256 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
5257 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
5258 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
5259 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
5260 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
5261 case 0x1000 + 60: return "LVM_SETHOTITEM";
5262 case 0x1000 + 61: return "LVM_GETHOTITEM";
5263 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
5264 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
5265 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
5266 case 0x1000 + 65: return "LVM_SETWORKAREA";
5269 case 0x1100 + 0: return "TVM_INSERTITEMA";
5270 case 0x1100 + 50: return "TVM_INSERTITEMW";
5271 case 0x1100 + 1: return "TVM_DELETEITEM";
5272 case 0x1100 + 2: return "TVM_EXPAND";
5273 case 0x1100 + 4: return "TVM_GETITEMRECT";
5274 case 0x1100 + 5: return "TVM_GETCOUNT";
5275 case 0x1100 + 6: return "TVM_GETINDENT";
5276 case 0x1100 + 7: return "TVM_SETINDENT";
5277 case 0x1100 + 8: return "TVM_GETIMAGELIST";
5278 case 0x1100 + 9: return "TVM_SETIMAGELIST";
5279 case 0x1100 + 10: return "TVM_GETNEXTITEM";
5280 case 0x1100 + 11: return "TVM_SELECTITEM";
5281 case 0x1100 + 12: return "TVM_GETITEMA";
5282 case 0x1100 + 62: return "TVM_GETITEMW";
5283 case 0x1100 + 13: return "TVM_SETITEMA";
5284 case 0x1100 + 63: return "TVM_SETITEMW";
5285 case 0x1100 + 14: return "TVM_EDITLABELA";
5286 case 0x1100 + 65: return "TVM_EDITLABELW";
5287 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
5288 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
5289 case 0x1100 + 17: return "TVM_HITTEST";
5290 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
5291 case 0x1100 + 19: return "TVM_SORTCHILDREN";
5292 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
5293 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
5294 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
5295 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
5296 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
5297 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
5298 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
5301 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
5302 case 0x1200 + 1: return "HDM_INSERTITEMA";
5303 case 0x1200 + 10: return "HDM_INSERTITEMW";
5304 case 0x1200 + 2: return "HDM_DELETEITEM";
5305 case 0x1200 + 3: return "HDM_GETITEMA";
5306 case 0x1200 + 11: return "HDM_GETITEMW";
5307 case 0x1200 + 4: return "HDM_SETITEMA";
5308 case 0x1200 + 12: return "HDM_SETITEMW";
5309 case 0x1200 + 5: return "HDM_LAYOUT";
5310 case 0x1200 + 6: return "HDM_HITTEST";
5311 case 0x1200 + 7: return "HDM_GETITEMRECT";
5312 case 0x1200 + 8: return "HDM_SETIMAGELIST";
5313 case 0x1200 + 9: return "HDM_GETIMAGELIST";
5314 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
5315 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
5316 case 0x1200 + 17: return "HDM_GETORDERARRAY";
5317 case 0x1200 + 18: return "HDM_SETORDERARRAY";
5318 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
5321 case 0x1300 + 2: return "TCM_GETIMAGELIST";
5322 case 0x1300 + 3: return "TCM_SETIMAGELIST";
5323 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
5324 case 0x1300 + 5: return "TCM_GETITEMA";
5325 case 0x1300 + 60: return "TCM_GETITEMW";
5326 case 0x1300 + 6: return "TCM_SETITEMA";
5327 case 0x1300 + 61: return "TCM_SETITEMW";
5328 case 0x1300 + 7: return "TCM_INSERTITEMA";
5329 case 0x1300 + 62: return "TCM_INSERTITEMW";
5330 case 0x1300 + 8: return "TCM_DELETEITEM";
5331 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
5332 case 0x1300 + 10: return "TCM_GETITEMRECT";
5333 case 0x1300 + 11: return "TCM_GETCURSEL";
5334 case 0x1300 + 12: return "TCM_SETCURSEL";
5335 case 0x1300 + 13: return "TCM_HITTEST";
5336 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
5337 case 0x1300 + 40: return "TCM_ADJUSTRECT";
5338 case 0x1300 + 41: return "TCM_SETITEMSIZE";
5339 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
5340 case 0x1300 + 43: return "TCM_SETPADDING";
5341 case 0x1300 + 44: return "TCM_GETROWCOUNT";
5342 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
5343 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
5344 case 0x1300 + 47: return "TCM_GETCURFOCUS";
5345 case 0x1300 + 48: return "TCM_SETCURFOCUS";
5346 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
5347 case 0x1300 + 50: return "TCM_DESELECTALL";
5350 case WM_USER
+1: return "TB_ENABLEBUTTON";
5351 case WM_USER
+2: return "TB_CHECKBUTTON";
5352 case WM_USER
+3: return "TB_PRESSBUTTON";
5353 case WM_USER
+4: return "TB_HIDEBUTTON";
5354 case WM_USER
+5: return "TB_INDETERMINATE";
5355 case WM_USER
+9: return "TB_ISBUTTONENABLED";
5356 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
5357 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
5358 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
5359 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
5360 case WM_USER
+17: return "TB_SETSTATE";
5361 case WM_USER
+18: return "TB_GETSTATE";
5362 case WM_USER
+19: return "TB_ADDBITMAP";
5363 case WM_USER
+20: return "TB_ADDBUTTONS";
5364 case WM_USER
+21: return "TB_INSERTBUTTON";
5365 case WM_USER
+22: return "TB_DELETEBUTTON";
5366 case WM_USER
+23: return "TB_GETBUTTON";
5367 case WM_USER
+24: return "TB_BUTTONCOUNT";
5368 case WM_USER
+25: return "TB_COMMANDTOINDEX";
5369 case WM_USER
+26: return "TB_SAVERESTOREA";
5370 case WM_USER
+76: return "TB_SAVERESTOREW";
5371 case WM_USER
+27: return "TB_CUSTOMIZE";
5372 case WM_USER
+28: return "TB_ADDSTRINGA";
5373 case WM_USER
+77: return "TB_ADDSTRINGW";
5374 case WM_USER
+29: return "TB_GETITEMRECT";
5375 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
5376 case WM_USER
+31: return "TB_SETBUTTONSIZE";
5377 case WM_USER
+32: return "TB_SETBITMAPSIZE";
5378 case WM_USER
+33: return "TB_AUTOSIZE";
5379 case WM_USER
+35: return "TB_GETTOOLTIPS";
5380 case WM_USER
+36: return "TB_SETTOOLTIPS";
5381 case WM_USER
+37: return "TB_SETPARENT";
5382 case WM_USER
+39: return "TB_SETROWS";
5383 case WM_USER
+40: return "TB_GETROWS";
5384 case WM_USER
+42: return "TB_SETCMDID";
5385 case WM_USER
+43: return "TB_CHANGEBITMAP";
5386 case WM_USER
+44: return "TB_GETBITMAP";
5387 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
5388 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
5389 case WM_USER
+46: return "TB_REPLACEBITMAP";
5390 case WM_USER
+47: return "TB_SETINDENT";
5391 case WM_USER
+48: return "TB_SETIMAGELIST";
5392 case WM_USER
+49: return "TB_GETIMAGELIST";
5393 case WM_USER
+50: return "TB_LOADIMAGES";
5394 case WM_USER
+51: return "TB_GETRECT";
5395 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
5396 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
5397 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
5398 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
5399 case WM_USER
+56: return "TB_SETSTYLE";
5400 case WM_USER
+57: return "TB_GETSTYLE";
5401 case WM_USER
+58: return "TB_GETBUTTONSIZE";
5402 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
5403 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
5404 case WM_USER
+61: return "TB_GETTEXTROWS";
5405 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
5408 static char s_szBuf
[128];
5409 sprintf(s_szBuf
, "<unknown message = %d>", message
);
5413 #endif //__WXDEBUG__
5415 static void TranslateKbdEventToMouse(wxWindowMSW
*win
,
5416 int *x
, int *y
, WPARAM
*flags
)
5418 // construct the key mask
5419 WPARAM
& fwKeys
= *flags
;
5421 fwKeys
= MK_RBUTTON
;
5422 if ( wxIsCtrlDown() )
5423 fwKeys
|= MK_CONTROL
;
5424 if ( wxIsShiftDown() )
5427 // simulate right mouse button click
5428 DWORD dwPos
= ::GetMessagePos();
5429 *x
= GET_X_LPARAM(dwPos
);
5430 *y
= GET_Y_LPARAM(dwPos
);
5432 win
->ScreenToClient(x
, y
);
5435 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
5439 HWND hwnd
= GetHwndOf(win
);
5440 HDC hdc
= ::GetDC(hwnd
);
5442 #if !wxDIALOG_UNIT_COMPATIBILITY
5443 // and select the current font into it
5444 HFONT hfont
= GetHfontOf(win
->GetFont());
5447 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
5451 // finally retrieve the text metrics from it
5452 GetTextMetrics(hdc
, &tm
);
5454 #if !wxDIALOG_UNIT_COMPATIBILITY
5458 (void)::SelectObject(hdc
, hfont
);
5462 ::ReleaseDC(hwnd
, hdc
);
5467 // Find the wxWindow at the current mouse position, returning the mouse
5469 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
5471 pt
= wxGetMousePosition();
5472 return wxFindWindowAtPoint(pt
);
5475 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
5480 HWND hWndHit
= ::WindowFromPoint(pt2
);
5482 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
5483 HWND hWnd
= hWndHit
;
5485 // Try to find a window with a wxWindow associated with it
5486 while (!win
&& (hWnd
!= 0))
5488 hWnd
= ::GetParent(hWnd
);
5489 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
5494 // Get the current mouse position.
5495 wxPoint
wxGetMousePosition()
5498 GetCursorPos( & pt
);
5500 return wxPoint(pt
.x
, pt
.y
);
5505 bool wxWindowMSW::RegisterHotKey(int hotkeyId
, int modifiers
, int keycode
)
5507 UINT win_modifiers
=0;
5508 if ( modifiers
& wxMOD_ALT
)
5509 win_modifiers
|= MOD_ALT
;
5510 if ( modifiers
& wxMOD_SHIFT
)
5511 win_modifiers
|= MOD_SHIFT
;
5512 if ( modifiers
& wxMOD_CONTROL
)
5513 win_modifiers
|= MOD_CONTROL
;
5514 if ( modifiers
& wxMOD_WIN
)
5515 win_modifiers
|= MOD_WIN
;
5517 if ( !::RegisterHotKey(GetHwnd(), hotkeyId
, win_modifiers
, keycode
) )
5519 wxLogLastError(_T("RegisterHotKey"));
5527 bool wxWindowMSW::UnregisterHotKey(int hotkeyId
)
5529 if ( !::UnregisterHotKey(GetHwnd(), hotkeyId
) )
5531 wxLogLastError(_T("UnregisterHotKey"));
5539 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam
, WXLPARAM lParam
)
5541 int hotkeyId
= wParam
;
5542 int virtualKey
= HIWORD(lParam
);
5543 int win_modifiers
= LOWORD(lParam
);
5545 wxKeyEvent
event(CreateKeyEvent(wxEVT_HOTKEY
, virtualKey
, wParam
, lParam
));
5546 event
.SetId(hotkeyId
);
5547 event
.m_shiftDown
= (win_modifiers
& MOD_SHIFT
) != 0;
5548 event
.m_controlDown
= (win_modifiers
& MOD_CONTROL
) != 0;
5549 event
.m_altDown
= (win_modifiers
& MOD_ALT
) != 0;
5550 event
.m_metaDown
= (win_modifiers
& MOD_WIN
) != 0;
5552 return GetEventHandler()->ProcessEvent(event
);
5555 #endif // wxUSE_HOTKEY