1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/windows.cpp
4 // Author: Julian Smart
5 // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "window.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
32 #include "wx/msw/wrapwin.h"
33 #include "wx/window.h"
38 #include "wx/dcclient.h"
39 #include "wx/dcmemory.h"
42 #include "wx/layout.h"
43 #include "wx/dialog.h"
45 #include "wx/listbox.h"
46 #include "wx/button.h"
47 #include "wx/msgdlg.h"
48 #include "wx/settings.h"
49 #include "wx/statbox.h"
52 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
53 #include "wx/ownerdrw.h"
56 #include "wx/module.h"
57 #include "wx/sysopt.h"
59 #if wxUSE_DRAG_AND_DROP
63 #if wxUSE_ACCESSIBILITY
64 #include "wx/access.h"
68 #define WM_GETOBJECT 0x003D
71 #define OBJID_CLIENT 0xFFFFFFFC
75 #include "wx/menuitem.h"
78 #include "wx/msw/private.h"
81 #include "wx/tooltip.h"
89 #include "wx/spinctrl.h"
90 #endif // wxUSE_SPINCTRL
95 #include "wx/textctrl.h"
96 #include "wx/notebook.h"
97 #include "wx/listctrl.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(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
112 #include <commctrl.h>
114 #elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler
115 #include "wx/msw/gnuwin32/extra.h"
118 #include "wx/msw/missing.h"
120 #if defined(__WXWINCE__)
121 #include "wx/msw/wince/missing.h"
124 #if defined(TME_LEAVE) && defined(WM_MOUSELEAVE)
125 #define HAVE_TRACKMOUSEEVENT
126 #endif // everything needed for TrackMouseEvent()
128 // ---------------------------------------------------------------------------
130 // ---------------------------------------------------------------------------
132 #if wxUSE_MENUS_NATIVE
133 wxMenu
*wxCurrentPopupMenu
= NULL
;
134 #endif // wxUSE_MENUS_NATIVE
137 extern wxChar
*wxCanvasClassName
;
139 extern const wxChar
*wxCanvasClassName
;
142 // true if we had already created the std colour map, used by
143 // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
144 static bool gs_hasStdCmap
= false;
146 // ---------------------------------------------------------------------------
148 // ---------------------------------------------------------------------------
150 // the window proc for all our windows
151 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
,
152 WPARAM wParam
, LPARAM lParam
);
156 const char *wxGetMessageName(int message
);
159 void wxRemoveHandleAssociation(wxWindowMSW
*win
);
160 extern void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
);
161 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
);
163 // get the text metrics for the current font
164 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
);
166 // find the window for the mouse event at the specified position
167 static wxWindowMSW
*FindWindowForMouseEvent(wxWindowMSW
*win
, int *x
, int *y
); //TW:REQ:Univ
169 // wrapper around BringWindowToTop() API
170 static inline void wxBringWindowToTop(HWND hwnd
)
172 #ifdef __WXMICROWIN__
173 // It seems that MicroWindows brings the _parent_ of the window to the top,
174 // which can be the wrong one.
176 // activate (set focus to) specified window
180 // raise top level parent to top of z order
181 if (!::SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
))
183 wxLogLastError(_T("SetWindowPos"));
189 // ensure that all our parent windows have WS_EX_CONTROLPARENT style
190 static void EnsureParentHasControlParentStyle(wxWindow
*parent
)
193 If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
194 parent as well as otherwise several Win32 functions using
195 GetNextDlgTabItem() to iterate over all controls such as
196 IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
197 all of them iterate over all the controls starting from the currently
198 focused one and stop iterating when they get back to the focus but
199 unless all parents have WS_EX_CONTROLPARENT bit set, they would never
200 get back to the initial (focused) window: as we do have this style,
201 GetNextDlgTabItem() will leave this window and continue in its parent,
202 but if the parent doesn't have it, it wouldn't recurse inside it later
203 on and so wouldn't have a chance of getting back to this window neither.
205 while ( parent
&& !parent
->IsTopLevel() )
207 LONG exStyle
= ::GetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
);
208 if ( !(exStyle
& WS_EX_CONTROLPARENT
) )
210 // force the parent to have this style
211 ::SetWindowLong(GetHwndOf(parent
), GWL_EXSTYLE
,
212 exStyle
| WS_EX_CONTROLPARENT
);
215 parent
= parent
->GetParent();
219 #endif // !__WXWINCE__
222 // On Windows CE, GetCursorPos can return an error, so use this function
224 bool GetCursorPosWinCE(POINT
* pt
)
226 DWORD pos
= GetMessagePos();
233 // ---------------------------------------------------------------------------
235 // ---------------------------------------------------------------------------
237 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
239 #ifdef __WXUNIVERSAL__
240 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW
, wxWindowBase
)
242 #if wxUSE_EXTENDED_RTTI
244 // windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls
245 // must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as
246 // windows with negative ids never can be recreated anyway
248 bool wxWindowStreamingCallback( const wxObject
*object
, wxWriter
* , wxPersister
* , wxxVariantArray
& )
250 const wxWindow
* win
= dynamic_cast<const wxWindow
*>(object
) ;
251 if ( win
&& win
->GetId() < 0 )
256 IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow
, wxWindowBase
,"wx/window.h", wxWindowStreamingCallback
)
258 // make wxWindowList known before the property is used
260 wxCOLLECTION_TYPE_INFO( wxWindow
* , wxWindowList
) ;
262 template<> void wxCollectionToVariantArray( wxWindowList
const &theList
, wxxVariantArray
&value
)
264 wxListCollectionToVariantArray
<wxWindowList::compatibility_iterator
>( theList
, value
) ;
267 WX_DEFINE_FLAGS( wxWindowStyle
)
269 wxBEGIN_FLAGS( wxWindowStyle
)
270 // new style border flags, we put them first to
271 // use them for streaming out
273 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
274 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
275 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
276 wxFLAGS_MEMBER(wxBORDER_RAISED
)
277 wxFLAGS_MEMBER(wxBORDER_STATIC
)
278 wxFLAGS_MEMBER(wxBORDER_NONE
)
280 // old style border flags
281 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
282 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
283 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
284 wxFLAGS_MEMBER(wxRAISED_BORDER
)
285 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
286 wxFLAGS_MEMBER(wxBORDER
)
288 // standard window styles
289 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
290 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
291 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
292 wxFLAGS_MEMBER(wxWANTS_CHARS
)
293 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
294 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
295 wxFLAGS_MEMBER(wxVSCROLL
)
296 wxFLAGS_MEMBER(wxHSCROLL
)
298 wxEND_FLAGS( wxWindowStyle
)
300 wxBEGIN_PROPERTIES_TABLE(wxWindow
)
301 wxEVENT_PROPERTY( Close
, wxEVT_CLOSE_WINDOW
, wxCloseEvent
)
302 wxEVENT_PROPERTY( Create
, wxEVT_CREATE
, wxWindowCreateEvent
)
303 wxEVENT_PROPERTY( Destroy
, wxEVT_DESTROY
, wxWindowDestroyEvent
)
304 // Always constructor Properties first
306 wxREADONLY_PROPERTY( Parent
,wxWindow
*, GetParent
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
307 wxPROPERTY( Id
,wxWindowID
, SetId
, GetId
, -1 /*wxID_ANY*/ , 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
308 wxPROPERTY( Position
,wxPoint
, SetPosition
, GetPosition
, wxDefaultPosition
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos
309 wxPROPERTY( Size
,wxSize
, SetSize
, GetSize
, wxDefaultSize
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size
310 wxPROPERTY( WindowStyle
, long , SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
312 // Then all relations of the object graph
314 wxREADONLY_PROPERTY_COLLECTION( Children
, wxWindowList
, wxWindowBase
* , GetWindowChildren
, wxPROP_OBJECT_GRAPH
/*flags*/ , wxT("Helpstring") , wxT("group"))
316 // and finally all other properties
318 wxPROPERTY( ExtraStyle
, long , SetExtraStyle
, GetExtraStyle
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle
319 wxPROPERTY( BackgroundColour
, wxColour
, SetBackgroundColour
, GetBackgroundColour
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg
320 wxPROPERTY( ForegroundColour
, wxColour
, SetForegroundColour
, GetForegroundColour
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg
321 wxPROPERTY( Enabled
, bool , Enable
, IsEnabled
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
322 wxPROPERTY( Shown
, bool , Show
, IsShown
, wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
324 // possible property candidates (not in xrc) or not valid in all subclasses
325 wxPROPERTY( Title
,wxString
, SetTitle
, GetTitle
, wxEmptyString
)
326 wxPROPERTY( Font
, wxFont
, SetFont
, GetWindowFont
, )
327 wxPROPERTY( Label
,wxString
, SetLabel
, GetLabel
, wxEmptyString
)
328 // MaxHeight, Width , MinHeight , Width
329 // TODO switch label to control and title to toplevels
331 wxPROPERTY( ThemeEnabled
, bool , SetThemeEnabled
, GetThemeEnabled
, )
332 //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , )
333 // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , )
334 wxPROPERTY( AutoLayout
, bool , SetAutoLayout
, GetAutoLayout
, )
339 wxEND_PROPERTIES_TABLE()
341 wxBEGIN_HANDLERS_TABLE(wxWindow
)
342 wxEND_HANDLERS_TABLE()
344 wxCONSTRUCTOR_DUMMY(wxWindow
)
347 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
349 #endif // __WXUNIVERSAL__/__WXMSW__
351 BEGIN_EVENT_TABLE(wxWindowMSW
, wxWindowBase
)
352 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged
)
353 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground
)
355 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog
)
359 // ===========================================================================
361 // ===========================================================================
363 // ---------------------------------------------------------------------------
364 // wxWindow utility functions
365 // ---------------------------------------------------------------------------
367 // Find an item given the MS Windows id
368 wxWindow
*wxWindowMSW::FindItem(long id
) const
371 wxControl
*item
= wxDynamicCastThis(wxControl
);
374 // is it we or one of our "internal" children?
375 if ( item
->GetId() == id
376 #ifndef __WXUNIVERSAL__
377 || (item
->GetSubcontrols().Index(id
) != wxNOT_FOUND
)
378 #endif // __WXUNIVERSAL__
384 #endif // wxUSE_CONTROLS
386 wxWindowList::compatibility_iterator current
= GetChildren().GetFirst();
389 wxWindow
*childWin
= current
->GetData();
391 wxWindow
*wnd
= childWin
->FindItem(id
);
395 current
= current
->GetNext();
401 // Find an item given the MS Windows handle
402 wxWindow
*wxWindowMSW::FindItemByHWND(WXHWND hWnd
, bool controlOnly
) const
404 wxWindowList::compatibility_iterator current
= GetChildren().GetFirst();
407 wxWindow
*parent
= current
->GetData();
409 // Do a recursive search.
410 wxWindow
*wnd
= parent
->FindItemByHWND(hWnd
);
416 || parent
->IsKindOf(CLASSINFO(wxControl
))
417 #endif // wxUSE_CONTROLS
420 wxWindow
*item
= current
->GetData();
421 if ( item
->GetHWND() == hWnd
)
425 if ( item
->ContainsHWND(hWnd
) )
430 current
= current
->GetNext();
435 // Default command handler
436 bool wxWindowMSW::MSWCommand(WXUINT
WXUNUSED(param
), WXWORD
WXUNUSED(id
))
441 // ----------------------------------------------------------------------------
442 // constructors and such
443 // ----------------------------------------------------------------------------
445 void wxWindowMSW::Init()
448 m_isBeingDeleted
= false;
450 m_mouseInWindow
= false;
451 m_lastKeydownProcessed
= false;
453 m_childrenDisabled
= NULL
;
462 #if wxUSE_MOUSEEVENT_HACK
465 m_lastMouseEvent
= -1;
466 #endif // wxUSE_MOUSEEVENT_HACK
470 wxWindowMSW::~wxWindowMSW()
472 m_isBeingDeleted
= true;
474 #ifndef __WXUNIVERSAL__
475 // VS: make sure there's no wxFrame with last focus set to us:
476 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
478 wxTopLevelWindow
*frame
= wxDynamicCast(win
, wxTopLevelWindow
);
481 if ( frame
->GetLastFocus() == this )
483 frame
->SetLastFocus(NULL
);
488 #endif // __WXUNIVERSAL__
490 // VS: destroy children first and _then_ detach *this from its parent.
491 // If we'd do it the other way around, children wouldn't be able
492 // find their parent frame (see above).
497 // VZ: test temp removed to understand what really happens here
498 //if (::IsWindow(GetHwnd()))
500 if ( !::DestroyWindow(GetHwnd()) )
501 wxLogLastError(wxT("DestroyWindow"));
504 // remove hWnd <-> wxWindow association
505 wxRemoveHandleAssociation(this);
508 delete m_childrenDisabled
;
511 // real construction (Init() must have been called before!)
512 bool wxWindowMSW::Create(wxWindow
*parent
,
517 const wxString
& name
)
519 wxCHECK_MSG( parent
, false, wxT("can't create wxWindow without parent") );
521 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
524 parent
->AddChild(this);
527 DWORD msflags
= MSWGetCreateWindowFlags(&exstyle
);
529 #ifdef __WXUNIVERSAL__
530 // no borders, we draw them ourselves
531 exstyle
&= ~(WS_EX_DLGMODALFRAME
|
535 msflags
&= ~WS_BORDER
;
536 #endif // wxUniversal
540 msflags
|= WS_VISIBLE
;
543 if ( !MSWCreate(wxCanvasClassName
, NULL
, pos
, size
, msflags
, exstyle
) )
551 // ---------------------------------------------------------------------------
553 // ---------------------------------------------------------------------------
555 void wxWindowMSW::SetFocus()
557 HWND hWnd
= GetHwnd();
558 wxCHECK_RET( hWnd
, _T("can't set focus to invalid window") );
560 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
564 if ( !::SetFocus(hWnd
) )
566 #if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
567 // was there really an error?
568 DWORD dwRes
= ::GetLastError();
571 HWND hwndFocus
= ::GetFocus();
572 if ( hwndFocus
!= hWnd
)
574 wxLogApiError(_T("SetFocus"), dwRes
);
581 void wxWindowMSW::SetFocusFromKbd()
583 // when the focus is given to the control with DLGC_HASSETSEL style from
584 // keyboard its contents should be entirely selected: this is what
585 // ::IsDialogMessage() does and so we should do it as well to provide the
586 // same LNF as the native programs
587 if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE
, 0, 0) & DLGC_HASSETSEL
)
589 ::SendMessage(GetHwnd(), EM_SETSEL
, 0, -1);
592 // do this after (maybe) setting the selection as like this when
593 // wxEVT_SET_FOCUS handler is called, the selection would have been already
594 // set correctly -- this may be important
595 wxWindowBase::SetFocusFromKbd();
598 // Get the window with the focus
599 wxWindow
*wxWindowBase::DoFindFocus()
601 HWND hWnd
= ::GetFocus();
604 return wxGetWindowFromHWND((WXHWND
)hWnd
);
610 bool wxWindowMSW::Enable(bool enable
)
612 if ( !wxWindowBase::Enable(enable
) )
615 HWND hWnd
= GetHwnd();
617 ::EnableWindow(hWnd
, (BOOL
)enable
);
619 // the logic below doesn't apply to the top level windows -- otherwise
620 // showing a modal dialog would result in total greying out (and ungreying
621 // out later) of everything which would be really ugly
625 // when the parent is disabled, all of its children should be disabled as
626 // well but when it is enabled back, only those of the children which
627 // hadn't been already disabled in the beginning should be enabled again,
628 // so we have to keep the list of those children
629 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
631 node
= node
->GetNext() )
633 wxWindow
*child
= node
->GetData();
634 if ( child
->IsTopLevel() )
636 // the logic below doesn't apply to top level children
642 // enable the child back unless it had been disabled before us
643 if ( !m_childrenDisabled
|| !m_childrenDisabled
->Find(child
) )
646 else // we're being disabled
648 if ( child
->IsEnabled() )
650 // disable it as children shouldn't stay enabled while the
654 else // child already disabled, remember it
656 // have we created the list of disabled children already?
657 if ( !m_childrenDisabled
)
658 m_childrenDisabled
= new wxWindowList
;
660 m_childrenDisabled
->Append(child
);
665 if ( enable
&& m_childrenDisabled
)
667 // we don't need this list any more, don't keep unused memory
668 delete m_childrenDisabled
;
669 m_childrenDisabled
= NULL
;
675 bool wxWindowMSW::Show(bool show
)
677 if ( !wxWindowBase::Show(show
) )
680 HWND hWnd
= GetHwnd();
681 int cshow
= show
? SW_SHOW
: SW_HIDE
;
682 ::ShowWindow(hWnd
, cshow
);
684 if ( show
&& IsTopLevel() )
686 wxBringWindowToTop(hWnd
);
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::SetTitle( const wxString
& title
)
707 SetWindowText(GetHwnd(), title
.c_str());
710 wxString
wxWindowMSW::GetTitle() const
712 return wxGetWindowText(GetHWND());
715 void wxWindowMSW::DoCaptureMouse()
717 HWND hWnd
= GetHwnd();
724 void wxWindowMSW::DoReleaseMouse()
726 if ( !::ReleaseCapture() )
728 wxLogLastError(_T("ReleaseCapture"));
732 /* static */ wxWindow
*wxWindowBase::GetCapture()
734 HWND hwnd
= ::GetCapture();
735 return hwnd
? wxFindWinFromHandle((WXHWND
)hwnd
) : (wxWindow
*)NULL
;
738 bool wxWindowMSW::SetFont(const wxFont
& font
)
740 if ( !wxWindowBase::SetFont(font
) )
746 HWND hWnd
= GetHwnd();
749 WXHANDLE hFont
= m_font
.GetResourceHandle();
751 wxASSERT_MSG( hFont
, wxT("should have valid font") );
753 ::SendMessage(hWnd
, WM_SETFONT
, (WPARAM
)hFont
, MAKELPARAM(TRUE
, 0));
758 bool wxWindowMSW::SetCursor(const wxCursor
& cursor
)
760 if ( !wxWindowBase::SetCursor(cursor
) )
768 HWND hWnd
= GetHwnd();
770 // Change the cursor NOW if we're within the correct window
773 ::GetCursorPosWinCE(&point
);
775 ::GetCursorPos(&point
);
778 RECT rect
= wxGetWindowRect(hWnd
);
780 if ( ::PtInRect(&rect
, point
) && !wxIsBusy() )
781 ::SetCursor(GetHcursorOf(m_cursor
));
787 void wxWindowMSW::WarpPointer (int x
, int y
)
789 ClientToScreen(&x
, &y
);
791 if ( !::SetCursorPos(x
, y
) )
793 wxLogLastError(_T("SetCursorPos"));
797 // ---------------------------------------------------------------------------
799 // ---------------------------------------------------------------------------
801 inline int GetScrollPosition(HWND hWnd
, int wOrient
)
803 #ifdef __WXMICROWIN__
804 return ::GetScrollPosWX(hWnd
, wOrient
);
806 WinStruct
<SCROLLINFO
> scrollInfo
;
807 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
808 scrollInfo
.fMask
= SIF_POS
;
809 if ( !::GetScrollInfo(hWnd
,
813 // Not neccessarily an error, if there are no scrollbars yet.
814 // wxLogLastError(_T("GetScrollInfo"));
816 return scrollInfo
.nPos
;
817 // return ::GetScrollPos(hWnd, wOrient);
821 int wxWindowMSW::GetScrollPos(int orient
) const
823 HWND hWnd
= GetHwnd();
824 wxCHECK_MSG( hWnd
, 0, _T("no HWND in GetScrollPos") );
826 return GetScrollPosition(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
);
829 // This now returns the whole range, not just the number
830 // of positions that we can scroll.
831 int wxWindowMSW::GetScrollRange(int orient
) const
834 HWND hWnd
= GetHwnd();
838 ::GetScrollRange(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
841 WinStruct
<SCROLLINFO
> scrollInfo
;
842 scrollInfo
.fMask
= SIF_RANGE
;
843 if ( !::GetScrollInfo(hWnd
,
844 orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
847 // Most of the time this is not really an error, since the return
848 // value can also be zero when there is no scrollbar yet.
849 // wxLogLastError(_T("GetScrollInfo"));
851 maxPos
= scrollInfo
.nMax
;
853 // undo "range - 1" done in SetScrollbar()
857 int wxWindowMSW::GetScrollThumb(int orient
) const
859 return orient
== wxHORIZONTAL
? m_xThumbSize
: m_yThumbSize
;
862 void wxWindowMSW::SetScrollPos(int orient
, int pos
, bool refresh
)
864 HWND hWnd
= GetHwnd();
865 wxCHECK_RET( hWnd
, _T("SetScrollPos: no HWND") );
867 WinStruct
<SCROLLINFO
> info
;
871 info
.fMask
= SIF_POS
;
872 if ( HasFlag(wxALWAYS_SHOW_SB
) )
874 // disable scrollbar instead of removing it then
875 info
.fMask
|= SIF_DISABLENOSCROLL
;
878 ::SetScrollInfo(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
882 // New function that will replace some of the above.
883 void wxWindowMSW::SetScrollbar(int orient
,
889 WinStruct
<SCROLLINFO
> info
;
890 info
.nPage
= pageSize
;
891 info
.nMin
= 0; // range is nMax - nMin + 1
892 info
.nMax
= range
- 1; // as both nMax and nMax are inclusive
894 info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
895 if ( HasFlag(wxALWAYS_SHOW_SB
) )
897 // disable scrollbar instead of removing it then
898 info
.fMask
|= SIF_DISABLENOSCROLL
;
901 HWND hWnd
= GetHwnd();
904 ::SetScrollInfo(hWnd
, orient
== wxHORIZONTAL
? SB_HORZ
: SB_VERT
,
908 *(orient
== wxHORIZONTAL
? &m_xThumbSize
: &m_yThumbSize
) = pageSize
;
911 void wxWindowMSW::ScrollWindow(int dx
, int dy
, const wxRect
*prect
)
917 rect
.left
= prect
->x
;
919 rect
.right
= prect
->x
+ prect
->width
;
920 rect
.bottom
= prect
->y
+ prect
->height
;
930 // FIXME: is this the exact equivalent of the line below?
931 ::ScrollWindowEx(GetHwnd(), dx
, dy
, pr
, pr
, 0, 0, SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
933 ::ScrollWindow(GetHwnd(), dx
, dy
, pr
, pr
);
937 static bool ScrollVertically(HWND hwnd
, int kind
, int count
)
939 int posStart
= GetScrollPosition(hwnd
, SB_VERT
);
942 for ( int n
= 0; n
< count
; n
++ )
944 ::SendMessage(hwnd
, WM_VSCROLL
, kind
, 0);
946 int posNew
= GetScrollPosition(hwnd
, SB_VERT
);
949 // don't bother to continue, we're already at top/bottom
956 return pos
!= posStart
;
959 bool wxWindowMSW::ScrollLines(int lines
)
961 bool down
= lines
> 0;
963 return ScrollVertically(GetHwnd(),
964 down
? SB_LINEDOWN
: SB_LINEUP
,
965 down
? lines
: -lines
);
968 bool wxWindowMSW::ScrollPages(int pages
)
970 bool down
= pages
> 0;
972 return ScrollVertically(GetHwnd(),
973 down
? SB_PAGEDOWN
: SB_PAGEUP
,
974 down
? pages
: -pages
);
977 // ---------------------------------------------------------------------------
979 // ---------------------------------------------------------------------------
981 void wxWindowMSW::SubclassWin(WXHWND hWnd
)
983 wxASSERT_MSG( !m_oldWndProc
, wxT("subclassing window twice?") );
985 HWND hwnd
= (HWND
)hWnd
;
986 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in SubclassWin") );
988 wxAssociateWinWithHandle(hwnd
, this);
990 m_oldWndProc
= (WXFARPROC
)wxGetWindowProc((HWND
)hWnd
);
992 // we don't need to subclass the window of our own class (in the Windows
993 // sense of the word)
994 if ( !wxCheckWindowWndProc(hWnd
, (WXFARPROC
)wxWndProc
) )
996 wxSetWindowProc(hwnd
, wxWndProc
);
1000 // don't bother restoring it neither: this also makes it easy to
1001 // implement IsOfStandardClass() method which returns true for the
1002 // standard controls and false for the wxWidgets own windows as it can
1003 // simply check m_oldWndProc
1004 m_oldWndProc
= NULL
;
1008 void wxWindowMSW::UnsubclassWin()
1010 wxRemoveHandleAssociation(this);
1012 // Restore old Window proc
1013 HWND hwnd
= GetHwnd();
1018 wxCHECK_RET( ::IsWindow(hwnd
), wxT("invalid HWND in UnsubclassWin") );
1022 if ( !wxCheckWindowWndProc((WXHWND
)hwnd
, m_oldWndProc
) )
1024 wxSetWindowProc(hwnd
, (WNDPROC
)m_oldWndProc
);
1027 m_oldWndProc
= NULL
;
1032 void wxWindowMSW::AssociateHandle(WXWidget handle
)
1036 if ( !::DestroyWindow(GetHwnd()) )
1037 wxLogLastError(wxT("DestroyWindow"));
1040 WXHWND wxhwnd
= (WXHWND
)handle
;
1043 SubclassWin(wxhwnd
);
1046 void wxWindowMSW::DissociateHandle()
1048 // this also calls SetHWND(0) for us
1053 bool wxCheckWindowWndProc(WXHWND hWnd
, WXFARPROC wndProc
)
1055 // Unicows note: the code below works, but only because WNDCLASS contains
1056 // original window handler rather that the unicows fake one. This may not
1057 // be on purpose, though; if it stops working with future versions of
1058 // unicows.dll, we can override unicows hooks by setting
1059 // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own
1060 // versions that keep track of fake<->real wnd proc mapping.
1062 // On WinCE (at least), the wndproc comparison doesn't work,
1063 // so have to use something like this.
1065 wxUnusedVar(wndProc
);
1067 extern wxChar
*wxCanvasClassName
;
1068 extern wxChar
*wxCanvasClassNameNR
;
1069 extern const wxChar
*wxMDIFrameClassName
;
1070 extern const wxChar
*wxMDIFrameClassNameNoRedraw
;
1071 extern const wxChar
*wxMDIChildFrameClassName
;
1072 extern const wxChar
*wxMDIChildFrameClassNameNoRedraw
;
1073 wxString
str(wxGetWindowClass(hWnd
));
1074 if (str
== wxCanvasClassName
||
1075 str
== wxCanvasClassNameNR
||
1076 str
== wxMDIFrameClassName
||
1077 str
== wxMDIFrameClassNameNoRedraw
||
1078 str
== wxMDIChildFrameClassName
||
1079 str
== wxMDIChildFrameClassNameNoRedraw
||
1080 str
== _T("wxTLWHiddenParent"))
1081 return true; // Effectively means don't subclass
1086 if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd
), &cls
) )
1088 wxLogLastError(_T("GetClassInfo"));
1093 return wndProc
== (WXFARPROC
)cls
.lpfnWndProc
;
1097 // ----------------------------------------------------------------------------
1099 // ----------------------------------------------------------------------------
1101 void wxWindowMSW::SetWindowStyleFlag(long flags
)
1103 long flagsOld
= GetWindowStyleFlag();
1104 if ( flags
== flagsOld
)
1107 // update the internal variable
1108 wxWindowBase::SetWindowStyleFlag(flags
);
1110 // now update the Windows style as well if needed - and if the window had
1111 // been already created
1115 WXDWORD exstyle
, exstyleOld
;
1116 long style
= MSWGetStyle(flags
, &exstyle
),
1117 styleOld
= MSWGetStyle(flagsOld
, &exstyleOld
);
1119 if ( style
!= styleOld
)
1121 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1122 // this function so instead of simply setting the style to the new
1123 // value we clear the bits which were set in styleOld but are set in
1124 // the new one and set the ones which were not set before
1125 long styleReal
= ::GetWindowLong(GetHwnd(), GWL_STYLE
);
1126 styleReal
&= ~styleOld
;
1129 ::SetWindowLong(GetHwnd(), GWL_STYLE
, styleReal
);
1132 // and the extended style
1133 if ( exstyle
!= exstyleOld
)
1135 long exstyleReal
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
);
1136 exstyleReal
&= ~exstyleOld
;
1137 exstyleReal
|= exstyle
;
1139 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyleReal
);
1141 // we must call SetWindowPos() to flush the cached extended style and
1142 // also to make the change to wxSTAY_ON_TOP style take effect: just
1143 // setting the style simply doesn't work
1144 if ( !::SetWindowPos(GetHwnd(),
1145 exstyleReal
& WS_EX_TOPMOST
? HWND_TOPMOST
1148 SWP_NOMOVE
| SWP_NOSIZE
) )
1150 wxLogLastError(_T("SetWindowPos"));
1155 WXDWORD
wxWindowMSW::MSWGetStyle(long flags
, WXDWORD
*exstyle
) const
1157 // translate common wxWidgets styles to Windows ones
1159 // most of windows are child ones, those which are not (such as
1160 // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle()
1161 WXDWORD style
= WS_CHILD
;
1163 // using this flag results in very significant reduction in flicker,
1164 // especially with controls inside the static boxes (as the interior of the
1165 // box is not redrawn twice).but sometimes results in redraw problems, so
1166 // optionally allow the old code to continue to use it provided a special
1167 // system option is turned on
1168 if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
1169 || (flags
& wxCLIP_CHILDREN
) )
1170 style
|= WS_CLIPCHILDREN
;
1172 // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
1173 // don't support overlapping windows and it only makes sense for them and,
1174 // presumably, gives the system some extra work (to manage more clipping
1175 // regions), so avoid it alltogether
1178 if ( flags
& wxVSCROLL
)
1179 style
|= WS_VSCROLL
;
1181 if ( flags
& wxHSCROLL
)
1182 style
|= WS_HSCROLL
;
1184 const wxBorder border
= GetBorder(flags
);
1186 // WS_BORDER is only required for wxBORDER_SIMPLE
1187 if ( border
== wxBORDER_SIMPLE
)
1190 // now deal with ext style if the caller wants it
1196 if ( flags
& wxTRANSPARENT_WINDOW
)
1197 *exstyle
|= WS_EX_TRANSPARENT
;
1203 case wxBORDER_DEFAULT
:
1204 wxFAIL_MSG( _T("unknown border style") );
1208 case wxBORDER_SIMPLE
:
1211 case wxBORDER_STATIC
:
1212 *exstyle
|= WS_EX_STATICEDGE
;
1215 case wxBORDER_RAISED
:
1216 *exstyle
|= WS_EX_DLGMODALFRAME
;
1219 case wxBORDER_SUNKEN
:
1220 *exstyle
|= WS_EX_CLIENTEDGE
;
1221 style
&= ~WS_BORDER
;
1224 case wxBORDER_DOUBLE
:
1225 *exstyle
|= WS_EX_DLGMODALFRAME
;
1229 // wxUniv doesn't use Windows dialog navigation functions at all
1230 #if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
1231 // to make the dialog navigation work with the nested panels we must
1232 // use this style (top level windows such as dialogs don't need it)
1233 if ( (flags
& wxTAB_TRAVERSAL
) && !IsTopLevel() )
1235 *exstyle
|= WS_EX_CONTROLPARENT
;
1237 #endif // __WXUNIVERSAL__
1243 // Setup background and foreground colours correctly
1244 void wxWindowMSW::SetupColours()
1247 SetBackgroundColour(GetParent()->GetBackgroundColour());
1250 bool wxWindowMSW::IsMouseInWindow() const
1252 // get the mouse position
1255 ::GetCursorPosWinCE(&pt
);
1257 ::GetCursorPos(&pt
);
1260 // find the window which currently has the cursor and go up the window
1261 // chain until we find this window - or exhaust it
1262 HWND hwnd
= ::WindowFromPoint(pt
);
1263 while ( hwnd
&& (hwnd
!= GetHwnd()) )
1264 hwnd
= ::GetParent(hwnd
);
1266 return hwnd
!= NULL
;
1269 void wxWindowMSW::OnInternalIdle()
1271 #ifndef HAVE_TRACKMOUSEEVENT
1272 // Check if we need to send a LEAVE event
1273 if ( m_mouseInWindow
)
1275 // note that we should generate the leave event whether the window has
1276 // or doesn't have mouse capture
1277 if ( !IsMouseInWindow() )
1279 GenerateMouseLeave();
1282 #endif // !HAVE_TRACKMOUSEEVENT
1284 if (wxUpdateUIEvent::CanUpdate(this))
1285 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
1288 // Set this window to be the child of 'parent'.
1289 bool wxWindowMSW::Reparent(wxWindowBase
*parent
)
1291 if ( !wxWindowBase::Reparent(parent
) )
1294 HWND hWndChild
= GetHwnd();
1295 HWND hWndParent
= GetParent() ? GetWinHwnd(GetParent()) : (HWND
)0;
1297 ::SetParent(hWndChild
, hWndParent
);
1300 if ( ::GetWindowLong(hWndChild
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT
)
1302 EnsureParentHasControlParentStyle(GetParent());
1304 #endif // !__WXWINCE__
1309 static inline void SendSetRedraw(HWND hwnd
, bool on
)
1311 #ifndef __WXMICROWIN__
1312 ::SendMessage(hwnd
, WM_SETREDRAW
, (WPARAM
)on
, 0);
1316 void wxWindowMSW::Freeze()
1318 if ( !m_frozenness
++ )
1321 SendSetRedraw(GetHwnd(), false);
1325 void wxWindowMSW::Thaw()
1327 wxASSERT_MSG( m_frozenness
> 0, _T("Thaw() without matching Freeze()") );
1329 if ( !--m_frozenness
)
1333 SendSetRedraw(GetHwnd(), true);
1335 // we need to refresh everything or otherwise the invalidated area
1336 // is not going to be repainted
1342 void wxWindowMSW::Refresh(bool eraseBack
, const wxRect
*rect
)
1344 HWND hWnd
= GetHwnd();
1351 mswRect
.left
= rect
->x
;
1352 mswRect
.top
= rect
->y
;
1353 mswRect
.right
= rect
->x
+ rect
->width
;
1354 mswRect
.bottom
= rect
->y
+ rect
->height
;
1363 #ifndef __SMARTPHONE__
1364 UINT flags
= RDW_INVALIDATE
| RDW_ALLCHILDREN
;
1368 ::RedrawWindow(hWnd
, pRect
, NULL
, flags
);
1370 ::InvalidateRect(hWnd
, pRect
, eraseBack
);
1375 void wxWindowMSW::Update()
1377 if ( !::UpdateWindow(GetHwnd()) )
1379 wxLogLastError(_T("UpdateWindow"));
1382 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1383 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1384 // handler needs to be really drawn right now
1389 // ---------------------------------------------------------------------------
1391 // ---------------------------------------------------------------------------
1394 #if wxUSE_DRAG_AND_DROP
1395 void wxWindowMSW::SetDropTarget(wxDropTarget
*pDropTarget
)
1397 if ( m_dropTarget
!= 0 ) {
1398 m_dropTarget
->Revoke(m_hWnd
);
1399 delete m_dropTarget
;
1402 m_dropTarget
= pDropTarget
;
1403 if ( m_dropTarget
!= 0 )
1404 m_dropTarget
->Register(m_hWnd
);
1406 #endif // wxUSE_DRAG_AND_DROP
1408 // old style file-manager drag&drop support: we retain the old-style
1409 // DragAcceptFiles in parallel with SetDropTarget.
1410 void wxWindowMSW::DragAcceptFiles(bool accept
)
1412 #if !defined(__WXWINCE__)
1413 HWND hWnd
= GetHwnd();
1415 ::DragAcceptFiles(hWnd
, (BOOL
)accept
);
1417 wxUnusedVar(accept
);
1421 // ----------------------------------------------------------------------------
1423 // ----------------------------------------------------------------------------
1427 void wxWindowMSW::DoSetToolTip(wxToolTip
*tooltip
)
1429 wxWindowBase::DoSetToolTip(tooltip
);
1432 m_tooltip
->SetWindow((wxWindow
*)this);
1435 #endif // wxUSE_TOOLTIPS
1437 // ---------------------------------------------------------------------------
1438 // moving and resizing
1439 // ---------------------------------------------------------------------------
1442 void wxWindowMSW::DoGetSize(int *x
, int *y
) const
1444 RECT rect
= wxGetWindowRect(GetHwnd());
1447 *x
= rect
.right
- rect
.left
;
1449 *y
= rect
.bottom
- rect
.top
;
1452 // Get size *available for subwindows* i.e. excluding menu bar etc.
1453 void wxWindowMSW::DoGetClientSize(int *x
, int *y
) const
1455 RECT rect
= wxGetClientRect(GetHwnd());
1463 void wxWindowMSW::DoGetPosition(int *x
, int *y
) const
1465 RECT rect
= wxGetWindowRect(GetHwnd());
1468 point
.x
= rect
.left
;
1471 // we do the adjustments with respect to the parent only for the "real"
1472 // children, not for the dialogs/frames
1473 if ( !IsTopLevel() )
1475 HWND hParentWnd
= 0;
1476 wxWindow
*parent
= GetParent();
1478 hParentWnd
= GetWinHwnd(parent
);
1480 // Since we now have the absolute screen coords, if there's a parent we
1481 // must subtract its top left corner
1484 ::ScreenToClient(hParentWnd
, &point
);
1489 // We may be faking the client origin. So a window that's really at (0,
1490 // 30) may appear (to wxWin apps) to be at (0, 0).
1491 wxPoint
pt(parent
->GetClientAreaOrigin());
1503 void wxWindowMSW::DoScreenToClient(int *x
, int *y
) const
1511 ::ScreenToClient(GetHwnd(), &pt
);
1519 void wxWindowMSW::DoClientToScreen(int *x
, int *y
) const
1527 ::ClientToScreen(GetHwnd(), &pt
);
1535 void wxWindowMSW::DoMoveWindow(int x
, int y
, int width
, int height
)
1537 // TODO: is this consistent with other platforms?
1538 // Still, negative width or height shouldn't be allowed
1544 // if our parent had prepared a defer window handle for us, use it (unless
1545 // we are a top level window)
1546 wxWindowMSW
*parent
= GetParent();
1547 HDWP hdwp
= parent
&& !IsTopLevel() ? (HDWP
)parent
->m_hDWP
: NULL
;
1550 hdwp
= ::DeferWindowPos(hdwp
, GetHwnd(), NULL
,
1551 x
, y
, width
, height
,
1555 wxLogLastError(_T("DeferWindowPos"));
1558 // hdwp must be updated as it may have been changed
1559 parent
->m_hDWP
= (WXHANDLE
)hdwp
;
1562 // otherwise (or if deferring failed) move the window in place immediately
1565 if ( !::MoveWindow(GetHwnd(), x
, y
, width
, height
, IsShown()) )
1567 wxLogLastError(wxT("MoveWindow"));
1572 // set the size of the window: if the dimensions are positive, just use them,
1573 // but if any of them is equal to -1, it means that we must find the value for
1574 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1575 // which case -1 is a valid value for x and y)
1577 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1578 // the width/height to best suit our contents, otherwise we reuse the current
1580 void wxWindowMSW::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1582 // get the current size and position...
1583 int currentX
, currentY
;
1584 GetPosition(¤tX
, ¤tY
);
1585 int currentW
,currentH
;
1586 GetSize(¤tW
, ¤tH
);
1588 // ... and don't do anything (avoiding flicker) if it's already ok
1589 if ( x
== currentX
&& y
== currentY
&&
1590 width
== currentW
&& height
== currentH
)
1595 if ( x
== wxDefaultCoord
&& !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1597 if ( y
== wxDefaultCoord
&& !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1600 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
1602 wxSize size
= wxDefaultSize
;
1603 if ( width
== wxDefaultCoord
)
1605 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1607 size
= DoGetBestSize();
1612 // just take the current one
1617 if ( height
== wxDefaultCoord
)
1619 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1621 if ( size
.x
== wxDefaultCoord
)
1623 size
= DoGetBestSize();
1625 //else: already called DoGetBestSize() above
1631 // just take the current one
1636 DoMoveWindow(x
, y
, width
, height
);
1639 void wxWindowMSW::DoSetClientSize(int width
, int height
)
1641 // setting the client size is less obvious than it it could have been
1642 // because in the result of changing the total size the window scrollbar
1643 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1644 // will not be correct as the difference between the total and client size
1645 // changes - so we keep changing it until we get it right
1647 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1648 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1649 // may become 3 if the window had 0 size originally and so we didn't
1650 // calculate the scrollbar correction correctly during the first iteration)
1651 // but just to be on the safe side we check for it instead of making it an
1652 // "infinite" loop (i.e. leaving break inside as the only way to get out)
1653 for ( int i
= 0; i
< 4; i
++ )
1656 ::GetClientRect(GetHwnd(), &rectClient
);
1658 // if the size is already ok, stop here (rectClient.left = top = 0)
1659 if ( (rectClient
.right
== width
|| width
== wxDefaultCoord
) &&
1660 (rectClient
.bottom
== height
|| height
== wxDefaultCoord
) )
1665 int widthClient
= width
,
1666 heightClient
= height
;
1668 // Find the difference between the entire window (title bar and all)
1669 // and the client area; add this to the new client size to move the
1672 ::GetWindowRect(GetHwnd(), &rectWin
);
1674 widthClient
+= rectWin
.right
- rectWin
.left
- rectClient
.right
;
1675 heightClient
+= rectWin
.bottom
- rectWin
.top
- rectClient
.bottom
;
1678 point
.x
= rectWin
.left
;
1679 point
.y
= rectWin
.top
;
1681 // MoveWindow positions the child windows relative to the parent, so
1682 // adjust if necessary
1683 if ( !IsTopLevel() )
1685 wxWindow
*parent
= GetParent();
1688 ::ScreenToClient(GetHwndOf(parent
), &point
);
1692 DoMoveWindow(point
.x
, point
.y
, widthClient
, heightClient
);
1696 // ---------------------------------------------------------------------------
1698 // ---------------------------------------------------------------------------
1700 int wxWindowMSW::GetCharHeight() const
1702 return wxGetTextMetrics(this).tmHeight
;
1705 int wxWindowMSW::GetCharWidth() const
1707 // +1 is needed because Windows apparently adds it when calculating the
1708 // dialog units size in pixels
1709 #if wxDIALOG_UNIT_COMPATIBILITY
1710 return wxGetTextMetrics(this).tmAveCharWidth
;
1712 return wxGetTextMetrics(this).tmAveCharWidth
+ 1;
1716 void wxWindowMSW::GetTextExtent(const wxString
& string
,
1718 int *descent
, int *externalLeading
,
1719 const wxFont
*theFont
) const
1721 wxASSERT_MSG( !theFont
|| theFont
->Ok(),
1722 _T("invalid font in GetTextExtent()") );
1726 fontToUse
= *theFont
;
1728 fontToUse
= GetFont();
1730 WindowHDC
hdc(GetHwnd());
1731 SelectInHDC
selectFont(hdc
, GetHfontOf(fontToUse
));
1735 GetTextExtentPoint(hdc
, string
, string
.length(), &sizeRect
);
1736 GetTextMetrics(hdc
, &tm
);
1743 *descent
= tm
.tmDescent
;
1744 if ( externalLeading
)
1745 *externalLeading
= tm
.tmExternalLeading
;
1748 // ---------------------------------------------------------------------------
1750 // ---------------------------------------------------------------------------
1752 #if wxUSE_MENUS_NATIVE
1754 // yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1755 // immediately, without waiting for the next event loop iteration
1757 // NB: this function should probably be made public later as it can almost
1758 // surely replace wxYield() elsewhere as well
1759 static void wxYieldForCommandsOnly()
1761 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1762 // want to process it here)
1764 while ( ::PeekMessage(&msg
, (HWND
)0, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
) )
1766 if ( msg
.message
== WM_QUIT
)
1768 // if we retrieved a WM_QUIT, insert back into the message queue.
1769 ::PostQuitMessage(0);
1773 // luckily (as we don't have access to wxEventLoopImpl method from here
1774 // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it
1776 ::TranslateMessage(&msg
);
1777 ::DispatchMessage(&msg
);
1781 bool wxWindowMSW::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1783 menu
->SetInvokingWindow(this);
1786 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
1788 wxPoint mouse
= ScreenToClient(wxGetMousePosition());
1789 x
= mouse
.x
; y
= mouse
.y
;
1792 HWND hWnd
= GetHwnd();
1793 HMENU hMenu
= GetHmenuOf(menu
);
1797 ::ClientToScreen(hWnd
, &point
);
1798 wxCurrentPopupMenu
= menu
;
1799 #if defined(__WXWINCE__)
1802 UINT flags
= TPM_RIGHTBUTTON
;
1804 ::TrackPopupMenu(hMenu
, flags
, point
.x
, point
.y
, 0, hWnd
, NULL
);
1806 // we need to do it righ now as otherwise the events are never going to be
1807 // sent to wxCurrentPopupMenu from HandleCommand()
1809 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1810 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1811 // destroyed as soon as we return (it can be a local variable in the caller
1812 // for example) and so we do need to process the event immediately
1813 wxYieldForCommandsOnly();
1815 wxCurrentPopupMenu
= NULL
;
1817 menu
->SetInvokingWindow(NULL
);
1822 #endif // wxUSE_MENUS_NATIVE
1824 // ===========================================================================
1825 // pre/post message processing
1826 // ===========================================================================
1828 WXLRESULT
wxWindowMSW::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
1831 return ::CallWindowProc(CASTWNDPROC m_oldWndProc
, GetHwnd(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
1833 return ::DefWindowProc(GetHwnd(), nMsg
, wParam
, lParam
);
1836 bool wxWindowMSW::MSWProcessMessage(WXMSG
* pMsg
)
1838 // wxUniversal implements tab traversal itself
1839 #ifndef __WXUNIVERSAL__
1840 if ( m_hWnd
!= 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL
) )
1842 // intercept dialog navigation keys
1843 MSG
*msg
= (MSG
*)pMsg
;
1845 // here we try to do all the job which ::IsDialogMessage() usually does
1847 if ( msg
->message
== WM_KEYDOWN
)
1849 bool bCtrlDown
= wxIsCtrlDown();
1850 bool bShiftDown
= wxIsShiftDown();
1852 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1853 // don't process it if it's the case (except for Ctrl-Tab/Enter
1854 // combinations which are always processed)
1858 lDlgCode
= ::SendMessage(msg
->hwnd
, WM_GETDLGCODE
, 0, 0);
1860 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
1861 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
1862 // it, of course, implies them
1863 if ( lDlgCode
& DLGC_WANTALLKEYS
)
1865 lDlgCode
|= DLGC_WANTTAB
| DLGC_WANTARROWS
;
1869 bool bForward
= true,
1870 bWindowChange
= false,
1873 // should we process this message specially?
1874 bool bProcess
= true;
1875 switch ( msg
->wParam
)
1878 if ( lDlgCode
& DLGC_WANTTAB
) {
1882 // Ctrl-Tab cycles thru notebook pages
1883 bWindowChange
= bCtrlDown
;
1884 bForward
= !bShiftDown
;
1891 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1899 if ( (lDlgCode
& DLGC_WANTARROWS
) || bCtrlDown
)
1906 wxButton
*btn
= wxDynamicCast(FindWindow(wxID_CANCEL
),wxButton
);
1908 // our own wxLogDialog should react to Esc
1909 // without Cancel button but this is a private class
1910 // so let's try recognize it by content
1911 #if wxUSE_LOG_DIALOG
1913 wxDynamicCast(this,wxDialog
) &&
1914 FindWindow(wxID_MORE
) &&
1915 FindWindow(wxID_OK
) &&
1916 !FindWindow(wxID_CANCEL
) &&
1917 GetTitle().MakeLower().StartsWith(wxTheApp
->GetAppName().c_str())
1919 btn
= wxDynamicCast(FindWindow(wxID_OK
),wxButton
);
1920 #endif // wxUSE_LOG_DIALOG
1921 if ( btn
&& btn
->IsEnabled() )
1923 // if we do have a cancel button, do press it
1924 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1926 // we consumed the message
1929 #endif // wxUSE_BUTTON
1937 if ( (lDlgCode
& DLGC_WANTMESSAGE
) && !bCtrlDown
)
1939 // control wants to process Enter itself, don't
1940 // call IsDialogMessage() which would interpret
1944 else if ( lDlgCode
& DLGC_BUTTON
)
1946 // let IsDialogMessage() handle this for all
1947 // buttons except the owner-drawn ones which it
1948 // just seems to ignore
1949 long style
= ::GetWindowLong(msg
->hwnd
, GWL_STYLE
);
1950 if ( (style
& BS_OWNERDRAW
) == BS_OWNERDRAW
)
1952 // emulate the button click
1953 wxWindow
*btn
= wxFindWinFromHandle((WXHWND
)msg
->hwnd
);
1955 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1960 // FIXME: this should be handled by
1961 // wxNavigationKeyEvent handler and not here!
1965 wxButton
*btn
= wxDynamicCast(GetDefaultItem(),
1967 if ( btn
&& btn
->IsEnabled() )
1969 // if we do have a default button, do press it
1970 btn
->MSWCommand(BN_CLICKED
, 0 /* unused */);
1974 else // no default button
1975 #endif // wxUSE_BUTTON
1977 // this is a quick and dirty test for a text
1979 if ( !(lDlgCode
& DLGC_HASSETSEL
) )
1981 // don't process Enter, the control might
1982 // need it for itself and don't let
1983 // ::IsDialogMessage() have it as it can
1984 // eat the Enter events sometimes
1987 else if (!IsTopLevel())
1989 // if not a top level window, let parent
1993 //else: treat Enter as TAB: pass to the next
1994 // control as this is the best thing to do
1995 // if the text doesn't handle Enter itself
2007 wxNavigationKeyEvent event
;
2008 event
.SetDirection(bForward
);
2009 event
.SetWindowChange(bWindowChange
);
2010 event
.SetFromTab(bFromTab
);
2011 event
.SetEventObject(this);
2013 if ( GetEventHandler()->ProcessEvent(event
) )
2020 // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the
2021 // message even when there is no cancel button and when the message is
2022 // needed by the control itself: in particular, it prevents the tree in
2023 // place edit control from being closed with Escape in a dialog
2024 if ( msg
->message
!= WM_KEYDOWN
|| msg
->wParam
!= VK_ESCAPE
)
2026 // ::IsDialogMessage() is broken and may sometimes hang the
2027 // application by going into an infinite loop, so we try to detect
2028 // [some of] the situatations when this may happen and not call it
2031 // assume we can call it by default
2032 bool canSafelyCallIsDlgMsg
= true;
2034 HWND hwndFocus
= ::GetFocus();
2036 // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter
2037 // an infinite loop, because it will recursively check the child
2038 // windows but not the window itself and so if none of the children
2039 // accepts focus it loops forever (as it only stops when it gets
2040 // back to the window it started from)
2042 // while it is very unusual that a window with WS_EX_CONTROLPARENT
2043 // style has the focus, it can happen. One such possibility is if
2044 // all windows are either toplevel, wxDialog, wxPanel or static
2045 // controls and no window can actually accept keyboard input.
2046 #if !defined(__WXWINCE__)
2047 if ( ::GetWindowLong(hwndFocus
, GWL_EXSTYLE
) & WS_EX_CONTROLPARENT
)
2049 // passimistic by default
2050 canSafelyCallIsDlgMsg
= false;
2051 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
2053 node
= node
->GetNext() )
2055 wxWindow
* const win
= node
->GetData();
2056 if ( win
->AcceptsFocus() &&
2057 !(::GetWindowLong(GetHwndOf(win
), GWL_EXSTYLE
) &
2058 WS_EX_CONTROLPARENT
) )
2060 // it shouldn't hang...
2061 canSafelyCallIsDlgMsg
= true;
2067 #endif // !__WXWINCE__
2069 if ( canSafelyCallIsDlgMsg
)
2071 // ::IsDialogMessage() can enter in an infinite loop when the
2072 // currently focused window is disabled or hidden and its
2073 // parent has WS_EX_CONTROLPARENT style, so don't call it in
2077 if ( !::IsWindowEnabled(hwndFocus
) ||
2078 !::IsWindowVisible(hwndFocus
) )
2080 // it would enter an infinite loop if we do this!
2081 canSafelyCallIsDlgMsg
= false;
2086 if ( !(::GetWindowLong(hwndFocus
, GWL_STYLE
) & WS_CHILD
) )
2088 // it's a top level window, don't go further -- e.g. even
2089 // if the parent of a dialog is disabled, this doesn't
2090 // break navigation inside the dialog
2094 hwndFocus
= ::GetParent(hwndFocus
);
2098 // let IsDialogMessage() have the message if it's safe to call it
2099 if ( canSafelyCallIsDlgMsg
&& ::IsDialogMessage(GetHwnd(), msg
) )
2101 // IsDialogMessage() did something...
2106 #endif // __WXUNIVERSAL__
2111 // relay mouse move events to the tooltip control
2112 MSG
*msg
= (MSG
*)pMsg
;
2113 if ( msg
->message
== WM_MOUSEMOVE
)
2114 m_tooltip
->RelayEvent(pMsg
);
2116 #endif // wxUSE_TOOLTIPS
2121 bool wxWindowMSW::MSWTranslateMessage(WXMSG
* pMsg
)
2123 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
2124 return m_acceleratorTable
.Translate(this, pMsg
);
2128 #endif // wxUSE_ACCEL
2131 bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG
* WXUNUSED(pMsg
))
2133 // preprocess all messages by default
2137 // ---------------------------------------------------------------------------
2138 // message params unpackers
2139 // ---------------------------------------------------------------------------
2141 void wxWindowMSW::UnpackCommand(WXWPARAM wParam
, WXLPARAM lParam
,
2142 WORD
*id
, WXHWND
*hwnd
, WORD
*cmd
)
2144 *id
= LOWORD(wParam
);
2145 *hwnd
= (WXHWND
)lParam
;
2146 *cmd
= HIWORD(wParam
);
2149 void wxWindowMSW::UnpackActivate(WXWPARAM wParam
, WXLPARAM lParam
,
2150 WXWORD
*state
, WXWORD
*minimized
, WXHWND
*hwnd
)
2152 *state
= LOWORD(wParam
);
2153 *minimized
= HIWORD(wParam
);
2154 *hwnd
= (WXHWND
)lParam
;
2157 void wxWindowMSW::UnpackScroll(WXWPARAM wParam
, WXLPARAM lParam
,
2158 WXWORD
*code
, WXWORD
*pos
, WXHWND
*hwnd
)
2160 *code
= LOWORD(wParam
);
2161 *pos
= HIWORD(wParam
);
2162 *hwnd
= (WXHWND
)lParam
;
2165 void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam
, WXLPARAM lParam
,
2166 WXHDC
*hdc
, WXHWND
*hwnd
)
2168 *hwnd
= (WXHWND
)lParam
;
2169 *hdc
= (WXHDC
)wParam
;
2172 void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam
, WXLPARAM lParam
,
2173 WXWORD
*item
, WXWORD
*flags
, WXHMENU
*hmenu
)
2175 *item
= (WXWORD
)wParam
;
2176 *flags
= HIWORD(wParam
);
2177 *hmenu
= (WXHMENU
)lParam
;
2180 // ---------------------------------------------------------------------------
2181 // Main wxWidgets window proc and the window proc for wxWindow
2182 // ---------------------------------------------------------------------------
2184 // Hook for new window just as it's being created, when the window isn't yet
2185 // associated with the handle
2186 static wxWindowMSW
*gs_winBeingCreated
= NULL
;
2188 // implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2189 // window being created and insures that it's always unset back later
2190 wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW
*winBeingCreated
)
2192 gs_winBeingCreated
= winBeingCreated
;
2195 wxWindowCreationHook::~wxWindowCreationHook()
2197 gs_winBeingCreated
= NULL
;
2201 LRESULT WXDLLEXPORT APIENTRY _EXPORT
wxWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2203 // trace all messages - useful for the debugging
2205 wxLogTrace(wxTraceMessages
,
2206 wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
2207 wxGetMessageName(message
), (long)hWnd
, (long)wParam
, lParam
);
2208 #endif // __WXDEBUG__
2210 wxWindowMSW
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
2212 // when we get the first message for the HWND we just created, we associate
2213 // it with wxWindow stored in gs_winBeingCreated
2214 if ( !wnd
&& gs_winBeingCreated
)
2216 wxAssociateWinWithHandle(hWnd
, gs_winBeingCreated
);
2217 wnd
= gs_winBeingCreated
;
2218 gs_winBeingCreated
= NULL
;
2219 wnd
->SetHWND((WXHWND
)hWnd
);
2225 rc
= wnd
->MSWWindowProc(message
, wParam
, lParam
);
2227 rc
= ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
2232 WXLRESULT
wxWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
2234 // did we process the message?
2235 bool processed
= false;
2245 // for most messages we should return 0 when we do process the message
2253 processed
= HandleCreate((WXLPCREATESTRUCT
)lParam
, &mayCreate
);
2256 // return 0 to allow window creation
2257 rc
.result
= mayCreate
? 0 : -1;
2263 // never set processed to true and *always* pass WM_DESTROY to
2264 // DefWindowProc() as Windows may do some internal cleanup when
2265 // processing it and failing to pass the message along may cause
2266 // memory and resource leaks!
2267 (void)HandleDestroy();
2271 processed
= HandleSize(LOWORD(lParam
), HIWORD(lParam
), wParam
);
2275 processed
= HandleMove(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2278 #if !defined(__WXWINCE__)
2281 LPRECT pRect
= (LPRECT
)lParam
;
2283 rc
.SetLeft(pRect
->left
);
2284 rc
.SetTop(pRect
->top
);
2285 rc
.SetRight(pRect
->right
);
2286 rc
.SetBottom(pRect
->bottom
);
2287 processed
= HandleMoving(rc
);
2289 pRect
->left
= rc
.GetLeft();
2290 pRect
->top
= rc
.GetTop();
2291 pRect
->right
= rc
.GetRight();
2292 pRect
->bottom
= rc
.GetBottom();
2299 LPRECT pRect
= (LPRECT
)lParam
;
2301 rc
.SetLeft(pRect
->left
);
2302 rc
.SetTop(pRect
->top
);
2303 rc
.SetRight(pRect
->right
);
2304 rc
.SetBottom(pRect
->bottom
);
2305 processed
= HandleSizing(rc
);
2307 pRect
->left
= rc
.GetLeft();
2308 pRect
->top
= rc
.GetTop();
2309 pRect
->right
= rc
.GetRight();
2310 pRect
->bottom
= rc
.GetBottom();
2314 #endif // !__WXWINCE__
2316 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2317 case WM_ACTIVATEAPP
:
2318 // This implicitly sends a wxEVT_ACTIVATE_APP event
2319 wxTheApp
->SetActive(wParam
!= 0, FindFocus());
2325 WXWORD state
, minimized
;
2327 UnpackActivate(wParam
, lParam
, &state
, &minimized
, &hwnd
);
2329 processed
= HandleActivate(state
, minimized
!= 0, (WXHWND
)hwnd
);
2334 processed
= HandleSetFocus((WXHWND
)(HWND
)wParam
);
2338 processed
= HandleKillFocus((WXHWND
)(HWND
)wParam
);
2341 case WM_PRINTCLIENT
:
2342 processed
= HandlePrintClient((WXHDC
)wParam
);
2348 wxPaintDCEx
dc((wxWindow
*)this, (WXHDC
)wParam
);
2350 processed
= HandlePaint();
2354 processed
= HandlePaint();
2359 #ifdef __WXUNIVERSAL__
2360 // Universal uses its own wxFrame/wxDialog, so we don't receive
2361 // close events unless we have this.
2363 #endif // __WXUNIVERSAL__
2365 // don't let the DefWindowProc() destroy our window - we'll do it
2366 // ourselves in ~wxWindow
2372 processed
= HandleShow(wParam
!= 0, (int)lParam
);
2376 processed
= HandleMouseMove(GET_X_LPARAM(lParam
),
2377 GET_Y_LPARAM(lParam
),
2381 #ifdef HAVE_TRACKMOUSEEVENT
2383 // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least)
2384 if ( m_mouseInWindow
)
2386 GenerateMouseLeave();
2389 // always pass processed back as false, this allows the window
2390 // manager to process the message too. This is needed to
2391 // ensure windows XP themes work properly as the mouse moves
2392 // over widgets like buttons. So don't set processed to true here.
2394 #endif // HAVE_TRACKMOUSEEVENT
2396 #if wxUSE_MOUSEWHEEL
2398 processed
= HandleMouseWheel(wParam
, lParam
);
2402 case WM_LBUTTONDOWN
:
2404 case WM_LBUTTONDBLCLK
:
2405 case WM_RBUTTONDOWN
:
2407 case WM_RBUTTONDBLCLK
:
2408 case WM_MBUTTONDOWN
:
2410 case WM_MBUTTONDBLCLK
:
2412 #ifdef __WXMICROWIN__
2413 // MicroWindows seems to ignore the fact that a window is
2414 // disabled. So catch mouse events and throw them away if
2416 wxWindowMSW
* win
= this;
2419 if (!win
->IsEnabled())
2425 win
= win
->GetParent();
2426 if ( !win
|| win
->IsTopLevel() )
2433 #endif // __WXMICROWIN__
2434 int x
= GET_X_LPARAM(lParam
),
2435 y
= GET_Y_LPARAM(lParam
);
2437 // redirect the event to a static control if necessary by
2438 // finding one under mouse
2440 if ( GetCapture() == this )
2442 // but don't do it if the mouse is captured by this window
2443 // because then it should really get this event itself
2448 win
= FindWindowForMouseEvent(this, &x
, &y
);
2450 // this should never happen
2451 wxCHECK_MSG( win
, 0,
2452 _T("FindWindowForMouseEvent() returned NULL") );
2455 processed
= win
->HandleMouseEvent(message
, x
, y
, wParam
);
2457 // if the app didn't eat the event, handle it in the default
2458 // way, that is by giving this window the focus
2461 // for the standard classes their WndProc sets the focus to
2462 // them anyhow and doing it from here results in some weird
2463 // problems, so don't do it for them (unnecessary anyhow)
2464 if ( !win
->IsOfStandardClass() )
2466 if ( message
== WM_LBUTTONDOWN
&& win
->AcceptsFocus() )
2478 case MM_JOY1BUTTONDOWN
:
2479 case MM_JOY2BUTTONDOWN
:
2480 case MM_JOY1BUTTONUP
:
2481 case MM_JOY2BUTTONUP
:
2482 processed
= HandleJoystickEvent(message
,
2483 GET_X_LPARAM(lParam
),
2484 GET_Y_LPARAM(lParam
),
2487 #endif // __WXMICROWIN__
2493 UnpackCommand(wParam
, lParam
, &id
, &hwnd
, &cmd
);
2495 processed
= HandleCommand(id
, cmd
, hwnd
);
2500 processed
= HandleNotify((int)wParam
, lParam
, &rc
.result
);
2503 // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU,
2504 // otherwise DefWindowProc() does it perfectly fine for us, but MSLU
2505 // apparently doesn't always behave properly and needs some help
2506 #if wxUSE_UNICODE_MSLU && defined(NF_QUERY)
2507 case WM_NOTIFYFORMAT
:
2508 if ( lParam
== NF_QUERY
)
2511 rc
.result
= NFR_UNICODE
;
2514 #endif // wxUSE_UNICODE_MSLU
2516 // for these messages we must return true if process the message
2519 case WM_MEASUREITEM
:
2521 int idCtrl
= (UINT
)wParam
;
2522 if ( message
== WM_DRAWITEM
)
2524 processed
= MSWOnDrawItem(idCtrl
,
2525 (WXDRAWITEMSTRUCT
*)lParam
);
2529 processed
= MSWOnMeasureItem(idCtrl
,
2530 (WXMEASUREITEMSTRUCT
*)lParam
);
2537 #endif // defined(WM_DRAWITEM)
2540 if ( !IsOfStandardClass() )
2542 // we always want to get the char events
2543 rc
.result
= DLGC_WANTCHARS
;
2545 if ( GetWindowStyleFlag() & wxWANTS_CHARS
)
2547 // in fact, we want everything
2548 rc
.result
|= DLGC_WANTARROWS
|
2555 //else: get the dlg code from the DefWindowProc()
2560 // If this has been processed by an event handler, return 0 now
2561 // (we've handled it).
2562 m_lastKeydownProcessed
= HandleKeyDown((WORD
) wParam
, lParam
);
2563 if ( m_lastKeydownProcessed
)
2572 // we consider these message "not interesting" to OnChar, so
2573 // just don't do anything more with them
2583 // avoid duplicate messages to OnChar for these ASCII keys:
2584 // they will be translated by TranslateMessage() and received
2606 // but set processed to false, not true to still pass them
2607 // to the control's default window proc - otherwise
2608 // built-in keyboard handling won't work
2613 // special case of VK_APPS: treat it the same as right mouse
2614 // click because both usually pop up a context menu
2616 processed
= HandleMouseEvent(WM_RBUTTONDOWN
, -1, -1, 0);
2621 // do generate a CHAR event
2622 processed
= HandleChar((WORD
)wParam
, lParam
);
2625 if (message
== WM_SYSKEYDOWN
) // Let Windows still handle the SYSKEYs
2632 // special case of VK_APPS: treat it the same as right mouse button
2633 if ( wParam
== VK_APPS
)
2635 processed
= HandleMouseEvent(WM_RBUTTONUP
, -1, -1, 0);
2640 processed
= HandleKeyUp((WORD
) wParam
, lParam
);
2645 case WM_CHAR
: // Always an ASCII character
2646 if ( m_lastKeydownProcessed
)
2648 // The key was handled in the EVT_KEY_DOWN and handling
2649 // a key in an EVT_KEY_DOWN handler is meant, by
2650 // design, to prevent EVT_CHARs from happening
2651 m_lastKeydownProcessed
= false;
2656 processed
= HandleChar((WORD
)wParam
, lParam
, true);
2662 processed
= HandleHotKey((WORD
)wParam
, lParam
);
2664 #endif // wxUSE_HOTKEY
2671 UnpackScroll(wParam
, lParam
, &code
, &pos
, &hwnd
);
2673 processed
= MSWOnScroll(message
== WM_HSCROLL
? wxHORIZONTAL
2679 // CTLCOLOR messages are sent by children to query the parent for their
2681 #ifndef __WXMICROWIN__
2682 case WM_CTLCOLORMSGBOX
:
2683 case WM_CTLCOLOREDIT
:
2684 case WM_CTLCOLORLISTBOX
:
2685 case WM_CTLCOLORBTN
:
2686 case WM_CTLCOLORDLG
:
2687 case WM_CTLCOLORSCROLLBAR
:
2688 case WM_CTLCOLORSTATIC
:
2692 UnpackCtlColor(wParam
, lParam
, &hdc
, &hwnd
);
2694 processed
= HandleCtlColor(&rc
.hBrush
, (WXHDC
)hdc
, (WXHWND
)hwnd
);
2697 #endif // !__WXMICROWIN__
2699 case WM_SYSCOLORCHANGE
:
2700 // the return value for this message is ignored
2701 processed
= HandleSysColorChange();
2704 #if !defined(__WXWINCE__)
2705 case WM_DISPLAYCHANGE
:
2706 processed
= HandleDisplayChange();
2710 case WM_PALETTECHANGED
:
2711 processed
= HandlePaletteChanged((WXHWND
) (HWND
) wParam
);
2714 case WM_CAPTURECHANGED
:
2715 processed
= HandleCaptureChanged((WXHWND
) (HWND
) lParam
);
2718 case WM_QUERYNEWPALETTE
:
2719 processed
= HandleQueryNewPalette();
2723 processed
= HandleEraseBkgnd((WXHDC
)(HDC
)wParam
);
2726 // we processed the message, i.e. erased the background
2731 #if !defined(__WXWINCE__)
2733 processed
= HandleDropFiles(wParam
);
2738 processed
= HandleInitDialog((WXHWND
)(HWND
)wParam
);
2742 // we never set focus from here
2747 #if !defined(__WXWINCE__)
2748 case WM_QUERYENDSESSION
:
2749 processed
= HandleQueryEndSession(lParam
, &rc
.allow
);
2753 processed
= HandleEndSession(wParam
!= 0, lParam
);
2756 case WM_GETMINMAXINFO
:
2757 processed
= HandleGetMinMaxInfo((MINMAXINFO
*)lParam
);
2762 processed
= HandleSetCursor((WXHWND
)(HWND
)wParam
,
2763 LOWORD(lParam
), // hit test
2764 HIWORD(lParam
)); // mouse msg
2768 // returning TRUE stops the DefWindowProc() from further
2769 // processing this message - exactly what we need because we've
2770 // just set the cursor.
2775 #if wxUSE_ACCESSIBILITY
2778 //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
2779 LPARAM dwObjId
= (LPARAM
) (DWORD
) lParam
;
2781 if (dwObjId
== (LPARAM
)OBJID_CLIENT
&& GetOrCreateAccessible())
2783 return LresultFromObject(IID_IAccessible
, wParam
, (IUnknown
*) GetAccessible()->GetIAccessible());
2789 #if defined(WM_HELP)
2792 // HELPINFO doesn't seem to be supported on WinCE.
2794 HELPINFO
* info
= (HELPINFO
*) lParam
;
2795 // Don't yet process menu help events, just windows
2796 if (info
->iContextType
== HELPINFO_WINDOW
)
2799 wxWindowMSW
* subjectOfHelp
= this;
2800 bool eventProcessed
= false;
2801 while (subjectOfHelp
&& !eventProcessed
)
2803 wxHelpEvent
helpEvent(wxEVT_HELP
,
2804 subjectOfHelp
->GetId(),
2808 wxPoint(info
->MousePos
.x
, info
->MousePos
.y
)
2812 helpEvent
.SetEventObject(this);
2814 GetEventHandler()->ProcessEvent(helpEvent
);
2816 // Go up the window hierarchy until the event is
2818 subjectOfHelp
= subjectOfHelp
->GetParent();
2821 processed
= eventProcessed
;
2824 else if (info
->iContextType
== HELPINFO_MENUITEM
)
2826 wxHelpEvent
helpEvent(wxEVT_HELP
, info
->iCtrlId
);
2827 helpEvent
.SetEventObject(this);
2828 processed
= GetEventHandler()->ProcessEvent(helpEvent
);
2831 //else: processed is already false
2837 #if !defined(__WXWINCE__)
2838 case WM_CONTEXTMENU
:
2840 // we don't convert from screen to client coordinates as
2841 // the event may be handled by a parent window
2842 wxPoint
pt(GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
2844 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
, GetId(), pt
);
2846 // we could have got an event from our child, reflect it back
2847 // to it if this is the case
2848 wxWindowMSW
*win
= NULL
;
2849 if ( (WXHWND
)wParam
!= m_hWnd
)
2851 win
= FindItemByHWND((WXHWND
)wParam
);
2857 evtCtx
.SetEventObject(win
);
2858 processed
= win
->GetEventHandler()->ProcessEvent(evtCtx
);
2864 // we're only interested in our own menus, not MF_SYSMENU
2865 if ( HIWORD(wParam
) == MF_POPUP
)
2867 // handle menu chars for ownerdrawn menu items
2868 int i
= HandleMenuChar(toupper(LOWORD(wParam
)), lParam
);
2869 if ( i
!= wxNOT_FOUND
)
2871 rc
.result
= MAKELRESULT(i
, MNC_EXECUTE
);
2881 wxLogTrace(wxTraceMessages
, wxT("Forwarding %s to DefWindowProc."),
2882 wxGetMessageName(message
));
2883 #endif // __WXDEBUG__
2884 rc
.result
= MSWDefWindowProc(message
, wParam
, lParam
);
2890 // ----------------------------------------------------------------------------
2891 // wxWindow <-> HWND map
2892 // ----------------------------------------------------------------------------
2894 wxWinHashTable
*wxWinHandleHash
= NULL
;
2896 wxWindow
*wxFindWinFromHandle(WXHWND hWnd
)
2898 return (wxWindow
*)wxWinHandleHash
->Get((long)hWnd
);
2901 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW
*win
)
2903 // adding NULL hWnd is (first) surely a result of an error and
2904 // (secondly) breaks menu command processing
2905 wxCHECK_RET( hWnd
!= (HWND
)NULL
,
2906 wxT("attempt to add a NULL hWnd to window list ignored") );
2908 wxWindow
*oldWin
= wxFindWinFromHandle((WXHWND
) hWnd
);
2910 if ( oldWin
&& (oldWin
!= win
) )
2912 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
2913 (int) hWnd
, win
->GetClassInfo()->GetClassName());
2916 #endif // __WXDEBUG__
2919 wxWinHandleHash
->Put((long)hWnd
, (wxWindow
*)win
);
2923 void wxRemoveHandleAssociation(wxWindowMSW
*win
)
2925 wxWinHandleHash
->Delete((long)win
->GetHWND());
2928 // ----------------------------------------------------------------------------
2929 // various MSW speciic class dependent functions
2930 // ----------------------------------------------------------------------------
2932 // Default destroyer - override if you destroy it in some other way
2933 // (e.g. with MDI child windows)
2934 void wxWindowMSW::MSWDestroyWindow()
2938 bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint
& pos
,
2941 int& w
, int& h
) const
2943 // yes, those are just some arbitrary hardcoded numbers
2944 static const int DEFAULT_Y
= 200;
2946 bool nonDefault
= false;
2948 if ( pos
.x
== wxDefaultCoord
)
2950 // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we
2951 // can just as well set it to CW_USEDEFAULT as well
2957 // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it
2958 // neither because it is not handled as a special value by Windows then
2959 // and so we have to choose some default value for it
2961 y
= pos
.y
== wxDefaultCoord
? DEFAULT_Y
: pos
.y
;
2967 NB: there used to be some code here which set the initial size of the
2968 window to the client size of the parent if no explicit size was
2969 specified. This was wrong because wxWidgets programs often assume
2970 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2971 it. To see why, you should understand that Windows sends WM_SIZE from
2972 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2973 from some base class ctor and so this WM_SIZE is not processed in the
2974 real class' OnSize() (because it's not fully constructed yet and the
2975 event goes to some base class OnSize() instead). So the WM_SIZE we
2976 rely on is the one sent when the parent frame resizes its children
2977 but here is the problem: if the child already has just the right
2978 size, nothing will happen as both wxWidgets and Windows check for
2979 this and ignore any attempts to change the window size to the size it
2980 already has - so no WM_SIZE would be sent.
2984 // we don't use CW_USEDEFAULT here for several reasons:
2986 // 1. it results in huge frames on modern screens (1000*800 is not
2987 // uncommon on my 1280*1024 screen) which is way too big for a half
2988 // empty frame of most of wxWidgets samples for example)
2990 // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which
2991 // the default is for whatever reason 8*8 which breaks client <->
2992 // window size calculations (it would be nice if it didn't, but it
2993 // does and the simplest way to fix it seemed to change the broken
2994 // default size anyhow)
2996 // 3. there is just no advantage in doing it: with x and y it is
2997 // possible that [future versions of] Windows position the new top
2998 // level window in some smart way which we can't do, but we can
2999 // guess a reasonably good size for a new window just as well
3002 // However, on PocketPC devices, we must use the default
3003 // size if possible.
3005 if (size
.x
== wxDefaultCoord
)
3009 if (size
.y
== wxDefaultCoord
)
3014 if ( size
.x
== wxDefaultCoord
|| size
.y
== wxDefaultCoord
)
3018 w
= WidthDefault(size
.x
);
3019 h
= HeightDefault(size
.y
);
3022 AdjustForParentClientOrigin(x
, y
);
3027 WXHWND
wxWindowMSW::MSWGetParent() const
3029 return m_parent
? m_parent
->GetHWND() : WXHWND(NULL
);
3032 bool wxWindowMSW::MSWCreate(const wxChar
*wclass
,
3033 const wxChar
*title
,
3037 WXDWORD extendedStyle
)
3039 // choose the position/size for the new window
3041 (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
);
3043 // controlId is menu handle for the top level windows, so set it to 0
3044 // unless we're creating a child window
3045 int controlId
= style
& WS_CHILD
? GetId() : 0;
3047 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
3048 // which is the same but without CS_[HV]REDRAW class styles so using it
3049 // ensures that the window is not fully repainted on each resize
3050 wxString
className(wclass
);
3051 if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE
) )
3053 className
+= wxT("NR");
3056 // do create the window
3057 wxWindowCreationHook
hook(this);
3059 m_hWnd
= (WXHWND
)::CreateWindowEx
3063 title
? title
: m_windowName
.c_str(),
3066 (HWND
)MSWGetParent(),
3069 NULL
// no extra data
3074 wxLogSysError(_("Can't create window of class %s"), className
.c_str());
3079 SubclassWin(m_hWnd
);
3084 // ===========================================================================
3085 // MSW message handlers
3086 // ===========================================================================
3088 // ---------------------------------------------------------------------------
3090 // ---------------------------------------------------------------------------
3094 bool wxWindowMSW::HandleNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
3096 #ifndef __WXMICROWIN__
3097 LPNMHDR hdr
= (LPNMHDR
)lParam
;
3098 HWND hWnd
= hdr
->hwndFrom
;
3099 wxWindow
*win
= wxFindWinFromHandle((WXHWND
)hWnd
);
3101 // if the control is one of our windows, let it handle the message itself
3104 return win
->MSWOnNotify(idCtrl
, lParam
, result
);
3107 // VZ: why did we do it? normally this is unnecessary and, besides, it
3108 // breaks the message processing for the toolbars because the tooltip
3109 // notifications were being forwarded to the toolbar child controls
3110 // (if it had any) before being passed to the toolbar itself, so in my
3111 // example the tooltip for the combobox was always shown instead of the
3112 // correct button tooltips
3114 // try all our children
3115 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3118 wxWindow
*child
= node
->GetData();
3119 if ( child
->MSWOnNotify(idCtrl
, lParam
, result
) )
3124 node
= node
->GetNext();
3128 // by default, handle it ourselves
3129 return MSWOnNotify(idCtrl
, lParam
, result
);
3130 #else // __WXMICROWIN__
3137 bool wxWindowMSW::HandleTooltipNotify(WXUINT code
,
3139 const wxString
& ttip
)
3141 // I don't know why it happens, but the versions of comctl32.dll starting
3142 // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally,
3143 // this message is supposed to be sent to Unicode programs only) -- hence
3144 // we need to handle it as well, otherwise no tooltips will be shown in
3147 if ( !(code
== (WXUINT
) TTN_NEEDTEXTA
|| code
== (WXUINT
) TTN_NEEDTEXTW
)
3150 // not a tooltip message or no tooltip to show anyhow
3155 LPTOOLTIPTEXT ttText
= (LPTOOLTIPTEXT
)lParam
;
3157 // We don't want to use the szText buffer because it has a limit of 80
3158 // bytes and this is not enough, especially for Unicode build where it
3159 // limits the tooltip string length to only 40 characters
3161 // The best would be, of course, to not impose any length limitations at
3162 // all but then the buffer would have to be dynamic and someone would have
3163 // to free it and we don't have the tooltip owner object here any more, so
3164 // for now use our own static buffer with a higher fixed max length.
3166 // Note that using a static buffer should not be a problem as only a single
3167 // tooltip can be shown at the same time anyhow.
3169 if ( code
== (WXUINT
) TTN_NEEDTEXTW
)
3171 // We need to convert tooltip from multi byte to Unicode on the fly.
3172 static wchar_t buf
[513];
3174 // Truncate tooltip length if needed as otherwise we might not have
3175 // enough space for it in the buffer and MultiByteToWideChar() would
3177 size_t tipLength
= wxMin(ttip
.Len(), WXSIZEOF(buf
) - 1);
3179 // Convert to WideChar without adding the NULL character. The NULL
3180 // character is added afterwards (this is more efficient).
3181 int len
= ::MultiByteToWideChar
3193 wxLogLastError(_T("MultiByteToWideChar()"));
3197 ttText
->lpszText
= (LPSTR
) buf
;
3199 else // TTN_NEEDTEXTA
3200 #endif // !wxUSE_UNICODE
3202 // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or
3203 // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
3204 // to copy the string we have into the buffer
3205 static wxChar buf
[513];
3206 wxStrncpy(buf
, ttip
.c_str(), WXSIZEOF(buf
) - 1);
3207 buf
[WXSIZEOF(buf
) - 1] = _T('\0');
3208 ttText
->lpszText
= buf
;
3214 #endif // wxUSE_TOOLTIPS
3216 bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl
),
3218 WXLPARAM
* WXUNUSED(result
))
3223 NMHDR
* hdr
= (NMHDR
*)lParam
;
3224 if ( HandleTooltipNotify(hdr
->code
, lParam
, m_tooltip
->GetTip()))
3231 wxUnusedVar(lParam
);
3232 #endif // wxUSE_TOOLTIPS
3239 // ---------------------------------------------------------------------------
3240 // end session messages
3241 // ---------------------------------------------------------------------------
3243 bool wxWindowMSW::HandleQueryEndSession(long logOff
, bool *mayEnd
)
3245 #ifdef ENDSESSION_LOGOFF
3246 wxCloseEvent
event(wxEVT_QUERY_END_SESSION
, wxID_ANY
);
3247 event
.SetEventObject(wxTheApp
);
3248 event
.SetCanVeto(true);
3249 event
.SetLoggingOff(logOff
== (long)ENDSESSION_LOGOFF
);
3251 bool rc
= wxTheApp
->ProcessEvent(event
);
3255 // we may end only if the app didn't veto session closing (double
3257 *mayEnd
= !event
.GetVeto();
3262 wxUnusedVar(logOff
);
3263 wxUnusedVar(mayEnd
);
3268 bool wxWindowMSW::HandleEndSession(bool endSession
, long logOff
)
3270 #ifdef ENDSESSION_LOGOFF
3271 // do nothing if the session isn't ending
3276 if ( (this != wxTheApp
->GetTopWindow()) )
3279 wxCloseEvent
event(wxEVT_END_SESSION
, wxID_ANY
);
3280 event
.SetEventObject(wxTheApp
);
3281 event
.SetCanVeto(false);
3282 event
.SetLoggingOff( (logOff
== (long)ENDSESSION_LOGOFF
) );
3284 return wxTheApp
->ProcessEvent(event
);
3286 wxUnusedVar(endSession
);
3287 wxUnusedVar(logOff
);
3292 // ---------------------------------------------------------------------------
3293 // window creation/destruction
3294 // ---------------------------------------------------------------------------
3296 bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs
, bool *mayCreate
)
3298 // VZ: why is this commented out for WinCE? If it doesn't support
3299 // WS_EX_CONTROLPARENT at all it should be somehow handled globally,
3300 // not with multiple #ifdef's!
3302 if ( ((CREATESTRUCT
*)cs
)->dwExStyle
& WS_EX_CONTROLPARENT
)
3303 EnsureParentHasControlParentStyle(GetParent());
3306 #endif // !__WXWINCE__
3308 // TODO: should generate this event from WM_NCCREATE
3309 wxWindowCreateEvent
event((wxWindow
*)this);
3310 (void)GetEventHandler()->ProcessEvent(event
);
3317 bool wxWindowMSW::HandleDestroy()
3321 // delete our drop target if we've got one
3322 #if wxUSE_DRAG_AND_DROP
3323 if ( m_dropTarget
!= NULL
)
3325 m_dropTarget
->Revoke(m_hWnd
);
3327 delete m_dropTarget
;
3328 m_dropTarget
= NULL
;
3330 #endif // wxUSE_DRAG_AND_DROP
3332 // WM_DESTROY handled
3336 // ---------------------------------------------------------------------------
3338 // ---------------------------------------------------------------------------
3340 bool wxWindowMSW::HandleActivate(int state
,
3341 bool WXUNUSED(minimized
),
3342 WXHWND
WXUNUSED(activate
))
3344 wxActivateEvent
event(wxEVT_ACTIVATE
,
3345 (state
== WA_ACTIVE
) || (state
== WA_CLICKACTIVE
),
3347 event
.SetEventObject(this);
3349 return GetEventHandler()->ProcessEvent(event
);
3352 bool wxWindowMSW::HandleSetFocus(WXHWND hwnd
)
3354 // Strangly enough, some controls get set focus events when they are being
3355 // deleted, even if they already had focus before.
3356 if ( m_isBeingDeleted
)
3361 // notify the parent keeping track of focus for the kbd navigation
3362 // purposes that we got it
3363 wxChildFocusEvent
eventFocus((wxWindow
*)this);
3364 (void)GetEventHandler()->ProcessEvent(eventFocus
);
3370 m_caret
->OnSetFocus();
3372 #endif // wxUSE_CARET
3375 // If it's a wxTextCtrl don't send the event as it will be done
3376 // after the control gets to process it from EN_FOCUS handler
3377 if ( wxDynamicCastThis(wxTextCtrl
) )
3381 #endif // wxUSE_TEXTCTRL
3383 wxFocusEvent
event(wxEVT_SET_FOCUS
, m_windowId
);
3384 event
.SetEventObject(this);
3386 // wxFindWinFromHandle() may return NULL, it is ok
3387 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3389 return GetEventHandler()->ProcessEvent(event
);
3392 bool wxWindowMSW::HandleKillFocus(WXHWND hwnd
)
3398 m_caret
->OnKillFocus();
3400 #endif // wxUSE_CARET
3403 // If it's a wxTextCtrl don't send the event as it will be done
3404 // after the control gets to process it.
3405 wxTextCtrl
*ctrl
= wxDynamicCastThis(wxTextCtrl
);
3412 // Don't send the event when in the process of being deleted. This can
3413 // only cause problems if the event handler tries to access the object.
3414 if ( m_isBeingDeleted
)
3419 wxFocusEvent
event(wxEVT_KILL_FOCUS
, m_windowId
);
3420 event
.SetEventObject(this);
3422 // wxFindWinFromHandle() may return NULL, it is ok
3423 event
.SetWindow(wxFindWinFromHandle(hwnd
));
3425 return GetEventHandler()->ProcessEvent(event
);
3428 // ---------------------------------------------------------------------------
3430 // ---------------------------------------------------------------------------
3432 bool wxWindowMSW::HandleShow(bool show
, int WXUNUSED(status
))
3434 wxShowEvent
event(GetId(), show
);
3435 event
.SetEventObject(this);
3437 return GetEventHandler()->ProcessEvent(event
);
3440 bool wxWindowMSW::HandleInitDialog(WXHWND
WXUNUSED(hWndFocus
))
3442 wxInitDialogEvent
event(GetId());
3443 event
.SetEventObject(this);
3445 return GetEventHandler()->ProcessEvent(event
);
3448 bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam
)
3450 #if defined (__WXMICROWIN__) || defined(__WXWINCE__)
3451 wxUnusedVar(wParam
);
3453 #else // __WXMICROWIN__
3454 HDROP hFilesInfo
= (HDROP
) wParam
;
3456 // Get the total number of files dropped
3457 UINT gwFilesDropped
= ::DragQueryFile
3465 wxString
*files
= new wxString
[gwFilesDropped
];
3466 for ( UINT wIndex
= 0; wIndex
< gwFilesDropped
; wIndex
++ )
3468 // first get the needed buffer length (+1 for terminating NUL)
3469 size_t len
= ::DragQueryFile(hFilesInfo
, wIndex
, NULL
, 0) + 1;
3471 // and now get the file name
3472 ::DragQueryFile(hFilesInfo
, wIndex
,
3473 wxStringBuffer(files
[wIndex
], len
), len
);
3475 DragFinish (hFilesInfo
);
3477 wxDropFilesEvent
event(wxEVT_DROP_FILES
, gwFilesDropped
, files
);
3478 event
.SetEventObject(this);
3481 DragQueryPoint(hFilesInfo
, (LPPOINT
) &dropPoint
);
3482 event
.m_pos
.x
= dropPoint
.x
;
3483 event
.m_pos
.y
= dropPoint
.y
;
3485 return GetEventHandler()->ProcessEvent(event
);
3490 bool wxWindowMSW::HandleSetCursor(WXHWND
WXUNUSED(hWnd
),
3492 int WXUNUSED(mouseMsg
))
3494 #ifndef __WXMICROWIN__
3495 // the logic is as follows:
3496 // -1. don't set cursor for non client area, including but not limited to
3497 // the title bar, scrollbars, &c
3498 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
3499 // 1. if we have the cursor set it unless wxIsBusy()
3500 // 2. if we're a top level window, set some cursor anyhow
3501 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
3503 if ( nHitTest
!= HTCLIENT
)
3508 HCURSOR hcursor
= 0;
3510 // first ask the user code - it may wish to set the cursor in some very
3511 // specific way (for example, depending on the current position)
3514 if ( !::GetCursorPosWinCE(&pt
) )
3516 if ( !::GetCursorPos(&pt
) )
3519 wxLogLastError(wxT("GetCursorPos"));
3524 ScreenToClient(&x
, &y
);
3525 wxSetCursorEvent
event(x
, y
);
3527 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
3528 if ( processedEvtSetCursor
&& event
.HasCursor() )
3530 hcursor
= GetHcursorOf(event
.GetCursor());
3535 bool isBusy
= wxIsBusy();
3537 // the test for processedEvtSetCursor is here to prevent using m_cursor
3538 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3539 // it - this is a way to say that our cursor shouldn't be used for this
3541 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
3543 hcursor
= GetHcursorOf(m_cursor
);
3550 hcursor
= wxGetCurrentBusyCursor();
3552 else if ( !hcursor
)
3554 const wxCursor
*cursor
= wxGetGlobalCursor();
3555 if ( cursor
&& cursor
->Ok() )
3557 hcursor
= GetHcursorOf(*cursor
);
3565 // wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor);
3567 ::SetCursor(hcursor
);
3569 // cursor set, stop here
3572 #endif // __WXMICROWIN__
3574 // pass up the window chain
3578 // ---------------------------------------------------------------------------
3579 // owner drawn stuff
3580 // ---------------------------------------------------------------------------
3582 #if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \
3583 (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__))
3584 #define WXUNUSED_UNLESS_ODRAWN(param) param
3586 #define WXUNUSED_UNLESS_ODRAWN(param)
3590 wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id
),
3591 WXDRAWITEMSTRUCT
* WXUNUSED_UNLESS_ODRAWN(itemStruct
))
3593 #if wxUSE_OWNER_DRAWN
3595 #if wxUSE_MENUS_NATIVE
3596 // is it a menu item?
3597 DRAWITEMSTRUCT
*pDrawStruct
= (DRAWITEMSTRUCT
*)itemStruct
;
3598 if ( id
== 0 && pDrawStruct
->CtlType
== ODT_MENU
)
3600 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pDrawStruct
->itemData
);
3602 wxCHECK_MSG( pMenuItem
&& pMenuItem
->IsKindOf(CLASSINFO(wxMenuItem
)),
3603 false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
3605 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3606 // the DC from being released
3607 wxDCTemp
dc((WXHDC
)pDrawStruct
->hDC
);
3608 wxRect
rect(pDrawStruct
->rcItem
.left
, pDrawStruct
->rcItem
.top
,
3609 pDrawStruct
->rcItem
.right
- pDrawStruct
->rcItem
.left
,
3610 pDrawStruct
->rcItem
.bottom
- pDrawStruct
->rcItem
.top
);
3612 return pMenuItem
->OnDrawItem
3616 (wxOwnerDrawn::wxODAction
)pDrawStruct
->itemAction
,
3617 (wxOwnerDrawn::wxODStatus
)pDrawStruct
->itemState
3620 #endif // wxUSE_MENUS_NATIVE
3622 #endif // USE_OWNER_DRAWN
3624 #if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)
3626 #if wxUSE_OWNER_DRAWN
3627 wxControl
*item
= wxDynamicCast(FindItem(id
), wxControl
);
3628 #else // !wxUSE_OWNER_DRAWN
3629 // we may still have owner-drawn buttons internally because we have to make
3630 // them owner-drawn to support colour change
3633 wxDynamicCast(FindItem(id
), wxButton
)
3638 #endif // USE_OWNER_DRAWN
3642 return item
->MSWOnDraw(itemStruct
);
3645 #endif // wxUSE_CONTROLS
3651 wxWindowMSW::MSWOnMeasureItem(int id
, WXMEASUREITEMSTRUCT
*itemStruct
)
3653 #if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
3654 // is it a menu item?
3655 MEASUREITEMSTRUCT
*pMeasureStruct
= (MEASUREITEMSTRUCT
*)itemStruct
;
3656 if ( id
== 0 && pMeasureStruct
->CtlType
== ODT_MENU
)
3658 wxMenuItem
*pMenuItem
= (wxMenuItem
*)(pMeasureStruct
->itemData
);
3660 // according to Carsten Fuchs the pointer may be NULL under XP if an
3661 // MDI child frame is initially maximized, see this for more info:
3662 // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745
3664 // so silently ignore it instead of asserting
3668 wxCHECK_MSG( wxDynamicCast(pMenuItem
, wxMenuItem
),
3669 false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
3672 bool rc
= pMenuItem
->OnMeasureItem(&w
, &h
);
3674 pMeasureStruct
->itemWidth
= w
;
3675 pMeasureStruct
->itemHeight
= h
;
3680 wxControl
*item
= wxDynamicCast(FindItem(id
), wxControl
);
3683 return item
->MSWOnMeasure(itemStruct
);
3687 wxUnusedVar(itemStruct
);
3688 #endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
3693 // ---------------------------------------------------------------------------
3694 // colours and palettes
3695 // ---------------------------------------------------------------------------
3697 bool wxWindowMSW::HandleSysColorChange()
3699 wxSysColourChangedEvent event
;
3700 event
.SetEventObject(this);
3702 (void)GetEventHandler()->ProcessEvent(event
);
3704 // always let the system carry on the default processing to allow the
3705 // native controls to react to the colours update
3709 bool wxWindowMSW::HandleDisplayChange()
3711 wxDisplayChangedEvent event
;
3712 event
.SetEventObject(this);
3714 return GetEventHandler()->ProcessEvent(event
);
3717 #ifndef __WXMICROWIN__
3719 bool wxWindowMSW::HandleCtlColor(WXHBRUSH
*brush
, WXHDC hDC
, WXHWND hWnd
)
3721 #if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
3725 wxControl
*item
= wxDynamicCast(FindItemByHWND(hWnd
, true), wxControl
);
3728 *brush
= item
->MSWControlColor(hDC
, hWnd
);
3730 #endif // wxUSE_CONTROLS
3733 return *brush
!= NULL
;
3736 #endif // __WXMICROWIN__
3738 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange
)
3741 // same as below except we don't respond to our own messages
3742 if ( hWndPalChange
!= GetHWND() )
3744 // check to see if we our our parents have a custom palette
3745 wxWindowMSW
*win
= this;
3746 while ( win
&& !win
->HasCustomPalette() )
3748 win
= win
->GetParent();
3751 if ( win
&& win
->HasCustomPalette() )
3753 // realize the palette to see whether redrawing is needed
3754 HDC hdc
= ::GetDC((HWND
) hWndPalChange
);
3755 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3756 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3758 int result
= ::RealizePalette(hdc
);
3760 // restore the palette (before releasing the DC)
3761 win
->m_palette
.SetHPALETTE((WXHPALETTE
)
3762 ::SelectPalette(hdc
, GetHpaletteOf(win
->m_palette
), FALSE
));
3763 ::RealizePalette(hdc
);
3764 ::ReleaseDC((HWND
) hWndPalChange
, hdc
);
3766 // now check for the need to redraw
3768 ::InvalidateRect((HWND
) hWndPalChange
, NULL
, TRUE
);
3772 #endif // wxUSE_PALETTE
3774 wxPaletteChangedEvent
event(GetId());
3775 event
.SetEventObject(this);
3776 event
.SetChangedWindow(wxFindWinFromHandle(hWndPalChange
));
3778 return GetEventHandler()->ProcessEvent(event
);
3781 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture
)
3783 wxMouseCaptureChangedEvent
event(GetId(), wxFindWinFromHandle(hWndGainedCapture
));
3784 event
.SetEventObject(this);
3786 return GetEventHandler()->ProcessEvent(event
);
3789 bool wxWindowMSW::HandleQueryNewPalette()
3793 // check to see if we our our parents have a custom palette
3794 wxWindowMSW
*win
= this;
3795 while (!win
->HasCustomPalette() && win
->GetParent()) win
= win
->GetParent();
3796 if (win
->HasCustomPalette()) {
3797 /* realize the palette to see whether redrawing is needed */
3798 HDC hdc
= ::GetDC((HWND
) GetHWND());
3799 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3800 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), FALSE
) );
3802 int result
= ::RealizePalette(hdc
);
3803 /* restore the palette (before releasing the DC) */
3804 win
->m_palette
.SetHPALETTE( (WXHPALETTE
)
3805 ::SelectPalette(hdc
, (HPALETTE
) win
->m_palette
.GetHPALETTE(), TRUE
) );
3806 ::RealizePalette(hdc
);
3807 ::ReleaseDC((HWND
) GetHWND(), hdc
);
3808 /* now check for the need to redraw */
3810 ::InvalidateRect((HWND
) GetHWND(), NULL
, TRUE
);
3812 #endif // wxUSE_PALETTE
3814 wxQueryNewPaletteEvent
event(GetId());
3815 event
.SetEventObject(this);
3817 return GetEventHandler()->ProcessEvent(event
) && event
.GetPaletteRealized();
3820 // Responds to colour changes: passes event on to children.
3821 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
))
3823 // the top level window also reset the standard colour map as it might have
3824 // changed (there is no need to do it for the non top level windows as we
3825 // only have to do it once)
3829 gs_hasStdCmap
= false;
3831 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3834 // Only propagate to non-top-level windows because Windows already
3835 // sends this event to all top-level ones
3836 wxWindow
*win
= node
->GetData();
3837 if ( !win
->IsTopLevel() )
3839 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3840 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3841 // the standard controls
3842 ::SendMessage(GetHwndOf(win
), WM_SYSCOLORCHANGE
, 0, 0);
3845 node
= node
->GetNext();
3849 extern wxCOLORMAP
*wxGetStdColourMap()
3851 static COLORREF s_stdColours
[wxSTD_COL_MAX
];
3852 static wxCOLORMAP s_cmap
[wxSTD_COL_MAX
];
3854 if ( !gs_hasStdCmap
)
3856 static bool s_coloursInit
= false;
3858 if ( !s_coloursInit
)
3860 // When a bitmap is loaded, the RGB values can change (apparently
3861 // because Windows adjusts them to care for the old programs always
3862 // using 0xc0c0c0 while the transparent colour for the new Windows
3863 // versions is different). But we do this adjustment ourselves so
3864 // we want to avoid Windows' "help" and for this we need to have a
3865 // reference bitmap which can tell us what the RGB values change
3867 wxBitmap
stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3868 if ( stdColourBitmap
.Ok() )
3870 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3871 wxASSERT_MSG( stdColourBitmap
.GetWidth() == wxSTD_COL_MAX
,
3872 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3875 memDC
.SelectObject(stdColourBitmap
);
3878 for ( size_t i
= 0; i
< WXSIZEOF(s_stdColours
); i
++ )
3880 memDC
.GetPixel(i
, 0, &colour
);
3881 s_stdColours
[i
] = wxColourToRGB(colour
);
3884 else // wxBITMAP_STD_COLOURS couldn't be loaded
3886 s_stdColours
[0] = RGB(000,000,000); // black
3887 s_stdColours
[1] = RGB(128,128,128); // dark grey
3888 s_stdColours
[2] = RGB(192,192,192); // light grey
3889 s_stdColours
[3] = RGB(255,255,255); // white
3890 //s_stdColours[4] = RGB(000,000,255); // blue
3891 //s_stdColours[5] = RGB(255,000,255); // magenta
3894 s_coloursInit
= true;
3897 gs_hasStdCmap
= true;
3899 // create the colour map
3900 #define INIT_CMAP_ENTRY(col) \
3901 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3902 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3904 INIT_CMAP_ENTRY(BTNTEXT
);
3905 INIT_CMAP_ENTRY(BTNSHADOW
);
3906 INIT_CMAP_ENTRY(BTNFACE
);
3907 INIT_CMAP_ENTRY(BTNHIGHLIGHT
);
3909 #undef INIT_CMAP_ENTRY
3915 // ---------------------------------------------------------------------------
3917 // ---------------------------------------------------------------------------
3919 bool wxWindowMSW::HandlePaint()
3921 HRGN hRegion
= ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3923 wxLogLastError(wxT("CreateRectRgn"));
3924 if ( ::GetUpdateRgn(GetHwnd(), hRegion
, FALSE
) == ERROR
)
3925 wxLogLastError(wxT("GetUpdateRgn"));
3927 m_updateRegion
= wxRegion((WXHRGN
) hRegion
);
3929 wxPaintEvent
event(m_windowId
);
3930 event
.SetEventObject(this);
3932 bool processed
= GetEventHandler()->ProcessEvent(event
);
3934 // note that we must generate NC event after the normal one as otherwise
3935 // BeginPaint() will happily overwrite our decorations with the background
3937 wxNcPaintEvent
eventNc(m_windowId
);
3938 eventNc
.SetEventObject(this);
3939 GetEventHandler()->ProcessEvent(eventNc
);
3944 // Can be called from an application's OnPaint handler
3945 void wxWindowMSW::OnPaint(wxPaintEvent
& event
)
3947 #ifdef __WXUNIVERSAL__
3950 HDC hDC
= (HDC
) wxPaintDC::FindDCInCache((wxWindow
*) event
.GetEventObject());
3953 MSWDefWindowProc(WM_PAINT
, (WPARAM
) hDC
, 0);
3958 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc
)
3963 dc
.SetWindow((wxWindow
*)this);
3966 wxEraseEvent
event(m_windowId
, &dc
);
3967 event
.SetEventObject(this);
3968 bool rc
= GetEventHandler()->ProcessEvent(event
);
3972 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
3973 dc
.SelectOldObjects(hdc
);
3978 void wxWindowMSW::OnEraseBackground(wxEraseEvent
& event
)
3980 // standard non top level controls (i.e. except the dialogs) always erase
3981 // their background themselves in HandleCtlColor() or have some control-
3982 // specific ways to set the colours (common controls)
3983 if ( IsOfStandardClass() && !IsTopLevel() )
3989 if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM
)
3991 // don't skip the event here, custom background means that the app
3992 // is drawing it itself in its OnPaint(), so don't draw it at all
3993 // now to avoid flicker
3998 // do default background painting
3999 if ( !DoEraseBackground(GetHdcOf(*event
.GetDC())) )
4001 // let the system paint the background
4006 bool wxWindowMSW::DoEraseBackground(WXHDC hDC
)
4008 HBRUSH hbr
= (HBRUSH
)MSWGetBgBrush(hDC
);
4012 wxFillRect(GetHwnd(), (HDC
)hDC
, hbr
);
4018 wxWindowMSW::MSWGetBgBrushForChild(WXHDC
WXUNUSED(hDC
), WXHWND hWnd
)
4022 // our background colour applies to:
4023 // 1. this window itself, always
4024 // 2. all children unless the colour is "not inheritable"
4025 // 3. even if it is not inheritable, our immediate transparent
4026 // children should still inherit it -- but not any transparent
4027 // children because it would look wrong if a child of non
4028 // transparent child would show our bg colour when the child itself
4030 wxWindow
*win
= wxFindWinFromHandle(hWnd
);
4033 (win
&& win
->HasTransparentBackground() &&
4034 win
->GetParent() == this) )
4036 // draw children with the same colour as the parent
4038 brush
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour());
4040 return (WXHBRUSH
)GetHbrushOf(*brush
);
4047 WXHBRUSH
wxWindowMSW::MSWGetBgBrush(WXHDC hDC
, WXHWND hWndToPaint
)
4050 hWndToPaint
= GetHWND();
4052 for ( wxWindowMSW
*win
= this; win
; win
= win
->GetParent() )
4054 WXHBRUSH hBrush
= win
->MSWGetBgBrushForChild(hDC
, hWndToPaint
);
4058 // background is not inherited beyond top level windows
4059 if ( win
->IsTopLevel() )
4066 bool wxWindowMSW::HandlePrintClient(WXHDC hDC
)
4068 // we receive this message when DrawThemeParentBackground() is
4069 // called from def window proc of several controls under XP and we
4070 // must draw properly themed background here
4072 // note that naively I'd expect filling the client rect with the
4073 // brush returned by MSWGetBgBrush() work -- but for some reason it
4074 // doesn't and we have to call parents MSWPrintChild() which is
4075 // supposed to call DrawThemeBackground() with appropriate params
4077 // also note that in this case lParam == PRF_CLIENT but we're
4078 // clearly expected to paint the background and nothing else!
4079 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
4081 if ( win
->MSWPrintChild(hDC
, (wxWindow
*)this) )
4084 if ( win
->IsTopLevel() || win
->InheritsBackgroundColour() )
4091 // ---------------------------------------------------------------------------
4092 // moving and resizing
4093 // ---------------------------------------------------------------------------
4095 bool wxWindowMSW::HandleMinimize()
4097 wxIconizeEvent
event(m_windowId
);
4098 event
.SetEventObject(this);
4100 return GetEventHandler()->ProcessEvent(event
);
4103 bool wxWindowMSW::HandleMaximize()
4105 wxMaximizeEvent
event(m_windowId
);
4106 event
.SetEventObject(this);
4108 return GetEventHandler()->ProcessEvent(event
);
4111 bool wxWindowMSW::HandleMove(int x
, int y
)
4114 wxMoveEvent
event(point
, m_windowId
);
4115 event
.SetEventObject(this);
4117 return GetEventHandler()->ProcessEvent(event
);
4120 bool wxWindowMSW::HandleMoving(wxRect
& rect
)
4122 wxMoveEvent
event(rect
, m_windowId
);
4123 event
.SetEventObject(this);
4125 bool rc
= GetEventHandler()->ProcessEvent(event
);
4127 rect
= event
.GetRect();
4131 bool wxWindowMSW::HandleSize(int WXUNUSED(w
), int WXUNUSED(h
), WXUINT wParam
)
4133 // when we resize this window, its children are probably going to be
4134 // repositioned as well, prepare to use DeferWindowPos() for them
4135 const int numChildren
= GetChildren().GetCount();
4136 if ( numChildren
> 1 )
4138 m_hDWP
= (WXHANDLE
)::BeginDeferWindowPos(numChildren
);
4141 wxLogLastError(_T("BeginDeferWindowPos"));
4145 // update this window size
4146 bool processed
= false;
4150 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
4151 // fall through nevertheless
4155 // we're not interested in these messages at all
4158 case SIZE_MINIMIZED
:
4159 processed
= HandleMinimize();
4162 case SIZE_MAXIMIZED
:
4163 /* processed = */ HandleMaximize();
4164 // fall through to send a normal size event as well
4167 // don't use w and h parameters as they specify the client size
4168 // while according to the docs EVT_SIZE handler is supposed to
4169 // receive the total size
4170 wxSizeEvent
event(GetSize(), m_windowId
);
4171 event
.SetEventObject(this);
4173 processed
= GetEventHandler()->ProcessEvent(event
);
4176 // and finally change the positions of all child windows at once
4179 // reset m_hDWP to NULL so that child windows don't try to use our
4180 // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
4181 // happen anyhow normally but who knows what weird flow of control we
4182 // may have depending on what the users EVT_SIZE handler does...)
4183 HDWP hDWP
= (HDWP
)m_hDWP
;
4186 // do put all child controls in place at once
4187 if ( !::EndDeferWindowPos(hDWP
) )
4189 wxLogLastError(_T("EndDeferWindowPos"));
4196 bool wxWindowMSW::HandleSizing(wxRect
& rect
)
4198 wxSizeEvent
event(rect
, m_windowId
);
4199 event
.SetEventObject(this);
4201 bool rc
= GetEventHandler()->ProcessEvent(event
);
4203 rect
= event
.GetRect();
4207 bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo
)
4210 wxUnusedVar(mmInfo
);
4213 MINMAXINFO
*info
= (MINMAXINFO
*)mmInfo
;
4217 int minWidth
= GetMinWidth(),
4218 minHeight
= GetMinHeight(),
4219 maxWidth
= GetMaxWidth(),
4220 maxHeight
= GetMaxHeight();
4222 if ( minWidth
!= wxDefaultCoord
)
4224 info
->ptMinTrackSize
.x
= minWidth
;
4228 if ( minHeight
!= wxDefaultCoord
)
4230 info
->ptMinTrackSize
.y
= minHeight
;
4234 if ( maxWidth
!= wxDefaultCoord
)
4236 info
->ptMaxTrackSize
.x
= maxWidth
;
4240 if ( maxHeight
!= wxDefaultCoord
)
4242 info
->ptMaxTrackSize
.y
= maxHeight
;
4250 // ---------------------------------------------------------------------------
4252 // ---------------------------------------------------------------------------
4254 bool wxWindowMSW::HandleCommand(WXWORD id
, WXWORD cmd
, WXHWND control
)
4256 #if wxUSE_MENUS_NATIVE
4257 if ( !cmd
&& wxCurrentPopupMenu
)
4259 wxMenu
*popupMenu
= wxCurrentPopupMenu
;
4260 wxCurrentPopupMenu
= NULL
;
4262 return popupMenu
->MSWCommand(cmd
, id
);
4264 #endif // wxUSE_MENUS_NATIVE
4266 wxWindow
*win
= NULL
;
4268 // first try to find it from HWND - this works even with the broken
4269 // programs using the same ids for different controls
4272 win
= wxFindWinFromHandle(control
);
4278 // must cast to a signed type before comparing with other ids!
4279 win
= FindItem((signed short)id
);
4284 return win
->MSWCommand(cmd
, id
);
4287 // the messages sent from the in-place edit control used by the treectrl
4288 // for label editing have id == 0, but they should _not_ be treated as menu
4289 // messages (they are EN_XXX ones, in fact) so don't translate anything
4290 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
4293 // If no child window, it may be an accelerator, e.g. for a popup menu
4296 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
);
4297 event
.SetEventObject(this);
4301 return GetEventHandler()->ProcessEvent(event
);
4305 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
4306 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
4307 // notifications to its parent which we want to reflect back to
4309 wxSpinCtrl
*spin
= wxSpinCtrl::GetSpinForTextCtrl(control
);
4310 if ( spin
&& spin
->ProcessTextCommand(cmd
, id
) )
4312 #endif // wxUSE_SPINCTRL
4314 #if wxUSE_CHOICE && defined(__SMARTPHONE__)
4315 // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND
4316 // notifications to its parent which we want to reflect back to
4318 wxChoice
*choice
= wxChoice::GetChoiceForListBox(control
);
4319 if ( choice
&& choice
->MSWCommand(cmd
, id
) )
4327 // ---------------------------------------------------------------------------
4329 // ---------------------------------------------------------------------------
4331 void wxWindowMSW::InitMouseEvent(wxMouseEvent
& event
,
4335 // our client coords are not quite the same as Windows ones
4336 wxPoint pt
= GetClientAreaOrigin();
4337 event
.m_x
= x
- pt
.x
;
4338 event
.m_y
= y
- pt
.y
;
4340 event
.m_shiftDown
= (flags
& MK_SHIFT
) != 0;
4341 event
.m_controlDown
= (flags
& MK_CONTROL
) != 0;
4342 event
.m_leftDown
= (flags
& MK_LBUTTON
) != 0;
4343 event
.m_middleDown
= (flags
& MK_MBUTTON
) != 0;
4344 event
.m_rightDown
= (flags
& MK_RBUTTON
) != 0;
4345 event
.m_altDown
= ::GetKeyState(VK_MENU
) < 0;
4348 event
.SetTimestamp(::GetMessageTime());
4351 event
.SetEventObject(this);
4352 event
.SetId(GetId());
4354 #if wxUSE_MOUSEEVENT_HACK
4357 m_lastMouseEvent
= event
.GetEventType();
4358 #endif // wxUSE_MOUSEEVENT_HACK
4361 // Windows doesn't send the mouse events to the static controls (which are
4362 // transparent in the sense that their WM_NCHITTEST handler returns
4363 // HTTRANSPARENT) at all but we want all controls to receive the mouse events
4364 // and so we manually check if we don't have a child window under mouse and if
4365 // we do, send the event to it instead of the window Windows had sent WM_XXX
4368 // Notice that this is not done for the mouse move events because this could
4369 // (would?) be too slow, but only for clicks which means that the static texts
4370 // still don't get move, enter nor leave events.
4371 static wxWindowMSW
*FindWindowForMouseEvent(wxWindowMSW
*win
, int *x
, int *y
) //TW:REQ:Univ
4373 wxCHECK_MSG( x
&& y
, win
, _T("NULL pointer in FindWindowForMouseEvent") );
4375 // first try to find a non transparent child: this allows us to send events
4376 // to a static text which is inside a static box, for example
4377 POINT pt
= { *x
, *y
};
4378 HWND hwnd
= GetHwndOf(win
),
4382 hwndUnderMouse
= ::ChildWindowFromPoint
4388 hwndUnderMouse
= ::ChildWindowFromPointEx
4398 if ( !hwndUnderMouse
|| hwndUnderMouse
== hwnd
)
4400 // now try any child window at all
4401 hwndUnderMouse
= ::ChildWindowFromPoint(hwnd
, pt
);
4404 // check that we have a child window which is susceptible to receive mouse
4405 // events: for this it must be shown and enabled
4406 if ( hwndUnderMouse
&&
4407 hwndUnderMouse
!= hwnd
&&
4408 ::IsWindowVisible(hwndUnderMouse
) &&
4409 ::IsWindowEnabled(hwndUnderMouse
) )
4411 wxWindow
*winUnderMouse
= wxFindWinFromHandle((WXHWND
)hwndUnderMouse
);
4412 if ( winUnderMouse
)
4414 // translate the mouse coords to the other window coords
4415 win
->ClientToScreen(x
, y
);
4416 winUnderMouse
->ScreenToClient(x
, y
);
4418 win
= winUnderMouse
;
4425 bool wxWindowMSW::HandleMouseEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4427 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
4428 // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST
4429 // from the message id and take the value in the table to get wxWin event
4431 static const wxEventType eventsMouse
[] =
4445 wxMouseEvent
event(eventsMouse
[msg
- WM_MOUSEMOVE
]);
4446 InitMouseEvent(event
, x
, y
, flags
);
4448 return GetEventHandler()->ProcessEvent(event
);
4451 bool wxWindowMSW::HandleMouseMove(int x
, int y
, WXUINT flags
)
4453 if ( !m_mouseInWindow
)
4455 // it would be wrong to assume that just because we get a mouse move
4456 // event that the mouse is inside the window: although this is usually
4457 // true, it is not if we had captured the mouse, so we need to check
4458 // the mouse coordinates here
4459 if ( !HasCapture() || IsMouseInWindow() )
4461 // Generate an ENTER event
4462 m_mouseInWindow
= true;
4464 #ifdef HAVE_TRACKMOUSEEVENT
4465 WinStruct
<TRACKMOUSEEVENT
> trackinfo
;
4467 trackinfo
.dwFlags
= TME_LEAVE
;
4468 trackinfo
.hwndTrack
= GetHwnd();
4470 // Use the commctrl.h _TrackMouseEvent(), which will call the real
4471 // TrackMouseEvent() if available or emulate it
4472 _TrackMouseEvent(&trackinfo
);
4473 #endif // HAVE_TRACKMOUSEEVENT
4475 wxMouseEvent
event(wxEVT_ENTER_WINDOW
);
4476 InitMouseEvent(event
, x
, y
, flags
);
4478 (void)GetEventHandler()->ProcessEvent(event
);
4482 #if wxUSE_MOUSEEVENT_HACK
4483 // Window gets a click down message followed by a mouse move message even
4484 // if position isn't changed! We want to discard the trailing move event
4485 // if x and y are the same.
4486 if ( (m_lastMouseEvent
== wxEVT_RIGHT_DOWN
||
4487 m_lastMouseEvent
== wxEVT_LEFT_DOWN
||
4488 m_lastMouseEvent
== wxEVT_MIDDLE_DOWN
) &&
4489 (m_lastMouseX
== x
&& m_lastMouseY
== y
) )
4491 m_lastMouseEvent
= wxEVT_MOTION
;
4495 #endif // wxUSE_MOUSEEVENT_HACK
4497 return HandleMouseEvent(WM_MOUSEMOVE
, x
, y
, flags
);
4501 bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam
, WXLPARAM lParam
)
4503 #if wxUSE_MOUSEWHEEL
4504 wxMouseEvent
event(wxEVT_MOUSEWHEEL
);
4505 InitMouseEvent(event
,
4506 GET_X_LPARAM(lParam
),
4507 GET_Y_LPARAM(lParam
),
4509 event
.m_wheelRotation
= (short)HIWORD(wParam
);
4510 event
.m_wheelDelta
= WHEEL_DELTA
;
4512 static int s_linesPerRotation
= -1;
4513 if ( s_linesPerRotation
== -1 )
4515 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES
, 0,
4516 &s_linesPerRotation
, 0))
4518 // this is not supposed to happen
4519 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
4521 // the default is 3, so use it if SystemParametersInfo() failed
4522 s_linesPerRotation
= 3;
4526 event
.m_linesPerAction
= s_linesPerRotation
;
4527 return GetEventHandler()->ProcessEvent(event
);
4529 #else // !wxUSE_MOUSEWHEEL
4530 wxUnusedVar(wParam
);
4531 wxUnusedVar(lParam
);
4534 #endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL
4537 void wxWindowMSW::GenerateMouseLeave()
4539 m_mouseInWindow
= false;
4542 if ( wxIsShiftDown() )
4544 if ( wxIsCtrlDown() )
4545 state
|= MK_CONTROL
;
4547 // Only the high-order bit should be tested
4548 if ( GetKeyState( VK_LBUTTON
) & (1<<15) )
4549 state
|= MK_LBUTTON
;
4550 if ( GetKeyState( VK_MBUTTON
) & (1<<15) )
4551 state
|= MK_MBUTTON
;
4552 if ( GetKeyState( VK_RBUTTON
) & (1<<15) )
4553 state
|= MK_RBUTTON
;
4557 if ( !::GetCursorPosWinCE(&pt
) )
4559 if ( !::GetCursorPos(&pt
) )
4562 wxLogLastError(_T("GetCursorPos"));
4565 // we need to have client coordinates here for symmetry with
4566 // wxEVT_ENTER_WINDOW
4567 RECT rect
= wxGetWindowRect(GetHwnd());
4571 wxMouseEvent
event(wxEVT_LEAVE_WINDOW
);
4572 InitMouseEvent(event
, pt
.x
, pt
.y
, state
);
4574 (void)GetEventHandler()->ProcessEvent(event
);
4577 // ---------------------------------------------------------------------------
4578 // keyboard handling
4579 // ---------------------------------------------------------------------------
4581 // create the key event of the given type for the given key - used by
4582 // HandleChar and HandleKeyDown/Up
4583 wxKeyEvent
wxWindowMSW::CreateKeyEvent(wxEventType evType
,
4586 WXWPARAM wParam
) const
4588 wxKeyEvent
event(evType
);
4589 event
.SetId(GetId());
4590 event
.m_shiftDown
= wxIsShiftDown();
4591 event
.m_controlDown
= wxIsCtrlDown();
4592 event
.m_altDown
= (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
;
4594 event
.SetEventObject((wxWindow
*)this); // const_cast
4595 event
.m_keyCode
= id
;
4597 event
.m_uniChar
= (wxChar
) wParam
;
4599 event
.m_rawCode
= (wxUint32
) wParam
;
4600 event
.m_rawFlags
= (wxUint32
) lParam
;
4602 event
.SetTimestamp(::GetMessageTime());
4605 // translate the position to client coords
4608 GetCursorPosWinCE(&pt
);
4613 GetWindowRect(GetHwnd(),&rect
);
4623 // isASCII is true only when we're called from WM_CHAR handler and not from
4625 bool wxWindowMSW::HandleChar(WXWPARAM wParam
, WXLPARAM lParam
, bool isASCII
)
4630 // If 1 -> 26, translate to either special keycode or just set
4631 // ctrlDown. IOW, Ctrl-C should result in keycode == 3 and
4632 // ControlDown() == true.
4634 if ( (id
> 0) && (id
< 27) )
4656 else // we're called from WM_KEYDOWN
4658 id
= wxCharCodeMSWToWX(wParam
, lParam
);
4661 // it's ASCII and will be processed here only when called from
4662 // WM_CHAR (i.e. when isASCII = true), don't process it now
4667 wxKeyEvent
event(CreateKeyEvent(wxEVT_CHAR
, id
, lParam
, wParam
));
4669 // the alphanumeric keys produced by pressing AltGr+something on European
4670 // keyboards have both Ctrl and Alt modifiers which may confuse the user
4671 // code as, normally, keys with Ctrl and/or Alt don't result in anything
4672 // alphanumeric, so pretend that there are no modifiers at all (the
4673 // KEY_DOWN event would still have the correct modifiers if they're really
4675 if ( event
.m_controlDown
&& event
.m_altDown
&&
4676 (id
>= 32 && id
< 256) )
4678 event
.m_controlDown
=
4679 event
.m_altDown
= false;
4682 return GetEventHandler()->ProcessEvent(event
);
4685 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam
, WXLPARAM lParam
)
4687 int id
= wxCharCodeMSWToWX(wParam
, lParam
);
4691 // normal ASCII char
4695 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4697 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_DOWN
, id
, lParam
, wParam
));
4698 if ( GetEventHandler()->ProcessEvent(event
) )
4707 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam
, WXLPARAM lParam
)
4709 int id
= wxCharCodeMSWToWX(wParam
, lParam
);
4713 // normal ASCII char
4717 if ( id
!= -1 ) // VZ: does this ever happen (FIXME)?
4719 wxKeyEvent
event(CreateKeyEvent(wxEVT_KEY_UP
, id
, lParam
, wParam
));
4720 if ( GetEventHandler()->ProcessEvent(event
) )
4727 int wxWindowMSW::HandleMenuChar(int chAccel
, WXLPARAM lParam
)
4729 // FIXME: implement GetMenuItemCount for WinCE, possibly
4730 // in terms of GetMenuItemInfo
4732 const HMENU hmenu
= (HMENU
)lParam
;
4736 mii
.cbSize
= sizeof(MENUITEMINFO
);
4737 mii
.fMask
= MIIM_TYPE
| MIIM_DATA
;
4739 // find if we have this letter in any owner drawn item
4740 const int count
= ::GetMenuItemCount(hmenu
);
4741 for ( int i
= 0; i
< count
; i
++ )
4743 if ( ::GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
) )
4745 if ( mii
.fType
== MFT_OWNERDRAW
)
4747 // dwItemData member of the MENUITEMINFO is a
4748 // pointer to the associated wxMenuItem -- see the
4749 // menu creation code
4750 wxMenuItem
*item
= (wxMenuItem
*)mii
.dwItemData
;
4752 const wxChar
*p
= wxStrchr(item
->GetText(), _T('&'));
4755 if ( *p
== _T('&') )
4757 // this is not the accel char, find the real one
4758 p
= wxStrchr(p
+ 1, _T('&'));
4760 else // got the accel char
4762 // FIXME-UNICODE: this comparison doesn't risk to work
4763 // for non ASCII accelerator characters I'm afraid, but
4765 if ( (wchar_t)wxToupper(*p
) == (wchar_t)chAccel
)
4771 // this one doesn't match
4778 else // failed to get the menu text?
4780 // it's not fatal, so don't show error, but still log
4782 wxLogLastError(_T("GetMenuItemInfo"));
4786 wxUnusedVar(chAccel
);
4787 wxUnusedVar(lParam
);
4792 // ---------------------------------------------------------------------------
4794 // ---------------------------------------------------------------------------
4796 bool wxWindowMSW::HandleJoystickEvent(WXUINT msg
, int x
, int y
, WXUINT flags
)
4800 if ( flags
& JOY_BUTTON1CHG
)
4801 change
= wxJOY_BUTTON1
;
4802 if ( flags
& JOY_BUTTON2CHG
)
4803 change
= wxJOY_BUTTON2
;
4804 if ( flags
& JOY_BUTTON3CHG
)
4805 change
= wxJOY_BUTTON3
;
4806 if ( flags
& JOY_BUTTON4CHG
)
4807 change
= wxJOY_BUTTON4
;
4810 if ( flags
& JOY_BUTTON1
)
4811 buttons
|= wxJOY_BUTTON1
;
4812 if ( flags
& JOY_BUTTON2
)
4813 buttons
|= wxJOY_BUTTON2
;
4814 if ( flags
& JOY_BUTTON3
)
4815 buttons
|= wxJOY_BUTTON3
;
4816 if ( flags
& JOY_BUTTON4
)
4817 buttons
|= wxJOY_BUTTON4
;
4819 // the event ids aren't consecutive so we can't use table based lookup
4821 wxEventType eventType
;
4826 eventType
= wxEVT_JOY_MOVE
;
4831 eventType
= wxEVT_JOY_MOVE
;
4836 eventType
= wxEVT_JOY_ZMOVE
;
4841 eventType
= wxEVT_JOY_ZMOVE
;
4844 case MM_JOY1BUTTONDOWN
:
4846 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4849 case MM_JOY2BUTTONDOWN
:
4851 eventType
= wxEVT_JOY_BUTTON_DOWN
;
4854 case MM_JOY1BUTTONUP
:
4856 eventType
= wxEVT_JOY_BUTTON_UP
;
4859 case MM_JOY2BUTTONUP
:
4861 eventType
= wxEVT_JOY_BUTTON_UP
;
4865 wxFAIL_MSG(wxT("no such joystick event"));
4870 wxJoystickEvent
event(eventType
, buttons
, joystick
, change
);
4871 event
.SetPosition(wxPoint(x
, y
));
4872 event
.SetEventObject(this);
4874 return GetEventHandler()->ProcessEvent(event
);
4884 // ---------------------------------------------------------------------------
4886 // ---------------------------------------------------------------------------
4888 bool wxWindowMSW::MSWOnScroll(int orientation
, WXWORD wParam
,
4889 WXWORD pos
, WXHWND control
)
4891 if ( control
&& control
!= m_hWnd
) // Prevent infinite recursion
4893 wxWindow
*child
= wxFindWinFromHandle(control
);
4895 return child
->MSWOnScroll(orientation
, wParam
, pos
, control
);
4898 wxScrollWinEvent event
;
4899 event
.SetPosition(pos
);
4900 event
.SetOrientation(orientation
);
4901 event
.SetEventObject(this);
4906 event
.SetEventType(wxEVT_SCROLLWIN_TOP
);
4910 event
.SetEventType(wxEVT_SCROLLWIN_BOTTOM
);
4914 event
.SetEventType(wxEVT_SCROLLWIN_LINEUP
);
4918 event
.SetEventType(wxEVT_SCROLLWIN_LINEDOWN
);
4922 event
.SetEventType(wxEVT_SCROLLWIN_PAGEUP
);
4926 event
.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN
);
4929 case SB_THUMBPOSITION
:
4931 // under Win32, the scrollbar range and position are 32 bit integers,
4932 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4933 // explicitly query the scrollbar for the correct position (this must
4934 // be done only for these two SB_ events as they are the only one
4935 // carrying the scrollbar position)
4937 WinStruct
<SCROLLINFO
> scrollInfo
;
4938 scrollInfo
.fMask
= SIF_TRACKPOS
;
4940 if ( !::GetScrollInfo(GetHwnd(),
4941 orientation
== wxHORIZONTAL
? SB_HORZ
4945 // Not neccessarily an error, if there are no scrollbars yet.
4946 // wxLogLastError(_T("GetScrollInfo"));
4949 event
.SetPosition(scrollInfo
.nTrackPos
);
4952 event
.SetEventType( wParam
== SB_THUMBPOSITION
4953 ? wxEVT_SCROLLWIN_THUMBRELEASE
4954 : wxEVT_SCROLLWIN_THUMBTRACK
);
4961 return GetEventHandler()->ProcessEvent(event
);
4964 // ===========================================================================
4966 // ===========================================================================
4968 void wxGetCharSize(WXHWND wnd
, int *x
, int *y
, const wxFont
& the_font
)
4971 HDC dc
= ::GetDC((HWND
) wnd
);
4974 // the_font.UseResource();
4975 // the_font.RealizeResource();
4976 HFONT fnt
= (HFONT
)the_font
.GetResourceHandle(); // const_cast
4978 was
= (HFONT
) SelectObject(dc
,fnt
);
4980 GetTextMetrics(dc
, &tm
);
4983 SelectObject(dc
,was
);
4985 ReleaseDC((HWND
)wnd
, dc
);
4988 *x
= tm
.tmAveCharWidth
;
4990 *y
= tm
.tmHeight
+ tm
.tmExternalLeading
;
4992 // the_font.ReleaseResource();
4995 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4996 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4997 int wxCharCodeMSWToWX(int keySym
, WXLPARAM lParam
)
5002 case VK_CANCEL
: id
= WXK_CANCEL
; break;
5003 case VK_BACK
: id
= WXK_BACK
; break;
5004 case VK_TAB
: id
= WXK_TAB
; break;
5005 case VK_CLEAR
: id
= WXK_CLEAR
; break;
5006 case VK_SHIFT
: id
= WXK_SHIFT
; break;
5007 case VK_CONTROL
: id
= WXK_CONTROL
; break;
5008 case VK_MENU
: id
= WXK_ALT
; break;
5009 case VK_PAUSE
: id
= WXK_PAUSE
; break;
5010 case VK_CAPITAL
: id
= WXK_CAPITAL
; break;
5011 case VK_SPACE
: id
= WXK_SPACE
; break;
5012 case VK_ESCAPE
: id
= WXK_ESCAPE
; break;
5013 case VK_PRIOR
: id
= WXK_PRIOR
; break;
5014 case VK_NEXT
: id
= WXK_NEXT
; break;
5015 case VK_END
: id
= WXK_END
; break;
5016 case VK_HOME
: id
= WXK_HOME
; break;
5017 case VK_LEFT
: id
= WXK_LEFT
; break;
5018 case VK_UP
: id
= WXK_UP
; break;
5019 case VK_RIGHT
: id
= WXK_RIGHT
; break;
5020 case VK_DOWN
: id
= WXK_DOWN
; break;
5021 case VK_SELECT
: id
= WXK_SELECT
; break;
5022 case VK_PRINT
: id
= WXK_PRINT
; break;
5023 case VK_EXECUTE
: id
= WXK_EXECUTE
; break;
5024 case VK_INSERT
: id
= WXK_INSERT
; break;
5025 case VK_DELETE
: id
= WXK_DELETE
; break;
5026 case VK_HELP
: id
= WXK_HELP
; break;
5027 case VK_NUMPAD0
: id
= WXK_NUMPAD0
; break;
5028 case VK_NUMPAD1
: id
= WXK_NUMPAD1
; break;
5029 case VK_NUMPAD2
: id
= WXK_NUMPAD2
; break;
5030 case VK_NUMPAD3
: id
= WXK_NUMPAD3
; break;
5031 case VK_NUMPAD4
: id
= WXK_NUMPAD4
; break;
5032 case VK_NUMPAD5
: id
= WXK_NUMPAD5
; break;
5033 case VK_NUMPAD6
: id
= WXK_NUMPAD6
; break;
5034 case VK_NUMPAD7
: id
= WXK_NUMPAD7
; break;
5035 case VK_NUMPAD8
: id
= WXK_NUMPAD8
; break;
5036 case VK_NUMPAD9
: id
= WXK_NUMPAD9
; break;
5037 case VK_MULTIPLY
: id
= WXK_NUMPAD_MULTIPLY
; break;
5038 case VK_ADD
: id
= WXK_NUMPAD_ADD
; break;
5039 case VK_SUBTRACT
: id
= WXK_NUMPAD_SUBTRACT
; break;
5040 case VK_DECIMAL
: id
= WXK_NUMPAD_DECIMAL
; break;
5041 case VK_DIVIDE
: id
= WXK_NUMPAD_DIVIDE
; break;
5042 case VK_F1
: id
= WXK_F1
; break;
5043 case VK_F2
: id
= WXK_F2
; break;
5044 case VK_F3
: id
= WXK_F3
; break;
5045 case VK_F4
: id
= WXK_F4
; break;
5046 case VK_F5
: id
= WXK_F5
; break;
5047 case VK_F6
: id
= WXK_F6
; break;
5048 case VK_F7
: id
= WXK_F7
; break;
5049 case VK_F8
: id
= WXK_F8
; break;
5050 case VK_F9
: id
= WXK_F9
; break;
5051 case VK_F10
: id
= WXK_F10
; break;
5052 case VK_F11
: id
= WXK_F11
; break;
5053 case VK_F12
: id
= WXK_F12
; break;
5054 case VK_F13
: id
= WXK_F13
; break;
5055 case VK_F14
: id
= WXK_F14
; break;
5056 case VK_F15
: id
= WXK_F15
; break;
5057 case VK_F16
: id
= WXK_F16
; break;
5058 case VK_F17
: id
= WXK_F17
; break;
5059 case VK_F18
: id
= WXK_F18
; break;
5060 case VK_F19
: id
= WXK_F19
; break;
5061 case VK_F20
: id
= WXK_F20
; break;
5062 case VK_F21
: id
= WXK_F21
; break;
5063 case VK_F22
: id
= WXK_F22
; break;
5064 case VK_F23
: id
= WXK_F23
; break;
5065 case VK_F24
: id
= WXK_F24
; break;
5066 case VK_NUMLOCK
: id
= WXK_NUMLOCK
; break;
5067 case VK_SCROLL
: id
= WXK_SCROLL
; break;
5069 // the mapping for these keys may be incorrect on non-US keyboards so
5070 // maybe we shouldn't map them to ASCII values at all
5071 case VK_OEM_1
: id
= ';'; break;
5072 case VK_OEM_PLUS
: id
= '+'; break;
5073 case VK_OEM_COMMA
: id
= ','; break;
5074 case VK_OEM_MINUS
: id
= '-'; break;
5075 case VK_OEM_PERIOD
: id
= '.'; break;
5076 case VK_OEM_2
: id
= '/'; break;
5077 case VK_OEM_3
: id
= '~'; break;
5078 case VK_OEM_4
: id
= '['; break;
5079 case VK_OEM_5
: id
= '\\'; break;
5080 case VK_OEM_6
: id
= ']'; break;
5081 case VK_OEM_7
: id
= '\''; break;
5084 case VK_LWIN
: id
= WXK_WINDOWS_LEFT
; break;
5085 case VK_RWIN
: id
= WXK_WINDOWS_RIGHT
; break;
5086 case VK_APPS
: id
= WXK_WINDOWS_MENU
; break;
5087 #endif // VK_APPS defined
5090 // the same key is sent for both the "return" key on the main
5091 // keyboard and the numeric keypad but we want to distinguish
5092 // between them: we do this using the "extended" bit (24) of lParam
5093 id
= lParam
& (1 << 24) ? WXK_NUMPAD_ENTER
: WXK_RETURN
;
5103 WXWORD
wxCharCodeWXToMSW(int id
, bool *isVirtual
)
5109 case WXK_CANCEL
: keySym
= VK_CANCEL
; break;
5110 case WXK_CLEAR
: keySym
= VK_CLEAR
; break;
5111 case WXK_SHIFT
: keySym
= VK_SHIFT
; break;
5112 case WXK_CONTROL
: keySym
= VK_CONTROL
; break;
5113 case WXK_ALT
: keySym
= VK_MENU
; break;
5114 case WXK_PAUSE
: keySym
= VK_PAUSE
; break;
5115 case WXK_CAPITAL
: keySym
= VK_CAPITAL
; break;
5116 case WXK_PRIOR
: keySym
= VK_PRIOR
; break;
5117 case WXK_NEXT
: keySym
= VK_NEXT
; break;
5118 case WXK_END
: keySym
= VK_END
; break;
5119 case WXK_HOME
: keySym
= VK_HOME
; break;
5120 case WXK_LEFT
: keySym
= VK_LEFT
; break;
5121 case WXK_UP
: keySym
= VK_UP
; break;
5122 case WXK_RIGHT
: keySym
= VK_RIGHT
; break;
5123 case WXK_DOWN
: keySym
= VK_DOWN
; break;
5124 case WXK_SELECT
: keySym
= VK_SELECT
; break;
5125 case WXK_PRINT
: keySym
= VK_PRINT
; break;
5126 case WXK_EXECUTE
: keySym
= VK_EXECUTE
; break;
5127 case WXK_INSERT
: keySym
= VK_INSERT
; break;
5128 case WXK_DELETE
: keySym
= VK_DELETE
; break;
5129 case WXK_HELP
: keySym
= VK_HELP
; break;
5130 case WXK_NUMPAD0
: keySym
= VK_NUMPAD0
; break;
5131 case WXK_NUMPAD1
: keySym
= VK_NUMPAD1
; break;
5132 case WXK_NUMPAD2
: keySym
= VK_NUMPAD2
; break;
5133 case WXK_NUMPAD3
: keySym
= VK_NUMPAD3
; break;
5134 case WXK_NUMPAD4
: keySym
= VK_NUMPAD4
; break;
5135 case WXK_NUMPAD5
: keySym
= VK_NUMPAD5
; break;
5136 case WXK_NUMPAD6
: keySym
= VK_NUMPAD6
; break;
5137 case WXK_NUMPAD7
: keySym
= VK_NUMPAD7
; break;
5138 case WXK_NUMPAD8
: keySym
= VK_NUMPAD8
; break;
5139 case WXK_NUMPAD9
: keySym
= VK_NUMPAD9
; break;
5140 case WXK_NUMPAD_MULTIPLY
: keySym
= VK_MULTIPLY
; break;
5141 case WXK_NUMPAD_ADD
: keySym
= VK_ADD
; break;
5142 case WXK_NUMPAD_SUBTRACT
: keySym
= VK_SUBTRACT
; break;
5143 case WXK_NUMPAD_DECIMAL
: keySym
= VK_DECIMAL
; break;
5144 case WXK_NUMPAD_DIVIDE
: keySym
= VK_DIVIDE
; break;
5145 case WXK_F1
: keySym
= VK_F1
; break;
5146 case WXK_F2
: keySym
= VK_F2
; break;
5147 case WXK_F3
: keySym
= VK_F3
; break;
5148 case WXK_F4
: keySym
= VK_F4
; break;
5149 case WXK_F5
: keySym
= VK_F5
; break;
5150 case WXK_F6
: keySym
= VK_F6
; break;
5151 case WXK_F7
: keySym
= VK_F7
; break;
5152 case WXK_F8
: keySym
= VK_F8
; break;
5153 case WXK_F9
: keySym
= VK_F9
; break;
5154 case WXK_F10
: keySym
= VK_F10
; break;
5155 case WXK_F11
: keySym
= VK_F11
; break;
5156 case WXK_F12
: keySym
= VK_F12
; break;
5157 case WXK_F13
: keySym
= VK_F13
; break;
5158 case WXK_F14
: keySym
= VK_F14
; break;
5159 case WXK_F15
: keySym
= VK_F15
; break;
5160 case WXK_F16
: keySym
= VK_F16
; break;
5161 case WXK_F17
: keySym
= VK_F17
; break;
5162 case WXK_F18
: keySym
= VK_F18
; break;
5163 case WXK_F19
: keySym
= VK_F19
; break;
5164 case WXK_F20
: keySym
= VK_F20
; break;
5165 case WXK_F21
: keySym
= VK_F21
; break;
5166 case WXK_F22
: keySym
= VK_F22
; break;
5167 case WXK_F23
: keySym
= VK_F23
; break;
5168 case WXK_F24
: keySym
= VK_F24
; break;
5169 case WXK_NUMLOCK
: keySym
= VK_NUMLOCK
; break;
5170 case WXK_SCROLL
: keySym
= VK_SCROLL
; break;
5181 bool wxGetKeyState(wxKeyCode key
)
5185 wxASSERT_MSG(key
!= WXK_LBUTTON
&& key
!= WXK_RBUTTON
&& key
!=
5186 WXK_MBUTTON
, wxT("can't use wxGetKeyState() for mouse buttons"));
5188 //High order with GetAsyncKeyState only available on WIN32
5190 //If the requested key is a LED key, return
5191 //true if the led is pressed
5192 if (key
== WXK_NUMLOCK
||
5193 key
== WXK_CAPITAL
||
5197 //low order bit means LED is highlighted,
5198 //high order means key is down
5199 //Here, for compat with other ports we want both
5200 return GetKeyState( wxCharCodeWXToMSW(key
, &bVirtual
) ) != 0;
5207 //low order bit means key pressed since last call
5208 //high order means key is down
5209 //We want only the high order bit - the key may not be down if only low order
5210 return ( GetAsyncKeyState( wxCharCodeWXToMSW(key
, &bVirtual
) ) & (1<<15) ) != 0;
5215 wxWindow
*wxGetActiveWindow()
5217 HWND hWnd
= GetActiveWindow();
5220 return wxFindWinFromHandle((WXHWND
) hWnd
);
5225 extern wxWindow
*wxGetWindowFromHWND(WXHWND hWnd
)
5227 HWND hwnd
= (HWND
)hWnd
;
5229 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
5230 // by code in msw/radiobox.cpp), for all the others we just search up the
5232 wxWindow
*win
= (wxWindow
*)NULL
;
5235 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
5239 // native radiobuttons return DLGC_RADIOBUTTON here and for any
5240 // wxWindow class which overrides WM_GETDLGCODE processing to
5241 // do it as well, win would be already non NULL
5242 if ( ::SendMessage(hwnd
, WM_GETDLGCODE
, 0, 0) & DLGC_RADIOBUTTON
)
5244 win
= (wxWindow
*)wxGetWindowUserData(hwnd
);
5246 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
5247 #endif // wxUSE_RADIOBOX
5249 // spin control text buddy window should be mapped to spin ctrl
5250 // itself so try it too
5251 #if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
5254 win
= wxSpinCtrl::GetSpinForTextCtrl((WXHWND
)hwnd
);
5256 #endif // wxUSE_SPINCTRL
5260 while ( hwnd
&& !win
)
5262 // this is a really ugly hack needed to avoid mistakenly returning the
5263 // parent frame wxWindow for the find/replace modeless dialog HWND -
5264 // this, in turn, is needed to call IsDialogMessage() from
5265 // wxApp::ProcessMessage() as for this we must return NULL from here
5267 // FIXME: this is clearly not the best way to do it but I think we'll
5268 // need to change HWND <-> wxWindow code more heavily than I can
5269 // do it now to fix it
5270 #ifndef __WXMICROWIN__
5271 if ( ::GetWindow(hwnd
, GW_OWNER
) )
5273 // it's a dialog box, don't go upwards
5278 hwnd
= ::GetParent(hwnd
);
5279 win
= wxFindWinFromHandle((WXHWND
)hwnd
);
5285 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
5287 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
5288 // in active frames and dialogs, regardless of where the focus is.
5289 static HHOOK wxTheKeyboardHook
= 0;
5290 static FARPROC wxTheKeyboardHookProc
= 0;
5291 int APIENTRY _EXPORT
5292 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
);
5294 void wxSetKeyboardHook(bool doIt
)
5298 wxTheKeyboardHookProc
= MakeProcInstance((FARPROC
) wxKeyboardHook
, wxGetInstance());
5299 wxTheKeyboardHook
= SetWindowsHookEx(WH_KEYBOARD
, (HOOKPROC
) wxTheKeyboardHookProc
, wxGetInstance(),
5301 GetCurrentThreadId()
5302 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
5307 UnhookWindowsHookEx(wxTheKeyboardHook
);
5311 int APIENTRY _EXPORT
5312 wxKeyboardHook(int nCode
, WORD wParam
, DWORD lParam
)
5314 DWORD hiWord
= HIWORD(lParam
);
5315 if ( nCode
!= HC_NOREMOVE
&& ((hiWord
& KF_UP
) == 0) )
5317 int id
= wxCharCodeMSWToWX(wParam
, lParam
);
5320 wxKeyEvent
event(wxEVT_CHAR_HOOK
);
5321 if ( (HIWORD(lParam
) & KF_ALTDOWN
) == KF_ALTDOWN
)
5322 event
.m_altDown
= true;
5324 event
.SetEventObject(NULL
);
5325 event
.m_keyCode
= id
;
5326 event
.m_shiftDown
= wxIsShiftDown();
5327 event
.m_controlDown
= wxIsCtrlDown();
5329 event
.SetTimestamp(::GetMessageTime());
5331 wxWindow
*win
= wxGetActiveWindow();
5332 wxEvtHandler
*handler
;
5335 handler
= win
->GetEventHandler();
5336 event
.SetId(win
->GetId());
5341 event
.SetId(wxID_ANY
);
5344 if ( handler
&& handler
->ProcessEvent(event
) )
5352 return (int)CallNextHookEx(wxTheKeyboardHook
, nCode
, wParam
, lParam
);
5355 #endif // !__WXMICROWIN__
5358 const char *wxGetMessageName(int message
)
5362 case 0x0000: return "WM_NULL";
5363 case 0x0001: return "WM_CREATE";
5364 case 0x0002: return "WM_DESTROY";
5365 case 0x0003: return "WM_MOVE";
5366 case 0x0005: return "WM_SIZE";
5367 case 0x0006: return "WM_ACTIVATE";
5368 case 0x0007: return "WM_SETFOCUS";
5369 case 0x0008: return "WM_KILLFOCUS";
5370 case 0x000A: return "WM_ENABLE";
5371 case 0x000B: return "WM_SETREDRAW";
5372 case 0x000C: return "WM_SETTEXT";
5373 case 0x000D: return "WM_GETTEXT";
5374 case 0x000E: return "WM_GETTEXTLENGTH";
5375 case 0x000F: return "WM_PAINT";
5376 case 0x0010: return "WM_CLOSE";
5377 case 0x0011: return "WM_QUERYENDSESSION";
5378 case 0x0012: return "WM_QUIT";
5379 case 0x0013: return "WM_QUERYOPEN";
5380 case 0x0014: return "WM_ERASEBKGND";
5381 case 0x0015: return "WM_SYSCOLORCHANGE";
5382 case 0x0016: return "WM_ENDSESSION";
5383 case 0x0017: return "WM_SYSTEMERROR";
5384 case 0x0018: return "WM_SHOWWINDOW";
5385 case 0x0019: return "WM_CTLCOLOR";
5386 case 0x001A: return "WM_WININICHANGE";
5387 case 0x001B: return "WM_DEVMODECHANGE";
5388 case 0x001C: return "WM_ACTIVATEAPP";
5389 case 0x001D: return "WM_FONTCHANGE";
5390 case 0x001E: return "WM_TIMECHANGE";
5391 case 0x001F: return "WM_CANCELMODE";
5392 case 0x0020: return "WM_SETCURSOR";
5393 case 0x0021: return "WM_MOUSEACTIVATE";
5394 case 0x0022: return "WM_CHILDACTIVATE";
5395 case 0x0023: return "WM_QUEUESYNC";
5396 case 0x0024: return "WM_GETMINMAXINFO";
5397 case 0x0026: return "WM_PAINTICON";
5398 case 0x0027: return "WM_ICONERASEBKGND";
5399 case 0x0028: return "WM_NEXTDLGCTL";
5400 case 0x002A: return "WM_SPOOLERSTATUS";
5401 case 0x002B: return "WM_DRAWITEM";
5402 case 0x002C: return "WM_MEASUREITEM";
5403 case 0x002D: return "WM_DELETEITEM";
5404 case 0x002E: return "WM_VKEYTOITEM";
5405 case 0x002F: return "WM_CHARTOITEM";
5406 case 0x0030: return "WM_SETFONT";
5407 case 0x0031: return "WM_GETFONT";
5408 case 0x0037: return "WM_QUERYDRAGICON";
5409 case 0x0039: return "WM_COMPAREITEM";
5410 case 0x0041: return "WM_COMPACTING";
5411 case 0x0044: return "WM_COMMNOTIFY";
5412 case 0x0046: return "WM_WINDOWPOSCHANGING";
5413 case 0x0047: return "WM_WINDOWPOSCHANGED";
5414 case 0x0048: return "WM_POWER";
5416 case 0x004A: return "WM_COPYDATA";
5417 case 0x004B: return "WM_CANCELJOURNAL";
5418 case 0x004E: return "WM_NOTIFY";
5419 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
5420 case 0x0051: return "WM_INPUTLANGCHANGE";
5421 case 0x0052: return "WM_TCARD";
5422 case 0x0053: return "WM_HELP";
5423 case 0x0054: return "WM_USERCHANGED";
5424 case 0x0055: return "WM_NOTIFYFORMAT";
5425 case 0x007B: return "WM_CONTEXTMENU";
5426 case 0x007C: return "WM_STYLECHANGING";
5427 case 0x007D: return "WM_STYLECHANGED";
5428 case 0x007E: return "WM_DISPLAYCHANGE";
5429 case 0x007F: return "WM_GETICON";
5430 case 0x0080: return "WM_SETICON";
5432 case 0x0081: return "WM_NCCREATE";
5433 case 0x0082: return "WM_NCDESTROY";
5434 case 0x0083: return "WM_NCCALCSIZE";
5435 case 0x0084: return "WM_NCHITTEST";
5436 case 0x0085: return "WM_NCPAINT";
5437 case 0x0086: return "WM_NCACTIVATE";
5438 case 0x0087: return "WM_GETDLGCODE";
5439 case 0x00A0: return "WM_NCMOUSEMOVE";
5440 case 0x00A1: return "WM_NCLBUTTONDOWN";
5441 case 0x00A2: return "WM_NCLBUTTONUP";
5442 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
5443 case 0x00A4: return "WM_NCRBUTTONDOWN";
5444 case 0x00A5: return "WM_NCRBUTTONUP";
5445 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
5446 case 0x00A7: return "WM_NCMBUTTONDOWN";
5447 case 0x00A8: return "WM_NCMBUTTONUP";
5448 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
5449 case 0x0100: return "WM_KEYDOWN";
5450 case 0x0101: return "WM_KEYUP";
5451 case 0x0102: return "WM_CHAR";
5452 case 0x0103: return "WM_DEADCHAR";
5453 case 0x0104: return "WM_SYSKEYDOWN";
5454 case 0x0105: return "WM_SYSKEYUP";
5455 case 0x0106: return "WM_SYSCHAR";
5456 case 0x0107: return "WM_SYSDEADCHAR";
5457 case 0x0108: return "WM_KEYLAST";
5459 case 0x010D: return "WM_IME_STARTCOMPOSITION";
5460 case 0x010E: return "WM_IME_ENDCOMPOSITION";
5461 case 0x010F: return "WM_IME_COMPOSITION";
5463 case 0x0110: return "WM_INITDIALOG";
5464 case 0x0111: return "WM_COMMAND";
5465 case 0x0112: return "WM_SYSCOMMAND";
5466 case 0x0113: return "WM_TIMER";
5467 case 0x0114: return "WM_HSCROLL";
5468 case 0x0115: return "WM_VSCROLL";
5469 case 0x0116: return "WM_INITMENU";
5470 case 0x0117: return "WM_INITMENUPOPUP";
5471 case 0x011F: return "WM_MENUSELECT";
5472 case 0x0120: return "WM_MENUCHAR";
5473 case 0x0121: return "WM_ENTERIDLE";
5474 case 0x0200: return "WM_MOUSEMOVE";
5475 case 0x0201: return "WM_LBUTTONDOWN";
5476 case 0x0202: return "WM_LBUTTONUP";
5477 case 0x0203: return "WM_LBUTTONDBLCLK";
5478 case 0x0204: return "WM_RBUTTONDOWN";
5479 case 0x0205: return "WM_RBUTTONUP";
5480 case 0x0206: return "WM_RBUTTONDBLCLK";
5481 case 0x0207: return "WM_MBUTTONDOWN";
5482 case 0x0208: return "WM_MBUTTONUP";
5483 case 0x0209: return "WM_MBUTTONDBLCLK";
5484 case 0x020A: return "WM_MOUSEWHEEL";
5485 case 0x0210: return "WM_PARENTNOTIFY";
5486 case 0x0211: return "WM_ENTERMENULOOP";
5487 case 0x0212: return "WM_EXITMENULOOP";
5489 case 0x0213: return "WM_NEXTMENU";
5490 case 0x0214: return "WM_SIZING";
5491 case 0x0215: return "WM_CAPTURECHANGED";
5492 case 0x0216: return "WM_MOVING";
5493 case 0x0218: return "WM_POWERBROADCAST";
5494 case 0x0219: return "WM_DEVICECHANGE";
5496 case 0x0220: return "WM_MDICREATE";
5497 case 0x0221: return "WM_MDIDESTROY";
5498 case 0x0222: return "WM_MDIACTIVATE";
5499 case 0x0223: return "WM_MDIRESTORE";
5500 case 0x0224: return "WM_MDINEXT";
5501 case 0x0225: return "WM_MDIMAXIMIZE";
5502 case 0x0226: return "WM_MDITILE";
5503 case 0x0227: return "WM_MDICASCADE";
5504 case 0x0228: return "WM_MDIICONARRANGE";
5505 case 0x0229: return "WM_MDIGETACTIVE";
5506 case 0x0230: return "WM_MDISETMENU";
5507 case 0x0233: return "WM_DROPFILES";
5509 case 0x0281: return "WM_IME_SETCONTEXT";
5510 case 0x0282: return "WM_IME_NOTIFY";
5511 case 0x0283: return "WM_IME_CONTROL";
5512 case 0x0284: return "WM_IME_COMPOSITIONFULL";
5513 case 0x0285: return "WM_IME_SELECT";
5514 case 0x0286: return "WM_IME_CHAR";
5515 case 0x0290: return "WM_IME_KEYDOWN";
5516 case 0x0291: return "WM_IME_KEYUP";
5518 case 0x0300: return "WM_CUT";
5519 case 0x0301: return "WM_COPY";
5520 case 0x0302: return "WM_PASTE";
5521 case 0x0303: return "WM_CLEAR";
5522 case 0x0304: return "WM_UNDO";
5523 case 0x0305: return "WM_RENDERFORMAT";
5524 case 0x0306: return "WM_RENDERALLFORMATS";
5525 case 0x0307: return "WM_DESTROYCLIPBOARD";
5526 case 0x0308: return "WM_DRAWCLIPBOARD";
5527 case 0x0309: return "WM_PAINTCLIPBOARD";
5528 case 0x030A: return "WM_VSCROLLCLIPBOARD";
5529 case 0x030B: return "WM_SIZECLIPBOARD";
5530 case 0x030C: return "WM_ASKCBFORMATNAME";
5531 case 0x030D: return "WM_CHANGECBCHAIN";
5532 case 0x030E: return "WM_HSCROLLCLIPBOARD";
5533 case 0x030F: return "WM_QUERYNEWPALETTE";
5534 case 0x0310: return "WM_PALETTEISCHANGING";
5535 case 0x0311: return "WM_PALETTECHANGED";
5537 case 0x0312: return "WM_HOTKEY";
5540 // common controls messages - although they're not strictly speaking
5541 // standard, it's nice to decode them nevertheless
5544 case 0x1000 + 0: return "LVM_GETBKCOLOR";
5545 case 0x1000 + 1: return "LVM_SETBKCOLOR";
5546 case 0x1000 + 2: return "LVM_GETIMAGELIST";
5547 case 0x1000 + 3: return "LVM_SETIMAGELIST";
5548 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
5549 case 0x1000 + 5: return "LVM_GETITEMA";
5550 case 0x1000 + 75: return "LVM_GETITEMW";
5551 case 0x1000 + 6: return "LVM_SETITEMA";
5552 case 0x1000 + 76: return "LVM_SETITEMW";
5553 case 0x1000 + 7: return "LVM_INSERTITEMA";
5554 case 0x1000 + 77: return "LVM_INSERTITEMW";
5555 case 0x1000 + 8: return "LVM_DELETEITEM";
5556 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
5557 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
5558 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
5559 case 0x1000 + 12: return "LVM_GETNEXTITEM";
5560 case 0x1000 + 13: return "LVM_FINDITEMA";
5561 case 0x1000 + 83: return "LVM_FINDITEMW";
5562 case 0x1000 + 14: return "LVM_GETITEMRECT";
5563 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
5564 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
5565 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
5566 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
5567 case 0x1000 + 18: return "LVM_HITTEST";
5568 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
5569 case 0x1000 + 20: return "LVM_SCROLL";
5570 case 0x1000 + 21: return "LVM_REDRAWITEMS";
5571 case 0x1000 + 22: return "LVM_ARRANGE";
5572 case 0x1000 + 23: return "LVM_EDITLABELA";
5573 case 0x1000 + 118: return "LVM_EDITLABELW";
5574 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
5575 case 0x1000 + 25: return "LVM_GETCOLUMNA";
5576 case 0x1000 + 95: return "LVM_GETCOLUMNW";
5577 case 0x1000 + 26: return "LVM_SETCOLUMNA";
5578 case 0x1000 + 96: return "LVM_SETCOLUMNW";
5579 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
5580 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
5581 case 0x1000 + 28: return "LVM_DELETECOLUMN";
5582 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
5583 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
5584 case 0x1000 + 31: return "LVM_GETHEADER";
5585 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
5586 case 0x1000 + 34: return "LVM_GETVIEWRECT";
5587 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
5588 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
5589 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
5590 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
5591 case 0x1000 + 39: return "LVM_GETTOPINDEX";
5592 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
5593 case 0x1000 + 41: return "LVM_GETORIGIN";
5594 case 0x1000 + 42: return "LVM_UPDATE";
5595 case 0x1000 + 43: return "LVM_SETITEMSTATE";
5596 case 0x1000 + 44: return "LVM_GETITEMSTATE";
5597 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
5598 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
5599 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
5600 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
5601 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
5602 case 0x1000 + 48: return "LVM_SORTITEMS";
5603 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
5604 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
5605 case 0x1000 + 51: return "LVM_GETITEMSPACING";
5606 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
5607 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
5608 case 0x1000 + 53: return "LVM_SETICONSPACING";
5609 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
5610 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
5611 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
5612 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
5613 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
5614 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
5615 case 0x1000 + 60: return "LVM_SETHOTITEM";
5616 case 0x1000 + 61: return "LVM_GETHOTITEM";
5617 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
5618 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
5619 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
5620 case 0x1000 + 65: return "LVM_SETWORKAREA";
5623 case 0x1100 + 0: return "TVM_INSERTITEMA";
5624 case 0x1100 + 50: return "TVM_INSERTITEMW";
5625 case 0x1100 + 1: return "TVM_DELETEITEM";
5626 case 0x1100 + 2: return "TVM_EXPAND";
5627 case 0x1100 + 4: return "TVM_GETITEMRECT";
5628 case 0x1100 + 5: return "TVM_GETCOUNT";
5629 case 0x1100 + 6: return "TVM_GETINDENT";
5630 case 0x1100 + 7: return "TVM_SETINDENT";
5631 case 0x1100 + 8: return "TVM_GETIMAGELIST";
5632 case 0x1100 + 9: return "TVM_SETIMAGELIST";
5633 case 0x1100 + 10: return "TVM_GETNEXTITEM";
5634 case 0x1100 + 11: return "TVM_SELECTITEM";
5635 case 0x1100 + 12: return "TVM_GETITEMA";
5636 case 0x1100 + 62: return "TVM_GETITEMW";
5637 case 0x1100 + 13: return "TVM_SETITEMA";
5638 case 0x1100 + 63: return "TVM_SETITEMW";
5639 case 0x1100 + 14: return "TVM_EDITLABELA";
5640 case 0x1100 + 65: return "TVM_EDITLABELW";
5641 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
5642 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
5643 case 0x1100 + 17: return "TVM_HITTEST";
5644 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
5645 case 0x1100 + 19: return "TVM_SORTCHILDREN";
5646 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
5647 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
5648 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
5649 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
5650 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
5651 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
5652 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
5655 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
5656 case 0x1200 + 1: return "HDM_INSERTITEMA";
5657 case 0x1200 + 10: return "HDM_INSERTITEMW";
5658 case 0x1200 + 2: return "HDM_DELETEITEM";
5659 case 0x1200 + 3: return "HDM_GETITEMA";
5660 case 0x1200 + 11: return "HDM_GETITEMW";
5661 case 0x1200 + 4: return "HDM_SETITEMA";
5662 case 0x1200 + 12: return "HDM_SETITEMW";
5663 case 0x1200 + 5: return "HDM_LAYOUT";
5664 case 0x1200 + 6: return "HDM_HITTEST";
5665 case 0x1200 + 7: return "HDM_GETITEMRECT";
5666 case 0x1200 + 8: return "HDM_SETIMAGELIST";
5667 case 0x1200 + 9: return "HDM_GETIMAGELIST";
5668 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
5669 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
5670 case 0x1200 + 17: return "HDM_GETORDERARRAY";
5671 case 0x1200 + 18: return "HDM_SETORDERARRAY";
5672 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
5675 case 0x1300 + 2: return "TCM_GETIMAGELIST";
5676 case 0x1300 + 3: return "TCM_SETIMAGELIST";
5677 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
5678 case 0x1300 + 5: return "TCM_GETITEMA";
5679 case 0x1300 + 60: return "TCM_GETITEMW";
5680 case 0x1300 + 6: return "TCM_SETITEMA";
5681 case 0x1300 + 61: return "TCM_SETITEMW";
5682 case 0x1300 + 7: return "TCM_INSERTITEMA";
5683 case 0x1300 + 62: return "TCM_INSERTITEMW";
5684 case 0x1300 + 8: return "TCM_DELETEITEM";
5685 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
5686 case 0x1300 + 10: return "TCM_GETITEMRECT";
5687 case 0x1300 + 11: return "TCM_GETCURSEL";
5688 case 0x1300 + 12: return "TCM_SETCURSEL";
5689 case 0x1300 + 13: return "TCM_HITTEST";
5690 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
5691 case 0x1300 + 40: return "TCM_ADJUSTRECT";
5692 case 0x1300 + 41: return "TCM_SETITEMSIZE";
5693 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
5694 case 0x1300 + 43: return "TCM_SETPADDING";
5695 case 0x1300 + 44: return "TCM_GETROWCOUNT";
5696 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
5697 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
5698 case 0x1300 + 47: return "TCM_GETCURFOCUS";
5699 case 0x1300 + 48: return "TCM_SETCURFOCUS";
5700 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
5701 case 0x1300 + 50: return "TCM_DESELECTALL";
5704 case WM_USER
+1: return "TB_ENABLEBUTTON";
5705 case WM_USER
+2: return "TB_CHECKBUTTON";
5706 case WM_USER
+3: return "TB_PRESSBUTTON";
5707 case WM_USER
+4: return "TB_HIDEBUTTON";
5708 case WM_USER
+5: return "TB_INDETERMINATE";
5709 case WM_USER
+9: return "TB_ISBUTTONENABLED";
5710 case WM_USER
+10: return "TB_ISBUTTONCHECKED";
5711 case WM_USER
+11: return "TB_ISBUTTONPRESSED";
5712 case WM_USER
+12: return "TB_ISBUTTONHIDDEN";
5713 case WM_USER
+13: return "TB_ISBUTTONINDETERMINATE";
5714 case WM_USER
+17: return "TB_SETSTATE";
5715 case WM_USER
+18: return "TB_GETSTATE";
5716 case WM_USER
+19: return "TB_ADDBITMAP";
5717 case WM_USER
+20: return "TB_ADDBUTTONS";
5718 case WM_USER
+21: return "TB_INSERTBUTTON";
5719 case WM_USER
+22: return "TB_DELETEBUTTON";
5720 case WM_USER
+23: return "TB_GETBUTTON";
5721 case WM_USER
+24: return "TB_BUTTONCOUNT";
5722 case WM_USER
+25: return "TB_COMMANDTOINDEX";
5723 case WM_USER
+26: return "TB_SAVERESTOREA";
5724 case WM_USER
+76: return "TB_SAVERESTOREW";
5725 case WM_USER
+27: return "TB_CUSTOMIZE";
5726 case WM_USER
+28: return "TB_ADDSTRINGA";
5727 case WM_USER
+77: return "TB_ADDSTRINGW";
5728 case WM_USER
+29: return "TB_GETITEMRECT";
5729 case WM_USER
+30: return "TB_BUTTONSTRUCTSIZE";
5730 case WM_USER
+31: return "TB_SETBUTTONSIZE";
5731 case WM_USER
+32: return "TB_SETBITMAPSIZE";
5732 case WM_USER
+33: return "TB_AUTOSIZE";
5733 case WM_USER
+35: return "TB_GETTOOLTIPS";
5734 case WM_USER
+36: return "TB_SETTOOLTIPS";
5735 case WM_USER
+37: return "TB_SETPARENT";
5736 case WM_USER
+39: return "TB_SETROWS";
5737 case WM_USER
+40: return "TB_GETROWS";
5738 case WM_USER
+42: return "TB_SETCMDID";
5739 case WM_USER
+43: return "TB_CHANGEBITMAP";
5740 case WM_USER
+44: return "TB_GETBITMAP";
5741 case WM_USER
+45: return "TB_GETBUTTONTEXTA";
5742 case WM_USER
+75: return "TB_GETBUTTONTEXTW";
5743 case WM_USER
+46: return "TB_REPLACEBITMAP";
5744 case WM_USER
+47: return "TB_SETINDENT";
5745 case WM_USER
+48: return "TB_SETIMAGELIST";
5746 case WM_USER
+49: return "TB_GETIMAGELIST";
5747 case WM_USER
+50: return "TB_LOADIMAGES";
5748 case WM_USER
+51: return "TB_GETRECT";
5749 case WM_USER
+52: return "TB_SETHOTIMAGELIST";
5750 case WM_USER
+53: return "TB_GETHOTIMAGELIST";
5751 case WM_USER
+54: return "TB_SETDISABLEDIMAGELIST";
5752 case WM_USER
+55: return "TB_GETDISABLEDIMAGELIST";
5753 case WM_USER
+56: return "TB_SETSTYLE";
5754 case WM_USER
+57: return "TB_GETSTYLE";
5755 case WM_USER
+58: return "TB_GETBUTTONSIZE";
5756 case WM_USER
+59: return "TB_SETBUTTONWIDTH";
5757 case WM_USER
+60: return "TB_SETMAXTEXTROWS";
5758 case WM_USER
+61: return "TB_GETTEXTROWS";
5759 case WM_USER
+41: return "TB_GETBITMAPFLAGS";
5762 static char s_szBuf
[128];
5763 sprintf(s_szBuf
, "<unknown message = %d>", message
);
5767 #endif //__WXDEBUG__
5769 static TEXTMETRIC
wxGetTextMetrics(const wxWindowMSW
*win
)
5773 HWND hwnd
= GetHwndOf(win
);
5774 HDC hdc
= ::GetDC(hwnd
);
5776 #if !wxDIALOG_UNIT_COMPATIBILITY
5777 // and select the current font into it
5778 HFONT hfont
= GetHfontOf(win
->GetFont());
5781 hfont
= (HFONT
)::SelectObject(hdc
, hfont
);
5785 // finally retrieve the text metrics from it
5786 GetTextMetrics(hdc
, &tm
);
5788 #if !wxDIALOG_UNIT_COMPATIBILITY
5792 (void)::SelectObject(hdc
, hfont
);
5796 ::ReleaseDC(hwnd
, hdc
);
5801 // Find the wxWindow at the current mouse position, returning the mouse
5803 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
5805 pt
= wxGetMousePosition();
5806 return wxFindWindowAtPoint(pt
);
5809 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
)
5814 HWND hWndHit
= ::WindowFromPoint(pt2
);
5816 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
5817 HWND hWnd
= hWndHit
;
5819 // Try to find a window with a wxWindow associated with it
5820 while (!win
&& (hWnd
!= 0))
5822 hWnd
= ::GetParent(hWnd
);
5823 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
5828 // Get the current mouse position.
5829 wxPoint
wxGetMousePosition()
5833 GetCursorPosWinCE(&pt
);
5835 GetCursorPos( & pt
);
5838 return wxPoint(pt
.x
, pt
.y
);
5843 #if defined(__SMARTPHONE__) || defined(__POCKETPC__)
5844 static void WinCEUnregisterHotKey(int modifiers
, int id
)
5846 // Register hotkeys for the hardware buttons
5848 typedef BOOL (WINAPI
*UnregisterFunc1Proc
)(UINT
, UINT
);
5850 UnregisterFunc1Proc procUnregisterFunc
;
5851 hCoreDll
= LoadLibrary(_T("coredll.dll"));
5854 procUnregisterFunc
= (UnregisterFunc1Proc
)GetProcAddress(hCoreDll
, _T("UnregisterFunc1"));
5855 if (procUnregisterFunc
)
5856 procUnregisterFunc(modifiers
, id
);
5857 FreeLibrary(hCoreDll
);
5862 bool wxWindowMSW::RegisterHotKey(int hotkeyId
, int modifiers
, int keycode
)
5864 UINT win_modifiers
=0;
5865 if ( modifiers
& wxMOD_ALT
)
5866 win_modifiers
|= MOD_ALT
;
5867 if ( modifiers
& wxMOD_SHIFT
)
5868 win_modifiers
|= MOD_SHIFT
;
5869 if ( modifiers
& wxMOD_CONTROL
)
5870 win_modifiers
|= MOD_CONTROL
;
5871 if ( modifiers
& wxMOD_WIN
)
5872 win_modifiers
|= MOD_WIN
;
5874 #if defined(__SMARTPHONE__) || defined(__POCKETPC__)
5875 // Required for PPC and Smartphone hardware buttons
5876 if (keycode
>= WXK_SPECIAL1
&& keycode
<= WXK_SPECIAL20
)
5877 WinCEUnregisterHotKey(win_modifiers
, hotkeyId
);
5880 if ( !::RegisterHotKey(GetHwnd(), hotkeyId
, win_modifiers
, keycode
) )
5882 wxLogLastError(_T("RegisterHotKey"));
5890 bool wxWindowMSW::UnregisterHotKey(int hotkeyId
)
5892 #if defined(__SMARTPHONE__) || defined(__POCKETPC__)
5893 WinCEUnregisterHotKey(MOD_WIN
, hotkeyId
);
5896 if ( !::UnregisterHotKey(GetHwnd(), hotkeyId
) )
5898 wxLogLastError(_T("UnregisterHotKey"));
5908 bool wxWindowMSW::HandleHotKey(WXWPARAM wParam
, WXLPARAM lParam
)
5910 int hotkeyId
= wParam
;
5911 int virtualKey
= HIWORD(lParam
);
5912 int win_modifiers
= LOWORD(lParam
);
5914 wxKeyEvent
event(CreateKeyEvent(wxEVT_HOTKEY
, virtualKey
, wParam
, lParam
));
5915 event
.SetId(hotkeyId
);
5916 event
.m_shiftDown
= (win_modifiers
& MOD_SHIFT
) != 0;
5917 event
.m_controlDown
= (win_modifiers
& MOD_CONTROL
) != 0;
5918 event
.m_altDown
= (win_modifiers
& MOD_ALT
) != 0;
5919 event
.m_metaDown
= (win_modifiers
& MOD_WIN
) != 0;
5921 return GetEventHandler()->ProcessEvent(event
);
5924 #endif // wxUSE_ACCEL
5926 #endif // wxUSE_HOTKEY
5928 // Not tested under WinCE
5931 // this class installs a message hook which really wakes up our idle processing
5932 // each time a WM_NULL is received (wxWakeUpIdle does this), even if we're
5933 // sitting inside a local modal loop (e.g. a menu is opened or scrollbar is
5934 // being dragged or even inside ::MessageBox()) and so don't control message
5935 // dispatching otherwise
5936 class wxIdleWakeUpModule
: public wxModule
5939 virtual bool OnInit()
5941 ms_hMsgHookProc
= ::SetWindowsHookEx
5944 &wxIdleWakeUpModule::MsgHookProc
,
5946 GetCurrentThreadId()
5949 if ( !ms_hMsgHookProc
)
5951 wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)"));
5959 virtual void OnExit()
5961 ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc
);
5964 static LRESULT CALLBACK
MsgHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
5966 MSG
*msg
= (MSG
*)lParam
;
5968 // only process the message if it is actually going to be removed from
5969 // the message queue, this prevents that the same event from being
5970 // processed multiple times if now someone just called PeekMessage()
5971 if ( msg
->message
== WM_NULL
&& wParam
== PM_REMOVE
)
5973 wxTheApp
->ProcessPendingEvents();
5976 return CallNextHookEx(ms_hMsgHookProc
, nCode
, wParam
, lParam
);
5980 static HHOOK ms_hMsgHookProc
;
5982 DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule
)
5985 HHOOK
wxIdleWakeUpModule::ms_hMsgHookProc
= 0;
5987 IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule
, wxModule
)
5989 #endif // __WXWINCE__
5994 static void wxAdjustZOrder(wxWindow
* parent
)
5996 if (parent
->IsKindOf(CLASSINFO(wxStaticBox
)))
5998 // Set the z-order correctly
5999 SetWindowPos((HWND
) parent
->GetHWND(), HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
6002 wxWindowList::compatibility_iterator current
= parent
->GetChildren().GetFirst();
6005 wxWindow
*childWin
= current
->GetData();
6006 wxAdjustZOrder(childWin
);
6007 current
= current
->GetNext();
6012 // We need to adjust the z-order of static boxes in WinCE, to
6013 // make 'contained' controls visible
6014 void wxWindowMSW::OnInitDialog( wxInitDialogEvent
& event
)
6017 wxAdjustZOrder(this);