1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/window.cpp
3 // Purpose: wxWindowMSW
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 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #include "wx/window.h"
30 #include "wx/msw/wrapwin.h"
31 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
32 #include "wx/msw/missing.h"
36 #include "wx/dcclient.h"
37 #include "wx/dcmemory.h"
40 #include "wx/layout.h"
41 #include "wx/dialog.h"
43 #include "wx/listbox.h"
44 #include "wx/button.h"
45 #include "wx/msgdlg.h"
46 #include "wx/settings.h"
47 #include "wx/statbox.h"
51 #include "wx/textctrl.h"
52 #include "wx/menuitem.h"
53 #include "wx/module.h"
56 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
57 #include "wx/ownerdrw.h"
60 #include "wx/hashmap.h"
61 #include "wx/evtloop.h"
63 #include "wx/sysopt.h"
65 #if wxUSE_DRAG_AND_DROP
69 #if wxUSE_ACCESSIBILITY
70 #include "wx/access.h"
74 #define WM_GETOBJECT 0x003D
77 #define OBJID_CLIENT 0xFFFFFFFC
81 #include "wx/msw/private.h"
84 #include "wx/tooltip.h"
92 #include "wx/spinctrl.h"
93 #endif // wxUSE_SPINCTRL
95 #include "wx/notebook.h"
96 #include "wx/listctrl.h"
97 #include "wx/dynlib.h"
101 #if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
102 #include <shellapi.h>
103 #include <mmsystem.h>
107 #include <windowsx.h>
110 #if !defined __WXWINCE__ && !defined NEED_PBT_H
114 #if defined(__WXWINCE__)
115 #include "wx/msw/wince/missing.h"
118 #include <shellapi.h>
120 #include <aygshell.h>
124 #if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS
125 #define HAVE_TRACKMOUSEEVENT
126 #endif // everything needed for TrackMouseEvent()
128 // if this is set to 1, we use deferred window sizing to reduce flicker when
129 // resizing complicated window hierarchies, but this can in theory result in
130 // different behaviour than the old code so we keep the possibility to use it
131 // by setting this to 0 (in the future this should be removed completely)
133 #define USE_DEFERRED_SIZING 0
135 #define USE_DEFERRED_SIZING 1
138 // set this to 1 to filter out duplicate mouse events, e.g. mouse move events
139 // when mouse position didnd't change
141 #define wxUSE_MOUSEEVENT_HACK 0
143 #define wxUSE_MOUSEEVENT_HACK 1
146 // not all compilers/platforms have X button related declarations (notably
147 // Windows CE doesn't, and probably some old SDKs don't neither)
148 #ifdef WM_XBUTTONDOWN
149 #define wxHAS_XBUTTON
152 // ---------------------------------------------------------------------------
154 // ---------------------------------------------------------------------------
156 #if wxUSE_MENUS_NATIVE
157 wxMenu
*wxCurrentPopupMenu
= NULL
;
158 #endif // wxUSE_MENUS_NATIVE
161 extern wxChar
*wxCanvasClassName
;
163 extern const wxChar
*wxCanvasClassName
;
166 // true if we had already created the std colour map, used by
167 // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
168 static bool gs_hasStdCmap
= false;
170 // last mouse event information we need to filter out the duplicates
171 #if wxUSE_MOUSEEVENT_HACK
172 static struct MouseEventInfoDummy
174 // mouse position (in screen coordinates)
177 // last mouse event type
180 #endif // wxUSE_MOUSEEVENT_HACK
182 // hash containing the registered handlers for the custom messages
183 WX_DECLARE_HASH_MAP(int, wxWindow::MSWMessageHandler
,
184 wxIntegerHash
, wxIntegerEqual
,
187 static MSWMessageHandlers gs_messageHandlers
;
189 // ---------------------------------------------------------------------------
191 // ---------------------------------------------------------------------------
193 // the window proc for all our windows
194 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
195 WPARAM wParam
, LPARAM lParam
);
199 const wxChar
*wxGetMessageName(int message
);
202 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
203 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
204 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
206 // get the text metrics for the current font
207 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
210 // find the window for the mouse event at the specified position
211 static wxWindowMSW
*FindWindowForMouseEvent(wxWindowMSW
*win
, int *x
, int *y
);
212 #endif // __WXWINCE__
214 // wrapper around BringWindowToTop() API
215 static inline void wxBringWindowToTop(HWND hwnd
)
217 #ifdef __WXMICROWIN__
218 // It seems that MicroWindows brings the _parent_ of the window to the top,
219 // which can be the wrong one.
221 // activate (set focus to) specified window
225 // raise top level parent to top of z order
226 if (!::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
))
228 wxLogLastError(_T("SetWindowPos"));
234 // ensure that all our parent windows have WS_EX_CONTROLPARENT style
235 static void EnsureParentHasControlParentStyle(wxWindow
*parent
)
238 If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
239 parent as well as otherwise several Win32 functions using
240 GetNextDlgTabItem() to iterate over all controls such as
241 IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
242 all of them iterate over all the controls starting from the currently
243 focused one and stop iterating when they get back to the focus but
244 unless all parents have WS_EX_CONTROLPARENT bit set, they would never
245 get back to the initial (focused) window: as we do have this style,
246 GetNextDlgTabItem() will leave this window and continue in its parent,
247 but if the parent doesn't have it, it wouldn't recurse inside it later
248 on and so wouldn't have a chance of getting back to this window either.
250 while ( parent
&& !parent
->IsTopLevel() )
252 LONG exStyle
= ::GetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
);
253 if ( !(exStyle
& WS_EX_CONTROLPARENT
) )
255 // force the parent to have this style
256 ::SetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
,
257 exStyle
| WS_EX_CONTROLPARENT
);
260 parent
= parent
->GetParent();
264 #endif // !__WXWINCE__
267 // On Windows CE, GetCursorPos can return an error, so use this function
269 bool GetCursorPosWinCE(POINT
* pt
)
271 if (!GetCursorPos(pt
))
273 DWORD pos
= GetMessagePos();
281 // ---------------------------------------------------------------------------
283 // ---------------------------------------------------------------------------
285 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
287 #ifdef __WXUNIVERSAL__
288 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
290 #if wxUSE_EXTENDED_RTTI
292 // windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls
293 // must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as
294 // windows with negative ids never can be recreated anyway
296 bool wxWindowStreamingCallback( const wxObject
*object
, wxWriter
* , wxPersister
* , wxxVariantArray
& )
298 const wxWindow
* win
= dynamic_cast<const wxWindow
*>(object
) ;
299 if ( win
&& win
->GetId() < 0 )
304 IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow
, wxWindowBase
,"wx/window.h", wxWindowStreamingCallback
)
306 // make wxWindowList known before the property is used
308 wxCOLLECTION_TYPE_INFO( wxWindow
* , wxWindowList
) ;
310 template<> void wxCollectionToVariantArray( wxWindowList
const &theList
, wxxVariantArray
&value
)
312 wxListCollectionToVariantArray
<wxWindowList::compatibility_iterator
>( theList
, value
) ;
315 WX_DEFINE_FLAGS( wxWindowStyle
)
317 wxBEGIN_FLAGS( wxWindowStyle
)
318 // new style border flags, we put them first to
319 // use them for streaming out
321 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
322 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
323 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
324 wxFLAGS_MEMBER(wxBORDER_RAISED
)
325 wxFLAGS_MEMBER(wxBORDER_STATIC
)
326 wxFLAGS_MEMBER(wxBORDER_NONE
)
328 // old style border flags
329 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
330 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
331 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
332 wxFLAGS_MEMBER(wxRAISED_BORDER
)
333 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
334 wxFLAGS_MEMBER(wxBORDER
)
336 // standard window styles
337 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
338 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
339 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
340 wxFLAGS_MEMBER(wxWANTS_CHARS
)
341 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
342 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
343 wxFLAGS_MEMBER(wxVSCROLL
)
344 wxFLAGS_MEMBER(wxHSCROLL
)
346 wxEND_FLAGS( wxWindowStyle
)
348 wxBEGIN_PROPERTIES_TABLE(wxWindow
)
349 wxEVENT_PROPERTY( Close
, wxEVT_CLOSE_WINDOW
, wxCloseEvent
)
350 wxEVENT_PROPERTY( Create
, wxEVT_CREATE
, wxWindowCreateEvent
)
351 wxEVENT_PROPERTY( Destroy
, wxEVT_DESTROY
, wxWindowDestroyEvent
)
352 // Always constructor Properties first
354 wxREADONLY_PROPERTY( Parent
,wxWindow
*, GetParent
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
355 wxPROPERTY( Id
,wxWindowID
, SetId
, GetId
, -1 /*wxID_ANY*/ , 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
356 wxPROPERTY( Position
,wxPoint
, SetPosition
, GetPosition
, wxDefaultPosition
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos
357 wxPROPERTY( Size
,wxSize
, SetSize
, GetSize
, wxDefaultSize
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size
358 wxPROPERTY( WindowStyle
, long , SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
360 // Then all relations of the object graph
362 wxREADONLY_PROPERTY_COLLECTION( Children
, wxWindowList
, wxWindowBase
* , GetWindowChildren
, wxPROP_OBJECT_GRAPH
/*flags*/ , wxT("Helpstring") , wxT("group"))
364 // and finally all other properties
366 wxPROPERTY( ExtraStyle
, long , SetExtraStyle
, GetExtraStyle
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle
367 wxPROPERTY( BackgroundColour
, wxColour
, SetBackgroundColour
, GetBackgroundColour
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg
368 wxPROPERTY( ForegroundColour
, wxColour
, SetForegroundColour
, GetForegroundColour
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg
369 wxPROPERTY( Enabled
, bool , Enable
, IsEnabled
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
370 wxPROPERTY( Shown
, bool , Show
, IsShown
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
372 // possible property candidates (not in xrc) or not valid in all subclasses
373 wxPROPERTY( Title
,wxString
, SetTitle
, GetTitle
, wxEmptyString
)
374 wxPROPERTY( Font
, wxFont
, SetFont
, GetWindowFont
, )
375 wxPROPERTY( Label
,wxString
, SetLabel
, GetLabel
, wxEmptyString
)
376 // MaxHeight, Width , MinHeight , Width
377 // TODO switch label to control and title to toplevels
379 wxPROPERTY( ThemeEnabled
, bool , SetThemeEnabled
, GetThemeEnabled
, )
380 //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , )
381 // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , )
382 wxPROPERTY( AutoLayout
, bool , SetAutoLayout
, GetAutoLayout
, )
387 wxEND_PROPERTIES_TABLE()
389 wxBEGIN_HANDLERS_TABLE(wxWindow
)
390 wxEND_HANDLERS_TABLE()
392 wxCONSTRUCTOR_DUMMY(wxWindow
)
395 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
397 #endif // __WXUNIVERSAL__/__WXMSW__
399 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
400 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
401 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
403 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
407 // ===========================================================================
409 // ===========================================================================
411 // ---------------------------------------------------------------------------
412 // wxWindow utility functions
413 // ---------------------------------------------------------------------------
415 // Find an item given the MS Windows id
416 wxWindow
*wxWindowMSW::FindItem(long id
) const
419 wxControl
*item
= wxDynamicCastThis(wxControl
);
422 // is it us or one of our "internal" children?
423 if ( item
->GetId() == id
424 #ifndef __WXUNIVERSAL__
425 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
426 #endif // __WXUNIVERSAL__
432 #endif // wxUSE_CONTROLS
434 wxWindowList::compatibility_iterator current
= GetChildren().GetFirst();
437 wxWindow
*childWin
= current
->GetData();
439 wxWindow
*wnd
= childWin
->FindItem(id
);
443 current
= current
->GetNext();
449 // Find an item given the MS Windows handle
450 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
452 wxWindowList::compatibility_iterator current
= GetChildren().GetFirst();
455 wxWindow
*parent
= current
->GetData();
457 // Do a recursive search.
458 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
464 || parent
->IsKindOf(CLASSINFO(wxControl
))
465 #endif // wxUSE_CONTROLS
468 wxWindow
*item
= current
->GetData();
469 if ( item
->GetHWND() == hWnd
)
473 if ( item
->ContainsHWND(hWnd
) )
478 current
= current
->GetNext();
483 // Default command handler
484 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
489 // ----------------------------------------------------------------------------
490 // constructors and such
491 // ----------------------------------------------------------------------------
493 void wxWindowMSW::Init()
496 m_isBeingDeleted
= false;
498 m_mouseInWindow
= false;
499 m_lastKeydownProcessed
= false;
509 m_pendingPosition
= wxDefaultPosition
;
510 m_pendingSize
= wxDefaultSize
;
513 m_contextMenuEnabled
= false;
518 wxWindowMSW::~wxWindowMSW()
520 m_isBeingDeleted
= true;
522 #ifndef __WXUNIVERSAL__
523 // VS: make sure there's no wxFrame with last focus set to us:
524 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
526 wxTopLevelWindow
*frame
= wxDynamicCast(win
, wxTopLevelWindow
);
529 if ( frame
->GetLastFocus() == this )
531 frame
->SetLastFocus(NULL
);
534 // apparently sometimes we can end up with our grand parent
535 // pointing to us as well: this is surely a bug in focus handling
536 // code but it's not clear where it happens so for now just try to
537 // fix it here by not breaking out of the loop
541 #endif // __WXUNIVERSAL__
543 // VS: destroy children first and _then_ detach *this from its parent.
544 // If we did it the other way around, children wouldn't be able
545 // find their parent frame (see above).
550 // VZ: test temp removed to understand what really happens here
551 //if (::IsWindow(GetHwnd()))
553 if ( !::DestroyWindow(GetHwnd()) )
554 wxLogLastError(wxT("DestroyWindow"));
557 // remove hWnd <-> wxWindow association
558 wxRemoveHandleAssociation(this);
563 // real construction (Init() must have been called before!)
564 bool wxWindowMSW::Create(wxWindow
*parent
,
569 const wxString
& name
)
571 wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") );
573 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
576 parent
->AddChild(this);
579 DWORD msflags
= MSWGetCreateWindowFlags(&exstyle
);
581 #ifdef __WXUNIVERSAL__
582 // no borders, we draw them ourselves
583 exstyle
&= ~(WS_EX_DLGMODALFRAME
|
587 msflags
&= ~WS_BORDER
;
588 #endif // wxUniversal
592 msflags
|= WS_VISIBLE
;
595 if ( !MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
) )
603 // ---------------------------------------------------------------------------
605 // ---------------------------------------------------------------------------
607 void wxWindowMSW::SetFocus()
609 HWND hWnd
= GetHwnd();
610 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
612 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
616 if ( !::SetFocus(hWnd
) )
618 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
619 // was there really an error?
620 DWORD dwRes
= ::GetLastError();
623 HWND hwndFocus
= ::GetFocus();
624 if ( hwndFocus
!= hWnd
)
626 wxLogApiError(_T("SetFocus"), dwRes
);
633 void wxWindowMSW::SetFocusFromKbd()
635 // when the focus is given to the control with DLGC_HASSETSEL style from
636 // keyboard its contents should be entirely selected: this is what
637 // ::IsDialogMessage() does and so we should do it as well to provide the
638 // same LNF as the native programs
639 if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL
)
641 ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1);
644 // do this after (maybe) setting the selection as like this when
645 // wxEVT_SET_FOCUS handler is called, the selection would have been already
646 // set correctly -- this may be important
647 wxWindowBase::SetFocusFromKbd();
650 // Get the window with the focus
651 wxWindow
*wxWindowBase::DoFindFocus()
653 HWND hWnd
= ::GetFocus();
656 return wxGetWindowFromHWND((WXHWND
)hWnd
);
662 void wxWindowMSW::DoEnable( bool enable
)
664 HWND hWnd
= GetHwnd();
666 ::EnableWindow(hWnd
, (BOOL
)enable
);
669 bool wxWindowMSW::Show(bool show
)
671 if ( !wxWindowBase::Show(show
) )
674 HWND hWnd
= GetHwnd();
676 // we could be called before the underlying window is created (this is
677 // actually useful to prevent it from being initially shown), e.g.
679 // wxFoo *foo = new wxFoo;
681 // foo->Create(parent, ...);
683 // should work without errors
686 ::ShowWindow(hWnd
, show
? SW_SHOW
: SW_HIDE
);
692 // Raise the window to the top of the Z order
693 void wxWindowMSW::Raise()
695 wxBringWindowToTop(GetHwnd());
698 // Lower the window to the bottom of the Z order
699 void wxWindowMSW::Lower()
701 ::SetWindowPos(GetHwnd(), HWND_BOTTOM
, 0, 0, 0, 0,
702 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
705 void wxWindowMSW::DoCaptureMouse()
707 HWND hWnd
= GetHwnd();
714 void wxWindowMSW::DoReleaseMouse()
716 if ( !::ReleaseCapture() )
718 wxLogLastError(_T("ReleaseCapture"));
722 /* static */ wxWindow
*wxWindowBase::GetCapture()
724 HWND hwnd
= ::GetCapture();
725 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
728 bool wxWindowMSW::SetFont(const wxFont
& font
)
730 if ( !wxWindowBase::SetFont(font
) )
736 HWND hWnd
= GetHwnd();
739 WXHANDLE hFont
= m_font
.GetResourceHandle();
741 wxASSERT_MSG( hFont
, wxT("should have valid font") );
743 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
748 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
750 if ( !wxWindowBase::SetCursor(cursor
) )
756 // don't "overwrite" busy cursor
757 if ( m_cursor
.Ok() && !wxIsBusy() )
759 // normally we should change the cursor only if it's over this window
760 // but we should do it always if we capture the mouse currently
761 bool set
= HasCapture();
764 HWND hWnd
= GetHwnd();
768 ::GetCursorPosWinCE(&point
);
770 ::GetCursorPos(&point
);
773 RECT rect
= wxGetWindowRect(hWnd
);
775 set
= ::PtInRect(&rect
, point
) != 0;
780 ::SetCursor(GetHcursorOf(m_cursor
));
782 //else: will be set later when the mouse enters this window
788 void wxWindowMSW::WarpPointer(int x
, int y
)
790 ClientToScreen(&x
, &y
);
792 if ( !::SetCursorPos(x
, y
) )
794 wxLogLastError(_T("SetCursorPos"));
798 void wxWindowMSW::MSWUpdateUIState(int action
, int state
)
800 // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good
801 // to use it on older systems -- and could possibly do some harm
802 static int s_needToUpdate
= -1;
803 if ( s_needToUpdate
== -1 )
806 s_needToUpdate
= wxGetOsVersion(&verMaj
, &verMin
) == wxOS_WINDOWS_NT
&&
810 if ( s_needToUpdate
)
812 // we send WM_CHANGEUISTATE so if nothing needs changing then the system
813 // won't send WM_UPDATEUISTATE
814 ::SendMessage(GetHwnd(), WM_CHANGEUISTATE
, MAKEWPARAM(action
, state
), 0);
818 // ---------------------------------------------------------------------------
820 // ---------------------------------------------------------------------------
822 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
824 #ifdef __WXMICROWIN__
825 return ::GetScrollPosWX(hWnd
, wOrient
);
827 WinStruct
<SCROLLINFO
> scrollInfo
;
828 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
829 scrollInfo
.fMask
= SIF_POS
;
830 ::GetScrollInfo(hWnd
, wOrient
, &scrollInfo
);
832 return scrollInfo
.nPos
;
837 int wxWindowMSW::GetScrollPos(int orient
) const
839 HWND hWnd
= GetHwnd();
840 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
842 return GetScrollPosition(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
);
845 // This now returns the whole range, not just the number
846 // of positions that we can scroll.
847 int wxWindowMSW::GetScrollRange(int orient
) const
850 HWND hWnd
= GetHwnd();
854 ::GetScrollRange(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
857 WinStruct
<SCROLLINFO
> scrollInfo
;
858 scrollInfo
.fMask
= SIF_RANGE
;
859 if ( !::GetScrollInfo(hWnd
,
860 orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
863 // Most of the time this is not really an error, since the return
864 // value can also be zero when there is no scrollbar yet.
865 // wxLogLastError(_T("GetScrollInfo"));
867 maxPos
= scrollInfo
.nMax
;
869 // undo "range - 1" done in SetScrollbar()
873 int wxWindowMSW::GetScrollThumb(int orient
) const
875 return orient
== wxHORIZONTAL
? m_xThumbSize
: m_yThumbSize
;
878 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
880 HWND hWnd
= GetHwnd();
881 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
883 WinStruct
<SCROLLINFO
> info
;
887 info
.fMask
= SIF_POS
;
888 if ( HasFlag(wxALWAYS_SHOW_SB
) )
890 // disable scrollbar instead of removing it then
891 info
.fMask
|= SIF_DISABLENOSCROLL
;
894 ::SetScrollInfo(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
898 // New function that will replace some of the above.
899 void wxWindowMSW::SetScrollbar(int orient
,
905 WinStruct
<SCROLLINFO
> info
;
906 info
.nPage
= pageSize
;
907 info
.nMin
= 0; // range is nMax - nMin + 1
908 info
.nMax
= range
- 1; // as both nMax and nMax are inclusive
910 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
911 if ( HasFlag(wxALWAYS_SHOW_SB
) )
913 // disable scrollbar instead of removing it then
914 info
.fMask
|= SIF_DISABLENOSCROLL
;
917 HWND hWnd
= GetHwnd();
920 // We have to set the variables here to make them valid in events
921 // triggered by ::SetScrollInfo()
922 *(orient
== wxHORIZONTAL
? &m_xThumbSize
: &m_yThumbSize
) = pageSize
;
924 ::SetScrollInfo(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
929 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
935 wxCopyRectToRECT(*prect
, rect
);
945 // FIXME: is this the exact equivalent of the line below?
946 ::ScrollWindowEx(GetHwnd(), dx
, dy
, pr
, pr
, 0, 0, SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
948 ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
);
952 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
954 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
957 for ( int n
= 0; n
< count
; n
++ )
959 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
961 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
964 // don't bother to continue, we're already at top/bottom
971 return pos
!= posStart
;
974 bool wxWindowMSW::ScrollLines(int lines
)
976 bool down
= lines
> 0;
978 return ScrollVertically(GetHwnd(),
979 down
? SB_LINEDOWN
: SB_LINEUP
,
980 down
? lines
: -lines
);
983 bool wxWindowMSW::ScrollPages(int pages
)
985 bool down
= pages
> 0;
987 return ScrollVertically(GetHwnd(),
988 down
? SB_PAGEDOWN
: SB_PAGEUP
,
989 down
? pages
: -pages
);
992 // ----------------------------------------------------------------------------
994 // ----------------------------------------------------------------------------
996 void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir
)
1001 const HWND hwnd
= GetHwnd();
1002 wxCHECK_RET( hwnd
, _T("layout direction must be set after window creation") );
1004 LONG styleOld
= ::GetWindowLong(hwnd
, GWL_EXSTYLE
);
1006 LONG styleNew
= styleOld
;
1009 case wxLayout_LeftToRight
:
1010 styleNew
&= ~WS_EX_LAYOUTRTL
;
1013 case wxLayout_RightToLeft
:
1014 styleNew
|= WS_EX_LAYOUTRTL
;
1018 wxFAIL_MSG(_T("unsupported layout direction"));
1022 if ( styleNew
!= styleOld
)
1024 ::SetWindowLong(hwnd
, GWL_EXSTYLE
, styleNew
);
1029 wxLayoutDirection
wxWindowMSW::GetLayoutDirection() const
1032 return wxLayout_Default
;
1034 const HWND hwnd
= GetHwnd();
1035 wxCHECK_MSG( hwnd
, wxLayout_Default
, _T("invalid window") );
1037 return ::GetWindowLong(hwnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
1038 ? wxLayout_RightToLeft
1039 : wxLayout_LeftToRight
;
1044 wxWindowMSW::AdjustForLayoutDirection(wxCoord x
,
1045 wxCoord
WXUNUSED(width
),
1046 wxCoord
WXUNUSED(widthTotal
)) const
1048 // Win32 mirrors the coordinates of RTL windows automatically, so don't
1049 // redo it ourselves
1053 // ---------------------------------------------------------------------------
1055 // ---------------------------------------------------------------------------
1057 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
1059 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
1061 HWND hwnd
= (HWND
)hWnd
;
1062 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
1064 wxAssociateWinWithHandle(hwnd
, this);
1066 m_oldWndProc
= (WXFARPROC
)wxGetWindowProc((HWND
)hWnd
);
1068 // we don't need to subclass the window of our own class (in the Windows
1069 // sense of the word)
1070 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
1072 wxSetWindowProc(hwnd
, wxWndProc
);
1076 // don't bother restoring it either: this also makes it easy to
1077 // implement IsOfStandardClass() method which returns true for the
1078 // standard controls and false for the wxWidgets own windows as it can
1079 // simply check m_oldWndProc
1080 m_oldWndProc
= NULL
;
1083 // we're officially created now, send the event
1084 wxWindowCreateEvent
event((wxWindow
*)this);
1085 (void)GetEventHandler()->ProcessEvent(event
);
1088 void wxWindowMSW::UnsubclassWin()
1090 wxRemoveHandleAssociation(this);
1092 // Restore old Window proc
1093 HWND hwnd
= GetHwnd();
1098 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
1102 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
1104 wxSetWindowProc(hwnd
, (WNDPROC
)m_oldWndProc
);
1107 m_oldWndProc
= NULL
;
1112 void wxWindowMSW::AssociateHandle(WXWidget handle
)
1116 if ( !::DestroyWindow(GetHwnd()) )
1117 wxLogLastError(wxT("DestroyWindow"));
1120 WXHWND wxhwnd
= (WXHWND
)handle
;
1123 SubclassWin(wxhwnd
);
1126 void wxWindowMSW::DissociateHandle()
1128 // this also calls SetHWND(0) for us
1133 bool wxCheckWindowWndProc(WXHWND hWnd
,
1134 WXFARPROC
WXUNUSED(wndProc
))
1136 // TODO: This list of window class names should be factored out so they can be
1137 // managed in one place and then accessed from here and other places, such as
1138 // wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
1141 extern wxChar
*wxCanvasClassName
;
1142 extern wxChar
*wxCanvasClassNameNR
;
1144 extern const wxChar
*wxCanvasClassName
;
1145 extern const wxChar
*wxCanvasClassNameNR
;
1147 extern const wxChar
*wxMDIFrameClassName
;
1148 extern const wxChar
*wxMDIFrameClassNameNoRedraw
;
1149 extern const wxChar
*wxMDIChildFrameClassName
;
1150 extern const wxChar
*wxMDIChildFrameClassNameNoRedraw
;
1151 wxString
str(wxGetWindowClass(hWnd
));
1152 if (str
== wxCanvasClassName
||
1153 str
== wxCanvasClassNameNR
||
1155 str
== _T("wxGLCanvasClass") ||
1156 str
== _T("wxGLCanvasClassNR") ||
1157 #endif // wxUSE_GLCANVAS
1158 str
== wxMDIFrameClassName
||
1159 str
== wxMDIFrameClassNameNoRedraw
||
1160 str
== wxMDIChildFrameClassName
||
1161 str
== wxMDIChildFrameClassNameNoRedraw
||
1162 str
== _T("wxTLWHiddenParent"))
1163 return true; // Effectively means don't subclass
1168 // ----------------------------------------------------------------------------
1170 // ----------------------------------------------------------------------------
1172 void wxWindowMSW::SetWindowStyleFlag(long flags
)
1174 long flagsOld
= GetWindowStyleFlag();
1175 if ( flags
== flagsOld
)
1178 // update the internal variable
1179 wxWindowBase::SetWindowStyleFlag(flags
);
1181 // and the real window flags
1182 MSWUpdateStyle(flagsOld
, GetExtraStyle());
1185 void wxWindowMSW::SetExtraStyle(long exflags
)
1187 long exflagsOld
= GetExtraStyle();
1188 if ( exflags
== exflagsOld
)
1191 // update the internal variable
1192 wxWindowBase::SetExtraStyle(exflags
);
1194 // and the real window flags
1195 MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld
);
1198 void wxWindowMSW::MSWUpdateStyle(long flagsOld
, long exflagsOld
)
1200 // now update the Windows style as well if needed - and if the window had
1201 // been already created
1205 // we may need to call SetWindowPos() when we change some styles
1206 bool callSWP
= false;
1209 long style
= MSWGetStyle(GetWindowStyleFlag(), &exstyle
);
1211 // this is quite a horrible hack but we need it because MSWGetStyle()
1212 // doesn't take exflags as parameter but uses GetExtraStyle() internally
1213 // and so we have to modify the window exflags temporarily to get the
1214 // correct exstyleOld
1215 long exflagsNew
= GetExtraStyle();
1216 wxWindowBase::SetExtraStyle(exflagsOld
);
1219 long styleOld
= MSWGetStyle(flagsOld
, &exstyleOld
);
1221 wxWindowBase::SetExtraStyle(exflagsNew
);
1224 if ( style
!= styleOld
)
1226 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1227 // this function so instead of simply setting the style to the new
1228 // value we clear the bits which were set in styleOld but are set in
1229 // the new one and set the ones which were not set before
1230 long styleReal
= ::GetWindowLong(GetHwnd(), GWL_STYLE
);
1231 styleReal
&= ~styleOld
;
1234 ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
);
1236 // we need to call SetWindowPos() if any of the styles affecting the
1237 // frame appearance have changed
1238 callSWP
= ((styleOld
^ style
) & (WS_BORDER
|
1247 // and the extended style
1248 long exstyleReal
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
);
1250 if ( exstyle
!= exstyleOld
)
1252 exstyleReal
&= ~exstyleOld
;
1253 exstyleReal
|= exstyle
;
1255 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
);
1257 // ex style changes don't take effect without calling SetWindowPos
1263 // we must call SetWindowPos() to flush the cached extended style and
1264 // also to make the change to wxSTAY_ON_TOP style take effect: just
1265 // setting the style simply doesn't work
1266 if ( !::SetWindowPos(GetHwnd(),
1267 exstyleReal
& WS_EX_TOPMOST
? HWND_TOPMOST
1270 SWP_NOMOVE
| SWP_NOSIZE
| SWP_FRAMECHANGED
) )
1272 wxLogLastError(_T("SetWindowPos"));
1277 WXDWORD
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD
*exstyle
) const
1279 // translate common wxWidgets styles to Windows ones
1281 // most of windows are child ones, those which are not (such as
1282 // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle()
1283 WXDWORD style
= WS_CHILD
;
1285 // using this flag results in very significant reduction in flicker,
1286 // especially with controls inside the static boxes (as the interior of the
1287 // box is not redrawn twice), but sometimes results in redraw problems, so
1288 // optionally allow the old code to continue to use it provided a special
1289 // system option is turned on
1290 if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
1291 || (flags
& wxCLIP_CHILDREN
) )
1292 style
|= WS_CLIPCHILDREN
;
1294 // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
1295 // don't support overlapping windows and it only makes sense for them and,
1296 // presumably, gives the system some extra work (to manage more clipping
1297 // regions), so avoid it alltogether
1300 if ( flags
& wxVSCROLL
)
1301 style
|= WS_VSCROLL
;
1303 if ( flags
& wxHSCROLL
)
1304 style
|= WS_HSCROLL
;
1306 const wxBorder border
= GetBorder(flags
);
1308 // WS_BORDER is only required for wxBORDER_SIMPLE
1309 if ( border
== wxBORDER_SIMPLE
)
1312 // now deal with ext style if the caller wants it
1318 if ( flags
& wxTRANSPARENT_WINDOW
)
1319 *exstyle
|= WS_EX_TRANSPARENT
;
1325 case wxBORDER_DEFAULT
:
1326 wxFAIL_MSG( _T("unknown border style") );
1330 case wxBORDER_SIMPLE
:
1333 case wxBORDER_STATIC
:
1334 *exstyle
|= WS_EX_STATICEDGE
;
1337 case wxBORDER_RAISED
:
1338 *exstyle
|= WS_EX_DLGMODALFRAME
;
1341 case wxBORDER_SUNKEN
:
1342 *exstyle
|= WS_EX_CLIENTEDGE
;
1343 style
&= ~WS_BORDER
;
1346 case wxBORDER_DOUBLE
:
1347 *exstyle
|= WS_EX_DLGMODALFRAME
;
1351 // wxUniv doesn't use Windows dialog navigation functions at all
1352 #if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
1353 // to make the dialog navigation work with the nested panels we must
1354 // use this style (top level windows such as dialogs don't need it)
1355 if ( (flags
& wxTAB_TRAVERSAL
) && !IsTopLevel() )
1357 *exstyle
|= WS_EX_CONTROLPARENT
;
1359 #endif // __WXUNIVERSAL__
1365 // Setup background and foreground colours correctly
1366 void wxWindowMSW::SetupColours()
1369 SetBackgroundColour(GetParent()->GetBackgroundColour());
1372 bool wxWindowMSW::IsMouseInWindow() const
1374 // get the mouse position
1377 ::GetCursorPosWinCE(&pt
);
1379 ::GetCursorPos(&pt
);
1382 // find the window which currently has the cursor and go up the window
1383 // chain until we find this window - or exhaust it
1384 HWND hwnd
= ::WindowFromPoint(pt
);
1385 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1386 hwnd
= ::GetParent(hwnd
);
1388 return hwnd
!= NULL
;
1391 void wxWindowMSW::OnInternalIdle()
1393 #ifndef HAVE_TRACKMOUSEEVENT
1394 // Check if we need to send a LEAVE event
1395 if ( m_mouseInWindow
)
1397 // note that we should generate the leave event whether the window has
1398 // or doesn't have mouse capture
1399 if ( !IsMouseInWindow() )
1401 GenerateMouseLeave();
1404 #endif // !HAVE_TRACKMOUSEEVENT
1406 if (wxUpdateUIEvent::CanUpdate(this))
1407 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
1410 // Set this window to be the child of 'parent'.
1411 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1413 if ( !wxWindowBase::Reparent(parent
) )
1416 HWND hWndChild
= GetHwnd();
1417 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1419 ::SetParent(hWndChild
, hWndParent
);
1422 if ( ::GetWindowLong(hWndChild
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT
)
1424 EnsureParentHasControlParentStyle(GetParent());
1426 #endif // !__WXWINCE__
1431 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1433 #ifndef __WXMICROWIN__
1434 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1438 void wxWindowMSW::Freeze()
1440 if ( !m_frozenness
++ )
1443 SendSetRedraw(GetHwnd(), false);
1447 void wxWindowMSW::Thaw()
1449 wxASSERT_MSG( m_frozenness
> 0, _T("Thaw() without matching Freeze()") );
1451 if ( --m_frozenness
== 0 )
1455 SendSetRedraw(GetHwnd(), true);
1457 // we need to refresh everything or otherwise the invalidated area
1458 // is not going to be repainted
1464 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1466 HWND hWnd
= GetHwnd();
1473 wxCopyRectToRECT(*rect
, mswRect
);
1481 // RedrawWindow not available on SmartPhone or eVC++ 3
1482 #if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
1483 UINT flags
= RDW_INVALIDATE
| RDW_ALLCHILDREN
;
1487 ::RedrawWindow(hWnd
, pRect
, NULL
, flags
);
1489 ::InvalidateRect(hWnd
, pRect
, eraseBack
);
1494 void wxWindowMSW::Update()
1496 if ( !::UpdateWindow(GetHwnd()) )
1498 wxLogLastError(_T("UpdateWindow"));
1501 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1502 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1503 // handler needs to be really drawn right now
1508 // ---------------------------------------------------------------------------
1510 // ---------------------------------------------------------------------------
1512 #if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__)
1516 // we need to lower the sibling static boxes so controls contained within can be
1518 static void AdjustStaticBoxZOrder(wxWindow
*parent
)
1520 // no sibling static boxes if we have no parent (ie TLW)
1524 for ( wxWindowList::compatibility_iterator node
= parent
->GetChildren().GetFirst();
1526 node
= node
->GetNext() )
1528 wxStaticBox
*statbox
= wxDynamicCast(node
->GetData(), wxStaticBox
);
1531 ::SetWindowPos(GetHwndOf(statbox
), HWND_BOTTOM
, 0, 0, 0, 0,
1532 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1537 #else // !wxUSE_STATBOX
1539 static inline void AdjustStaticBoxZOrder(wxWindow
* WXUNUSED(parent
))
1543 #endif // wxUSE_STATBOX/!wxUSE_STATBOX
1545 #endif // drag and drop is used
1547 #if wxUSE_DRAG_AND_DROP
1548 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1550 if ( m_dropTarget
!= 0 ) {
1551 m_dropTarget
->Revoke(m_hWnd
);
1552 delete m_dropTarget
;
1555 m_dropTarget
= pDropTarget
;
1556 if ( m_dropTarget
!= 0 )
1558 AdjustStaticBoxZOrder(GetParent());
1559 m_dropTarget
->Register(m_hWnd
);
1562 #endif // wxUSE_DRAG_AND_DROP
1564 // old-style file manager drag&drop support: we retain the old-style
1565 // DragAcceptFiles in parallel with SetDropTarget.
1566 void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept
))
1569 HWND hWnd
= GetHwnd();
1572 AdjustStaticBoxZOrder(GetParent());
1573 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1578 // ----------------------------------------------------------------------------
1580 // ----------------------------------------------------------------------------
1584 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1586 wxWindowBase::DoSetToolTip(tooltip
);
1589 m_tooltip
->SetWindow((wxWindow
*)this);
1592 #endif // wxUSE_TOOLTIPS
1594 // ---------------------------------------------------------------------------
1595 // moving and resizing
1596 // ---------------------------------------------------------------------------
1598 bool wxWindowMSW::IsSizeDeferred() const
1600 #if USE_DEFERRED_SIZING
1601 if ( m_pendingPosition
!= wxDefaultPosition
||
1602 m_pendingSize
!= wxDefaultSize
)
1604 #endif // USE_DEFERRED_SIZING
1610 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1612 #if USE_DEFERRED_SIZING
1613 // if SetSize() had been called at wx level but not realized at Windows
1614 // level yet (i.e. EndDeferWindowPos() not called), we still should return
1615 // the new and not the old position to the other wx code
1616 if ( m_pendingSize
!= wxDefaultSize
)
1619 *x
= m_pendingSize
.x
;
1621 *y
= m_pendingSize
.y
;
1623 else // use current size
1624 #endif // USE_DEFERRED_SIZING
1626 RECT rect
= wxGetWindowRect(GetHwnd());
1629 *x
= rect
.right
- rect
.left
;
1631 *y
= rect
.bottom
- rect
.top
;
1635 // Get size *available for subwindows* i.e. excluding menu bar etc.
1636 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1638 #if USE_DEFERRED_SIZING
1639 if ( m_pendingSize
!= wxDefaultSize
)
1641 // we need to calculate the client size corresponding to pending size
1643 rect
.left
= m_pendingPosition
.x
;
1644 rect
.top
= m_pendingPosition
.y
;
1645 rect
.right
= rect
.left
+ m_pendingSize
.x
;
1646 rect
.bottom
= rect
.top
+ m_pendingSize
.y
;
1648 ::SendMessage(GetHwnd(), WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
);
1651 *x
= rect
.right
- rect
.left
;
1653 *y
= rect
.bottom
- rect
.top
;
1656 #endif // USE_DEFERRED_SIZING
1658 RECT rect
= wxGetClientRect(GetHwnd());
1667 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1669 wxWindow
* const parent
= GetParent();
1672 if ( m_pendingPosition
!= wxDefaultPosition
)
1674 pos
= m_pendingPosition
;
1676 else // use current position
1678 RECT rect
= wxGetWindowRect(GetHwnd());
1681 point
.x
= rect
.left
;
1684 // we do the adjustments with respect to the parent only for the "real"
1685 // children, not for the dialogs/frames
1686 if ( !IsTopLevel() )
1688 if ( wxTheApp
->GetLayoutDirection() == wxLayout_RightToLeft
)
1690 // In RTL mode, we want the logical left x-coordinate,
1691 // which would be the physical right x-coordinate.
1692 point
.x
= rect
.right
;
1695 // Since we now have the absolute screen coords, if there's a
1696 // parent we must subtract its top left corner
1699 ::ScreenToClient(GetHwndOf(parent
), &point
);
1707 // we also must adjust by the client area offset: a control which is just
1708 // under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx
1709 if ( parent
&& !IsTopLevel() )
1711 const wxPoint
pt(parent
->GetClientAreaOrigin());
1722 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1730 ::ScreenToClient(GetHwnd(), &pt
);
1738 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1746 ::ClientToScreen(GetHwnd(), &pt
);
1755 wxWindowMSW::DoMoveSibling(WXHWND hwnd
, int x
, int y
, int width
, int height
)
1757 #if USE_DEFERRED_SIZING
1758 // if our parent had prepared a defer window handle for us, use it (unless
1759 // we are a top level window)
1760 wxWindowMSW
* const parent
= IsTopLevel() ? NULL
: GetParent();
1762 HDWP hdwp
= parent
? (HDWP
)parent
->m_hDWP
: NULL
;
1765 hdwp
= ::DeferWindowPos(hdwp
, (HWND
)hwnd
, NULL
, x
, y
, width
, height
,
1766 SWP_NOZORDER
| SWP_NOOWNERZORDER
| SWP_NOACTIVATE
);
1769 wxLogLastError(_T("DeferWindowPos"));
1775 // hdwp must be updated as it may have been changed
1776 parent
->m_hDWP
= (WXHANDLE
)hdwp
;
1781 // did deferred move, remember new coordinates of the window as they're
1782 // different from what Windows would return for it
1786 // otherwise (or if deferring failed) move the window in place immediately
1787 #endif // USE_DEFERRED_SIZING
1788 if ( !::MoveWindow((HWND
)hwnd
, x
, y
, width
, height
, IsShown()) )
1790 wxLogLastError(wxT("MoveWindow"));
1793 // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move,
1794 // ignored otherwise
1798 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1800 // TODO: is this consistent with other platforms?
1801 // Still, negative width or height shouldn't be allowed
1807 if ( DoMoveSibling(m_hWnd
, x
, y
, width
, height
) )
1809 #if USE_DEFERRED_SIZING
1810 m_pendingPosition
= wxPoint(x
, y
);
1811 m_pendingSize
= wxSize(width
, height
);
1812 #endif // USE_DEFERRED_SIZING
1816 // set the size of the window: if the dimensions are positive, just use them,
1817 // but if any of them is equal to -1, it means that we must find the value for
1818 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1819 // which case -1 is a valid value for x and y)
1821 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1822 // the width/height to best suit our contents, otherwise we reuse the current
1824 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1826 // get the current size and position...
1827 int currentX
, currentY
;
1828 int currentW
, currentH
;
1830 GetPosition(¤tX
, ¤tY
);
1831 GetSize(¤tW
, ¤tH
);
1833 // ... and don't do anything (avoiding flicker) if it's already ok unless
1834 // we're forced to resize the window
1835 if ( x
== currentX
&& y
== currentY
&&
1836 width
== currentW
&& height
== currentH
&&
1837 !(sizeFlags
& wxSIZE_FORCE
) )
1842 if ( x
== wxDefaultCoord
&& !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1844 if ( y
== wxDefaultCoord
&& !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1847 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1849 wxSize size
= wxDefaultSize
;
1850 if ( width
== wxDefaultCoord
)
1852 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1854 size
= DoGetBestSize();
1859 // just take the current one
1864 if ( height
== wxDefaultCoord
)
1866 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1868 if ( size
.x
== wxDefaultCoord
)
1870 size
= DoGetBestSize();
1872 //else: already called DoGetBestSize() above
1878 // just take the current one
1883 DoMoveWindow(x
, y
, width
, height
);
1886 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1888 // setting the client size is less obvious than it could have been
1889 // because in the result of changing the total size the window scrollbar
1890 // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect()
1891 // doesn't take neither into account) and so the client size will not be
1892 // correct as the difference between the total and client size changes --
1893 // so we keep changing it until we get it right
1895 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1896 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1897 // may become 3 if the window had 0 size originally and so we didn't
1898 // calculate the scrollbar correction correctly during the first iteration)
1899 // but just to be on the safe side we check for it instead of making it an
1900 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1901 for ( int i
= 0; i
< 4; i
++ )
1904 ::GetClientRect(GetHwnd(), &rectClient
);
1906 // if the size is already ok, stop here (NB: rectClient.left = top = 0)
1907 if ( (rectClient
.right
== width
|| width
== wxDefaultCoord
) &&
1908 (rectClient
.bottom
== height
|| height
== wxDefaultCoord
) )
1913 // Find the difference between the entire window (title bar and all)
1914 // and the client area; add this to the new client size to move the
1917 ::GetWindowRect(GetHwnd(), &rectWin
);
1919 const int widthWin
= rectWin
.right
- rectWin
.left
,
1920 heightWin
= rectWin
.bottom
- rectWin
.top
;
1922 // MoveWindow positions the child windows relative to the parent, so
1923 // adjust if necessary
1924 if ( !IsTopLevel() )
1926 wxWindow
*parent
= GetParent();
1929 ::ScreenToClient(GetHwndOf(parent
), (POINT
*)&rectWin
);
1933 // don't call DoMoveWindow() because we want to move window immediately
1934 // and not defer it here as otherwise the value returned by
1935 // GetClient/WindowRect() wouldn't change as the window wouldn't be
1937 if ( !::MoveWindow(GetHwnd(),
1940 width
+ widthWin
- rectClient
.right
,
1941 height
+ heightWin
- rectClient
.bottom
,
1944 wxLogLastError(_T("MoveWindow"));
1949 // ---------------------------------------------------------------------------
1951 // ---------------------------------------------------------------------------
1953 int wxWindowMSW::GetCharHeight() const
1955 return wxGetTextMetrics(this).tmHeight
;
1958 int wxWindowMSW::GetCharWidth() const
1960 // +1 is needed because Windows apparently adds it when calculating the
1961 // dialog units size in pixels
1962 #if wxDIALOG_UNIT_COMPATIBILITY
1963 return wxGetTextMetrics(this).tmAveCharWidth
;
1965 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1969 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1971 int *descent
, int *externalLeading
,
1972 const wxFont
*theFont
) const
1974 wxASSERT_MSG( !theFont
|| theFont
->Ok(),
1975 _T("invalid font in GetTextExtent()") );
1979 fontToUse
= *theFont
;
1981 fontToUse
= GetFont();
1983 WindowHDC
hdc(GetHwnd());
1984 SelectInHDC
selectFont(hdc
, GetHfontOf(fontToUse
));
1988 ::GetTextExtentPoint32(hdc
, string
.wx_str(), string
.length(), &sizeRect
);
1989 GetTextMetrics(hdc
, &tm
);
1996 *descent
= tm
.tmDescent
;
1997 if ( externalLeading
)
1998 *externalLeading
= tm
.tmExternalLeading
;
2001 // ---------------------------------------------------------------------------
2003 // ---------------------------------------------------------------------------
2005 #if wxUSE_MENUS_NATIVE
2007 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
2008 // immediately, without waiting for the next event loop iteration
2010 // NB: this function should probably be made public later as it can almost
2011 // surely replace wxYield() elsewhere as well
2012 static void wxYieldForCommandsOnly()
2014 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
2015 // want to process it here)
2017 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) )
2019 if ( msg
.message
== WM_QUIT
)
2021 // if we retrieved a WM_QUIT, insert back into the message queue.
2022 ::PostQuitMessage(0);
2026 // luckily (as we don't have access to wxEventLoopImpl method from here
2027 // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it
2029 ::TranslateMessage(&msg
);
2030 ::DispatchMessage(&msg
);
2034 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
2036 menu
->SetInvokingWindow(this);
2039 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
2041 wxPoint mouse
= ScreenToClient(wxGetMousePosition());
2042 x
= mouse
.x
; y
= mouse
.y
;
2045 HWND hWnd
= GetHwnd();
2046 HMENU hMenu
= GetHmenuOf(menu
);
2050 ::ClientToScreen(hWnd
, &point
);
2051 wxCurrentPopupMenu
= menu
;
2052 #if defined(__WXWINCE__)
2053 static const UINT flags
= 0;
2054 #else // !__WXWINCE__
2055 UINT flags
= TPM_RIGHTBUTTON
;
2056 // NT4 doesn't support TPM_RECURSE and simply doesn't show the menu at all
2057 // when it's use, I'm not sure about Win95/98 but prefer to err on the safe
2058 // side and not to use it there neither -- modify the test if it does work
2060 if ( wxGetWinVersion() >= wxWinVersion_5
)
2062 // using TPM_RECURSE allows us to show a popup menu while another menu
2063 // is opened which can be useful and is supported by the other
2064 // platforms, so allow it under Windows too
2065 flags
|= TPM_RECURSE
;
2067 #endif // __WXWINCE__/!__WXWINCE__
2069 ::TrackPopupMenu(hMenu
, flags
, point
.x
, point
.y
, 0, hWnd
, NULL
);
2071 // we need to do it right now as otherwise the events are never going to be
2072 // sent to wxCurrentPopupMenu from HandleCommand()
2074 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
2075 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
2076 // destroyed as soon as we return (it can be a local variable in the caller
2077 // for example) and so we do need to process the event immediately
2078 wxYieldForCommandsOnly();
2080 wxCurrentPopupMenu
= NULL
;
2082 menu
->SetInvokingWindow(NULL
);
2087 #endif // wxUSE_MENUS_NATIVE
2089 // ===========================================================================
2090 // pre/post message processing
2091 // ===========================================================================
2093 WXLRESULT
wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
2096 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
2098 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
2101 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
2103 // wxUniversal implements tab traversal itself
2104 #ifndef __WXUNIVERSAL__
2105 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
2107 // intercept dialog navigation keys
2108 MSG
*msg
= (MSG
*)pMsg
;
2110 // here we try to do all the job which ::IsDialogMessage() usually does
2112 if ( msg
->message
== WM_KEYDOWN
)
2114 bool bCtrlDown
= wxIsCtrlDown();
2115 bool bShiftDown
= wxIsShiftDown();
2117 // WM_GETDLGCODE: ask the control if it wants the key for itself,
2118 // don't process it if it's the case (except for Ctrl-Tab/Enter
2119 // combinations which are always processed)
2120 LONG lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
2122 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
2123 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
2124 // it, of course, implies them
2125 if ( lDlgCode
& DLGC_WANTALLKEYS
)
2127 lDlgCode
|= DLGC_WANTTAB
| DLGC_WANTARROWS
;
2130 bool bForward
= true,
2131 bWindowChange
= false,
2134 // should we process this message specially?
2135 bool bProcess
= true;
2136 switch ( msg
->wParam
)
2139 if ( (lDlgCode
& DLGC_WANTTAB
) && !bCtrlDown
)
2141 // let the control have the TAB
2144 else // use it for navigation
2146 // Ctrl-Tab cycles thru notebook pages
2147 bWindowChange
= bCtrlDown
;
2148 bForward
= !bShiftDown
;
2155 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
2163 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
2172 // we treat PageUp/Dn as arrows because chances are that
2173 // a control which needs arrows also needs them for
2174 // navigation (e.g. wxTextCtrl, wxListCtrl, ...)
2175 if ( (lDlgCode
& DLGC_WANTARROWS
) && !bCtrlDown
)
2177 else // OTOH Ctrl-PageUp/Dn works as [Shift-]Ctrl-Tab
2178 bWindowChange
= true;
2183 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
2185 // control wants to process Enter itself, don't
2186 // call IsDialogMessage() which would consume it
2191 // currently active button should get enter press even
2192 // if there is a default button elsewhere so check if
2193 // this window is a button first
2194 wxWindow
*btn
= NULL
;
2195 if ( lDlgCode
& DLGC_DEFPUSHBUTTON
)
2197 // let IsDialogMessage() handle this for all
2198 // buttons except the owner-drawn ones which it
2199 // just seems to ignore
2200 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
2201 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
2203 // emulate the button click
2204 btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
2209 else // not a button itself, do we have default button?
2212 tlw
= wxDynamicCast(wxGetTopLevelParent(this),
2216 btn
= wxDynamicCast(tlw
->GetDefaultItem(),
2221 if ( btn
&& btn
->IsEnabled() )
2223 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
2227 #endif // wxUSE_BUTTON
2230 // map Enter presses into button presses on PDAs
2231 wxJoystickEvent
event(wxEVT_JOY_BUTTON_DOWN
);
2232 event
.SetEventObject(this);
2233 if ( GetEventHandler()->ProcessEvent(event
) )
2235 #endif // __WXWINCE__
2245 wxNavigationKeyEvent event
;
2246 event
.SetDirection(bForward
);
2247 event
.SetWindowChange(bWindowChange
);
2248 event
.SetFromTab(bFromTab
);
2249 event
.SetEventObject(this);
2251 if ( GetEventHandler()->ProcessEvent(event
) )
2253 // as we don't call IsDialogMessage(), which would take of
2254 // this by default, we need to manually send this message
2255 // so that controls can change their UI state if needed
2256 MSWUpdateUIState(UIS_CLEAR
, UISF_HIDEFOCUS
);
2263 if ( ::IsDialogMessage(GetHwnd(), msg
) )
2265 // IsDialogMessage() did something...
2269 #endif // __WXUNIVERSAL__
2274 // relay mouse move events to the tooltip control
2275 MSG
*msg
= (MSG
*)pMsg
;
2276 if ( msg
->message
== WM_MOUSEMOVE
)
2277 wxToolTip::RelayEvent(pMsg
);
2279 #endif // wxUSE_TOOLTIPS
2284 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
2286 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
2287 return m_acceleratorTable
.Translate(this, pMsg
);
2291 #endif // wxUSE_ACCEL
2294 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* msg
)
2296 // all tests below have to deal with various bugs/misfeatures of
2297 // IsDialogMessage(): we have to prevent it from being called from our
2298 // MSWProcessMessage() in some situations
2300 // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the
2301 // message even when there is no cancel button and when the message is
2302 // needed by the control itself: in particular, it prevents the tree in
2303 // place edit control from being closed with Escape in a dialog
2304 if ( msg
->message
== WM_KEYDOWN
&& msg
->wParam
== VK_ESCAPE
)
2309 // ::IsDialogMessage() is broken and may sometimes hang the application by
2310 // going into an infinite loop when it tries to find the control to give
2311 // focus to when Alt-<key> is pressed, so we try to detect [some of] the
2312 // situations when this may happen and not call it then
2313 if ( msg
->message
!= WM_SYSCHAR
)
2316 // assume we can call it by default
2317 bool canSafelyCallIsDlgMsg
= true;
2319 HWND hwndFocus
= ::GetFocus();
2321 // if the currently focused window itself has WS_EX_CONTROLPARENT style,
2322 // ::IsDialogMessage() will also enter an infinite loop, because it will
2323 // recursively check the child windows but not the window itself and so if
2324 // none of the children accepts focus it loops forever (as it only stops
2325 // when it gets back to the window it started from)
2327 // while it is very unusual that a window with WS_EX_CONTROLPARENT
2328 // style has the focus, it can happen. One such possibility is if
2329 // all windows are either toplevel, wxDialog, wxPanel or static
2330 // controls and no window can actually accept keyboard input.
2331 #if !defined(__WXWINCE__)
2332 if ( ::GetWindowLong(hwndFocus
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT
)
2334 // pessimistic by default
2335 canSafelyCallIsDlgMsg
= false;
2336 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
2338 node
= node
->GetNext() )
2340 wxWindow
* const win
= node
->GetData();
2341 if ( win
->CanAcceptFocus() &&
2342 !(::GetWindowLong(GetHwndOf(win
), GWL_EXSTYLE
) &
2343 WS_EX_CONTROLPARENT
) )
2345 // it shouldn't hang...
2346 canSafelyCallIsDlgMsg
= true;
2352 #endif // !__WXWINCE__
2354 if ( canSafelyCallIsDlgMsg
)
2356 // ::IsDialogMessage() can enter in an infinite loop when the
2357 // currently focused window is disabled or hidden and its
2358 // parent has WS_EX_CONTROLPARENT style, so don't call it in
2362 if ( !::IsWindowEnabled(hwndFocus
) ||
2363 !::IsWindowVisible(hwndFocus
) )
2365 // it would enter an infinite loop if we do this!
2366 canSafelyCallIsDlgMsg
= false;
2371 if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) )
2373 // it's a top level window, don't go further -- e.g. even
2374 // if the parent of a dialog is disabled, this doesn't
2375 // break navigation inside the dialog
2379 hwndFocus
= ::GetParent(hwndFocus
);
2383 return canSafelyCallIsDlgMsg
;
2386 // ---------------------------------------------------------------------------
2387 // message params unpackers
2388 // ---------------------------------------------------------------------------
2390 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2391 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
2393 *id
= LOWORD(wParam
);
2394 *hwnd
= (WXHWND
)lParam
;
2395 *cmd
= HIWORD(wParam
);
2398 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2399 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2401 *state
= LOWORD(wParam
);
2402 *minimized
= HIWORD(wParam
);
2403 *hwnd
= (WXHWND
)lParam
;
2406 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2407 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2409 *code
= LOWORD(wParam
);
2410 *pos
= HIWORD(wParam
);
2411 *hwnd
= (WXHWND
)lParam
;
2414 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2415 WXHDC
*hdc
, WXHWND
*hwnd
)
2417 *hwnd
= (WXHWND
)lParam
;
2418 *hdc
= (WXHDC
)wParam
;
2421 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2422 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2424 *item
= (WXWORD
)wParam
;
2425 *flags
= HIWORD(wParam
);
2426 *hmenu
= (WXHMENU
)lParam
;
2429 // ---------------------------------------------------------------------------
2430 // Main wxWidgets window proc and the window proc for wxWindow
2431 // ---------------------------------------------------------------------------
2433 // Hook for new window just as it's being created, when the window isn't yet
2434 // associated with the handle
2435 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2437 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2438 // window being created and insures that it's always unset back later
2439 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2441 gs_winBeingCreated
= winBeingCreated
;
2444 wxWindowCreationHook::~wxWindowCreationHook()
2446 gs_winBeingCreated
= NULL
;
2450 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2452 // trace all messages - useful for the debugging
2454 wxLogTrace(wxTraceMessages
,
2455 wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
2456 wxGetMessageName(message
), (long)hWnd
, (long)wParam
, lParam
);
2457 #endif // __WXDEBUG__
2459 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2461 // when we get the first message for the HWND we just created, we associate
2462 // it with wxWindow stored in gs_winBeingCreated
2463 if ( !wnd
&& gs_winBeingCreated
)
2465 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2466 wnd
= gs_winBeingCreated
;
2467 gs_winBeingCreated
= NULL
;
2468 wnd
->SetHWND((WXHWND
)hWnd
);
2473 if ( wnd
&& wxGUIEventLoop::AllowProcessing(wnd
) )
2474 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2476 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2481 WXLRESULT
wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2483 // did we process the message?
2484 bool processed
= false;
2494 // for most messages we should return 0 when we do process the message
2502 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2505 // return 0 to allow window creation
2506 rc
.result
= mayCreate
? 0 : -1;
2512 // never set processed to true and *always* pass WM_DESTROY to
2513 // DefWindowProc() as Windows may do some internal cleanup when
2514 // processing it and failing to pass the message along may cause
2515 // memory and resource leaks!
2516 (void)HandleDestroy();
2520 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), wParam
);
2524 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2527 #if !defined(__WXWINCE__)
2530 LPRECT pRect
= (LPRECT
)lParam
;
2532 rc
.SetLeft(pRect
->left
);
2533 rc
.SetTop(pRect
->top
);
2534 rc
.SetRight(pRect
->right
);
2535 rc
.SetBottom(pRect
->bottom
);
2536 processed
= HandleMoving(rc
);
2538 pRect
->left
= rc
.GetLeft();
2539 pRect
->top
= rc
.GetTop();
2540 pRect
->right
= rc
.GetRight();
2541 pRect
->bottom
= rc
.GetBottom();
2548 LPRECT pRect
= (LPRECT
)lParam
;
2550 rc
.SetLeft(pRect
->left
);
2551 rc
.SetTop(pRect
->top
);
2552 rc
.SetRight(pRect
->right
);
2553 rc
.SetBottom(pRect
->bottom
);
2554 processed
= HandleSizing(rc
);
2556 pRect
->left
= rc
.GetLeft();
2557 pRect
->top
= rc
.GetTop();
2558 pRect
->right
= rc
.GetRight();
2559 pRect
->bottom
= rc
.GetBottom();
2563 #endif // !__WXWINCE__
2565 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2566 case WM_ACTIVATEAPP
:
2567 // This implicitly sends a wxEVT_ACTIVATE_APP event
2568 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2574 WXWORD state
, minimized
;
2576 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2578 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2583 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2587 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2590 case WM_PRINTCLIENT
:
2591 processed
= HandlePrintClient((WXHDC
)wParam
);
2597 wxPaintDCEx
dc((wxWindow
*)this, (WXHDC
)wParam
);
2599 processed
= HandlePaint();
2603 processed
= HandlePaint();
2608 #ifdef __WXUNIVERSAL__
2609 // Universal uses its own wxFrame/wxDialog, so we don't receive
2610 // close events unless we have this.
2612 #endif // __WXUNIVERSAL__
2614 // don't let the DefWindowProc() destroy our window - we'll do it
2615 // ourselves in ~wxWindow
2621 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2625 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2626 GET_Y_LPARAM(lParam
),
2630 #ifdef HAVE_TRACKMOUSEEVENT
2632 // filter out excess WM_MOUSELEAVE events sent after PopupMenu()
2634 if ( m_mouseInWindow
)
2636 GenerateMouseLeave();
2639 // always pass processed back as false, this allows the window
2640 // manager to process the message too. This is needed to
2641 // ensure windows XP themes work properly as the mouse moves
2642 // over widgets like buttons. So don't set processed to true here.
2644 #endif // HAVE_TRACKMOUSEEVENT
2646 #if wxUSE_MOUSEWHEEL
2648 processed
= HandleMouseWheel(wParam
, lParam
);
2652 case WM_LBUTTONDOWN
:
2654 case WM_LBUTTONDBLCLK
:
2655 case WM_RBUTTONDOWN
:
2657 case WM_RBUTTONDBLCLK
:
2658 case WM_MBUTTONDOWN
:
2660 case WM_MBUTTONDBLCLK
:
2661 #ifdef wxHAS_XBUTTON
2662 case WM_XBUTTONDOWN
:
2664 case WM_XBUTTONDBLCLK
:
2665 #endif // wxHAS_XBUTTON
2667 #ifdef __WXMICROWIN__
2668 // MicroWindows seems to ignore the fact that a window is
2669 // disabled. So catch mouse events and throw them away if
2671 wxWindowMSW
* win
= this;
2674 if (!win
->IsEnabled())
2680 win
= win
->GetParent();
2681 if ( !win
|| win
->IsTopLevel() )
2688 #endif // __WXMICROWIN__
2689 int x
= GET_X_LPARAM(lParam
),
2690 y
= GET_Y_LPARAM(lParam
);
2693 // redirect the event to a static control if necessary by
2694 // finding one under mouse because under CE the static controls
2695 // don't generate mouse events (even with SS_NOTIFY)
2697 if ( GetCapture() == this )
2699 // but don't do it if the mouse is captured by this window
2700 // because then it should really get this event itself
2705 win
= FindWindowForMouseEvent(this, &x
, &y
);
2707 // this should never happen
2708 wxCHECK_MSG( win
, 0,
2709 _T("FindWindowForMouseEvent() returned NULL") );
2712 if (IsContextMenuEnabled() && message
== WM_LBUTTONDOWN
)
2714 SHRGINFO shrgi
= {0};
2716 shrgi
.cbSize
= sizeof(SHRGINFO
);
2717 shrgi
.hwndClient
= (HWND
) GetHWND();
2721 shrgi
.dwFlags
= SHRG_RETURNCMD
;
2722 // shrgi.dwFlags = SHRG_NOTIFYPARENT;
2724 if (GN_CONTEXTMENU
== ::SHRecognizeGesture(&shrgi
))
2727 pt
= ClientToScreen(pt
);
2729 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2731 evtCtx
.SetEventObject(this);
2732 if (GetEventHandler()->ProcessEvent(evtCtx
))
2741 #else // !__WXWINCE__
2742 wxWindowMSW
*win
= this;
2743 #endif // __WXWINCE__/!__WXWINCE__
2745 processed
= win
->HandleMouseEvent(message
, x
, y
, wParam
);
2747 // if the app didn't eat the event, handle it in the default
2748 // way, that is by giving this window the focus
2751 // for the standard classes their WndProc sets the focus to
2752 // them anyhow and doing it from here results in some weird
2753 // problems, so don't do it for them (unnecessary anyhow)
2754 if ( !win
->IsOfStandardClass() )
2756 if ( message
== WM_LBUTTONDOWN
&& win
->IsFocusable() )
2768 case MM_JOY1BUTTONDOWN
:
2769 case MM_JOY2BUTTONDOWN
:
2770 case MM_JOY1BUTTONUP
:
2771 case MM_JOY2BUTTONUP
:
2772 processed
= HandleJoystickEvent(message
,
2773 GET_X_LPARAM(lParam
),
2774 GET_Y_LPARAM(lParam
),
2777 #endif // __WXMICROWIN__
2783 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2785 processed
= HandleCommand(id
, cmd
, hwnd
);
2790 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2793 // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU,
2794 // otherwise DefWindowProc() does it perfectly fine for us, but MSLU
2795 // apparently doesn't always behave properly and needs some help
2796 #if wxUSE_UNICODE_MSLU && defined(NF_QUERY)
2797 case WM_NOTIFYFORMAT
:
2798 if ( lParam
== NF_QUERY
)
2801 rc
.result
= NFR_UNICODE
;
2804 #endif // wxUSE_UNICODE_MSLU
2806 // for these messages we must return true if process the message
2809 case WM_MEASUREITEM
:
2811 int idCtrl
= (UINT
)wParam
;
2812 if ( message
== WM_DRAWITEM
)
2814 processed
= MSWOnDrawItem(idCtrl
,
2815 (WXDRAWITEMSTRUCT
*)lParam
);
2819 processed
= MSWOnMeasureItem(idCtrl
,
2820 (WXMEASUREITEMSTRUCT
*)lParam
);
2827 #endif // defined(WM_DRAWITEM)
2830 if ( !IsOfStandardClass() || HasFlag(wxWANTS_CHARS
) )
2832 // we always want to get the char events
2833 rc
.result
= DLGC_WANTCHARS
;
2835 if ( HasFlag(wxWANTS_CHARS
) )
2837 // in fact, we want everything
2838 rc
.result
|= DLGC_WANTARROWS
|
2845 //else: get the dlg code from the DefWindowProc()
2850 // If this has been processed by an event handler, return 0 now
2851 // (we've handled it).
2852 m_lastKeydownProcessed
= HandleKeyDown((WORD
) wParam
, lParam
);
2853 if ( m_lastKeydownProcessed
)
2862 // we consider these messages "not interesting" to OnChar, so
2863 // just don't do anything more with them
2873 // avoid duplicate messages to OnChar for these ASCII keys:
2874 // they will be translated by TranslateMessage() and received
2906 // but set processed to false, not true to still pass them
2907 // to the control's default window proc - otherwise
2908 // built-in keyboard handling won't work
2913 // special case of VK_APPS: treat it the same as right mouse
2914 // click because both usually pop up a context menu
2916 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, -1, -1, 0);
2921 // do generate a CHAR event
2922 processed
= HandleChar((WORD
)wParam
, lParam
);
2925 if (message
== WM_SYSKEYDOWN
) // Let Windows still handle the SYSKEYs
2932 // special case of VK_APPS: treat it the same as right mouse button
2933 if ( wParam
== VK_APPS
)
2935 processed
= HandleMouseEvent(WM_RBUTTONUP
, -1, -1, 0);
2940 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2945 case WM_CHAR
: // Always an ASCII character
2946 if ( m_lastKeydownProcessed
)
2948 // The key was handled in the EVT_KEY_DOWN and handling
2949 // a key in an EVT_KEY_DOWN handler is meant, by
2950 // design, to prevent EVT_CHARs from happening
2951 m_lastKeydownProcessed
= false;
2956 processed
= HandleChar((WORD
)wParam
, lParam
, true);
2962 processed
= HandleHotKey((WORD
)wParam
, lParam
);
2964 #endif // wxUSE_HOTKEY
2971 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2973 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2979 // CTLCOLOR messages are sent by children to query the parent for their
2981 #ifndef __WXMICROWIN__
2982 case WM_CTLCOLORMSGBOX
:
2983 case WM_CTLCOLOREDIT
:
2984 case WM_CTLCOLORLISTBOX
:
2985 case WM_CTLCOLORBTN
:
2986 case WM_CTLCOLORDLG
:
2987 case WM_CTLCOLORSCROLLBAR
:
2988 case WM_CTLCOLORSTATIC
:
2992 UnpackCtlColor(wParam
, lParam
, &hdc
, &hwnd
);
2994 processed
= HandleCtlColor(&rc
.hBrush
, (WXHDC
)hdc
, (WXHWND
)hwnd
);
2997 #endif // !__WXMICROWIN__
2999 case WM_SYSCOLORCHANGE
:
3000 // the return value for this message is ignored
3001 processed
= HandleSysColorChange();
3004 #if !defined(__WXWINCE__)
3005 case WM_DISPLAYCHANGE
:
3006 processed
= HandleDisplayChange();
3010 case WM_PALETTECHANGED
:
3011 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
3014 case WM_CAPTURECHANGED
:
3015 processed
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
);
3018 case WM_SETTINGCHANGE
:
3019 processed
= HandleSettingChange(wParam
, lParam
);
3022 case WM_QUERYNEWPALETTE
:
3023 processed
= HandleQueryNewPalette();
3027 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
3030 // we processed the message, i.e. erased the background
3035 #if !defined(__WXWINCE__)
3037 processed
= HandleDropFiles(wParam
);
3042 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
3046 // we never set focus from here
3051 #if !defined(__WXWINCE__)
3052 case WM_QUERYENDSESSION
:
3053 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
3057 processed
= HandleEndSession(wParam
!= 0, lParam
);
3060 case WM_GETMINMAXINFO
:
3061 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
3066 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
3067 LOWORD(lParam
), // hit test
3068 HIWORD(lParam
)); // mouse msg
3072 // returning TRUE stops the DefWindowProc() from further
3073 // processing this message - exactly what we need because we've
3074 // just set the cursor.
3079 #if wxUSE_ACCESSIBILITY
3082 //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
3083 LPARAM dwObjId
= (LPARAM
) (DWORD
) lParam
;
3085 if (dwObjId
== (LPARAM
)OBJID_CLIENT
&& GetOrCreateAccessible())
3087 return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible());
3093 #if defined(WM_HELP)
3096 // by default, WM_HELP is propagated by DefWindowProc() upwards
3097 // to the window parent but as we do it ourselves already
3098 // (wxHelpEvent is derived from wxCommandEvent), we don't want
3099 // to get the other events if we process this message at all
3102 // WM_HELP doesn't use lParam under CE
3104 HELPINFO
* info
= (HELPINFO
*) lParam
;
3105 if ( info
->iContextType
== HELPINFO_WINDOW
)
3107 #endif // !__WXWINCE__
3108 wxHelpEvent helpEvent
3113 wxGetMousePosition() // what else?
3115 wxPoint(info
->MousePos
.x
, info
->MousePos
.y
)
3119 helpEvent
.SetEventObject(this);
3120 GetEventHandler()->ProcessEvent(helpEvent
);
3123 else if ( info
->iContextType
== HELPINFO_MENUITEM
)
3125 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
3126 helpEvent
.SetEventObject(this);
3127 GetEventHandler()->ProcessEvent(helpEvent
);
3130 else // unknown help event?
3134 #endif // !__WXWINCE__
3139 #if !defined(__WXWINCE__)
3140 case WM_CONTEXTMENU
:
3142 // we don't convert from screen to client coordinates as
3143 // the event may be handled by a parent window
3144 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
3146 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
3148 // we could have got an event from our child, reflect it back
3149 // to it if this is the case
3150 wxWindowMSW
*win
= NULL
;
3151 if ( (WXHWND
)wParam
!= m_hWnd
)
3153 win
= FindItemByHWND((WXHWND
)wParam
);
3159 evtCtx
.SetEventObject(win
);
3160 processed
= win
->GetEventHandler()->ProcessEvent(evtCtx
);
3167 // we're only interested in our own menus, not MF_SYSMENU
3168 if ( HIWORD(wParam
) == MF_POPUP
)
3170 // handle menu chars for ownerdrawn menu items
3171 int i
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
);
3172 if ( i
!= wxNOT_FOUND
)
3174 rc
.result
= MAKELRESULT(i
, MNC_EXECUTE
);
3179 #endif // wxUSE_MENUS
3182 case WM_POWERBROADCAST
:
3185 processed
= HandlePower(wParam
, lParam
, &vetoed
);
3186 rc
.result
= processed
&& vetoed
? BROADCAST_QUERY_DENY
: TRUE
;
3189 #endif // __WXWINCE__
3192 // try a custom message handler
3193 const MSWMessageHandlers::const_iterator
3194 i
= gs_messageHandlers
.find(message
);
3195 if ( i
!= gs_messageHandlers
.end() )
3197 processed
= (*i
->second
)(this, message
, wParam
, lParam
);
3204 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
3205 wxGetMessageName(message
));
3206 #endif // __WXDEBUG__
3207 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
3213 // ----------------------------------------------------------------------------
3214 // wxWindow <-> HWND map
3215 // ----------------------------------------------------------------------------
3217 wxWinHashTable
*wxWinHandleHash
= NULL
;
3219 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
3221 return (wxWindow
*)wxWinHandleHash
->Get((long)hWnd
);
3224 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
3226 // adding NULL hWnd is (first) surely a result of an error and
3227 // (secondly) breaks menu command processing
3228 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
3229 wxT("attempt to add a NULL hWnd to window list ignored") );
3231 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
3233 if ( oldWin
&& (oldWin
!= win
) )
3235 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
3236 (int) hWnd
, win
->GetClassInfo()->GetClassName());
3239 #endif // __WXDEBUG__
3242 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
3246 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
3248 wxWinHandleHash
->Delete((long)win
->GetHWND());
3251 // ----------------------------------------------------------------------------
3252 // various MSW speciic class dependent functions
3253 // ----------------------------------------------------------------------------
3255 // Default destroyer - override if you destroy it in some other way
3256 // (e.g. with MDI child windows)
3257 void wxWindowMSW::MSWDestroyWindow()
3261 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
3264 int& w
, int& h
) const
3266 // yes, those are just some arbitrary hardcoded numbers
3267 static const int DEFAULT_Y
= 200;
3269 bool nonDefault
= false;
3271 if ( pos
.x
== wxDefaultCoord
)
3273 // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we
3274 // can just as well set it to CW_USEDEFAULT as well
3280 // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it
3281 // neither because it is not handled as a special value by Windows then
3282 // and so we have to choose some default value for it
3284 y
= pos
.y
== wxDefaultCoord
? DEFAULT_Y
: pos
.y
;
3290 NB: there used to be some code here which set the initial size of the
3291 window to the client size of the parent if no explicit size was
3292 specified. This was wrong because wxWidgets programs often assume
3293 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
3294 it. To see why, you should understand that Windows sends WM_SIZE from
3295 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
3296 from some base class ctor and so this WM_SIZE is not processed in the
3297 real class' OnSize() (because it's not fully constructed yet and the
3298 event goes to some base class OnSize() instead). So the WM_SIZE we
3299 rely on is the one sent when the parent frame resizes its children
3300 but here is the problem: if the child already has just the right
3301 size, nothing will happen as both wxWidgets and Windows check for
3302 this and ignore any attempts to change the window size to the size it
3303 already has - so no WM_SIZE would be sent.
3307 // we don't use CW_USEDEFAULT here for several reasons:
3309 // 1. it results in huge frames on modern screens (1000*800 is not
3310 // uncommon on my 1280*1024 screen) which is way too big for a half
3311 // empty frame of most of wxWidgets samples for example)
3313 // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which
3314 // the default is for whatever reason 8*8 which breaks client <->
3315 // window size calculations (it would be nice if it didn't, but it
3316 // does and the simplest way to fix it seemed to change the broken
3317 // default size anyhow)
3319 // 3. there is just no advantage in doing it: with x and y it is
3320 // possible that [future versions of] Windows position the new top
3321 // level window in some smart way which we can't do, but we can
3322 // guess a reasonably good size for a new window just as well
3325 // However, on PocketPC devices, we must use the default
3326 // size if possible.
3328 if (size
.x
== wxDefaultCoord
)
3332 if (size
.y
== wxDefaultCoord
)
3337 if ( size
.x
== wxDefaultCoord
|| size
.y
== wxDefaultCoord
)
3341 w
= WidthDefault(size
.x
);
3342 h
= HeightDefault(size
.y
);
3345 AdjustForParentClientOrigin(x
, y
);
3350 WXHWND
wxWindowMSW::MSWGetParent() const
3352 return m_parent
? m_parent
->GetHWND() : WXHWND(NULL
);
3355 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
3356 const wxChar
*title
,
3360 WXDWORD extendedStyle
)
3362 // choose the position/size for the new window
3364 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
3366 // controlId is menu handle for the top level windows, so set it to 0
3367 // unless we're creating a child window
3368 int controlId
= style
& WS_CHILD
? GetId() : 0;
3370 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
3371 // which is the same but without CS_[HV]REDRAW class styles so using it
3372 // ensures that the window is not fully repainted on each resize
3373 wxString
className(wclass
);
3374 if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE
) )
3376 className
+= wxT("NR");
3379 // do create the window
3380 wxWindowCreationHook
hook(this);
3382 m_hWnd
= (WXHWND
)::CreateWindowEx
3386 title
? title
: m_windowName
.wx_str(),
3389 (HWND
)MSWGetParent(),
3392 NULL
// no extra data
3397 wxLogSysError(_("Can't create window of class %s"), className
.c_str());
3402 SubclassWin(m_hWnd
);
3407 // ===========================================================================
3408 // MSW message handlers
3409 // ===========================================================================
3411 // ---------------------------------------------------------------------------
3413 // ---------------------------------------------------------------------------
3415 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
3417 #ifndef __WXMICROWIN__
3418 LPNMHDR hdr
= (LPNMHDR
)lParam
;
3419 HWND hWnd
= hdr
->hwndFrom
;
3420 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
3422 // if the control is one of our windows, let it handle the message itself
3425 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
3428 // VZ: why did we do it? normally this is unnecessary and, besides, it
3429 // breaks the message processing for the toolbars because the tooltip
3430 // notifications were being forwarded to the toolbar child controls
3431 // (if it had any) before being passed to the toolbar itself, so in my
3432 // example the tooltip for the combobox was always shown instead of the
3433 // correct button tooltips
3435 // try all our children
3436 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3439 wxWindow
*child
= node
->GetData();
3440 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
3445 node
= node
->GetNext();
3449 // by default, handle it ourselves
3450 return MSWOnNotify(idCtrl
, lParam
, result
);
3451 #else // __WXMICROWIN__
3458 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
,
3460 const wxString
& ttip
)
3462 // I don't know why it happens, but the versions of comctl32.dll starting
3463 // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally,
3464 // this message is supposed to be sent to Unicode programs only) -- hence
3465 // we need to handle it as well, otherwise no tooltips will be shown in
3468 if ( !(code
== (WXUINT
) TTN_NEEDTEXTA
|| code
== (WXUINT
) TTN_NEEDTEXTW
)
3471 // not a tooltip message or no tooltip to show anyhow
3476 LPTOOLTIPTEXT ttText
= (LPTOOLTIPTEXT
)lParam
;
3478 // We don't want to use the szText buffer because it has a limit of 80
3479 // bytes and this is not enough, especially for Unicode build where it
3480 // limits the tooltip string length to only 40 characters
3482 // The best would be, of course, to not impose any length limitations at
3483 // all but then the buffer would have to be dynamic and someone would have
3484 // to free it and we don't have the tooltip owner object here any more, so
3485 // for now use our own static buffer with a higher fixed max length.
3487 // Note that using a static buffer should not be a problem as only a single
3488 // tooltip can be shown at the same time anyhow.
3490 if ( code
== (WXUINT
) TTN_NEEDTEXTW
)
3492 // We need to convert tooltip from multi byte to Unicode on the fly.
3493 static wchar_t buf
[513];
3495 // Truncate tooltip length if needed as otherwise we might not have
3496 // enough space for it in the buffer and MultiByteToWideChar() would
3498 size_t tipLength
= wxMin(ttip
.length(), WXSIZEOF(buf
) - 1);
3500 // Convert to WideChar without adding the NULL character. The NULL
3501 // character is added afterwards (this is more efficient).
3502 int len
= ::MultiByteToWideChar
3514 wxLogLastError(_T("MultiByteToWideChar()"));
3518 ttText
->lpszText
= (LPSTR
) buf
;
3520 else // TTN_NEEDTEXTA
3521 #endif // !wxUSE_UNICODE
3523 // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or
3524 // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
3525 // to copy the string we have into the buffer
3526 static wxChar buf
[513];
3527 wxStrncpy(buf
, ttip
.c_str(), WXSIZEOF(buf
) - 1);
3528 buf
[WXSIZEOF(buf
) - 1] = _T('\0');
3529 ttText
->lpszText
= buf
;
3535 #endif // wxUSE_TOOLTIPS
3537 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
3539 WXLPARAM
* WXUNUSED(result
))
3544 NMHDR
* hdr
= (NMHDR
*)lParam
;
3545 if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip()))
3552 wxUnusedVar(lParam
);
3553 #endif // wxUSE_TOOLTIPS
3558 // ---------------------------------------------------------------------------
3559 // end session messages
3560 // ---------------------------------------------------------------------------
3562 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
3564 #ifdef ENDSESSION_LOGOFF
3565 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, wxID_ANY
);
3566 event
.SetEventObject(wxTheApp
);
3567 event
.SetCanVeto(true);
3568 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
3570 bool rc
= wxTheApp
->ProcessEvent(event
);
3574 // we may end only if the app didn't veto session closing (double
3576 *mayEnd
= !event
.GetVeto();
3581 wxUnusedVar(logOff
);
3582 wxUnusedVar(mayEnd
);
3587 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
3589 #ifdef ENDSESSION_LOGOFF
3590 // do nothing if the session isn't ending
3595 if ( (this != wxTheApp
->GetTopWindow()) )
3598 wxCloseEvent
event(wxEVT_END_SESSION
, wxID_ANY
);
3599 event
.SetEventObject(wxTheApp
);
3600 event
.SetCanVeto(false);
3601 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
3603 return wxTheApp
->ProcessEvent(event
);
3605 wxUnusedVar(endSession
);
3606 wxUnusedVar(logOff
);
3611 // ---------------------------------------------------------------------------
3612 // window creation/destruction
3613 // ---------------------------------------------------------------------------
3615 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT
WXUNUSED_IN_WINCE(cs
),
3618 // VZ: why is this commented out for WinCE? If it doesn't support
3619 // WS_EX_CONTROLPARENT at all it should be somehow handled globally,
3620 // not with multiple #ifdef's!
3622 if ( ((CREATESTRUCT
*)cs
)->dwExStyle
& WS_EX_CONTROLPARENT
)
3623 EnsureParentHasControlParentStyle(GetParent());
3624 #endif // !__WXWINCE__
3631 bool wxWindowMSW::HandleDestroy()
3635 // delete our drop target if we've got one
3636 #if wxUSE_DRAG_AND_DROP
3637 if ( m_dropTarget
!= NULL
)
3639 m_dropTarget
->Revoke(m_hWnd
);
3641 delete m_dropTarget
;
3642 m_dropTarget
= NULL
;
3644 #endif // wxUSE_DRAG_AND_DROP
3646 // WM_DESTROY handled
3650 // ---------------------------------------------------------------------------
3652 // ---------------------------------------------------------------------------
3654 bool wxWindowMSW::HandleActivate(int state
,
3655 bool WXUNUSED(minimized
),
3656 WXHWND
WXUNUSED(activate
))
3658 wxActivateEvent
event(wxEVT_ACTIVATE
,
3659 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3661 event
.SetEventObject(this);
3663 return GetEventHandler()->ProcessEvent(event
);
3666 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3668 // Strangly enough, some controls get set focus events when they are being
3669 // deleted, even if they already had focus before.
3670 if ( m_isBeingDeleted
)
3675 // notify the parent keeping track of focus for the kbd navigation
3676 // purposes that we got it
3677 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3678 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3684 m_caret
->OnSetFocus();
3686 #endif // wxUSE_CARET
3689 // If it's a wxTextCtrl don't send the event as it will be done
3690 // after the control gets to process it from EN_FOCUS handler
3691 if ( wxDynamicCastThis(wxTextCtrl
) )
3695 #endif // wxUSE_TEXTCTRL
3697 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3698 event
.SetEventObject(this);
3700 // wxFindWinFromHandle() may return NULL, it is ok
3701 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3703 return GetEventHandler()->ProcessEvent(event
);
3706 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3712 m_caret
->OnKillFocus();
3714 #endif // wxUSE_CARET
3717 // If it's a wxTextCtrl don't send the event as it will be done
3718 // after the control gets to process it.
3719 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3726 // Don't send the event when in the process of being deleted. This can
3727 // only cause problems if the event handler tries to access the object.
3728 if ( m_isBeingDeleted
)
3733 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3734 event
.SetEventObject(this);
3736 // wxFindWinFromHandle() may return NULL, it is ok
3737 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3739 return GetEventHandler()->ProcessEvent(event
);
3742 // ---------------------------------------------------------------------------
3744 // ---------------------------------------------------------------------------
3746 void wxWindowMSW::SetLabel( const wxString
& label
)
3748 SetWindowText(GetHwnd(), label
.c_str());
3751 wxString
wxWindowMSW::GetLabel() const
3753 return wxGetWindowText(GetHWND());
3756 // ---------------------------------------------------------------------------
3758 // ---------------------------------------------------------------------------
3760 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3762 wxShowEvent
event(GetId(), show
);
3763 event
.SetEventObject(this);
3765 return GetEventHandler()->ProcessEvent(event
);
3768 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3770 wxInitDialogEvent
event(GetId());
3771 event
.SetEventObject(this);
3773 return GetEventHandler()->ProcessEvent(event
);
3776 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3778 #if defined (__WXMICROWIN__) || defined(__WXWINCE__)
3779 wxUnusedVar(wParam
);
3781 #else // __WXMICROWIN__
3782 HDROP hFilesInfo
= (HDROP
) wParam
;
3784 // Get the total number of files dropped
3785 UINT gwFilesDropped
= ::DragQueryFile
3793 wxString
*files
= new wxString
[gwFilesDropped
];
3794 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3796 // first get the needed buffer length (+1 for terminating NUL)
3797 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3799 // and now get the file name
3800 ::DragQueryFile(hFilesInfo
, wIndex
,
3801 wxStringBuffer(files
[wIndex
], len
), len
);
3803 DragFinish (hFilesInfo
);
3805 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3806 event
.SetEventObject(this);
3809 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3810 event
.m_pos
.x
= dropPoint
.x
;
3811 event
.m_pos
.y
= dropPoint
.y
;
3813 return GetEventHandler()->ProcessEvent(event
);
3818 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3820 int WXUNUSED(mouseMsg
))
3822 #ifndef __WXMICROWIN__
3823 // the logic is as follows:
3824 // 0. if we're busy, set the busy cursor (even for non client elements)
3825 // 1. don't set custom cursor for non client area of enabled windows
3826 // 2. ask user EVT_SET_CURSOR handler for the cursor
3827 // 3. if still no cursor but we're in a TLW, set the global cursor
3829 HCURSOR hcursor
= 0;
3832 hcursor
= wxGetCurrentBusyCursor();
3836 if ( nHitTest
!= HTCLIENT
)
3839 // first ask the user code - it may wish to set the cursor in some very
3840 // specific way (for example, depending on the current position)
3843 if ( !::GetCursorPosWinCE(&pt
))
3845 if ( !::GetCursorPos(&pt
) )
3848 wxLogLastError(wxT("GetCursorPos"));
3853 ScreenToClient(&x
, &y
);
3854 wxSetCursorEvent
event(x
, y
);
3856 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3857 if ( processedEvtSetCursor
&& event
.HasCursor() )
3859 hcursor
= GetHcursorOf(event
.GetCursor());
3864 // the test for processedEvtSetCursor is here to prevent using
3865 // m_cursor if the user code caught EVT_SET_CURSOR() and returned
3866 // nothing from it - this is a way to say that our cursor shouldn't
3867 // be used for this point
3868 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3870 hcursor
= GetHcursorOf(m_cursor
);
3873 if ( !hcursor
&& !GetParent() )
3875 const wxCursor
*cursor
= wxGetGlobalCursor();
3876 if ( cursor
&& cursor
->Ok() )
3878 hcursor
= GetHcursorOf(*cursor
);
3887 ::SetCursor(hcursor
);
3889 // cursor set, stop here
3892 #endif // __WXMICROWIN__
3894 // pass up the window chain
3898 bool wxWindowMSW::HandlePower(WXWPARAM
WXUNUSED_IN_WINCE(wParam
),
3899 WXLPARAM
WXUNUSED(lParam
),
3900 bool *WXUNUSED_IN_WINCE(vetoed
))
3906 wxEventType evtType
;
3909 case PBT_APMQUERYSUSPEND
:
3910 evtType
= wxEVT_POWER_SUSPENDING
;
3913 case PBT_APMQUERYSUSPENDFAILED
:
3914 evtType
= wxEVT_POWER_SUSPEND_CANCEL
;
3917 case PBT_APMSUSPEND
:
3918 evtType
= wxEVT_POWER_SUSPENDED
;
3921 case PBT_APMRESUMESUSPEND
:
3922 #ifdef PBT_APMRESUMEAUTOMATIC
3923 case PBT_APMRESUMEAUTOMATIC
:
3925 evtType
= wxEVT_POWER_RESUME
;
3929 wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam
);
3932 // these messages are currently not mapped to wx events
3933 case PBT_APMQUERYSTANDBY
:
3934 case PBT_APMQUERYSTANDBYFAILED
:
3935 case PBT_APMSTANDBY
:
3936 case PBT_APMRESUMESTANDBY
:
3937 case PBT_APMBATTERYLOW
:
3938 case PBT_APMPOWERSTATUSCHANGE
:
3939 case PBT_APMOEMEVENT
:
3940 case PBT_APMRESUMECRITICAL
:
3941 evtType
= wxEVT_NULL
;
3945 // don't handle unknown messages
3946 if ( evtType
== wxEVT_NULL
)
3949 // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events?
3951 wxPowerEvent
event(evtType
);
3952 if ( !GetEventHandler()->ProcessEvent(event
) )
3955 *vetoed
= event
.IsVetoed();
3961 bool wxWindowMSW::IsDoubleBuffered() const
3963 for ( const wxWindowMSW
*wnd
= this;
3964 wnd
&& !wnd
->IsTopLevel(); wnd
=
3967 if ( ::GetWindowLong(GetHwndOf(wnd
), GWL_EXSTYLE
) & WS_EX_COMPOSITED
)
3974 // ---------------------------------------------------------------------------
3975 // owner drawn stuff
3976 // ---------------------------------------------------------------------------
3978 #if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \
3979 (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__))
3980 #define WXUNUSED_UNLESS_ODRAWN(param) param
3982 #define WXUNUSED_UNLESS_ODRAWN(param)
3986 wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id
),
3987 WXDRAWITEMSTRUCT
* WXUNUSED_UNLESS_ODRAWN(itemStruct
))
3989 #if wxUSE_OWNER_DRAWN
3991 #if wxUSE_MENUS_NATIVE
3992 // is it a menu item?
3993 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3994 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3996 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3998 // see comment before the same test in MSWOnMeasureItem() below
4002 wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
),
4003 false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
4005 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
4006 // the DC from being released
4007 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
4008 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
4009 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
4010 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
4012 return pMenuItem
->OnDrawItem
4016 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
4017 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
4020 #endif // wxUSE_MENUS_NATIVE
4022 #endif // USE_OWNER_DRAWN
4024 #if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)
4026 #if wxUSE_OWNER_DRAWN
4027 wxControl
*item
= wxDynamicCast(FindItem(id
), wxControl
);
4028 #else // !wxUSE_OWNER_DRAWN
4029 // we may still have owner-drawn buttons internally because we have to make
4030 // them owner-drawn to support colour change
4033 wxDynamicCast(FindItem(id
), wxButton
)
4038 #endif // USE_OWNER_DRAWN
4042 return item
->MSWOnDraw(itemStruct
);
4045 #endif // wxUSE_CONTROLS
4051 wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
4053 #if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
4054 // is it a menu item?
4055 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
4056 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
4058 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
4060 // according to Carsten Fuchs the pointer may be NULL under XP if an
4061 // MDI child frame is initially maximized, see this for more info:
4062 // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745
4064 // so silently ignore it instead of asserting
4068 wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
),
4069 false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
4072 bool rc
= pMenuItem
->OnMeasureItem(&w
, &h
);
4074 pMeasureStruct
->itemWidth
= w
;
4075 pMeasureStruct
->itemHeight
= h
;
4080 wxControl
*item
= wxDynamicCast(FindItem(id
), wxControl
);
4083 return item
->MSWOnMeasure(itemStruct
);
4087 wxUnusedVar(itemStruct
);
4088 #endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
4093 // ---------------------------------------------------------------------------
4094 // colours and palettes
4095 // ---------------------------------------------------------------------------
4097 bool wxWindowMSW::HandleSysColorChange()
4099 wxSysColourChangedEvent event
;
4100 event
.SetEventObject(this);
4102 (void)GetEventHandler()->ProcessEvent(event
);
4104 // always let the system carry on the default processing to allow the
4105 // native controls to react to the colours update
4109 bool wxWindowMSW::HandleDisplayChange()
4111 wxDisplayChangedEvent event
;
4112 event
.SetEventObject(this);
4114 return GetEventHandler()->ProcessEvent(event
);
4117 #ifndef __WXMICROWIN__
4119 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
, WXHDC hDC
, WXHWND hWnd
)
4121 #if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
4125 wxControl
*item
= wxDynamicCast(FindItemByHWND(hWnd
, true), wxControl
);
4128 *brush
= item
->MSWControlColor(hDC
, hWnd
);
4130 #endif // wxUSE_CONTROLS
4133 return *brush
!= NULL
;
4136 #endif // __WXMICROWIN__
4138 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
4141 // same as below except we don't respond to our own messages
4142 if ( hWndPalChange
!= GetHWND() )
4144 // check to see if we our our parents have a custom palette
4145 wxWindowMSW
*win
= this;
4146 while ( win
&& !win
->HasCustomPalette() )
4148 win
= win
->GetParent();
4151 if ( win
&& win
->HasCustomPalette() )
4153 // realize the palette to see whether redrawing is needed
4154 HDC hdc
= ::GetDC((HWND
) hWndPalChange
);
4155 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
4156 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
4158 int result
= ::RealizePalette(hdc
);
4160 // restore the palette (before releasing the DC)
4161 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
4162 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
4163 ::RealizePalette(hdc
);
4164 ::ReleaseDC((HWND
) hWndPalChange
, hdc
);
4166 // now check for the need to redraw
4168 ::InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
);
4172 #endif // wxUSE_PALETTE
4174 wxPaletteChangedEvent
event(GetId());
4175 event
.SetEventObject(this);
4176 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
4178 return GetEventHandler()->ProcessEvent(event
);
4181 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
)
4183 // notify windows on the capture stack about lost capture
4184 // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
4185 wxWindowBase::NotifyCaptureLost();
4187 wxWindow
*win
= wxFindWinFromHandle(hWndGainedCapture
);
4188 wxMouseCaptureChangedEvent
event(GetId(), win
);
4189 event
.SetEventObject(this);
4190 return GetEventHandler()->ProcessEvent(event
);
4193 bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam
, WXLPARAM lParam
)
4195 // despite MSDN saying "(This message cannot be sent directly to a window.)"
4196 // we need to send this to child windows (it is only sent to top-level
4197 // windows) so {list,tree}ctrls can adjust their font size if necessary
4198 // this is exactly how explorer does it to enable the font size changes
4200 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
4203 // top-level windows already get this message from the system
4204 wxWindow
*win
= node
->GetData();
4205 if ( !win
->IsTopLevel() )
4207 ::SendMessage(GetHwndOf(win
), WM_SETTINGCHANGE
, wParam
, lParam
);
4210 node
= node
->GetNext();
4213 // let the system handle it
4217 bool wxWindowMSW::HandleQueryNewPalette()
4221 // check to see if we our our parents have a custom palette
4222 wxWindowMSW
*win
= this;
4223 while (!win
->HasCustomPalette() && win
->GetParent()) win
= win
->GetParent();
4224 if (win
->HasCustomPalette()) {
4225 /* realize the palette to see whether redrawing is needed */
4226 HDC hdc
= ::GetDC((HWND
) GetHWND());
4227 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
4228 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) );
4230 int result
= ::RealizePalette(hdc
);
4231 /* restore the palette (before releasing the DC) */
4232 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
4233 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) );
4234 ::RealizePalette(hdc
);
4235 ::ReleaseDC((HWND
) GetHWND(), hdc
);
4236 /* now check for the need to redraw */
4238 ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
);
4240 #endif // wxUSE_PALETTE
4242 wxQueryNewPaletteEvent
event(GetId());
4243 event
.SetEventObject(this);
4245 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
4248 // Responds to colour changes: passes event on to children.
4249 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
))
4251 // the top level window also reset the standard colour map as it might have
4252 // changed (there is no need to do it for the non top level windows as we
4253 // only have to do it once)
4257 gs_hasStdCmap
= false;
4259 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
4262 // Only propagate to non-top-level windows because Windows already
4263 // sends this event to all top-level ones
4264 wxWindow
*win
= node
->GetData();
4265 if ( !win
->IsTopLevel() )
4267 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
4268 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
4269 // the standard controls
4270 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
4273 node
= node
->GetNext();
4277 extern wxCOLORMAP
*wxGetStdColourMap()
4279 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
4280 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
4282 if ( !gs_hasStdCmap
)
4284 static bool s_coloursInit
= false;
4286 if ( !s_coloursInit
)
4288 // When a bitmap is loaded, the RGB values can change (apparently
4289 // because Windows adjusts them to care for the old programs always
4290 // using 0xc0c0c0 while the transparent colour for the new Windows
4291 // versions is different). But we do this adjustment ourselves so
4292 // we want to avoid Windows' "help" and for this we need to have a
4293 // reference bitmap which can tell us what the RGB values change
4295 wxLogNull logNo
; // suppress error if we couldn't load the bitmap
4296 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
4297 if ( stdColourBitmap
.Ok() )
4299 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
4300 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
4301 _T("forgot to update wxBITMAP_STD_COLOURS!") );
4304 memDC
.SelectObject(stdColourBitmap
);
4307 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
4309 memDC
.GetPixel(i
, 0, &colour
);
4310 s_stdColours
[i
] = wxColourToRGB(colour
);
4313 else // wxBITMAP_STD_COLOURS couldn't be loaded
4315 s_stdColours
[0] = RGB(000,000,000); // black
4316 s_stdColours
[1] = RGB(128,128,128); // dark grey
4317 s_stdColours
[2] = RGB(192,192,192); // light grey
4318 s_stdColours
[3] = RGB(255,255,255); // white
4319 //s_stdColours[4] = RGB(000,000,255); // blue
4320 //s_stdColours[5] = RGB(255,000,255); // magenta
4323 s_coloursInit
= true;
4326 gs_hasStdCmap
= true;
4328 // create the colour map
4329 #define INIT_CMAP_ENTRY(col) \
4330 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
4331 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
4333 INIT_CMAP_ENTRY(BTNTEXT
);
4334 INIT_CMAP_ENTRY(BTNSHADOW
);
4335 INIT_CMAP_ENTRY(BTNFACE
);
4336 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
4338 #undef INIT_CMAP_ENTRY
4344 // ---------------------------------------------------------------------------
4346 // ---------------------------------------------------------------------------
4348 bool wxWindowMSW::HandlePaint()
4350 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
4352 wxLogLastError(wxT("CreateRectRgn"));
4353 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
4354 wxLogLastError(wxT("GetUpdateRgn"));
4356 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
4358 wxPaintEvent
event(m_windowId
);
4359 event
.SetEventObject(this);
4361 bool processed
= GetEventHandler()->ProcessEvent(event
);
4363 // note that we must generate NC event after the normal one as otherwise
4364 // BeginPaint() will happily overwrite our decorations with the background
4366 wxNcPaintEvent
eventNc(m_windowId
);
4367 eventNc
.SetEventObject(this);
4368 GetEventHandler()->ProcessEvent(eventNc
);
4373 // Can be called from an application's OnPaint handler
4374 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
4376 #ifdef __WXUNIVERSAL__
4379 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
4382 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
4387 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
4389 wxDCTemp
dc(hdc
, GetClientSize());
4392 dc
.SetWindow((wxWindow
*)this);
4394 wxEraseEvent
event(m_windowId
, &dc
);
4395 event
.SetEventObject(this);
4396 bool rc
= GetEventHandler()->ProcessEvent(event
);
4398 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
4399 dc
.SelectOldObjects(hdc
);
4404 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
4406 // standard non top level controls (i.e. except the dialogs) always erase
4407 // their background themselves in HandleCtlColor() or have some control-
4408 // specific ways to set the colours (common controls)
4409 if ( IsOfStandardClass() && !IsTopLevel() )
4415 if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM
)
4417 // don't skip the event here, custom background means that the app
4418 // is drawing it itself in its OnPaint(), so don't draw it at all
4419 // now to avoid flicker
4424 // do default background painting
4425 if ( !DoEraseBackground(GetHdcOf(*event
.GetDC())) )
4427 // let the system paint the background
4432 bool wxWindowMSW::DoEraseBackground(WXHDC hDC
)
4434 HBRUSH hbr
= (HBRUSH
)MSWGetBgBrush(hDC
);
4438 wxFillRect(GetHwnd(), (HDC
)hDC
, hbr
);
4444 wxWindowMSW::MSWGetBgBrushForChild(WXHDC
WXUNUSED(hDC
), WXHWND hWnd
)
4448 // our background colour applies to:
4449 // 1. this window itself, always
4450 // 2. all children unless the colour is "not inheritable"
4451 // 3. even if it is not inheritable, our immediate transparent
4452 // children should still inherit it -- but not any transparent
4453 // children because it would look wrong if a child of non
4454 // transparent child would show our bg colour when the child itself
4456 wxWindow
*win
= wxFindWinFromHandle(hWnd
);
4459 (win
&& win
->HasTransparentBackground() &&
4460 win
->GetParent() == this) )
4462 // draw children with the same colour as the parent
4464 brush
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour());
4466 return (WXHBRUSH
)GetHbrushOf(*brush
);
4473 WXHBRUSH
wxWindowMSW::MSWGetBgBrush(WXHDC hDC
, WXHWND hWndToPaint
)
4476 hWndToPaint
= GetHWND();
4478 for ( wxWindowMSW
*win
= this; win
; win
= win
->GetParent() )
4480 WXHBRUSH hBrush
= win
->MSWGetBgBrushForChild(hDC
, hWndToPaint
);
4484 // background is not inherited beyond top level windows
4485 if ( win
->IsTopLevel() )
4492 bool wxWindowMSW::HandlePrintClient(WXHDC hDC
)
4494 // we receive this message when DrawThemeParentBackground() is
4495 // called from def window proc of several controls under XP and we
4496 // must draw properly themed background here
4498 // note that naively I'd expect filling the client rect with the
4499 // brush returned by MSWGetBgBrush() work -- but for some reason it
4500 // doesn't and we have to call parents MSWPrintChild() which is
4501 // supposed to call DrawThemeBackground() with appropriate params
4503 // also note that in this case lParam == PRF_CLIENT but we're
4504 // clearly expected to paint the background and nothing else!
4506 if ( IsTopLevel() || InheritsBackgroundColour() )
4509 // sometimes we don't want the parent to handle it at all, instead
4510 // return whatever value this window wants
4511 if ( !MSWShouldPropagatePrintChild() )
4512 return MSWPrintChild(hDC
, (wxWindow
*)this);
4514 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
4516 if ( win
->MSWPrintChild(hDC
, (wxWindow
*)this) )
4519 if ( win
->IsTopLevel() || win
->InheritsBackgroundColour() )
4526 // ---------------------------------------------------------------------------
4527 // moving and resizing
4528 // ---------------------------------------------------------------------------
4530 bool wxWindowMSW::HandleMinimize()
4532 wxIconizeEvent
event(m_windowId
);
4533 event
.SetEventObject(this);
4535 return GetEventHandler()->ProcessEvent(event
);
4538 bool wxWindowMSW::HandleMaximize()
4540 wxMaximizeEvent
event(m_windowId
);
4541 event
.SetEventObject(this);
4543 return GetEventHandler()->ProcessEvent(event
);
4546 bool wxWindowMSW::HandleMove(int x
, int y
)
4549 wxMoveEvent
event(point
, m_windowId
);
4550 event
.SetEventObject(this);
4552 return GetEventHandler()->ProcessEvent(event
);
4555 bool wxWindowMSW::HandleMoving(wxRect
& rect
)
4557 wxMoveEvent
event(rect
, m_windowId
);
4558 event
.SetEventObject(this);
4560 bool rc
= GetEventHandler()->ProcessEvent(event
);
4562 rect
= event
.GetRect();
4566 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), WXUINT wParam
)
4568 #if USE_DEFERRED_SIZING
4569 // when we resize this window, its children are probably going to be
4570 // repositioned as well, prepare to use DeferWindowPos() for them
4571 int numChildren
= 0;
4572 for ( HWND child
= ::GetWindow(GetHwndOf(this), GW_CHILD
);
4574 child
= ::GetWindow(child
, GW_HWNDNEXT
) )
4579 // Protect against valid m_hDWP being overwritten
4580 bool useDefer
= false;
4582 if ( numChildren
> 1 )
4586 m_hDWP
= (WXHANDLE
)::BeginDeferWindowPos(numChildren
);
4589 wxLogLastError(_T("BeginDeferWindowPos"));
4595 #endif // USE_DEFERRED_SIZING
4597 // update this window size
4598 bool processed
= false;
4602 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
4603 // fall through nevertheless
4607 // we're not interested in these messages at all
4610 case SIZE_MINIMIZED
:
4611 processed
= HandleMinimize();
4614 case SIZE_MAXIMIZED
:
4615 /* processed = */ HandleMaximize();
4616 // fall through to send a normal size event as well
4619 // don't use w and h parameters as they specify the client size
4620 // while according to the docs EVT_SIZE handler is supposed to
4621 // receive the total size
4622 wxSizeEvent
event(GetSize(), m_windowId
);
4623 event
.SetEventObject(this);
4625 processed
= GetEventHandler()->ProcessEvent(event
);
4628 #if USE_DEFERRED_SIZING
4629 // and finally change the positions of all child windows at once
4630 if ( useDefer
&& m_hDWP
)
4632 // reset m_hDWP to NULL so that child windows don't try to use our
4633 // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
4634 // happen anyhow normally but who knows what weird flow of control we
4635 // may have depending on what the users EVT_SIZE handler does...)
4636 HDWP hDWP
= (HDWP
)m_hDWP
;
4639 // do put all child controls in place at once
4640 if ( !::EndDeferWindowPos(hDWP
) )
4642 wxLogLastError(_T("EndDeferWindowPos"));
4645 // Reset our children's pending pos/size values.
4646 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
4648 node
= node
->GetNext() )
4650 wxWindowMSW
*child
= node
->GetData();
4651 child
->m_pendingPosition
= wxDefaultPosition
;
4652 child
->m_pendingSize
= wxDefaultSize
;
4655 #endif // USE_DEFERRED_SIZING
4660 bool wxWindowMSW::HandleSizing(wxRect
& rect
)
4662 wxSizeEvent
event(rect
, m_windowId
);
4663 event
.SetEventObject(this);
4665 bool rc
= GetEventHandler()->ProcessEvent(event
);
4667 rect
= event
.GetRect();
4671 bool wxWindowMSW::HandleGetMinMaxInfo(void *WXUNUSED_IN_WINCE(mmInfo
))
4676 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
4680 int minWidth
= GetMinWidth(),
4681 minHeight
= GetMinHeight(),
4682 maxWidth
= GetMaxWidth(),
4683 maxHeight
= GetMaxHeight();
4685 if ( minWidth
!= wxDefaultCoord
)
4687 info
->ptMinTrackSize
.x
= minWidth
;
4691 if ( minHeight
!= wxDefaultCoord
)
4693 info
->ptMinTrackSize
.y
= minHeight
;
4697 if ( maxWidth
!= wxDefaultCoord
)
4699 info
->ptMaxTrackSize
.x
= maxWidth
;
4703 if ( maxHeight
!= wxDefaultCoord
)
4705 info
->ptMaxTrackSize
.y
= maxHeight
;
4713 // ---------------------------------------------------------------------------
4715 // ---------------------------------------------------------------------------
4717 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
4719 #if wxUSE_MENUS_NATIVE
4720 if ( !cmd
&& wxCurrentPopupMenu
)
4722 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
4723 wxCurrentPopupMenu
= NULL
;
4725 return popupMenu
->MSWCommand(cmd
, id
);
4727 #endif // wxUSE_MENUS_NATIVE
4729 wxWindow
*win
= NULL
;
4731 // first try to find it from HWND - this works even with the broken
4732 // programs using the same ids for different controls
4735 win
= wxFindWinFromHandle(control
);
4741 // must cast to a signed type before comparing with other ids!
4742 win
= FindItem((signed short)id
);
4747 return win
->MSWCommand(cmd
, id
);
4750 // the messages sent from the in-place edit control used by the treectrl
4751 // for label editing have id == 0, but they should _not_ be treated as menu
4752 // messages (they are EN_XXX ones, in fact) so don't translate anything
4753 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
4756 // If no child window, it may be an accelerator, e.g. for a popup menu
4759 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
4760 event
.SetEventObject(this);
4764 return GetEventHandler()->ProcessEvent(event
);
4768 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4769 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
4770 // notifications to its parent which we want to reflect back to
4772 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
4773 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
4775 #endif // wxUSE_SPINCTRL
4777 #if wxUSE_CHOICE && defined(__SMARTPHONE__)
4778 // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND
4779 // notifications to its parent which we want to reflect back to
4781 wxChoice
*choice
= wxChoice::GetChoiceForListBox(control
);
4782 if ( choice
&& choice
->MSWCommand(cmd
, id
) )
4790 // ---------------------------------------------------------------------------
4792 // ---------------------------------------------------------------------------
4794 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
4798 // our client coords are not quite the same as Windows ones
4799 wxPoint pt
= GetClientAreaOrigin();
4800 event
.m_x
= x
- pt
.x
;
4801 event
.m_y
= y
- pt
.y
;
4803 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
4804 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
4805 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
4806 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
4807 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
4808 #ifdef wxHAS_XBUTTON
4809 event
.m_aux1Down
= (flags
& MK_XBUTTON1
) != 0;
4810 event
.m_aux2Down
= (flags
& MK_XBUTTON2
) != 0;
4811 #endif // wxHAS_XBUTTON
4812 event
.m_altDown
= ::GetKeyState(VK_MENU
) < 0;
4815 event
.SetTimestamp(::GetMessageTime());
4818 event
.SetEventObject(this);
4819 event
.SetId(GetId());
4821 #if wxUSE_MOUSEEVENT_HACK
4822 gs_lastMouseEvent
.pos
= ClientToScreen(wxPoint(x
, y
));
4823 gs_lastMouseEvent
.type
= event
.GetEventType();
4824 #endif // wxUSE_MOUSEEVENT_HACK
4828 // Windows doesn't send the mouse events to the static controls (which are
4829 // transparent in the sense that their WM_NCHITTEST handler returns
4830 // HTTRANSPARENT) at all but we want all controls to receive the mouse events
4831 // and so we manually check if we don't have a child window under mouse and if
4832 // we do, send the event to it instead of the window Windows had sent WM_XXX
4835 // Notice that this is not done for the mouse move events because this could
4836 // (would?) be too slow, but only for clicks which means that the static texts
4837 // still don't get move, enter nor leave events.
4838 static wxWindowMSW
*FindWindowForMouseEvent(wxWindowMSW
*win
, int *x
, int *y
)
4840 wxCHECK_MSG( x
&& y
, win
, _T("NULL pointer in FindWindowForMouseEvent") );
4842 // first try to find a non transparent child: this allows us to send events
4843 // to a static text which is inside a static box, for example
4844 POINT pt
= { *x
, *y
};
4845 HWND hwnd
= GetHwndOf(win
),
4849 hwndUnderMouse
= ::ChildWindowFromPoint
4855 hwndUnderMouse
= ::ChildWindowFromPointEx
4865 if ( !hwndUnderMouse
|| hwndUnderMouse
== hwnd
)
4867 // now try any child window at all
4868 hwndUnderMouse
= ::ChildWindowFromPoint(hwnd
, pt
);
4871 // check that we have a child window which is susceptible to receive mouse
4872 // events: for this it must be shown and enabled
4873 if ( hwndUnderMouse
&&
4874 hwndUnderMouse
!= hwnd
&&
4875 ::IsWindowVisible(hwndUnderMouse
) &&
4876 ::IsWindowEnabled(hwndUnderMouse
) )
4878 wxWindow
*winUnderMouse
= wxFindWinFromHandle((WXHWND
)hwndUnderMouse
);
4879 if ( winUnderMouse
)
4881 // translate the mouse coords to the other window coords
4882 win
->ClientToScreen(x
, y
);
4883 winUnderMouse
->ScreenToClient(x
, y
);
4885 win
= winUnderMouse
;
4891 #endif // __WXWINCE__
4893 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4895 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
4896 // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST
4897 // from the message id and take the value in the table to get wxWin event
4899 static const wxEventType eventsMouse
[] =
4910 wxEVT_MIDDLE_DCLICK
,
4911 0, // this one is for wxEVT_MOTION which is not used here
4920 #ifdef wxHAS_XBUTTON
4921 // the same messages are used for both auxillary mouse buttons so we need
4922 // to adjust the index manually
4925 case WM_XBUTTONDOWN
:
4927 case WM_XBUTTONDBLCLK
:
4928 if ( flags
& MK_XBUTTON2
)
4929 msg
+= wxEVT_AUX2_DOWN
- wxEVT_AUX1_DOWN
;
4931 #endif // wxHAS_XBUTTON
4933 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
4934 InitMouseEvent(event
, x
, y
, flags
);
4936 return GetEventHandler()->ProcessEvent(event
);
4939 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
4941 if ( !m_mouseInWindow
)
4943 // it would be wrong to assume that just because we get a mouse move
4944 // event that the mouse is inside the window: although this is usually
4945 // true, it is not if we had captured the mouse, so we need to check
4946 // the mouse coordinates here
4947 if ( !HasCapture() || IsMouseInWindow() )
4949 // Generate an ENTER event
4950 m_mouseInWindow
= true;
4952 #ifdef HAVE_TRACKMOUSEEVENT
4953 typedef BOOL (WINAPI
*_TrackMouseEvent_t
)(LPTRACKMOUSEEVENT
);
4955 static const _TrackMouseEvent_t
4956 s_pfn_TrackMouseEvent
= _TrackMouseEvent
;
4957 #else // !__WXWINCE__
4958 static _TrackMouseEvent_t s_pfn_TrackMouseEvent
;
4959 static bool s_initDone
= false;
4964 wxDynamicLibrary
dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM
);
4965 if ( dllComCtl32
.IsLoaded() )
4967 s_pfn_TrackMouseEvent
= (_TrackMouseEvent_t
)
4968 dllComCtl32
.GetSymbol(_T("_TrackMouseEvent"));
4973 // notice that it's ok to unload comctl32.dll here as it won't
4974 // be really unloaded, being still in use because we link to it
4978 if ( s_pfn_TrackMouseEvent
)
4979 #endif // __WXWINCE__/!__WXWINCE__
4981 WinStruct
<TRACKMOUSEEVENT
> trackinfo
;
4983 trackinfo
.dwFlags
= TME_LEAVE
;
4984 trackinfo
.hwndTrack
= GetHwnd();
4986 (*s_pfn_TrackMouseEvent
)(&trackinfo
);
4988 #endif // HAVE_TRACKMOUSEEVENT
4990 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
4991 InitMouseEvent(event
, x
, y
, flags
);
4993 (void)GetEventHandler()->ProcessEvent(event
);
4996 #ifdef HAVE_TRACKMOUSEEVENT
4997 else // mouse not in window
4999 // Check if we need to send a LEAVE event
5000 // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so
5001 // send it here if we are using native mouse leave tracking
5002 if ( HasCapture() && !IsMouseInWindow() )
5004 GenerateMouseLeave();
5007 #endif // HAVE_TRACKMOUSEEVENT
5009 #if wxUSE_MOUSEEVENT_HACK
5010 // Windows often generates mouse events even if mouse position hasn't
5011 // changed (http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/66576)
5013 // Filter this out as it can result in unexpected behaviour compared to
5015 if ( gs_lastMouseEvent
.type
== wxEVT_RIGHT_DOWN
||
5016 gs_lastMouseEvent
.type
== wxEVT_LEFT_DOWN
||
5017 gs_lastMouseEvent
.type
== wxEVT_MIDDLE_DOWN
||
5018 gs_lastMouseEvent
.type
== wxEVT_MOTION
)
5020 if ( ClientToScreen(wxPoint(x
, y
)) == gs_lastMouseEvent
.pos
)
5022 gs_lastMouseEvent
.type
= wxEVT_MOTION
;
5027 #endif // wxUSE_MOUSEEVENT_HACK
5029 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
5033 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
5035 #if wxUSE_MOUSEWHEEL
5036 // notice that WM_MOUSEWHEEL position is in screen coords (as it's
5037 // forwarded up to the parent by DefWindowProc()) and not in the client
5038 // ones as all the other messages, translate them to the client coords for
5041 pt
= ScreenToClient(wxPoint(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
)));
5042 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
5043 InitMouseEvent(event
, pt
.x
, pt
.y
, LOWORD(wParam
));
5044 event
.m_wheelRotation
= (short)HIWORD(wParam
);
5045 event
.m_wheelDelta
= WHEEL_DELTA
;
5047 static int s_linesPerRotation
= -1;
5048 if ( s_linesPerRotation
== -1 )
5050 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
5051 &s_linesPerRotation
, 0))
5053 // this is not supposed to happen
5054 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
5056 // the default is 3, so use it if SystemParametersInfo() failed
5057 s_linesPerRotation
= 3;
5061 event
.m_linesPerAction
= s_linesPerRotation
;
5062 return GetEventHandler()->ProcessEvent(event
);
5064 #else // !wxUSE_MOUSEWHEEL
5065 wxUnusedVar(wParam
);
5066 wxUnusedVar(lParam
);
5069 #endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL
5072 void wxWindowMSW::GenerateMouseLeave()
5074 m_mouseInWindow
= false;
5077 if ( wxIsShiftDown() )
5079 if ( wxIsCtrlDown() )
5080 state
|= MK_CONTROL
;
5082 // Only the high-order bit should be tested
5083 if ( GetKeyState( VK_LBUTTON
) & (1<<15) )
5084 state
|= MK_LBUTTON
;
5085 if ( GetKeyState( VK_MBUTTON
) & (1<<15) )
5086 state
|= MK_MBUTTON
;
5087 if ( GetKeyState( VK_RBUTTON
) & (1<<15) )
5088 state
|= MK_RBUTTON
;
5092 if ( !::GetCursorPosWinCE(&pt
) )
5094 if ( !::GetCursorPos(&pt
) )
5097 wxLogLastError(_T("GetCursorPos"));
5100 // we need to have client coordinates here for symmetry with
5101 // wxEVT_ENTER_WINDOW
5102 RECT rect
= wxGetWindowRect(GetHwnd());
5106 wxMouseEvent
event(wxEVT_LEAVE_WINDOW
);
5107 InitMouseEvent(event
, pt
.x
, pt
.y
, state
);
5109 (void)GetEventHandler()->ProcessEvent(event
);
5112 // ---------------------------------------------------------------------------
5113 // keyboard handling
5114 // ---------------------------------------------------------------------------
5116 // create the key event of the given type for the given key - used by
5117 // HandleChar and HandleKeyDown/Up
5118 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
5121 WXWPARAM wParam
) const
5123 wxKeyEvent
event(evType
);
5124 event
.SetId(GetId());
5125 event
.m_shiftDown
= wxIsShiftDown();
5126 event
.m_controlDown
= wxIsCtrlDown();
5127 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
5129 event
.SetEventObject((wxWindow
*)this); // const_cast
5130 event
.m_keyCode
= id
;
5132 event
.m_uniChar
= (wxChar
) wParam
;
5134 event
.m_rawCode
= (wxUint32
) wParam
;
5135 event
.m_rawFlags
= (wxUint32
) lParam
;
5137 event
.SetTimestamp(::GetMessageTime());
5140 // translate the position to client coords
5143 GetCursorPosWinCE(&pt
);
5148 GetWindowRect(GetHwnd(),&rect
);
5158 // isASCII is true only when we're called from WM_CHAR handler and not from
5160 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
5167 else // we're called from WM_KEYDOWN
5169 // don't pass lParam to wxCharCodeMSWToWX() here because we don't want
5170 // to get numpad key codes: CHAR events should use the logical keys
5171 // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events
5172 id
= wxCharCodeMSWToWX(wParam
);
5175 // it's ASCII and will be processed here only when called from
5176 // WM_CHAR (i.e. when isASCII = true), don't process it now
5181 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
));
5183 // the alphanumeric keys produced by pressing AltGr+something on European
5184 // keyboards have both Ctrl and Alt modifiers which may confuse the user
5185 // code as, normally, keys with Ctrl and/or Alt don't result in anything
5186 // alphanumeric, so pretend that there are no modifiers at all (the
5187 // KEY_DOWN event would still have the correct modifiers if they're really
5189 if ( event
.m_controlDown
&& event
.m_altDown
&&
5190 (id
>= 32 && id
< 256) )
5192 event
.m_controlDown
=
5193 event
.m_altDown
= false;
5196 return GetEventHandler()->ProcessEvent(event
);
5199 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
5201 int id
= wxCharCodeMSWToWX(wParam
, lParam
);
5205 // normal ASCII char
5209 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
));
5210 return GetEventHandler()->ProcessEvent(event
);
5213 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
5215 int id
= wxCharCodeMSWToWX(wParam
, lParam
);
5219 // normal ASCII char
5223 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
));
5224 return GetEventHandler()->ProcessEvent(event
);
5228 int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel
),
5229 WXLPARAM
WXUNUSED_IN_WINCE(lParam
))
5231 // FIXME: implement GetMenuItemCount for WinCE, possibly
5232 // in terms of GetMenuItemInfo
5234 const HMENU hmenu
= (HMENU
)lParam
;
5238 mii
.cbSize
= sizeof(MENUITEMINFO
);
5240 // we could use MIIM_FTYPE here as we only need to know if the item is
5241 // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but
5242 // MIIM_FTYPE is not supported under Win95
5243 mii
.fMask
= MIIM_TYPE
| MIIM_DATA
;
5245 // find if we have this letter in any owner drawn item
5246 const int count
= ::GetMenuItemCount(hmenu
);
5247 for ( int i
= 0; i
< count
; i
++ )
5249 // previous loop iteration could modify it, reset it back before
5250 // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData
5253 if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) )
5255 if ( mii
.fType
== MFT_OWNERDRAW
)
5257 // dwItemData member of the MENUITEMINFO is a
5258 // pointer to the associated wxMenuItem -- see the
5259 // menu creation code
5260 wxMenuItem
*item
= (wxMenuItem
*)mii
.dwItemData
;
5262 const wxChar
*p
= wxStrchr(item
->GetText().wx_str(), _T('&'));
5265 if ( *p
== _T('&') )
5267 // this is not the accel char, find the real one
5268 p
= wxStrchr(p
+ 1, _T('&'));
5270 else // got the accel char
5272 // FIXME-UNICODE: this comparison doesn't risk to work
5273 // for non ASCII accelerator characters I'm afraid, but
5275 if ( (wchar_t)wxToupper(*p
) == (wchar_t)chAccel
)
5281 // this one doesn't match
5288 else // failed to get the menu text?
5290 // it's not fatal, so don't show error, but still log it
5291 wxLogLastError(_T("GetMenuItemInfo"));
5298 bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg
)
5300 const wxEventType type
= ( nMsg
== WM_CUT
) ? wxEVT_COMMAND_TEXT_CUT
:
5301 ( nMsg
== WM_COPY
) ? wxEVT_COMMAND_TEXT_COPY
:
5302 /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE
;
5303 wxClipboardTextEvent
evt(type
, GetId());
5305 evt
.SetEventObject(this);
5307 return GetEventHandler()->ProcessEvent(evt
);
5309 #endif // wxUSE_MENUS
5311 // ---------------------------------------------------------------------------
5313 // ---------------------------------------------------------------------------
5315 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
5319 if ( flags
& JOY_BUTTON1CHG
)
5320 change
= wxJOY_BUTTON1
;
5321 if ( flags
& JOY_BUTTON2CHG
)
5322 change
= wxJOY_BUTTON2
;
5323 if ( flags
& JOY_BUTTON3CHG
)
5324 change
= wxJOY_BUTTON3
;
5325 if ( flags
& JOY_BUTTON4CHG
)
5326 change
= wxJOY_BUTTON4
;
5329 if ( flags
& JOY_BUTTON1
)
5330 buttons
|= wxJOY_BUTTON1
;
5331 if ( flags
& JOY_BUTTON2
)
5332 buttons
|= wxJOY_BUTTON2
;
5333 if ( flags
& JOY_BUTTON3
)
5334 buttons
|= wxJOY_BUTTON3
;
5335 if ( flags
& JOY_BUTTON4
)
5336 buttons
|= wxJOY_BUTTON4
;
5338 // the event ids aren't consecutive so we can't use table based lookup
5340 wxEventType eventType
;
5345 eventType
= wxEVT_JOY_MOVE
;
5350 eventType
= wxEVT_JOY_MOVE
;
5355 eventType
= wxEVT_JOY_ZMOVE
;
5360 eventType
= wxEVT_JOY_ZMOVE
;
5363 case MM_JOY1BUTTONDOWN
:
5365 eventType
= wxEVT_JOY_BUTTON_DOWN
;
5368 case MM_JOY2BUTTONDOWN
:
5370 eventType
= wxEVT_JOY_BUTTON_DOWN
;
5373 case MM_JOY1BUTTONUP
:
5375 eventType
= wxEVT_JOY_BUTTON_UP
;
5378 case MM_JOY2BUTTONUP
:
5380 eventType
= wxEVT_JOY_BUTTON_UP
;
5384 wxFAIL_MSG(wxT("no such joystick event"));
5389 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
5390 event
.SetPosition(wxPoint(x
, y
));
5391 event
.SetEventObject(this);
5393 return GetEventHandler()->ProcessEvent(event
);
5403 // ---------------------------------------------------------------------------
5405 // ---------------------------------------------------------------------------
5407 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
5408 WXWORD pos
, WXHWND control
)
5410 if ( control
&& control
!= m_hWnd
) // Prevent infinite recursion
5412 wxWindow
*child
= wxFindWinFromHandle(control
);
5414 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
5417 wxScrollWinEvent event
;
5418 event
.SetPosition(pos
);
5419 event
.SetOrientation(orientation
);
5420 event
.SetEventObject(this);
5425 event
.SetEventType(wxEVT_SCROLLWIN_TOP
);
5429 event
.SetEventType(wxEVT_SCROLLWIN_BOTTOM
);
5433 event
.SetEventType(wxEVT_SCROLLWIN_LINEUP
);
5437 event
.SetEventType(wxEVT_SCROLLWIN_LINEDOWN
);
5441 event
.SetEventType(wxEVT_SCROLLWIN_PAGEUP
);
5445 event
.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN
);
5448 case SB_THUMBPOSITION
:
5450 // under Win32, the scrollbar range and position are 32 bit integers,
5451 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
5452 // explicitly query the scrollbar for the correct position (this must
5453 // be done only for these two SB_ events as they are the only one
5454 // carrying the scrollbar position)
5456 WinStruct
<SCROLLINFO
> scrollInfo
;
5457 scrollInfo
.fMask
= SIF_TRACKPOS
;
5459 if ( !::GetScrollInfo(GetHwnd(),
5460 orientation
== wxHORIZONTAL
? SB_HORZ
5464 // Not necessarily an error, if there are no scrollbars yet.
5465 // wxLogLastError(_T("GetScrollInfo"));
5468 event
.SetPosition(scrollInfo
.nTrackPos
);
5471 event
.SetEventType( wParam
== SB_THUMBPOSITION
5472 ? wxEVT_SCROLLWIN_THUMBRELEASE
5473 : wxEVT_SCROLLWIN_THUMBTRACK
);
5480 return GetEventHandler()->ProcessEvent(event
);
5483 // ----------------------------------------------------------------------------
5484 // custom message handlers
5485 // ----------------------------------------------------------------------------
5488 wxWindowMSW::MSWRegisterMessageHandler(int msg
, MSWMessageHandler handler
)
5490 wxCHECK_MSG( gs_messageHandlers
.find(msg
) == gs_messageHandlers
.end(),
5491 false, _T("registering handler for the same message twice") );
5493 gs_messageHandlers
[msg
] = handler
;
5498 wxWindowMSW::MSWUnregisterMessageHandler(int msg
, MSWMessageHandler handler
)
5500 const MSWMessageHandlers::iterator i
= gs_messageHandlers
.find(msg
);
5501 wxCHECK_RET( i
!= gs_messageHandlers
.end() && i
->second
== handler
,
5502 _T("unregistering non-registered handler?") );
5504 gs_messageHandlers
.erase(i
);
5507 // ===========================================================================
5509 // ===========================================================================
5511 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
& the_font
)
5514 HDC dc
= ::GetDC((HWND
) wnd
);
5517 // the_font.UseResource();
5518 // the_font.RealizeResource();
5519 HFONT fnt
= (HFONT
)the_font
.GetResourceHandle(); // const_cast
5521 was
= (HFONT
) SelectObject(dc
,fnt
);
5523 GetTextMetrics(dc
, &tm
);
5526 SelectObject(dc
,was
);
5528 ReleaseDC((HWND
)wnd
, dc
);
5531 *x
= tm
.tmAveCharWidth
;
5533 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
5535 // the_font.ReleaseResource();
5538 // use the "extended" bit (24) of lParam to distinguish extended keys
5539 // from normal keys as the same key is sent
5541 int ChooseNormalOrExtended(int lParam
, int keyNormal
, int keyExtended
)
5543 // except that if lParam is 0, it means we don't have real lParam from
5544 // WM_KEYDOWN but are just translating just a VK constant (e.g. done from
5545 // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a
5546 // non-numpad (hence extended) key as this is a more common case
5547 return !lParam
|| (lParam
& (1 << 24)) ? keyExtended
: keyNormal
;
5550 // this array contains the Windows virtual key codes which map one to one to
5551 // WXK_xxx constants and is used in wxCharCodeMSWToWX/WXToMSW() below
5553 // note that keys having a normal and numpad version (e.g. WXK_HOME and
5554 // WXK_NUMPAD_HOME) are not included in this table as the mapping is not 1-to-1
5555 static const struct wxKeyMapping
5559 } gs_specialKeys
[] =
5561 { VK_CANCEL
, WXK_CANCEL
},
5562 { VK_BACK
, WXK_BACK
},
5563 { VK_TAB
, WXK_TAB
},
5564 { VK_CLEAR
, WXK_CLEAR
},
5565 { VK_SHIFT
, WXK_SHIFT
},
5566 { VK_CONTROL
, WXK_CONTROL
},
5567 { VK_MENU
, WXK_ALT
},
5568 { VK_PAUSE
, WXK_PAUSE
},
5569 { VK_CAPITAL
, WXK_CAPITAL
},
5570 { VK_SPACE
, WXK_SPACE
},
5571 { VK_ESCAPE
, WXK_ESCAPE
},
5572 { VK_SELECT
, WXK_SELECT
},
5573 { VK_PRINT
, WXK_PRINT
},
5574 { VK_EXECUTE
, WXK_EXECUTE
},
5575 { VK_SNAPSHOT
, WXK_SNAPSHOT
},
5576 { VK_HELP
, WXK_HELP
},
5578 { VK_NUMPAD0
, WXK_NUMPAD0
},
5579 { VK_NUMPAD1
, WXK_NUMPAD1
},
5580 { VK_NUMPAD2
, WXK_NUMPAD2
},
5581 { VK_NUMPAD3
, WXK_NUMPAD3
},
5582 { VK_NUMPAD4
, WXK_NUMPAD4
},
5583 { VK_NUMPAD5
, WXK_NUMPAD5
},
5584 { VK_NUMPAD6
, WXK_NUMPAD6
},
5585 { VK_NUMPAD7
, WXK_NUMPAD7
},
5586 { VK_NUMPAD8
, WXK_NUMPAD8
},
5587 { VK_NUMPAD9
, WXK_NUMPAD9
},
5588 { VK_MULTIPLY
, WXK_NUMPAD_MULTIPLY
},
5589 { VK_ADD
, WXK_NUMPAD_ADD
},
5590 { VK_SUBTRACT
, WXK_NUMPAD_SUBTRACT
},
5591 { VK_DECIMAL
, WXK_NUMPAD_DECIMAL
},
5592 { VK_DIVIDE
, WXK_NUMPAD_DIVIDE
},
5603 { VK_F10
, WXK_F10
},
5604 { VK_F11
, WXK_F11
},
5605 { VK_F12
, WXK_F12
},
5606 { VK_F13
, WXK_F13
},
5607 { VK_F14
, WXK_F14
},
5608 { VK_F15
, WXK_F15
},
5609 { VK_F16
, WXK_F16
},
5610 { VK_F17
, WXK_F17
},
5611 { VK_F18
, WXK_F18
},
5612 { VK_F19
, WXK_F19
},
5613 { VK_F20
, WXK_F20
},
5614 { VK_F21
, WXK_F21
},
5615 { VK_F22
, WXK_F22
},
5616 { VK_F23
, WXK_F23
},
5617 { VK_F24
, WXK_F24
},
5619 { VK_NUMLOCK
, WXK_NUMLOCK
},
5620 { VK_SCROLL
, WXK_SCROLL
},
5623 { VK_LWIN
, WXK_WINDOWS_LEFT
},
5624 { VK_RWIN
, WXK_WINDOWS_RIGHT
},
5625 { VK_APPS
, WXK_WINDOWS_MENU
},
5626 #endif // VK_APPS defined
5629 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
5630 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
5631 int wxCharCodeMSWToWX(int vk
, WXLPARAM lParam
)
5633 // check the table first
5634 for ( size_t n
= 0; n
< WXSIZEOF(gs_specialKeys
); n
++ )
5636 if ( gs_specialKeys
[n
].vk
== vk
)
5637 return gs_specialKeys
[n
].wxk
;
5640 // keys requiring special handling
5644 // the mapping for these keys may be incorrect on non-US keyboards so
5645 // maybe we shouldn't map them to ASCII values at all
5646 case VK_OEM_1
: wxk
= ';'; break;
5647 case VK_OEM_PLUS
: wxk
= '+'; break;
5648 case VK_OEM_COMMA
: wxk
= ','; break;
5649 case VK_OEM_MINUS
: wxk
= '-'; break;
5650 case VK_OEM_PERIOD
: wxk
= '.'; break;
5651 case VK_OEM_2
: wxk
= '/'; break;
5652 case VK_OEM_3
: wxk
= '~'; break;
5653 case VK_OEM_4
: wxk
= '['; break;
5654 case VK_OEM_5
: wxk
= '\\'; break;
5655 case VK_OEM_6
: wxk
= ']'; break;
5656 case VK_OEM_7
: wxk
= '\''; break;
5658 // handle extended keys
5660 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_PAGEUP
, WXK_PAGEUP
);
5664 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_PAGEDOWN
, WXK_PAGEDOWN
);
5668 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_END
, WXK_END
);
5672 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_HOME
, WXK_HOME
);
5676 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_LEFT
, WXK_LEFT
);
5680 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_UP
, WXK_UP
);
5684 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_RIGHT
, WXK_RIGHT
);
5688 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_DOWN
, WXK_DOWN
);
5692 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_INSERT
, WXK_INSERT
);
5696 wxk
= ChooseNormalOrExtended(lParam
, WXK_NUMPAD_DELETE
, WXK_DELETE
);
5700 // don't use ChooseNormalOrExtended() here as the keys are reversed
5701 // here: numpad enter is the extended one
5702 wxk
= lParam
&& (lParam
& (1 << 24)) ? WXK_NUMPAD_ENTER
: WXK_RETURN
;
5712 WXWORD
wxCharCodeWXToMSW(int wxk
, bool *isVirtual
)
5717 // check the table first
5718 for ( size_t n
= 0; n
< WXSIZEOF(gs_specialKeys
); n
++ )
5720 if ( gs_specialKeys
[n
].wxk
== wxk
)
5721 return gs_specialKeys
[n
].vk
;
5724 // and then check for special keys not included in the table
5729 case WXK_NUMPAD_PAGEUP
:
5734 case WXK_NUMPAD_PAGEDOWN
:
5739 case WXK_NUMPAD_END
:
5744 case WXK_NUMPAD_HOME
:
5749 case WXK_NUMPAD_LEFT
:
5759 case WXK_NUMPAD_RIGHT
:
5764 case WXK_NUMPAD_DOWN
:
5769 case WXK_NUMPAD_INSERT
:
5774 case WXK_NUMPAD_DELETE
:
5788 #ifndef SM_SWAPBUTTON
5789 #define SM_SWAPBUTTON 23
5792 // small helper for wxGetKeyState() and wxGetMouseState()
5793 static inline bool wxIsKeyDown(WXWORD vk
)
5798 if (GetSystemMetrics(SM_SWAPBUTTON
)) vk
= VK_RBUTTON
;
5801 if (GetSystemMetrics(SM_SWAPBUTTON
)) vk
= VK_LBUTTON
;
5804 // the low order bit indicates whether the key was pressed since the last
5805 // call and the high order one indicates whether it is down right now and
5806 // we only want that one
5807 return (GetAsyncKeyState(vk
) & (1<<15)) != 0;
5810 bool wxGetKeyState(wxKeyCode key
)
5812 // although this does work under Windows, it is not supported under other
5813 // platforms so don't allow it, you must use wxGetMouseState() instead
5814 wxASSERT_MSG( key
!= VK_LBUTTON
&&
5815 key
!= VK_RBUTTON
&&
5817 wxT("can't use wxGetKeyState() for mouse buttons") );
5819 const WXWORD vk
= wxCharCodeWXToMSW(key
);
5821 // if the requested key is a LED key, return true if the led is pressed
5822 if ( key
== WXK_NUMLOCK
|| key
== WXK_CAPITAL
|| key
== WXK_SCROLL
)
5824 // low order bit means LED is highlighted and high order one means the
5825 // key is down; for compatibility with the other ports return true if
5826 // either one is set
5827 return GetKeyState(vk
) != 0;
5832 return wxIsKeyDown(vk
);
5837 wxMouseState
wxGetMouseState()
5841 GetCursorPos( &pt
);
5845 ms
.SetLeftDown(wxIsKeyDown(VK_LBUTTON
));
5846 ms
.SetMiddleDown(wxIsKeyDown(VK_MBUTTON
));
5847 ms
.SetRightDown(wxIsKeyDown(VK_RBUTTON
));
5848 #ifdef wxHAS_XBUTTON
5849 ms
.SetAux1Down(wxIsKeyDown(VK_XBUTTON1
));
5850 ms
.SetAux2Down(wxIsKeyDown(VK_XBUTTON2
));
5851 #endif // wxHAS_XBUTTON
5853 ms
.SetControlDown(wxIsKeyDown(VK_CONTROL
));
5854 ms
.SetShiftDown(wxIsKeyDown(VK_SHIFT
));
5855 ms
.SetAltDown(wxIsKeyDown(VK_MENU
));
5856 // ms.SetMetaDown();
5862 wxWindow
*wxGetActiveWindow()
5864 HWND hWnd
= GetActiveWindow();
5867 return wxFindWinFromHandle((WXHWND
) hWnd
);
5872 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
5874 HWND hwnd
= (HWND
)hWnd
;
5876 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
5877 // by code in msw/radiobox.cpp), for all the others we just search up the
5879 wxWindow
*win
= (wxWindow
*)NULL
;
5882 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
5886 // native radiobuttons return DLGC_RADIOBUTTON here and for any
5887 // wxWindow class which overrides WM_GETDLGCODE processing to
5888 // do it as well, win would be already non NULL
5889 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
5891 win
= (wxWindow
*)wxGetWindowUserData(hwnd
);
5893 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
5894 #endif // wxUSE_RADIOBOX
5896 // spin control text buddy window should be mapped to spin ctrl
5897 // itself so try it too
5898 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
5901 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
5903 #endif // wxUSE_SPINCTRL
5907 while ( hwnd
&& !win
)
5909 // this is a really ugly hack needed to avoid mistakenly returning the
5910 // parent frame wxWindow for the find/replace modeless dialog HWND -
5911 // this, in turn, is needed to call IsDialogMessage() from
5912 // wxApp::ProcessMessage() as for this we must return NULL from here
5914 // FIXME: this is clearly not the best way to do it but I think we'll
5915 // need to change HWND <-> wxWindow code more heavily than I can
5916 // do it now to fix it
5917 #ifndef __WXMICROWIN__
5918 if ( ::GetWindow(hwnd
, GW_OWNER
) )
5920 // it's a dialog box, don't go upwards
5925 hwnd
= ::GetParent(hwnd
);
5926 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
5932 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
5934 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
5935 // in active frames and dialogs, regardless of where the focus is.
5936 static HHOOK wxTheKeyboardHook
= 0;
5937 static FARPROC wxTheKeyboardHookProc
= 0;
5938 int APIENTRY _EXPORT
5939 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
5941 void wxSetKeyboardHook(bool doIt
)
5945 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
5946 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
5948 GetCurrentThreadId()
5949 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
5954 UnhookWindowsHookEx(wxTheKeyboardHook
);
5958 int APIENTRY _EXPORT
5959 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
5961 DWORD hiWord
= HIWORD(lParam
);
5962 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
5964 int id
= wxCharCodeMSWToWX(wParam
, lParam
);
5967 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
5968 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
5969 event
.m_altDown
= true;
5971 event
.SetEventObject(NULL
);
5972 event
.m_keyCode
= id
;
5973 event
.m_shiftDown
= wxIsShiftDown();
5974 event
.m_controlDown
= wxIsCtrlDown();
5976 event
.SetTimestamp(::GetMessageTime());
5978 wxWindow
*win
= wxGetActiveWindow();
5979 wxEvtHandler
*handler
;
5982 handler
= win
->GetEventHandler();
5983 event
.SetId(win
->GetId());
5988 event
.SetId(wxID_ANY
);
5991 if ( handler
&& handler
->ProcessEvent(event
) )
5999 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
6002 #endif // !__WXMICROWIN__
6005 const wxChar
*wxGetMessageName(int message
)
6009 case 0x0000: return wxT("WM_NULL");
6010 case 0x0001: return wxT("WM_CREATE");
6011 case 0x0002: return wxT("WM_DESTROY");
6012 case 0x0003: return wxT("WM_MOVE");
6013 case 0x0005: return wxT("WM_SIZE");
6014 case 0x0006: return wxT("WM_ACTIVATE");
6015 case 0x0007: return wxT("WM_SETFOCUS");
6016 case 0x0008: return wxT("WM_KILLFOCUS");
6017 case 0x000A: return wxT("WM_ENABLE");
6018 case 0x000B: return wxT("WM_SETREDRAW");
6019 case 0x000C: return wxT("WM_SETTEXT");
6020 case 0x000D: return wxT("WM_GETTEXT");
6021 case 0x000E: return wxT("WM_GETTEXTLENGTH");
6022 case 0x000F: return wxT("WM_PAINT");
6023 case 0x0010: return wxT("WM_CLOSE");
6024 case 0x0011: return wxT("WM_QUERYENDSESSION");
6025 case 0x0012: return wxT("WM_QUIT");
6026 case 0x0013: return wxT("WM_QUERYOPEN");
6027 case 0x0014: return wxT("WM_ERASEBKGND");
6028 case 0x0015: return wxT("WM_SYSCOLORCHANGE");
6029 case 0x0016: return wxT("WM_ENDSESSION");
6030 case 0x0017: return wxT("WM_SYSTEMERROR");
6031 case 0x0018: return wxT("WM_SHOWWINDOW");
6032 case 0x0019: return wxT("WM_CTLCOLOR");
6033 case 0x001A: return wxT("WM_WININICHANGE");
6034 case 0x001B: return wxT("WM_DEVMODECHANGE");
6035 case 0x001C: return wxT("WM_ACTIVATEAPP");
6036 case 0x001D: return wxT("WM_FONTCHANGE");
6037 case 0x001E: return wxT("WM_TIMECHANGE");
6038 case 0x001F: return wxT("WM_CANCELMODE");
6039 case 0x0020: return wxT("WM_SETCURSOR");
6040 case 0x0021: return wxT("WM_MOUSEACTIVATE");
6041 case 0x0022: return wxT("WM_CHILDACTIVATE");
6042 case 0x0023: return wxT("WM_QUEUESYNC");
6043 case 0x0024: return wxT("WM_GETMINMAXINFO");
6044 case 0x0026: return wxT("WM_PAINTICON");
6045 case 0x0027: return wxT("WM_ICONERASEBKGND");
6046 case 0x0028: return wxT("WM_NEXTDLGCTL");
6047 case 0x002A: return wxT("WM_SPOOLERSTATUS");
6048 case 0x002B: return wxT("WM_DRAWITEM");
6049 case 0x002C: return wxT("WM_MEASUREITEM");
6050 case 0x002D: return wxT("WM_DELETEITEM");
6051 case 0x002E: return wxT("WM_VKEYTOITEM");
6052 case 0x002F: return wxT("WM_CHARTOITEM");
6053 case 0x0030: return wxT("WM_SETFONT");
6054 case 0x0031: return wxT("WM_GETFONT");
6055 case 0x0037: return wxT("WM_QUERYDRAGICON");
6056 case 0x0039: return wxT("WM_COMPAREITEM");
6057 case 0x0041: return wxT("WM_COMPACTING");
6058 case 0x0044: return wxT("WM_COMMNOTIFY");
6059 case 0x0046: return wxT("WM_WINDOWPOSCHANGING");
6060 case 0x0047: return wxT("WM_WINDOWPOSCHANGED");
6061 case 0x0048: return wxT("WM_POWER");
6063 case 0x004A: return wxT("WM_COPYDATA");
6064 case 0x004B: return wxT("WM_CANCELJOURNAL");
6065 case 0x004E: return wxT("WM_NOTIFY");
6066 case 0x0050: return wxT("WM_INPUTLANGCHANGEREQUEST");
6067 case 0x0051: return wxT("WM_INPUTLANGCHANGE");
6068 case 0x0052: return wxT("WM_TCARD");
6069 case 0x0053: return wxT("WM_HELP");
6070 case 0x0054: return wxT("WM_USERCHANGED");
6071 case 0x0055: return wxT("WM_NOTIFYFORMAT");
6072 case 0x007B: return wxT("WM_CONTEXTMENU");
6073 case 0x007C: return wxT("WM_STYLECHANGING");
6074 case 0x007D: return wxT("WM_STYLECHANGED");
6075 case 0x007E: return wxT("WM_DISPLAYCHANGE");
6076 case 0x007F: return wxT("WM_GETICON");
6077 case 0x0080: return wxT("WM_SETICON");
6079 case 0x0081: return wxT("WM_NCCREATE");
6080 case 0x0082: return wxT("WM_NCDESTROY");
6081 case 0x0083: return wxT("WM_NCCALCSIZE");
6082 case 0x0084: return wxT("WM_NCHITTEST");
6083 case 0x0085: return wxT("WM_NCPAINT");
6084 case 0x0086: return wxT("WM_NCACTIVATE");
6085 case 0x0087: return wxT("WM_GETDLGCODE");
6086 case 0x00A0: return wxT("WM_NCMOUSEMOVE");
6087 case 0x00A1: return wxT("WM_NCLBUTTONDOWN");
6088 case 0x00A2: return wxT("WM_NCLBUTTONUP");
6089 case 0x00A3: return wxT("WM_NCLBUTTONDBLCLK");
6090 case 0x00A4: return wxT("WM_NCRBUTTONDOWN");
6091 case 0x00A5: return wxT("WM_NCRBUTTONUP");
6092 case 0x00A6: return wxT("WM_NCRBUTTONDBLCLK");
6093 case 0x00A7: return wxT("WM_NCMBUTTONDOWN");
6094 case 0x00A8: return wxT("WM_NCMBUTTONUP");
6095 case 0x00A9: return wxT("WM_NCMBUTTONDBLCLK");
6097 case 0x00B0: return wxT("EM_GETSEL");
6098 case 0x00B1: return wxT("EM_SETSEL");
6099 case 0x00B2: return wxT("EM_GETRECT");
6100 case 0x00B3: return wxT("EM_SETRECT");
6101 case 0x00B4: return wxT("EM_SETRECTNP");
6102 case 0x00B5: return wxT("EM_SCROLL");
6103 case 0x00B6: return wxT("EM_LINESCROLL");
6104 case 0x00B7: return wxT("EM_SCROLLCARET");
6105 case 0x00B8: return wxT("EM_GETMODIFY");
6106 case 0x00B9: return wxT("EM_SETMODIFY");
6107 case 0x00BA: return wxT("EM_GETLINECOUNT");
6108 case 0x00BB: return wxT("EM_LINEINDEX");
6109 case 0x00BC: return wxT("EM_SETHANDLE");
6110 case 0x00BD: return wxT("EM_GETHANDLE");
6111 case 0x00BE: return wxT("EM_GETTHUMB");
6112 case 0x00C1: return wxT("EM_LINELENGTH");
6113 case 0x00C2: return wxT("EM_REPLACESEL");
6114 case 0x00C4: return wxT("EM_GETLINE");
6115 case 0x00C5: return wxT("EM_LIMITTEXT/EM_SETLIMITTEXT"); /* ;win40 Name change */
6116 case 0x00C6: return wxT("EM_CANUNDO");
6117 case 0x00C7: return wxT("EM_UNDO");
6118 case 0x00C8: return wxT("EM_FMTLINES");
6119 case 0x00C9: return wxT("EM_LINEFROMCHAR");
6120 case 0x00CB: return wxT("EM_SETTABSTOPS");
6121 case 0x00CC: return wxT("EM_SETPASSWORDCHAR");
6122 case 0x00CD: return wxT("EM_EMPTYUNDOBUFFER");
6123 case 0x00CE: return wxT("EM_GETFIRSTVISIBLELINE");
6124 case 0x00CF: return wxT("EM_SETREADONLY");
6125 case 0x00D0: return wxT("EM_SETWORDBREAKPROC");
6126 case 0x00D1: return wxT("EM_GETWORDBREAKPROC");
6127 case 0x00D2: return wxT("EM_GETPASSWORDCHAR");
6128 case 0x00D3: return wxT("EM_SETMARGINS");
6129 case 0x00D4: return wxT("EM_GETMARGINS");
6130 case 0x00D5: return wxT("EM_GETLIMITTEXT");
6131 case 0x00D6: return wxT("EM_POSFROMCHAR");
6132 case 0x00D7: return wxT("EM_CHARFROMPOS");
6133 case 0x00D8: return wxT("EM_SETIMESTATUS");
6134 case 0x00D9: return wxT("EM_GETIMESTATUS");
6136 case 0x0100: return wxT("WM_KEYDOWN");
6137 case 0x0101: return wxT("WM_KEYUP");
6138 case 0x0102: return wxT("WM_CHAR");
6139 case 0x0103: return wxT("WM_DEADCHAR");
6140 case 0x0104: return wxT("WM_SYSKEYDOWN");
6141 case 0x0105: return wxT("WM_SYSKEYUP");
6142 case 0x0106: return wxT("WM_SYSCHAR");
6143 case 0x0107: return wxT("WM_SYSDEADCHAR");
6144 case 0x0108: return wxT("WM_KEYLAST");
6146 case 0x010D: return wxT("WM_IME_STARTCOMPOSITION");
6147 case 0x010E: return wxT("WM_IME_ENDCOMPOSITION");
6148 case 0x010F: return wxT("WM_IME_COMPOSITION");
6150 case 0x0110: return wxT("WM_INITDIALOG");
6151 case 0x0111: return wxT("WM_COMMAND");
6152 case 0x0112: return wxT("WM_SYSCOMMAND");
6153 case 0x0113: return wxT("WM_TIMER");
6154 case 0x0114: return wxT("WM_HSCROLL");
6155 case 0x0115: return wxT("WM_VSCROLL");
6156 case 0x0116: return wxT("WM_INITMENU");
6157 case 0x0117: return wxT("WM_INITMENUPOPUP");
6158 case 0x011F: return wxT("WM_MENUSELECT");
6159 case 0x0120: return wxT("WM_MENUCHAR");
6160 case 0x0121: return wxT("WM_ENTERIDLE");
6162 case 0x0132: return wxT("WM_CTLCOLORMSGBOX");
6163 case 0x0133: return wxT("WM_CTLCOLOREDIT");
6164 case 0x0134: return wxT("WM_CTLCOLORLISTBOX");
6165 case 0x0135: return wxT("WM_CTLCOLORBTN");
6166 case 0x0136: return wxT("WM_CTLCOLORDLG");
6167 case 0x0137: return wxT("WM_CTLCOLORSCROLLBAR");
6168 case 0x0138: return wxT("WM_CTLCOLORSTATIC");
6169 case 0x01E1: return wxT("MN_GETHMENU");
6171 case 0x0200: return wxT("WM_MOUSEMOVE");
6172 case 0x0201: return wxT("WM_LBUTTONDOWN");
6173 case 0x0202: return wxT("WM_LBUTTONUP");
6174 case 0x0203: return wxT("WM_LBUTTONDBLCLK");
6175 case 0x0204: return wxT("WM_RBUTTONDOWN");
6176 case 0x0205: return wxT("WM_RBUTTONUP");
6177 case 0x0206: return wxT("WM_RBUTTONDBLCLK");
6178 case 0x0207: return wxT("WM_MBUTTONDOWN");
6179 case 0x0208: return wxT("WM_MBUTTONUP");
6180 case 0x0209: return wxT("WM_MBUTTONDBLCLK");
6181 case 0x020A: return wxT("WM_MOUSEWHEEL");
6182 case 0x020B: return wxT("WM_XBUTTONDOWN");
6183 case 0x020C: return wxT("WM_XBUTTONUP");
6184 case 0x020D: return wxT("WM_XBUTTONDBLCLK");
6185 case 0x0210: return wxT("WM_PARENTNOTIFY");
6186 case 0x0211: return wxT("WM_ENTERMENULOOP");
6187 case 0x0212: return wxT("WM_EXITMENULOOP");
6189 case 0x0213: return wxT("WM_NEXTMENU");
6190 case 0x0214: return wxT("WM_SIZING");
6191 case 0x0215: return wxT("WM_CAPTURECHANGED");
6192 case 0x0216: return wxT("WM_MOVING");
6193 case 0x0218: return wxT("WM_POWERBROADCAST");
6194 case 0x0219: return wxT("WM_DEVICECHANGE");
6196 case 0x0220: return wxT("WM_MDICREATE");
6197 case 0x0221: return wxT("WM_MDIDESTROY");
6198 case 0x0222: return wxT("WM_MDIACTIVATE");
6199 case 0x0223: return wxT("WM_MDIRESTORE");
6200 case 0x0224: return wxT("WM_MDINEXT");
6201 case 0x0225: return wxT("WM_MDIMAXIMIZE");
6202 case 0x0226: return wxT("WM_MDITILE");
6203 case 0x0227: return wxT("WM_MDICASCADE");
6204 case 0x0228: return wxT("WM_MDIICONARRANGE");
6205 case 0x0229: return wxT("WM_MDIGETACTIVE");
6206 case 0x0230: return wxT("WM_MDISETMENU");
6207 case 0x0233: return wxT("WM_DROPFILES");
6209 case 0x0281: return wxT("WM_IME_SETCONTEXT");
6210 case 0x0282: return wxT("WM_IME_NOTIFY");
6211 case 0x0283: return wxT("WM_IME_CONTROL");
6212 case 0x0284: return wxT("WM_IME_COMPOSITIONFULL");
6213 case 0x0285: return wxT("WM_IME_SELECT");
6214 case 0x0286: return wxT("WM_IME_CHAR");
6215 case 0x0290: return wxT("WM_IME_KEYDOWN");
6216 case 0x0291: return wxT("WM_IME_KEYUP");
6218 case 0x02A0: return wxT("WM_NCMOUSEHOVER");
6219 case 0x02A1: return wxT("WM_MOUSEHOVER");
6220 case 0x02A2: return wxT("WM_NCMOUSELEAVE");
6221 case 0x02A3: return wxT("WM_MOUSELEAVE");
6223 case 0x0300: return wxT("WM_CUT");
6224 case 0x0301: return wxT("WM_COPY");
6225 case 0x0302: return wxT("WM_PASTE");
6226 case 0x0303: return wxT("WM_CLEAR");
6227 case 0x0304: return wxT("WM_UNDO");
6228 case 0x0305: return wxT("WM_RENDERFORMAT");
6229 case 0x0306: return wxT("WM_RENDERALLFORMATS");
6230 case 0x0307: return wxT("WM_DESTROYCLIPBOARD");
6231 case 0x0308: return wxT("WM_DRAWCLIPBOARD");
6232 case 0x0309: return wxT("WM_PAINTCLIPBOARD");
6233 case 0x030A: return wxT("WM_VSCROLLCLIPBOARD");
6234 case 0x030B: return wxT("WM_SIZECLIPBOARD");
6235 case 0x030C: return wxT("WM_ASKCBFORMATNAME");
6236 case 0x030D: return wxT("WM_CHANGECBCHAIN");
6237 case 0x030E: return wxT("WM_HSCROLLCLIPBOARD");
6238 case 0x030F: return wxT("WM_QUERYNEWPALETTE");
6239 case 0x0310: return wxT("WM_PALETTEISCHANGING");
6240 case 0x0311: return wxT("WM_PALETTECHANGED");
6241 case 0x0312: return wxT("WM_HOTKEY");
6243 case 0x0317: return wxT("WM_PRINT");
6244 case 0x0318: return wxT("WM_PRINTCLIENT");
6246 // common controls messages - although they're not strictly speaking
6247 // standard, it's nice to decode them nevertheless
6250 case 0x1000 + 0: return wxT("LVM_GETBKCOLOR");
6251 case 0x1000 + 1: return wxT("LVM_SETBKCOLOR");
6252 case 0x1000 + 2: return wxT("LVM_GETIMAGELIST");
6253 case 0x1000 + 3: return wxT("LVM_SETIMAGELIST");
6254 case 0x1000 + 4: return wxT("LVM_GETITEMCOUNT");
6255 case 0x1000 + 5: return wxT("LVM_GETITEMA");
6256 case 0x1000 + 75: return wxT("LVM_GETITEMW");
6257 case 0x1000 + 6: return wxT("LVM_SETITEMA");
6258 case 0x1000 + 76: return wxT("LVM_SETITEMW");
6259 case 0x1000 + 7: return wxT("LVM_INSERTITEMA");
6260 case 0x1000 + 77: return wxT("LVM_INSERTITEMW");
6261 case 0x1000 + 8: return wxT("LVM_DELETEITEM");
6262 case 0x1000 + 9: return wxT("LVM_DELETEALLITEMS");
6263 case 0x1000 + 10: return wxT("LVM_GETCALLBACKMASK");
6264 case 0x1000 + 11: return wxT("LVM_SETCALLBACKMASK");
6265 case 0x1000 + 12: return wxT("LVM_GETNEXTITEM");
6266 case 0x1000 + 13: return wxT("LVM_FINDITEMA");
6267 case 0x1000 + 83: return wxT("LVM_FINDITEMW");
6268 case 0x1000 + 14: return wxT("LVM_GETITEMRECT");
6269 case 0x1000 + 15: return wxT("LVM_SETITEMPOSITION");
6270 case 0x1000 + 16: return wxT("LVM_GETITEMPOSITION");
6271 case 0x1000 + 17: return wxT("LVM_GETSTRINGWIDTHA");
6272 case 0x1000 + 87: return wxT("LVM_GETSTRINGWIDTHW");
6273 case 0x1000 + 18: return wxT("LVM_HITTEST");
6274 case 0x1000 + 19: return wxT("LVM_ENSUREVISIBLE");
6275 case 0x1000 + 20: return wxT("LVM_SCROLL");
6276 case 0x1000 + 21: return wxT("LVM_REDRAWITEMS");
6277 case 0x1000 + 22: return wxT("LVM_ARRANGE");
6278 case 0x1000 + 23: return wxT("LVM_EDITLABELA");
6279 case 0x1000 + 118: return wxT("LVM_EDITLABELW");
6280 case 0x1000 + 24: return wxT("LVM_GETEDITCONTROL");
6281 case 0x1000 + 25: return wxT("LVM_GETCOLUMNA");
6282 case 0x1000 + 95: return wxT("LVM_GETCOLUMNW");
6283 case 0x1000 + 26: return wxT("LVM_SETCOLUMNA");
6284 case 0x1000 + 96: return wxT("LVM_SETCOLUMNW");
6285 case 0x1000 + 27: return wxT("LVM_INSERTCOLUMNA");
6286 case 0x1000 + 97: return wxT("LVM_INSERTCOLUMNW");
6287 case 0x1000 + 28: return wxT("LVM_DELETECOLUMN");
6288 case 0x1000 + 29: return wxT("LVM_GETCOLUMNWIDTH");
6289 case 0x1000 + 30: return wxT("LVM_SETCOLUMNWIDTH");
6290 case 0x1000 + 31: return wxT("LVM_GETHEADER");
6291 case 0x1000 + 33: return wxT("LVM_CREATEDRAGIMAGE");
6292 case 0x1000 + 34: return wxT("LVM_GETVIEWRECT");
6293 case 0x1000 + 35: return wxT("LVM_GETTEXTCOLOR");
6294 case 0x1000 + 36: return wxT("LVM_SETTEXTCOLOR");
6295 case 0x1000 + 37: return wxT("LVM_GETTEXTBKCOLOR");
6296 case 0x1000 + 38: return wxT("LVM_SETTEXTBKCOLOR");
6297 case 0x1000 + 39: return wxT("LVM_GETTOPINDEX");
6298 case 0x1000 + 40: return wxT("LVM_GETCOUNTPERPAGE");
6299 case 0x1000 + 41: return wxT("LVM_GETORIGIN");
6300 case 0x1000 + 42: return wxT("LVM_UPDATE");
6301 case 0x1000 + 43: return wxT("LVM_SETITEMSTATE");
6302 case 0x1000 + 44: return wxT("LVM_GETITEMSTATE");
6303 case 0x1000 + 45: return wxT("LVM_GETITEMTEXTA");
6304 case 0x1000 + 115: return wxT("LVM_GETITEMTEXTW");
6305 case 0x1000 + 46: return wxT("LVM_SETITEMTEXTA");
6306 case 0x1000 + 116: return wxT("LVM_SETITEMTEXTW");
6307 case 0x1000 + 47: return wxT("LVM_SETITEMCOUNT");
6308 case 0x1000 + 48: return wxT("LVM_SORTITEMS");
6309 case 0x1000 + 49: return wxT("LVM_SETITEMPOSITION32");
6310 case 0x1000 + 50: return wxT("LVM_GETSELECTEDCOUNT");
6311 case 0x1000 + 51: return wxT("LVM_GETITEMSPACING");
6312 case 0x1000 + 52: return wxT("LVM_GETISEARCHSTRINGA");
6313 case 0x1000 + 117: return wxT("LVM_GETISEARCHSTRINGW");
6314 case 0x1000 + 53: return wxT("LVM_SETICONSPACING");
6315 case 0x1000 + 54: return wxT("LVM_SETEXTENDEDLISTVIEWSTYLE");
6316 case 0x1000 + 55: return wxT("LVM_GETEXTENDEDLISTVIEWSTYLE");
6317 case 0x1000 + 56: return wxT("LVM_GETSUBITEMRECT");
6318 case 0x1000 + 57: return wxT("LVM_SUBITEMHITTEST");
6319 case 0x1000 + 58: return wxT("LVM_SETCOLUMNORDERARRAY");
6320 case 0x1000 + 59: return wxT("LVM_GETCOLUMNORDERARRAY");
6321 case 0x1000 + 60: return wxT("LVM_SETHOTITEM");
6322 case 0x1000 + 61: return wxT("LVM_GETHOTITEM");
6323 case 0x1000 + 62: return wxT("LVM_SETHOTCURSOR");
6324 case 0x1000 + 63: return wxT("LVM_GETHOTCURSOR");
6325 case 0x1000 + 64: return wxT("LVM_APPROXIMATEVIEWRECT");
6326 case 0x1000 + 65: return wxT("LVM_SETWORKAREA");
6329 case 0x1100 + 0: return wxT("TVM_INSERTITEMA");
6330 case 0x1100 + 50: return wxT("TVM_INSERTITEMW");
6331 case 0x1100 + 1: return wxT("TVM_DELETEITEM");
6332 case 0x1100 + 2: return wxT("TVM_EXPAND");
6333 case 0x1100 + 4: return wxT("TVM_GETITEMRECT");
6334 case 0x1100 + 5: return wxT("TVM_GETCOUNT");
6335 case 0x1100 + 6: return wxT("TVM_GETINDENT");
6336 case 0x1100 + 7: return wxT("TVM_SETINDENT");
6337 case 0x1100 + 8: return wxT("TVM_GETIMAGELIST");
6338 case 0x1100 + 9: return wxT("TVM_SETIMAGELIST");
6339 case 0x1100 + 10: return wxT("TVM_GETNEXTITEM");
6340 case 0x1100 + 11: return wxT("TVM_SELECTITEM");
6341 case 0x1100 + 12: return wxT("TVM_GETITEMA");
6342 case 0x1100 + 62: return wxT("TVM_GETITEMW");
6343 case 0x1100 + 13: return wxT("TVM_SETITEMA");
6344 case 0x1100 + 63: return wxT("TVM_SETITEMW");
6345 case 0x1100 + 14: return wxT("TVM_EDITLABELA");
6346 case 0x1100 + 65: return wxT("TVM_EDITLABELW");
6347 case 0x1100 + 15: return wxT("TVM_GETEDITCONTROL");
6348 case 0x1100 + 16: return wxT("TVM_GETVISIBLECOUNT");
6349 case 0x1100 + 17: return wxT("TVM_HITTEST");
6350 case 0x1100 + 18: return wxT("TVM_CREATEDRAGIMAGE");
6351 case 0x1100 + 19: return wxT("TVM_SORTCHILDREN");
6352 case 0x1100 + 20: return wxT("TVM_ENSUREVISIBLE");
6353 case 0x1100 + 21: return wxT("TVM_SORTCHILDRENCB");
6354 case 0x1100 + 22: return wxT("TVM_ENDEDITLABELNOW");
6355 case 0x1100 + 23: return wxT("TVM_GETISEARCHSTRINGA");
6356 case 0x1100 + 64: return wxT("TVM_GETISEARCHSTRINGW");
6357 case 0x1100 + 24: return wxT("TVM_SETTOOLTIPS");
6358 case 0x1100 + 25: return wxT("TVM_GETTOOLTIPS");
6361 case 0x1200 + 0: return wxT("HDM_GETITEMCOUNT");
6362 case 0x1200 + 1: return wxT("HDM_INSERTITEMA");
6363 case 0x1200 + 10: return wxT("HDM_INSERTITEMW");
6364 case 0x1200 + 2: return wxT("HDM_DELETEITEM");
6365 case 0x1200 + 3: return wxT("HDM_GETITEMA");
6366 case 0x1200 + 11: return wxT("HDM_GETITEMW");
6367 case 0x1200 + 4: return wxT("HDM_SETITEMA");
6368 case 0x1200 + 12: return wxT("HDM_SETITEMW");
6369 case 0x1200 + 5: return wxT("HDM_LAYOUT");
6370 case 0x1200 + 6: return wxT("HDM_HITTEST");
6371 case 0x1200 + 7: return wxT("HDM_GETITEMRECT");
6372 case 0x1200 + 8: return wxT("HDM_SETIMAGELIST");
6373 case 0x1200 + 9: return wxT("HDM_GETIMAGELIST");
6374 case 0x1200 + 15: return wxT("HDM_ORDERTOINDEX");
6375 case 0x1200 + 16: return wxT("HDM_CREATEDRAGIMAGE");
6376 case 0x1200 + 17: return wxT("HDM_GETORDERARRAY");
6377 case 0x1200 + 18: return wxT("HDM_SETORDERARRAY");
6378 case 0x1200 + 19: return wxT("HDM_SETHOTDIVIDER");
6381 case 0x1300 + 2: return wxT("TCM_GETIMAGELIST");
6382 case 0x1300 + 3: return wxT("TCM_SETIMAGELIST");
6383 case 0x1300 + 4: return wxT("TCM_GETITEMCOUNT");
6384 case 0x1300 + 5: return wxT("TCM_GETITEMA");
6385 case 0x1300 + 60: return wxT("TCM_GETITEMW");
6386 case 0x1300 + 6: return wxT("TCM_SETITEMA");
6387 case 0x1300 + 61: return wxT("TCM_SETITEMW");
6388 case 0x1300 + 7: return wxT("TCM_INSERTITEMA");
6389 case 0x1300 + 62: return wxT("TCM_INSERTITEMW");
6390 case 0x1300 + 8: return wxT("TCM_DELETEITEM");
6391 case 0x1300 + 9: return wxT("TCM_DELETEALLITEMS");
6392 case 0x1300 + 10: return wxT("TCM_GETITEMRECT");
6393 case 0x1300 + 11: return wxT("TCM_GETCURSEL");
6394 case 0x1300 + 12: return wxT("TCM_SETCURSEL");
6395 case 0x1300 + 13: return wxT("TCM_HITTEST");
6396 case 0x1300 + 14: return wxT("TCM_SETITEMEXTRA");
6397 case 0x1300 + 40: return wxT("TCM_ADJUSTRECT");
6398 case 0x1300 + 41: return wxT("TCM_SETITEMSIZE");
6399 case 0x1300 + 42: return wxT("TCM_REMOVEIMAGE");
6400 case 0x1300 + 43: return wxT("TCM_SETPADDING");
6401 case 0x1300 + 44: return wxT("TCM_GETROWCOUNT");
6402 case 0x1300 + 45: return wxT("TCM_GETTOOLTIPS");
6403 case 0x1300 + 46: return wxT("TCM_SETTOOLTIPS");
6404 case 0x1300 + 47: return wxT("TCM_GETCURFOCUS");
6405 case 0x1300 + 48: return wxT("TCM_SETCURFOCUS");
6406 case 0x1300 + 49: return wxT("TCM_SETMINTABWIDTH");
6407 case 0x1300 + 50: return wxT("TCM_DESELECTALL");
6410 case WM_USER
+1: return wxT("TB_ENABLEBUTTON");
6411 case WM_USER
+2: return wxT("TB_CHECKBUTTON");
6412 case WM_USER
+3: return wxT("TB_PRESSBUTTON");
6413 case WM_USER
+4: return wxT("TB_HIDEBUTTON");
6414 case WM_USER
+5: return wxT("TB_INDETERMINATE");
6415 case WM_USER
+9: return wxT("TB_ISBUTTONENABLED");
6416 case WM_USER
+10: return wxT("TB_ISBUTTONCHECKED");
6417 case WM_USER
+11: return wxT("TB_ISBUTTONPRESSED");
6418 case WM_USER
+12: return wxT("TB_ISBUTTONHIDDEN");
6419 case WM_USER
+13: return wxT("TB_ISBUTTONINDETERMINATE");
6420 case WM_USER
+17: return wxT("TB_SETSTATE");
6421 case WM_USER
+18: return wxT("TB_GETSTATE");
6422 case WM_USER
+19: return wxT("TB_ADDBITMAP");
6423 case WM_USER
+20: return wxT("TB_ADDBUTTONS");
6424 case WM_USER
+21: return wxT("TB_INSERTBUTTON");
6425 case WM_USER
+22: return wxT("TB_DELETEBUTTON");
6426 case WM_USER
+23: return wxT("TB_GETBUTTON");
6427 case WM_USER
+24: return wxT("TB_BUTTONCOUNT");
6428 case WM_USER
+25: return wxT("TB_COMMANDTOINDEX");
6429 case WM_USER
+26: return wxT("TB_SAVERESTOREA");
6430 case WM_USER
+76: return wxT("TB_SAVERESTOREW");
6431 case WM_USER
+27: return wxT("TB_CUSTOMIZE");
6432 case WM_USER
+28: return wxT("TB_ADDSTRINGA");
6433 case WM_USER
+77: return wxT("TB_ADDSTRINGW");
6434 case WM_USER
+29: return wxT("TB_GETITEMRECT");
6435 case WM_USER
+30: return wxT("TB_BUTTONSTRUCTSIZE");
6436 case WM_USER
+31: return wxT("TB_SETBUTTONSIZE");
6437 case WM_USER
+32: return wxT("TB_SETBITMAPSIZE");
6438 case WM_USER
+33: return wxT("TB_AUTOSIZE");
6439 case WM_USER
+35: return wxT("TB_GETTOOLTIPS");
6440 case WM_USER
+36: return wxT("TB_SETTOOLTIPS");
6441 case WM_USER
+37: return wxT("TB_SETPARENT");
6442 case WM_USER
+39: return wxT("TB_SETROWS");
6443 case WM_USER
+40: return wxT("TB_GETROWS");
6444 case WM_USER
+42: return wxT("TB_SETCMDID");
6445 case WM_USER
+43: return wxT("TB_CHANGEBITMAP");
6446 case WM_USER
+44: return wxT("TB_GETBITMAP");
6447 case WM_USER
+45: return wxT("TB_GETBUTTONTEXTA");
6448 case WM_USER
+75: return wxT("TB_GETBUTTONTEXTW");
6449 case WM_USER
+46: return wxT("TB_REPLACEBITMAP");
6450 case WM_USER
+47: return wxT("TB_SETINDENT");
6451 case WM_USER
+48: return wxT("TB_SETIMAGELIST");
6452 case WM_USER
+49: return wxT("TB_GETIMAGELIST");
6453 case WM_USER
+50: return wxT("TB_LOADIMAGES");
6454 case WM_USER
+51: return wxT("TB_GETRECT");
6455 case WM_USER
+52: return wxT("TB_SETHOTIMAGELIST");
6456 case WM_USER
+53: return wxT("TB_GETHOTIMAGELIST");
6457 case WM_USER
+54: return wxT("TB_SETDISABLEDIMAGELIST");
6458 case WM_USER
+55: return wxT("TB_GETDISABLEDIMAGELIST");
6459 case WM_USER
+56: return wxT("TB_SETSTYLE");
6460 case WM_USER
+57: return wxT("TB_GETSTYLE");
6461 case WM_USER
+58: return wxT("TB_GETBUTTONSIZE");
6462 case WM_USER
+59: return wxT("TB_SETBUTTONWIDTH");
6463 case WM_USER
+60: return wxT("TB_SETMAXTEXTROWS");
6464 case WM_USER
+61: return wxT("TB_GETTEXTROWS");
6465 case WM_USER
+41: return wxT("TB_GETBITMAPFLAGS");
6468 static wxString s_szBuf
;
6469 s_szBuf
.Printf(wxT("<unknown message = %d>"), message
);
6470 return s_szBuf
.c_str();
6473 #endif //__WXDEBUG__
6475 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
6479 HWND hwnd
= GetHwndOf(win
);
6480 HDC hdc
= ::GetDC(hwnd
);
6482 #if !wxDIALOG_UNIT_COMPATIBILITY
6483 // and select the current font into it
6484 HFONT hfont
= GetHfontOf(win
->GetFont());
6487 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
6491 // finally retrieve the text metrics from it
6492 GetTextMetrics(hdc
, &tm
);
6494 #if !wxDIALOG_UNIT_COMPATIBILITY
6498 (void)::SelectObject(hdc
, hfont
);
6502 ::ReleaseDC(hwnd
, hdc
);
6507 // Find the wxWindow at the current mouse position, returning the mouse
6509 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
6511 pt
= wxGetMousePosition();
6512 return wxFindWindowAtPoint(pt
);
6515 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
6521 HWND hWnd
= ::WindowFromPoint(pt2
);
6523 return wxGetWindowFromHWND((WXHWND
)hWnd
);
6526 // Get the current mouse position.
6527 wxPoint
wxGetMousePosition()
6531 GetCursorPosWinCE(&pt
);
6533 GetCursorPos( & pt
);
6536 return wxPoint(pt
.x
, pt
.y
);
6541 #if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6542 static void WinCEUnregisterHotKey(int modifiers
, int id
)
6544 // Register hotkeys for the hardware buttons
6546 typedef BOOL (WINAPI
*UnregisterFunc1Proc
)(UINT
, UINT
);
6548 UnregisterFunc1Proc procUnregisterFunc
;
6549 hCoreDll
= LoadLibrary(_T("coredll.dll"));
6552 procUnregisterFunc
= (UnregisterFunc1Proc
)GetProcAddress(hCoreDll
, _T("UnregisterFunc1"));
6553 if (procUnregisterFunc
)
6554 procUnregisterFunc(modifiers
, id
);
6555 FreeLibrary(hCoreDll
);
6560 bool wxWindowMSW::RegisterHotKey(int hotkeyId
, int modifiers
, int keycode
)
6562 UINT win_modifiers
=0;
6563 if ( modifiers
& wxMOD_ALT
)
6564 win_modifiers
|= MOD_ALT
;
6565 if ( modifiers
& wxMOD_SHIFT
)
6566 win_modifiers
|= MOD_SHIFT
;
6567 if ( modifiers
& wxMOD_CONTROL
)
6568 win_modifiers
|= MOD_CONTROL
;
6569 if ( modifiers
& wxMOD_WIN
)
6570 win_modifiers
|= MOD_WIN
;
6572 #if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6573 // Required for PPC and Smartphone hardware buttons
6574 if (keycode
>= WXK_SPECIAL1
&& keycode
<= WXK_SPECIAL20
)
6575 WinCEUnregisterHotKey(win_modifiers
, hotkeyId
);
6578 if ( !::RegisterHotKey(GetHwnd(), hotkeyId
, win_modifiers
, keycode
) )
6580 wxLogLastError(_T("RegisterHotKey"));
6588 bool wxWindowMSW::UnregisterHotKey(int hotkeyId
)
6590 #if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6591 WinCEUnregisterHotKey(MOD_WIN
, hotkeyId
);
6594 if ( !::UnregisterHotKey(GetHwnd(), hotkeyId
) )
6596 wxLogLastError(_T("UnregisterHotKey"));
6606 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam
, WXLPARAM lParam
)
6608 int hotkeyId
= wParam
;
6609 int virtualKey
= HIWORD(lParam
);
6610 int win_modifiers
= LOWORD(lParam
);
6612 wxKeyEvent
event(CreateKeyEvent(wxEVT_HOTKEY
, virtualKey
, wParam
, lParam
));
6613 event
.SetId(hotkeyId
);
6614 event
.m_shiftDown
= (win_modifiers
& MOD_SHIFT
) != 0;
6615 event
.m_controlDown
= (win_modifiers
& MOD_CONTROL
) != 0;
6616 event
.m_altDown
= (win_modifiers
& MOD_ALT
) != 0;
6617 event
.m_metaDown
= (win_modifiers
& MOD_WIN
) != 0;
6619 return GetEventHandler()->ProcessEvent(event
);
6622 #endif // wxUSE_ACCEL
6624 #endif // wxUSE_HOTKEY
6626 // Not tested under WinCE
6629 // this class installs a message hook which really wakes up our idle processing
6630 // each time a WM_NULL is received (wxWakeUpIdle does this), even if we're
6631 // sitting inside a local modal loop (e.g. a menu is opened or scrollbar is
6632 // being dragged or even inside ::MessageBox()) and so don't control message
6633 // dispatching otherwise
6634 class wxIdleWakeUpModule
: public wxModule
6637 virtual bool OnInit()
6639 ms_hMsgHookProc
= ::SetWindowsHookEx
6642 &wxIdleWakeUpModule::MsgHookProc
,
6644 GetCurrentThreadId()
6647 if ( !ms_hMsgHookProc
)
6649 wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)"));
6657 virtual void OnExit()
6659 ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc
);
6662 static LRESULT CALLBACK
MsgHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
6664 MSG
*msg
= (MSG
*)lParam
;
6666 // only process the message if it is actually going to be removed from
6667 // the message queue, this prevents that the same event from being
6668 // processed multiple times if now someone just called PeekMessage()
6669 if ( msg
->message
== WM_NULL
&& wParam
== PM_REMOVE
)
6671 wxTheApp
->ProcessPendingEvents();
6674 return CallNextHookEx(ms_hMsgHookProc
, nCode
, wParam
, lParam
);
6678 static HHOOK ms_hMsgHookProc
;
6680 DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule
)
6683 HHOOK
wxIdleWakeUpModule::ms_hMsgHookProc
= 0;
6685 IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule
, wxModule
)
6687 #endif // __WXWINCE__
6692 static void wxAdjustZOrder(wxWindow
* parent
)
6694 if (parent
->IsKindOf(CLASSINFO(wxStaticBox
)))
6696 // Set the z-order correctly
6697 SetWindowPos((HWND
) parent
->GetHWND(), HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
6700 wxWindowList::compatibility_iterator current
= parent
->GetChildren().GetFirst();
6703 wxWindow
*childWin
= current
->GetData();
6704 wxAdjustZOrder(childWin
);
6705 current
= current
->GetNext();
6710 // We need to adjust the z-order of static boxes in WinCE, to
6711 // make 'contained' controls visible
6712 void wxWindowMSW::OnInitDialog( wxInitDialogEvent
& event
)
6715 wxAdjustZOrder(this);