]> git.saurik.com Git - wxWidgets.git/blame - src/msw/window.cpp
Really set standard cursor when over title bar and decos
[wxWidgets.git] / src / msw / window.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
faa49bfd
WS
2// Name: src/msw/window.cpp
3// Purpose: wxWindowMSW
2bda0e17 4// Author: Julian Smart
a23fd0e1 5// Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation
2bda0e17
KB
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
a23fd0e1
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
09914df7 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
e4db172a
WS
27#include "wx/window.h"
28
2bda0e17 29#ifndef WX_PRECOMP
9ed0d735 30 #include "wx/msw/wrapwin.h"
57bd4c60
WS
31 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
32 #include "wx/msw/missing.h"
0c589ad0 33 #include "wx/accel.h"
3a19e16d
VZ
34 #include "wx/menu.h"
35 #include "wx/dc.h"
36 #include "wx/dcclient.h"
8e92ccef 37 #include "wx/dcmemory.h"
3a19e16d
VZ
38 #include "wx/utils.h"
39 #include "wx/app.h"
3a19e16d
VZ
40 #include "wx/layout.h"
41 #include "wx/dialog.h"
42 #include "wx/frame.h"
43 #include "wx/listbox.h"
44 #include "wx/button.h"
3a19e16d 45 #include "wx/msgdlg.h"
1f3943e0 46 #include "wx/settings.h"
8d753488 47 #include "wx/statbox.h"
1e2aa2f8 48 #include "wx/sizer.h"
88a7a4e1 49 #include "wx/intl.h"
e4db172a 50 #include "wx/log.h"
fec9cc08 51 #include "wx/textctrl.h"
25466131 52 #include "wx/menuitem.h"
02761f6c 53 #include "wx/module.h"
2bda0e17
KB
54#endif
55
61fef19b 56#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
09914df7 57 #include "wx/ownerdrw.h"
2bda0e17
KB
58#endif
59
5acec112 60#include "wx/hashmap.h"
a3dc1da9 61#include "wx/evtloop.h"
355debca 62#include "wx/power.h"
c6430ed0 63#include "wx/sysopt.h"
d79df32c 64
9e2896e5
VZ
65#if wxUSE_DRAG_AND_DROP
66 #include "wx/dnd.h"
2bda0e17
KB
67#endif
68
ed5317e5
JS
69#if wxUSE_ACCESSIBILITY
70 #include "wx/access.h"
bef8d481 71 #include <ole2.h>
ed5317e5
JS
72 #include <oleacc.h>
73 #ifndef WM_GETOBJECT
74 #define WM_GETOBJECT 0x003D
75 #endif
76 #ifndef OBJID_CLIENT
77 #define OBJID_CLIENT 0xFFFFFFFC
78 #endif
79#endif
80
0c589ad0 81#include "wx/msw/private.h"
888dde65 82#include "wx/msw/dcclient.h"
0c589ad0 83
750b78ba 84#if wxUSE_TOOLTIPS
42e69d6b 85 #include "wx/tooltip.h"
750b78ba
JS
86#endif
87
789295bf
VZ
88#if wxUSE_CARET
89 #include "wx/caret.h"
90#endif // wxUSE_CARET
91
6fe19057
VZ
92#if wxUSE_SPINCTRL
93 #include "wx/spinctrl.h"
94#endif // wxUSE_SPINCTRL
95
d9317fd4 96#include "wx/notebook.h"
5c6c3176 97#include "wx/listctrl.h"
aafb9978 98#include "wx/dynlib.h"
2a47d3c1 99
2bda0e17
KB
100#include <string.h>
101
d61c1a6f 102#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
3a19e16d
VZ
103 #include <shellapi.h>
104 #include <mmsystem.h>
2bda0e17
KB
105#endif
106
107#ifdef __WIN32__
3a19e16d 108 #include <windowsx.h>
2bda0e17
KB
109#endif
110
dcfd4ac4 111#if !defined __WXWINCE__ && !defined NEED_PBT_H
dbc74bcc
WS
112 #include <pbt.h>
113#endif
2bda0e17 114
7f0586ef 115#if defined(__WXWINCE__)
4e5c6c33 116 #include "wx/msw/wince/missing.h"
7d4f65e3
JS
117#ifdef __POCKETPC__
118 #include <windows.h>
119 #include <shellapi.h>
120 #include <ole2.h>
121 #include <aygshell.h>
122#endif
7f0586ef
JS
123#endif
124
a047aff2
JS
125#if wxUSE_UXTHEME
126 #include "wx/msw/uxtheme.h"
127 #define EP_EDITTEXT 1
128 #define ETS_NORMAL 1
129 #define ETS_HOT 2
130 #define ETS_SELECTED 3
131 #define ETS_DISABLED 4
132 #define ETS_FOCUSED 5
133 #define ETS_READONLY 6
134 #define ETS_ASSIST 7
135#endif
136
21487550
VZ
137// define the constants used by AnimateWindow() if our SDK doesn't have them
138#ifndef AW_CENTER
139 #define AW_HOR_POSITIVE 0x00000001
140 #define AW_HOR_NEGATIVE 0x00000002
141 #define AW_VER_POSITIVE 0x00000004
142 #define AW_VER_NEGATIVE 0x00000008
143 #define AW_CENTER 0x00000010
144 #define AW_HIDE 0x00010000
145 #define AW_ACTIVATE 0x00020000
146 #define AW_SLIDE 0x00040000
147 #define AW_BLEND 0x00080000
148#endif
149
aafb9978 150#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS
4e5c6c33
VZ
151 #define HAVE_TRACKMOUSEEVENT
152#endif // everything needed for TrackMouseEvent()
153
7d86a2d4
VZ
154// if this is set to 1, we use deferred window sizing to reduce flicker when
155// resizing complicated window hierarchies, but this can in theory result in
156// different behaviour than the old code so we keep the possibility to use it
157// by setting this to 0 (in the future this should be removed completely)
f2197644
JS
158#ifdef __WXWINCE__
159#define USE_DEFERRED_SIZING 0
160#else
8e44f3ca 161#define USE_DEFERRED_SIZING 1
f2197644 162#endif
8e44f3ca 163
c358ea41
VZ
164// set this to 1 to filter out duplicate mouse events, e.g. mouse move events
165// when mouse position didnd't change
166#ifdef __WXWINCE__
167 #define wxUSE_MOUSEEVENT_HACK 0
168#else
169 #define wxUSE_MOUSEEVENT_HACK 1
170#endif
171
2f68482e
VZ
172// not all compilers/platforms have X button related declarations (notably
173// Windows CE doesn't, and probably some old SDKs don't neither)
174#ifdef WM_XBUTTONDOWN
175 #define wxHAS_XBUTTON
176#endif
177
a23fd0e1 178// ---------------------------------------------------------------------------
42e69d6b 179// global variables
a23fd0e1 180// ---------------------------------------------------------------------------
47cbd6da 181
1950edc3
RR
182#if wxUSE_MENUS_NATIVE
183extern wxMenu *wxCurrentPopupMenu;
184#endif
185
90c1530a
VZ
186// true if we had already created the std colour map, used by
187// wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
08158721 188static bool gs_hasStdCmap = false;
90c1530a 189
c358ea41
VZ
190// last mouse event information we need to filter out the duplicates
191#if wxUSE_MOUSEEVENT_HACK
2b053ae9 192static struct MouseEventInfoDummy
c358ea41
VZ
193{
194 // mouse position (in screen coordinates)
195 wxPoint pos;
196
197 // last mouse event type
198 wxEventType type;
199} gs_lastMouseEvent;
200#endif // wxUSE_MOUSEEVENT_HACK
201
5acec112
VZ
202// hash containing the registered handlers for the custom messages
203WX_DECLARE_HASH_MAP(int, wxWindow::MSWMessageHandler,
204 wxIntegerHash, wxIntegerEqual,
205 MSWMessageHandlers);
206
207static MSWMessageHandlers gs_messageHandlers;
208
dca0f651
VZ
209// hash containing all our windows, it uses HWND keys and wxWindow* values
210WX_DECLARE_HASH_MAP(HWND, wxWindow *,
211 wxPointerHash, wxPointerEqual,
212 WindowHandles);
213
214static WindowHandles gs_windowHandles;
215
42e69d6b
VZ
216// ---------------------------------------------------------------------------
217// private functions
218// ---------------------------------------------------------------------------
219
220// the window proc for all our windows
3135f4a7 221LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
42e69d6b 222 WPARAM wParam, LPARAM lParam);
577baeef 223
42e69d6b
VZ
224
225#ifdef __WXDEBUG__
4a712ba3 226 const wxChar *wxGetMessageName(int message);
42e69d6b 227#endif //__WXDEBUG__
2bda0e17 228
1e6feb95 229void wxRemoveHandleAssociation(wxWindowMSW *win);
cc972ac6 230extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
2bda0e17 231
f6bcfd97 232// get the text metrics for the current font
1e6feb95
VZ
233static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
234
42b1fb63 235#ifdef __WXWINCE__
dfafa702 236// find the window for the mouse event at the specified position
42b1fb63
VZ
237static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y);
238#endif // __WXWINCE__
dfafa702 239
c48926e1 240// wrapper around BringWindowToTop() API
44d5b352 241static inline void wxBringWindowToTop(HWND hwnd)
c48926e1
VZ
242{
243#ifdef __WXMICROWIN__
244 // It seems that MicroWindows brings the _parent_ of the window to the top,
245 // which can be the wrong one.
246
247 // activate (set focus to) specified window
248 ::SetFocus(hwnd);
313901f3 249#endif
c48926e1
VZ
250
251 // raise top level parent to top of z order
313901f3 252 if (!::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE))
c48926e1 253 {
313901f3 254 wxLogLastError(_T("SetWindowPos"));
c48926e1 255 }
c48926e1 256}
f6bcfd97 257
e0c5c96f
VZ
258#ifndef __WXWINCE__
259
ee471817
VZ
260// ensure that all our parent windows have WS_EX_CONTROLPARENT style
261static void EnsureParentHasControlParentStyle(wxWindow *parent)
262{
263 /*
264 If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
265 parent as well as otherwise several Win32 functions using
266 GetNextDlgTabItem() to iterate over all controls such as
267 IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
268 all of them iterate over all the controls starting from the currently
269 focused one and stop iterating when they get back to the focus but
270 unless all parents have WS_EX_CONTROLPARENT bit set, they would never
271 get back to the initial (focused) window: as we do have this style,
272 GetNextDlgTabItem() will leave this window and continue in its parent,
273 but if the parent doesn't have it, it wouldn't recurse inside it later
90e572f1 274 on and so wouldn't have a chance of getting back to this window either.
ee471817 275 */
ee471817
VZ
276 while ( parent && !parent->IsTopLevel() )
277 {
d66d0500 278 LONG exStyle = wxGetWindowExStyle(parent);
ee471817
VZ
279 if ( !(exStyle & WS_EX_CONTROLPARENT) )
280 {
281 // force the parent to have this style
d66d0500 282 wxSetWindowExStyle(parent, exStyle | WS_EX_CONTROLPARENT);
ee471817
VZ
283 }
284
285 parent = parent->GetParent();
286 }
ee471817
VZ
287}
288
e0c5c96f
VZ
289#endif // !__WXWINCE__
290
f2325516
JS
291#ifdef __WXWINCE__
292// On Windows CE, GetCursorPos can return an error, so use this function
293// instead
294bool GetCursorPosWinCE(POINT* pt)
295{
7d30268c
JS
296 if (!GetCursorPos(pt))
297 {
298 DWORD pos = GetMessagePos();
299 pt->x = LOWORD(pos);
300 pt->y = HIWORD(pos);
301 }
f2325516
JS
302 return true;
303}
304#endif
305
a23fd0e1
VZ
306// ---------------------------------------------------------------------------
307// event tables
308// ---------------------------------------------------------------------------
309
1e6feb95
VZ
310// in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
311// method
312#ifdef __WXUNIVERSAL__
313 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW, wxWindowBase)
314#else // __WXMSW__
51596bcb 315#if wxUSE_EXTENDED_RTTI
6a89f9ee 316
f3291a82
SC
317// windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls
318// must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as
319// windows with negative ids never can be recreated anyway
320
321bool wxWindowStreamingCallback( const wxObject *object, wxWriter * , wxPersister * , wxxVariantArray & )
322{
323 const wxWindow * win = dynamic_cast<const wxWindow*>(object) ;
324 if ( win && win->GetId() < 0 )
325 return false ;
326 return true ;
327}
328
329IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow, wxWindowBase,"wx/window.h", wxWindowStreamingCallback)
51596bcb 330
6a89f9ee
SC
331// make wxWindowList known before the property is used
332
321239b6 333wxCOLLECTION_TYPE_INFO( wxWindow* , wxWindowList ) ;
6a89f9ee
SC
334
335template<> void wxCollectionToVariantArray( wxWindowList const &theList, wxxVariantArray &value)
336{
0c6b0084 337 wxListCollectionToVariantArray<wxWindowList::compatibility_iterator>( theList , value ) ;
6a89f9ee
SC
338}
339
bc9fb572
JS
340WX_DEFINE_FLAGS( wxWindowStyle )
341
321239b6 342wxBEGIN_FLAGS( wxWindowStyle )
bc9fb572
JS
343 // new style border flags, we put them first to
344 // use them for streaming out
5c6c3176 345
321239b6
SC
346 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
347 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
348 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
349 wxFLAGS_MEMBER(wxBORDER_RAISED)
350 wxFLAGS_MEMBER(wxBORDER_STATIC)
351 wxFLAGS_MEMBER(wxBORDER_NONE)
35bbb0c6 352
bc9fb572 353 // old style border flags
321239b6
SC
354 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
355 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
356 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
357 wxFLAGS_MEMBER(wxRAISED_BORDER)
358 wxFLAGS_MEMBER(wxSTATIC_BORDER)
cb0afb26 359 wxFLAGS_MEMBER(wxBORDER)
bc9fb572
JS
360
361 // standard window styles
321239b6
SC
362 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
363 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
364 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
365 wxFLAGS_MEMBER(wxWANTS_CHARS)
cb0afb26 366 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
321239b6
SC
367 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
368 wxFLAGS_MEMBER(wxVSCROLL)
369 wxFLAGS_MEMBER(wxHSCROLL)
370
371wxEND_FLAGS( wxWindowStyle )
372
373wxBEGIN_PROPERTIES_TABLE(wxWindow)
3a3c8603
DS
374 wxEVENT_PROPERTY( Close , wxEVT_CLOSE_WINDOW , wxCloseEvent)
375 wxEVENT_PROPERTY( Create , wxEVT_CREATE , wxWindowCreateEvent )
376 wxEVENT_PROPERTY( Destroy , wxEVT_DESTROY , wxWindowDestroyEvent )
51741307
SC
377 // Always constructor Properties first
378
af498247 379 wxREADONLY_PROPERTY( Parent,wxWindow*, GetParent, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
fb7e28db 380 wxPROPERTY( Id,wxWindowID, SetId, GetId, -1 /*wxID_ANY*/ , 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
abb74e0f
WS
381 wxPROPERTY( Position,wxPoint, SetPosition , GetPosition, wxDefaultPosition , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos
382 wxPROPERTY( Size,wxSize, SetSize, GetSize, wxDefaultSize , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size
af498247 383 wxPROPERTY( WindowStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
51741307
SC
384
385 // Then all relations of the object graph
386
321239b6 387 wxREADONLY_PROPERTY_COLLECTION( Children , wxWindowList , wxWindowBase* , GetWindowChildren , wxPROP_OBJECT_GRAPH /*flags*/ , wxT("Helpstring") , wxT("group"))
51741307
SC
388
389 // and finally all other properties
390
3a3c8603
DS
391 wxPROPERTY( ExtraStyle , long , SetExtraStyle , GetExtraStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle
392 wxPROPERTY( BackgroundColour , wxColour , SetBackgroundColour , GetBackgroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg
393 wxPROPERTY( ForegroundColour , wxColour , SetForegroundColour , GetForegroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg
394 wxPROPERTY( Enabled , bool , Enable , IsEnabled , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
395 wxPROPERTY( Shown , bool , Show , IsShown , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
51741307
SC
396#if 0
397 // possible property candidates (not in xrc) or not valid in all subclasses
8b5d5223 398 wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxEmptyString )
3a3c8603 399 wxPROPERTY( Font , wxFont , SetFont , GetWindowFont , )
8b5d5223 400 wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxEmptyString )
3a3c8603
DS
401 // MaxHeight, Width , MinHeight , Width
402 // TODO switch label to control and title to toplevels
6a89f9ee 403
3a3c8603
DS
404 wxPROPERTY( ThemeEnabled , bool , SetThemeEnabled , GetThemeEnabled , )
405 //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , )
406 // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , )
407 wxPROPERTY( AutoLayout , bool , SetAutoLayout , GetAutoLayout , )
6a89f9ee
SC
408
409
410
51741307 411#endif
321239b6 412wxEND_PROPERTIES_TABLE()
51596bcb 413
321239b6
SC
414wxBEGIN_HANDLERS_TABLE(wxWindow)
415wxEND_HANDLERS_TABLE()
51596bcb 416
321239b6 417wxCONSTRUCTOR_DUMMY(wxWindow)
6a89f9ee 418
51596bcb 419#else
1e6feb95 420 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
51596bcb 421#endif
1e6feb95
VZ
422#endif // __WXUNIVERSAL__/__WXMSW__
423
424BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase)
1e6feb95 425 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged)
8681b094 426 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
79099b80 427#ifdef __WXWINCE__
1e6feb95 428 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
79099b80 429#endif
2bda0e17
KB
430END_EVENT_TABLE()
431
a23fd0e1
VZ
432// ===========================================================================
433// implementation
434// ===========================================================================
435
42e69d6b
VZ
436// ---------------------------------------------------------------------------
437// wxWindow utility functions
438// ---------------------------------------------------------------------------
439
2bda0e17 440// Find an item given the MS Windows id
1e6feb95 441wxWindow *wxWindowMSW::FindItem(long id) const
2bda0e17 442{
1e6feb95 443#if wxUSE_CONTROLS
f7637829 444 wxControl *item = wxDynamicCastThis(wxControl);
f048e32f
VZ
445 if ( item )
446 {
90e572f1 447 // is it us or one of our "internal" children?
1e6feb95
VZ
448 if ( item->GetId() == id
449#ifndef __WXUNIVERSAL__
450 || (item->GetSubcontrols().Index(id) != wxNOT_FOUND)
451#endif // __WXUNIVERSAL__
452 )
f048e32f
VZ
453 {
454 return item;
455 }
456 }
1e6feb95 457#endif // wxUSE_CONTROLS
f048e32f 458
222ed1d6 459 wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
2d0a075d
JS
460 while (current)
461 {
42e69d6b 462 wxWindow *childWin = current->GetData();
2bda0e17 463
42e69d6b 464 wxWindow *wnd = childWin->FindItem(id);
cc2b7472 465 if ( wnd )
42e69d6b 466 return wnd;
2bda0e17 467
42e69d6b 468 current = current->GetNext();
2bda0e17 469 }
42e69d6b 470
2d0a075d 471 return NULL;
2bda0e17
KB
472}
473
474// Find an item given the MS Windows handle
1e6feb95 475wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const
2bda0e17 476{
222ed1d6 477 wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
2d0a075d 478 while (current)
2bda0e17 479 {
42e69d6b
VZ
480 wxWindow *parent = current->GetData();
481
2d0a075d 482 // Do a recursive search.
42e69d6b 483 wxWindow *wnd = parent->FindItemByHWND(hWnd);
cc2b7472 484 if ( wnd )
42e69d6b 485 return wnd;
2d0a075d 486
1e6feb95
VZ
487 if ( !controlOnly
488#if wxUSE_CONTROLS
489 || parent->IsKindOf(CLASSINFO(wxControl))
490#endif // wxUSE_CONTROLS
491 )
2d0a075d 492 {
42e69d6b
VZ
493 wxWindow *item = current->GetData();
494 if ( item->GetHWND() == hWnd )
2d0a075d
JS
495 return item;
496 else
497 {
498 if ( item->ContainsHWND(hWnd) )
499 return item;
500 }
501 }
42e69d6b
VZ
502
503 current = current->GetNext();
2bda0e17 504 }
2d0a075d 505 return NULL;
2bda0e17
KB
506}
507
508// Default command handler
1e6feb95 509bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id))
2bda0e17 510{
08158721 511 return false;
2bda0e17
KB
512}
513
fd3f686c
VZ
514// ----------------------------------------------------------------------------
515// constructors and such
516// ----------------------------------------------------------------------------
517
1e6feb95 518void wxWindowMSW::Init()
2bda0e17 519{
cc2b7472 520 // MSW specific
08158721 521 m_isBeingDeleted = false;
5a403e3f 522 m_oldWndProc = NULL;
08158721
DS
523 m_mouseInWindow = false;
524 m_lastKeydownProcessed = false;
2bda0e17 525
319fefa9 526 m_hWnd = 0;
220f77b0 527 m_hDWP = 0;
319fefa9 528
2d0a075d
JS
529 m_xThumbSize = 0;
530 m_yThumbSize = 0;
2bda0e17 531
67644c1d
RD
532 m_pendingPosition = wxDefaultPosition;
533 m_pendingSize = wxDefaultSize;
7d4f65e3
JS
534
535#ifdef __POCKETPC__
536 m_contextMenuEnabled = false;
537#endif
fd3f686c
VZ
538}
539
2bda0e17 540// Destructor
1e6feb95 541wxWindowMSW::~wxWindowMSW()
2bda0e17 542{
08158721 543 m_isBeingDeleted = true;
2bda0e17 544
2e9f62da 545#ifndef __WXUNIVERSAL__
4a41c655 546 // VS: make sure there's no wxFrame with last focus set to us:
2e9f62da 547 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
4a41c655 548 {
085ad686 549 wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
4a41c655
VS
550 if ( frame )
551 {
c5053639 552 if ( frame->GetLastFocus() == this )
2e9f62da 553 {
085ad686 554 frame->SetLastFocus(NULL);
2e9f62da 555 }
4552892f
VZ
556
557 // apparently sometimes we can end up with our grand parent
558 // pointing to us as well: this is surely a bug in focus handling
559 // code but it's not clear where it happens so for now just try to
560 // fix it here by not breaking out of the loop
561 //break;
4a41c655
VS
562 }
563 }
2e9f62da 564#endif // __WXUNIVERSAL__
2bda0e17 565
cc0c7cd8 566 // VS: destroy children first and _then_ detach *this from its parent.
90e572f1 567 // If we did it the other way around, children wouldn't be able
cc0c7cd8
VS
568 // find their parent frame (see above).
569 DestroyChildren();
570
cc2b7472 571 if ( m_hWnd )
42e69d6b 572 {
98440bc3
VZ
573 // VZ: test temp removed to understand what really happens here
574 //if (::IsWindow(GetHwnd()))
df61c009
JS
575 {
576 if ( !::DestroyWindow(GetHwnd()) )
f6bcfd97 577 wxLogLastError(wxT("DestroyWindow"));
df61c009 578 }
2bda0e17 579
c50f1fb9
VZ
580 // remove hWnd <-> wxWindow association
581 wxRemoveHandleAssociation(this);
582 }
d7cbabe0 583
2bda0e17
KB
584}
585
d9698bd4
VZ
586/* static */
587const wxChar *wxWindowMSW::MSWGetRegisteredClassName()
588{
589 return wxApp::GetRegisteredClassName(_T("wxWindow"), COLOR_BTNFACE);
590}
591
fd3f686c 592// real construction (Init() must have been called before!)
1e6feb95
VZ
593bool wxWindowMSW::Create(wxWindow *parent,
594 wxWindowID id,
595 const wxPoint& pos,
596 const wxSize& size,
597 long style,
598 const wxString& name)
2d0a075d 599{
08158721 600 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
2bda0e17 601
8d99be5f 602 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
08158721 603 return false;
42e69d6b 604
fd3f686c 605 parent->AddChild(this);
2bda0e17 606
b2d5a7ee 607 WXDWORD exstyle;
e49d97e6 608 DWORD msflags = MSWGetCreateWindowFlags(&exstyle);
1e6feb95
VZ
609
610#ifdef __WXUNIVERSAL__
d1fe917b 611 // no borders, we draw them ourselves
76c79ff4
VZ
612 exstyle &= ~(WS_EX_DLGMODALFRAME |
613 WS_EX_STATICEDGE |
614 WS_EX_CLIENTEDGE |
615 WS_EX_WINDOWEDGE);
d1fe917b 616 msflags &= ~WS_BORDER;
b2d5a7ee 617#endif // wxUniversal
1e6feb95 618
ff792344 619 if ( IsShown() )
e49d97e6
VZ
620 {
621 msflags |= WS_VISIBLE;
622 }
1e6feb95 623
d9698bd4
VZ
624 if ( !MSWCreate(MSWGetRegisteredClassName(),
625 NULL, pos, size, msflags, exstyle) )
45956e37
VZ
626 return false;
627
628 InheritAttributes();
629
630 return true;
2bda0e17
KB
631}
632
42e69d6b
VZ
633// ---------------------------------------------------------------------------
634// basic operations
635// ---------------------------------------------------------------------------
636
1e6feb95 637void wxWindowMSW::SetFocus()
2bda0e17 638{
a23fd0e1 639 HWND hWnd = GetHwnd();
1e6feb95
VZ
640 wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
641
7f0586ef 642#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95 643 ::SetLastError(0);
8cb172b4 644#endif
d0a3d109 645
1e6feb95
VZ
646 if ( !::SetFocus(hWnd) )
647 {
5262eb0a 648#if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
1e6feb95
VZ
649 // was there really an error?
650 DWORD dwRes = ::GetLastError();
651 if ( dwRes )
652 {
5262eb0a
VZ
653 HWND hwndFocus = ::GetFocus();
654 if ( hwndFocus != hWnd )
655 {
656 wxLogApiError(_T("SetFocus"), dwRes);
657 }
1e6feb95 658 }
5262eb0a 659#endif // Debug
1e6feb95 660 }
2bda0e17
KB
661}
662
ddf9d04f
VZ
663void wxWindowMSW::SetFocusFromKbd()
664{
ddf9d04f
VZ
665 // when the focus is given to the control with DLGC_HASSETSEL style from
666 // keyboard its contents should be entirely selected: this is what
667 // ::IsDialogMessage() does and so we should do it as well to provide the
668 // same LNF as the native programs
669 if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE, 0, 0) & DLGC_HASSETSEL )
670 {
671 ::SendMessage(GetHwnd(), EM_SETSEL, 0, -1);
672 }
1b1ca07a
VZ
673
674 // do this after (maybe) setting the selection as like this when
675 // wxEVT_SET_FOCUS handler is called, the selection would have been already
676 // set correctly -- this may be important
677 wxWindowBase::SetFocusFromKbd();
ddf9d04f
VZ
678}
679
42e69d6b 680// Get the window with the focus
0fe02759 681wxWindow *wxWindowBase::DoFindFocus()
42e69d6b
VZ
682{
683 HWND hWnd = ::GetFocus();
684 if ( hWnd )
685 {
a2242341 686 return wxGetWindowFromHWND((WXHWND)hWnd);
42e69d6b
VZ
687 }
688
689 return NULL;
690}
691
47a8a4d5 692void wxWindowMSW::DoEnable( bool enable )
2bda0e17 693{
a23fd0e1 694 HWND hWnd = GetHwnd();
cc2b7472 695 if ( hWnd )
2d0a075d 696 ::EnableWindow(hWnd, (BOOL)enable);
2bda0e17
KB
697}
698
1e6feb95 699bool wxWindowMSW::Show(bool show)
42e69d6b
VZ
700{
701 if ( !wxWindowBase::Show(show) )
08158721 702 return false;
42e69d6b
VZ
703
704 HWND hWnd = GetHwnd();
42e69d6b 705
a068160f
VZ
706 // we could be called before the underlying window is created (this is
707 // actually useful to prevent it from being initially shown), e.g.
708 //
709 // wxFoo *foo = new wxFoo;
710 // foo->Hide();
711 // foo->Create(parent, ...);
712 //
713 // should work without errors
714 if ( hWnd )
42e69d6b 715 {
a068160f 716 ::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
42e69d6b
VZ
717 }
718
89267fe5
VS
719 if ( IsFrozen() )
720 {
721 // DoFreeze/DoThaw don't do anything if the window is not shown, so
722 // we have to call them from here now
723 if ( show )
724 DoFreeze();
725 else
726 DoThaw();
727 }
728
08158721 729 return true;
42e69d6b
VZ
730}
731
376d7d97
VZ
732bool
733wxWindowMSW::MSWShowWithEffect(bool show,
734 wxShowEffect effect,
eed04c99 735 unsigned timeout)
376d7d97 736{
30443550
VS
737 if ( !wxWindowBase::Show(show) )
738 return false;
739
376d7d97
VZ
740 typedef BOOL (WINAPI *AnimateWindow_t)(HWND, DWORD, DWORD);
741
742 static AnimateWindow_t s_pfnAnimateWindow = NULL;
743 static bool s_initDone = false;
744 if ( !s_initDone )
745 {
e2fc2bd5 746 wxDynamicLibrary dllUser32(_T("user32.dll"), wxDL_VERBATIM | wxDL_QUIET);
376d7d97
VZ
747 wxDL_INIT_FUNC(s_pfn, AnimateWindow, dllUser32);
748
749 s_initDone = true;
750
751 // notice that it's ok to unload user32.dll here as it won't be really
752 // unloaded, being still in use because we link to it statically too
753 }
754
755 if ( !s_pfnAnimateWindow )
756 return Show(show);
757
7157abfb
VZ
758 // Show() has a side effect of sending a WM_SIZE to the window, which helps
759 // ensuring that it's laid out correctly, but AnimateWindow() doesn't do
760 // this so send the event ourselves
761 SendSizeEvent();
762
376d7d97
VZ
763 // prepare to use AnimateWindow()
764
765 if ( !timeout )
766 timeout = 200; // this is the default animation timeout, per MSDN
767
768 DWORD dwFlags = show ? 0 : AW_HIDE;
eed04c99 769
376d7d97
VZ
770 switch ( effect )
771 {
eed04c99
VS
772 case wxSHOW_EFFECT_ROLL_TO_LEFT:
773 dwFlags |= AW_HOR_NEGATIVE;
774 break;
775
776 case wxSHOW_EFFECT_ROLL_TO_RIGHT:
777 dwFlags |= AW_HOR_POSITIVE;
778 break;
779
780 case wxSHOW_EFFECT_ROLL_TO_TOP:
781 dwFlags |= AW_VER_NEGATIVE;
782 break;
783
784 case wxSHOW_EFFECT_ROLL_TO_BOTTOM:
785 dwFlags |= AW_VER_POSITIVE;
786 break;
787
788 case wxSHOW_EFFECT_SLIDE_TO_LEFT:
789 dwFlags |= AW_SLIDE | AW_HOR_NEGATIVE;
790 break;
791
792 case wxSHOW_EFFECT_SLIDE_TO_RIGHT:
793 dwFlags |= AW_SLIDE | AW_HOR_POSITIVE;
794 break;
795
796 case wxSHOW_EFFECT_SLIDE_TO_TOP:
797 dwFlags |= AW_SLIDE | AW_VER_NEGATIVE;
376d7d97
VZ
798 break;
799
eed04c99
VS
800 case wxSHOW_EFFECT_SLIDE_TO_BOTTOM:
801 dwFlags |= AW_SLIDE | AW_VER_POSITIVE;
376d7d97
VZ
802 break;
803
804 case wxSHOW_EFFECT_BLEND:
805 dwFlags |= AW_BLEND;
806 break;
807
808 case wxSHOW_EFFECT_EXPAND:
809 dwFlags |= AW_CENTER;
810 break;
811
812
813 case wxSHOW_EFFECT_MAX:
814 wxFAIL_MSG( _T("invalid window show effect") );
815 return false;
816
817 default:
818 wxFAIL_MSG( _T("unknown window show effect") );
819 return false;
820 }
821
376d7d97
VZ
822 if ( !(*s_pfnAnimateWindow)(GetHwnd(), timeout, dwFlags) )
823 {
824 wxLogLastError(_T("AnimateWindow"));
825
826 return false;
827 }
828
829 return true;
830}
831
42e69d6b 832// Raise the window to the top of the Z order
1e6feb95 833void wxWindowMSW::Raise()
42e69d6b 834{
c48926e1 835 wxBringWindowToTop(GetHwnd());
42e69d6b
VZ
836}
837
838// Lower the window to the bottom of the Z order
1e6feb95 839void wxWindowMSW::Lower()
42e69d6b
VZ
840{
841 ::SetWindowPos(GetHwnd(), HWND_BOTTOM, 0, 0, 0, 0,
842 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
843}
844
94633ad9 845void wxWindowMSW::DoCaptureMouse()
2bda0e17 846{
a23fd0e1 847 HWND hWnd = GetHwnd();
1e6feb95 848 if ( hWnd )
2d0a075d 849 {
1e6feb95 850 ::SetCapture(hWnd);
2d0a075d 851 }
2bda0e17
KB
852}
853
94633ad9 854void wxWindowMSW::DoReleaseMouse()
2bda0e17 855{
1e6feb95 856 if ( !::ReleaseCapture() )
2d0a075d 857 {
1e6feb95 858 wxLogLastError(_T("ReleaseCapture"));
2d0a075d 859 }
2bda0e17
KB
860}
861
1e6feb95
VZ
862/* static */ wxWindow *wxWindowBase::GetCapture()
863{
864 HWND hwnd = ::GetCapture();
dca0f651 865 return hwnd ? wxFindWinFromHandle(hwnd) : NULL;
1e6feb95
VZ
866}
867
868bool wxWindowMSW::SetFont(const wxFont& font)
2bda0e17 869{
42e69d6b
VZ
870 if ( !wxWindowBase::SetFont(font) )
871 {
872 // nothing to do
08158721 873 return false;
2d0a075d 874 }
195896c7 875
42e69d6b
VZ
876 HWND hWnd = GetHwnd();
877 if ( hWnd != 0 )
878 {
d8df8893
VZ
879 // note the use of GetFont() instead of m_font: our own font could have
880 // just been reset and in this case we need to change the font used by
881 // the native window to the default for this class, i.e. exactly what
882 // GetFont() returns
883 WXHANDLE hFont = GetFont().GetResourceHandle();
2bda0e17 884
223d09f6 885 wxASSERT_MSG( hFont, wxT("should have valid font") );
3a19e16d 886
c50f1fb9 887 ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
42e69d6b 888 }
2bda0e17 889
08158721 890 return true;
42e69d6b 891}
1e6feb95 892bool wxWindowMSW::SetCursor(const wxCursor& cursor)
2bda0e17 893{
42e69d6b
VZ
894 if ( !wxWindowBase::SetCursor(cursor) )
895 {
896 // no change
08158721 897 return false;
42e69d6b
VZ
898 }
899
8e75dca8
VZ
900 // don't "overwrite" busy cursor
901 if ( m_cursor.Ok() && !wxIsBusy() )
8a9c2246 902 {
a8b2285e
VZ
903 // normally we should change the cursor only if it's over this window
904 // but we should do it always if we capture the mouse currently
905 bool set = HasCapture();
906 if ( !set )
907 {
908 HWND hWnd = GetHwnd();
909
910 POINT point;
911#ifdef __WXWINCE__
912 ::GetCursorPosWinCE(&point);
913#else
914 ::GetCursorPos(&point);
915#endif
916
917 RECT rect = wxGetWindowRect(hWnd);
918
919 set = ::PtInRect(&rect, point) != 0;
920 }
921
922 if ( set )
923 {
924 ::SetCursor(GetHcursorOf(m_cursor));
925 }
926 //else: will be set later when the mouse enters this window
8a9c2246 927 }
3a19e16d 928
08158721 929 return true;
3a19e16d
VZ
930}
931
d7e0024b 932void wxWindowMSW::WarpPointer(int x, int y)
2bda0e17 933{
1e6feb95 934 ClientToScreen(&x, &y);
42e69d6b 935
1e6feb95
VZ
936 if ( !::SetCursorPos(x, y) )
937 {
938 wxLogLastError(_T("SetCursorPos"));
939 }
2bda0e17
KB
940}
941
1ca78aa1 942void wxWindowMSW::MSWUpdateUIState(int action, int state)
d7e0024b 943{
1ca78aa1 944 // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good
d7e0024b
VZ
945 // to use it on older systems -- and could possibly do some harm
946 static int s_needToUpdate = -1;
947 if ( s_needToUpdate == -1 )
948 {
949 int verMaj, verMin;
406d283a 950 s_needToUpdate = wxGetOsVersion(&verMaj, &verMin) == wxOS_WINDOWS_NT &&
d7e0024b
VZ
951 verMaj >= 5;
952 }
953
954 if ( s_needToUpdate )
955 {
1ca78aa1
JS
956 // we send WM_CHANGEUISTATE so if nothing needs changing then the system
957 // won't send WM_UPDATEUISTATE
958 ::SendMessage(GetHwnd(), WM_CHANGEUISTATE, MAKEWPARAM(action, state), 0);
d7e0024b
VZ
959 }
960}
961
42e69d6b
VZ
962// ---------------------------------------------------------------------------
963// scrolling stuff
964// ---------------------------------------------------------------------------
2d0a075d 965
1ddb6d28
VZ
966namespace
967{
968
9cd6d737
VZ
969inline int GetScrollPosition(HWND hWnd, int wOrient)
970{
971#ifdef __WXMICROWIN__
972 return ::GetScrollPosWX(hWnd, wOrient);
973#else
f676b387 974 WinStruct<SCROLLINFO> scrollInfo;
4676948b 975 scrollInfo.cbSize = sizeof(SCROLLINFO);
7f0586ef 976 scrollInfo.fMask = SIF_POS;
e795e8b5 977 ::GetScrollInfo(hWnd, wOrient, &scrollInfo );
a71d815b 978
7f0586ef 979 return scrollInfo.nPos;
e795e8b5 980
9cd6d737
VZ
981#endif
982}
983
1ddb6d28
VZ
984inline UINT WXOrientToSB(int orient)
985{
986 return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
987}
988
989} // anonymous namespace
990
1e6feb95 991int wxWindowMSW::GetScrollPos(int orient) const
2bda0e17 992{
42e69d6b 993 HWND hWnd = GetHwnd();
9cd6d737
VZ
994 wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
995
1ddb6d28 996 return GetScrollPosition(hWnd, WXOrientToSB(orient));
42e69d6b 997}
2bda0e17 998
42e69d6b
VZ
999// This now returns the whole range, not just the number
1000// of positions that we can scroll.
1e6feb95 1001int wxWindowMSW::GetScrollRange(int orient) const
42e69d6b 1002{
7f0586ef 1003 int maxPos;
a23fd0e1 1004 HWND hWnd = GetHwnd();
0cf5de11 1005 if ( !hWnd )
42e69d6b 1006 return 0;
f676b387 1007 WinStruct<SCROLLINFO> scrollInfo;
7f0586ef 1008 scrollInfo.fMask = SIF_RANGE;
1ddb6d28 1009 if ( !::GetScrollInfo(hWnd, WXOrientToSB(orient), &scrollInfo) )
7f0586ef 1010 {
f676b387
RD
1011 // Most of the time this is not really an error, since the return
1012 // value can also be zero when there is no scrollbar yet.
1013 // wxLogLastError(_T("GetScrollInfo"));
7f0586ef
JS
1014 }
1015 maxPos = scrollInfo.nMax;
0cf5de11
VZ
1016
1017 // undo "range - 1" done in SetScrollbar()
1018 return maxPos + 1;
cc2b7472 1019}
2bda0e17 1020
1e6feb95 1021int wxWindowMSW::GetScrollThumb(int orient) const
2bda0e17 1022{
0cf5de11 1023 return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
2bda0e17
KB
1024}
1025
1e6feb95 1026void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
2bda0e17 1027{
5f3286d1
VZ
1028 HWND hWnd = GetHwnd();
1029 wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") );
72fd19a1 1030
0cf5de11 1031 WinStruct<SCROLLINFO> info;
42e69d6b
VZ
1032 info.nPage = 0;
1033 info.nMin = 0;
1034 info.nPos = pos;
1035 info.fMask = SIF_POS;
a647d42a
VZ
1036 if ( HasFlag(wxALWAYS_SHOW_SB) )
1037 {
1038 // disable scrollbar instead of removing it then
1039 info.fMask |= SIF_DISABLENOSCROLL;
1040 }
2d0a075d 1041
1ddb6d28 1042 ::SetScrollInfo(hWnd, WXOrientToSB(orient), &info, refresh);
2bda0e17
KB
1043}
1044
42e69d6b 1045// New function that will replace some of the above.
0cf5de11
VZ
1046void wxWindowMSW::SetScrollbar(int orient,
1047 int pos,
1048 int pageSize,
1049 int range,
1050 bool refresh)
1051{
1ddb6d28
VZ
1052 // We have to set the variables here to make them valid in events
1053 // triggered by ::SetScrollInfo()
1054 *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
1055
1056 HWND hwnd = GetHwnd();
1057 if ( !hwnd )
1058 return;
1059
0cf5de11 1060 WinStruct<SCROLLINFO> info;
1ddb6d28
VZ
1061 if ( range != -1 )
1062 {
1063 info.nPage = pageSize;
1064 info.nMin = 0; // range is nMax - nMin + 1
1065 info.nMax = range - 1; // as both nMax and nMax are inclusive
1066 info.nPos = pos;
1067
1068 // enable the scrollbar if it had been disabled before by specifying
1069 // SIF_DISABLENOSCROLL below: as we can't know whether this had been
1070 // done or not just do it always
1071 ::EnableScrollBar(hwnd, WXOrientToSB(orient), ESB_ENABLE_BOTH);
1072 }
1073 //else: leave all the fields to be 0
1074
42e69d6b 1075 info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
1ddb6d28 1076 if ( HasFlag(wxALWAYS_SHOW_SB) || range == -1 )
a647d42a
VZ
1077 {
1078 // disable scrollbar instead of removing it then
1079 info.fMask |= SIF_DISABLENOSCROLL;
1080 }
2bda0e17 1081
1ddb6d28 1082 ::SetScrollInfo(hwnd, WXOrientToSB(orient), &info, refresh);
81d66cf3
JS
1083}
1084
1e6feb95 1085void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
2bda0e17 1086{
574c939e
KB
1087 RECT rect;
1088 RECT *pr;
1e6feb95 1089 if ( prect )
2d0a075d 1090 {
f9c980f6 1091 wxCopyRectToRECT(*prect, rect);
f797e53d
VZ
1092 pr = &rect;
1093 }
1094 else
1095 {
1096 pr = NULL;
304b8bc1 1097
2d0a075d 1098 }
2bda0e17 1099
7f0586ef
JS
1100#ifdef __WXWINCE__
1101 // FIXME: is this the exact equivalent of the line below?
304b8bc1 1102 ::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
7f0586ef 1103#else
f797e53d 1104 ::ScrollWindow(GetHwnd(), dx, dy, pr, pr);
7f0586ef 1105#endif
2bda0e17
KB
1106}
1107
9cd6d737 1108static bool ScrollVertically(HWND hwnd, int kind, int count)
b9b3393e 1109{
9cd6d737
VZ
1110 int posStart = GetScrollPosition(hwnd, SB_VERT);
1111
1112 int pos = posStart;
c0cdd6cc
VZ
1113 for ( int n = 0; n < count; n++ )
1114 {
1115 ::SendMessage(hwnd, WM_VSCROLL, kind, 0);
9cd6d737
VZ
1116
1117 int posNew = GetScrollPosition(hwnd, SB_VERT);
1118 if ( posNew == pos )
1119 {
1120 // don't bother to continue, we're already at top/bottom
1121 break;
1122 }
1123
1124 pos = posNew;
c0cdd6cc 1125 }
9cd6d737
VZ
1126
1127 return pos != posStart;
b9b3393e
VZ
1128}
1129
9cd6d737 1130bool wxWindowMSW::ScrollLines(int lines)
b9b3393e
VZ
1131{
1132 bool down = lines > 0;
1133
9cd6d737
VZ
1134 return ScrollVertically(GetHwnd(),
1135 down ? SB_LINEDOWN : SB_LINEUP,
1136 down ? lines : -lines);
b9b3393e
VZ
1137}
1138
9cd6d737 1139bool wxWindowMSW::ScrollPages(int pages)
b9b3393e
VZ
1140{
1141 bool down = pages > 0;
1142
9cd6d737
VZ
1143 return ScrollVertically(GetHwnd(),
1144 down ? SB_PAGEDOWN : SB_PAGEUP,
1145 down ? pages : -pages);
b9b3393e
VZ
1146}
1147
978af864
VZ
1148// ----------------------------------------------------------------------------
1149// RTL support
1150// ----------------------------------------------------------------------------
1151
1152void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
1153{
08a58133
WS
1154#ifdef __WXWINCE__
1155 wxUnusedVar(dir);
1156#else
d66d0500
VZ
1157 wxCHECK_RET( GetHwnd(),
1158 _T("layout direction must be set after window creation") );
978af864 1159
d66d0500 1160 LONG styleOld = wxGetWindowExStyle(this);
978af864
VZ
1161
1162 LONG styleNew = styleOld;
1163 switch ( dir )
1164 {
1165 case wxLayout_LeftToRight:
1166 styleNew &= ~WS_EX_LAYOUTRTL;
1167 break;
1168
1169 case wxLayout_RightToLeft:
1170 styleNew |= WS_EX_LAYOUTRTL;
1171 break;
1172
1173 default:
1174 wxFAIL_MSG(_T("unsupported layout direction"));
1175 break;
1176 }
1177
1178 if ( styleNew != styleOld )
1179 {
d66d0500 1180 wxSetWindowExStyle(this, styleNew);
978af864 1181 }
08a58133 1182#endif
978af864
VZ
1183}
1184
1185wxLayoutDirection wxWindowMSW::GetLayoutDirection() const
1186{
08a58133
WS
1187#ifdef __WXWINCE__
1188 return wxLayout_Default;
1189#else
d66d0500 1190 wxCHECK_MSG( GetHwnd(), wxLayout_Default, _T("invalid window") );
978af864 1191
d66d0500
VZ
1192 return wxHasWindowExStyle(this, WS_EX_LAYOUTRTL) ? wxLayout_RightToLeft
1193 : wxLayout_LeftToRight;
08a58133 1194#endif
978af864
VZ
1195}
1196
1197wxCoord
1198wxWindowMSW::AdjustForLayoutDirection(wxCoord x,
1199 wxCoord WXUNUSED(width),
1200 wxCoord WXUNUSED(widthTotal)) const
1201{
1202 // Win32 mirrors the coordinates of RTL windows automatically, so don't
1203 // redo it ourselves
1204 return x;
1205}
1206
42e69d6b
VZ
1207// ---------------------------------------------------------------------------
1208// subclassing
1209// ---------------------------------------------------------------------------
1210
1e6feb95 1211void wxWindowMSW::SubclassWin(WXHWND hWnd)
2bda0e17 1212{
223d09f6 1213 wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") );
2bda0e17 1214
c50f1fb9 1215 HWND hwnd = (HWND)hWnd;
223d09f6 1216 wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") );
c50f1fb9 1217
e322e3b6
VZ
1218 SetHWND(hWnd);
1219
c50f1fb9 1220 wxAssociateWinWithHandle(hwnd, this);
2bda0e17 1221
975b6bcf 1222 m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd);
b2d5a7ee 1223
b225f659
VZ
1224 // we don't need to subclass the window of our own class (in the Windows
1225 // sense of the word)
3a3c8603 1226 if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
b225f659 1227 {
975b6bcf 1228 wxSetWindowProc(hwnd, wxWndProc);
b225f659
VZ
1229 }
1230 else
1231 {
90e572f1 1232 // don't bother restoring it either: this also makes it easy to
08158721 1233 // implement IsOfStandardClass() method which returns true for the
77ffb593 1234 // standard controls and false for the wxWidgets own windows as it can
5a403e3f 1235 // simply check m_oldWndProc
b225f659
VZ
1236 m_oldWndProc = NULL;
1237 }
e7c652bc
VZ
1238
1239 // we're officially created now, send the event
1240 wxWindowCreateEvent event((wxWindow *)this);
937013e0 1241 (void)HandleWindowEvent(event);
2bda0e17
KB
1242}
1243
1e6feb95 1244void wxWindowMSW::UnsubclassWin()
2bda0e17 1245{
42e69d6b 1246 wxRemoveHandleAssociation(this);
2bda0e17 1247
42e69d6b 1248 // Restore old Window proc
c50f1fb9
VZ
1249 HWND hwnd = GetHwnd();
1250 if ( hwnd )
42e69d6b 1251 {
ed4780ea 1252 SetHWND(0);
c50f1fb9 1253
223d09f6 1254 wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
c50f1fb9 1255
b225f659 1256 if ( m_oldWndProc )
42e69d6b 1257 {
eb5e4d9a 1258 if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) )
b225f659 1259 {
975b6bcf 1260 wxSetWindowProc(hwnd, (WNDPROC)m_oldWndProc);
b225f659
VZ
1261 }
1262
1263 m_oldWndProc = NULL;
42e69d6b 1264 }
42e69d6b 1265 }
2bda0e17
KB
1266}
1267
a4d1972d 1268void wxWindowMSW::AssociateHandle(WXWidget handle)
ed4780ea
VZ
1269{
1270 if ( m_hWnd )
1271 {
1272 if ( !::DestroyWindow(GetHwnd()) )
1273 wxLogLastError(wxT("DestroyWindow"));
1274 }
a4d1972d 1275
ed4780ea
VZ
1276 WXHWND wxhwnd = (WXHWND)handle;
1277
e322e3b6 1278 // this also calls SetHWND(wxhwnd)
ed4780ea
VZ
1279 SubclassWin(wxhwnd);
1280}
1281
1282void wxWindowMSW::DissociateHandle()
a4d1972d 1283{
ed4780ea 1284 // this also calls SetHWND(0) for us
a4d1972d 1285 UnsubclassWin();
ed4780ea
VZ
1286}
1287
1288
0c0d1521 1289bool wxCheckWindowWndProc(WXHWND hWnd,
11f104e5 1290 WXFARPROC WXUNUSED(wndProc))
eb5e4d9a 1291{
d9698bd4
VZ
1292 const wxString str(wxGetWindowClass(hWnd));
1293
1294 // TODO: get rid of wxTLWHiddenParent special case (currently it's not
1295 // registered by wxApp but using ad hoc code in msw/toplevel.cpp);
1296 // there is also a hidden window class used by sockets &c
1297 return wxApp::IsRegisteredClassName(str) || str == _T("wxTLWHiddenParent");
eb5e4d9a
VS
1298}
1299
b2d5a7ee
VZ
1300// ----------------------------------------------------------------------------
1301// Style handling
1302// ----------------------------------------------------------------------------
1303
1304void wxWindowMSW::SetWindowStyleFlag(long flags)
1305{
1306 long flagsOld = GetWindowStyleFlag();
1307 if ( flags == flagsOld )
1308 return;
1309
1310 // update the internal variable
1311 wxWindowBase::SetWindowStyleFlag(flags);
1312
7bd6bf45
VZ
1313 // and the real window flags
1314 MSWUpdateStyle(flagsOld, GetExtraStyle());
1315}
1316
1317void wxWindowMSW::SetExtraStyle(long exflags)
1318{
1319 long exflagsOld = GetExtraStyle();
1320 if ( exflags == exflagsOld )
1321 return;
1322
1323 // update the internal variable
1324 wxWindowBase::SetExtraStyle(exflags);
1325
1326 // and the real window flags
1327 MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld);
1328}
1329
1330void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld)
1331{
5b2f31eb
VZ
1332 // now update the Windows style as well if needed - and if the window had
1333 // been already created
1334 if ( !GetHwnd() )
1335 return;
1336
9ce75461
VZ
1337 // we may need to call SetWindowPos() when we change some styles
1338 bool callSWP = false;
1339
7bd6bf45
VZ
1340 WXDWORD exstyle;
1341 long style = MSWGetStyle(GetWindowStyleFlag(), &exstyle);
1342
1343 // this is quite a horrible hack but we need it because MSWGetStyle()
1344 // doesn't take exflags as parameter but uses GetExtraStyle() internally
1345 // and so we have to modify the window exflags temporarily to get the
1346 // correct exstyleOld
1347 long exflagsNew = GetExtraStyle();
1348 wxWindowBase::SetExtraStyle(exflagsOld);
1349
1350 WXDWORD exstyleOld;
1351 long styleOld = MSWGetStyle(flagsOld, &exstyleOld);
1352
1353 wxWindowBase::SetExtraStyle(exflagsNew);
1354
b2d5a7ee
VZ
1355
1356 if ( style != styleOld )
1357 {
1358 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1359 // this function so instead of simply setting the style to the new
1360 // value we clear the bits which were set in styleOld but are set in
1361 // the new one and set the ones which were not set before
1362 long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE);
1363 styleReal &= ~styleOld;
1364 styleReal |= style;
1365
1366 ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
9ce75461 1367
7bd6bf45
VZ
1368 // we need to call SetWindowPos() if any of the styles affecting the
1369 // frame appearance have changed
9ce75461
VZ
1370 callSWP = ((styleOld ^ style ) & (WS_BORDER |
1371 WS_THICKFRAME |
1372 WS_CAPTION |
1373 WS_DLGFRAME |
1374 WS_MAXIMIZEBOX |
1375 WS_MINIMIZEBOX |
1376 WS_SYSMENU) ) != 0;
b2d5a7ee
VZ
1377 }
1378
1379 // and the extended style
d66d0500 1380 long exstyleReal = wxGetWindowExStyle(this);
9ce75461 1381
b2d5a7ee
VZ
1382 if ( exstyle != exstyleOld )
1383 {
b2d5a7ee
VZ
1384 exstyleReal &= ~exstyleOld;
1385 exstyleReal |= exstyle;
1386
d66d0500 1387 wxSetWindowExStyle(this, exstyleReal);
b2d5a7ee 1388
9ce75461
VZ
1389 // ex style changes don't take effect without calling SetWindowPos
1390 callSWP = true;
1391 }
1392
1393 if ( callSWP )
1394 {
85d8df29 1395 // we must call SetWindowPos() to flush the cached extended style and
b2d5a7ee
VZ
1396 // also to make the change to wxSTAY_ON_TOP style take effect: just
1397 // setting the style simply doesn't work
1398 if ( !::SetWindowPos(GetHwnd(),
1399 exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
1400 : HWND_NOTOPMOST,
1401 0, 0, 0, 0,
9ce75461 1402 SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED) )
b2d5a7ee
VZ
1403 {
1404 wxLogLastError(_T("SetWindowPos"));
1405 }
1406 }
1407}
1408
a047aff2
JS
1409wxBorder wxWindowMSW::GetDefaultBorderForControl() const
1410{
28319afe 1411 return wxBORDER_THEME;
a047aff2
JS
1412}
1413
4c0d2cd3
JS
1414wxBorder wxWindowMSW::GetDefaultBorder() const
1415{
dc797d8e 1416 return wxWindowBase::GetDefaultBorder();
4c0d2cd3
JS
1417}
1418
28bf925c 1419// Translate wxBORDER_THEME (and other border styles if necessary) to the value
dc797d8e
JS
1420// that makes most sense for this Windows environment
1421wxBorder wxWindowMSW::TranslateBorder(wxBorder border) const
1422{
1423#if defined(__POCKETPC__) || defined(__SMARTPHONE__)
1424 if (border == wxBORDER_THEME || border == wxBORDER_SUNKEN || border == wxBORDER_SIMPLE)
1425 return wxBORDER_SIMPLE;
1426 else
1427 return wxBORDER_NONE;
1428#else
1429#if wxUSE_UXTHEME
1430 if (border == wxBORDER_THEME)
1431 {
1432 if (CanApplyThemeBorder())
1433 {
1434 wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
1435 if (theme)
1436 return wxBORDER_THEME;
1437 }
28bf925c 1438 return wxBORDER_SUNKEN;
dc797d8e
JS
1439 }
1440#endif
1441 return border;
1442#endif
dc797d8e
JS
1443}
1444
1445
b2d5a7ee
VZ
1446WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
1447{
77ffb593 1448 // translate common wxWidgets styles to Windows ones
af495479
VZ
1449
1450 // most of windows are child ones, those which are not (such as
1451 // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle()
1452 WXDWORD style = WS_CHILD;
b2d5a7ee 1453
9b6ae450
VZ
1454 // using this flag results in very significant reduction in flicker,
1455 // especially with controls inside the static boxes (as the interior of the
90e572f1 1456 // box is not redrawn twice), but sometimes results in redraw problems, so
c7e1d004
VZ
1457 // optionally allow the old code to continue to use it provided a special
1458 // system option is turned on
1459 if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
1460 || (flags & wxCLIP_CHILDREN) )
c6430ed0 1461 style |= WS_CLIPCHILDREN;
9b6ae450
VZ
1462
1463 // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
1464 // don't support overlapping windows and it only makes sense for them and,
1465 // presumably, gives the system some extra work (to manage more clipping
1466 // regions), so avoid it alltogether
b2d5a7ee 1467
b2d5a7ee 1468
f9007c32
JS
1469 if ( flags & wxVSCROLL )
1470 style |= WS_VSCROLL;
1471
1472 if ( flags & wxHSCROLL )
1473 style |= WS_HSCROLL;
1474
dc797d8e
JS
1475 const wxBorder border = TranslateBorder(GetBorder(flags));
1476
1477 // After translation, border is now optimized for the specific version of Windows
1478 // and theme engine presence.
577baeef 1479
65bc172c
VZ
1480 // WS_BORDER is only required for wxBORDER_SIMPLE
1481 if ( border == wxBORDER_SIMPLE )
b2d5a7ee 1482 style |= WS_BORDER;
577baeef 1483
b2d5a7ee
VZ
1484 // now deal with ext style if the caller wants it
1485 if ( exstyle )
1486 {
1487 *exstyle = 0;
1488
7f0586ef 1489#ifndef __WXWINCE__
b2d5a7ee
VZ
1490 if ( flags & wxTRANSPARENT_WINDOW )
1491 *exstyle |= WS_EX_TRANSPARENT;
7f0586ef 1492#endif
b2d5a7ee 1493
fe3d9123 1494 switch ( border )
b2d5a7ee 1495 {
78cd9c69
JS
1496 default:
1497 case wxBORDER_DEFAULT:
1498 wxFAIL_MSG( _T("unknown border style") );
1499 // fall through
b2d5a7ee
VZ
1500
1501 case wxBORDER_NONE:
1502 case wxBORDER_SIMPLE:
78cd9c69 1503 case wxBORDER_THEME:
b2d5a7ee
VZ
1504 break;
1505
1506 case wxBORDER_STATIC:
1507 *exstyle |= WS_EX_STATICEDGE;
1508 break;
1509
1510 case wxBORDER_RAISED:
7699361c 1511 *exstyle |= WS_EX_DLGMODALFRAME;
b2d5a7ee
VZ
1512 break;
1513
b2d5a7ee
VZ
1514 case wxBORDER_SUNKEN:
1515 *exstyle |= WS_EX_CLIENTEDGE;
fe3d9123 1516 style &= ~WS_BORDER;
b2d5a7ee
VZ
1517 break;
1518
78cd9c69
JS
1519// case wxBORDER_DOUBLE:
1520// *exstyle |= WS_EX_DLGMODALFRAME;
1521// break;
b2d5a7ee 1522 }
d515c32d 1523
09168de7 1524 // wxUniv doesn't use Windows dialog navigation functions at all
7f0586ef 1525#if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
5b9c12e1 1526 // to make the dialog navigation work with the nested panels we must
09168de7
VZ
1527 // use this style (top level windows such as dialogs don't need it)
1528 if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
d515c32d
VZ
1529 {
1530 *exstyle |= WS_EX_CONTROLPARENT;
1531 }
09168de7 1532#endif // __WXUNIVERSAL__
b2d5a7ee
VZ
1533 }
1534
1535 return style;
1536}
eb5e4d9a 1537
42e69d6b 1538// Setup background and foreground colours correctly
1e6feb95 1539void wxWindowMSW::SetupColours()
42e69d6b
VZ
1540{
1541 if ( GetParent() )
1542 SetBackgroundColour(GetParent()->GetBackgroundColour());
1543}
a23fd0e1 1544
1e6feb95
VZ
1545bool wxWindowMSW::IsMouseInWindow() const
1546{
1547 // get the mouse position
1548 POINT pt;
f2325516
JS
1549#ifdef __WXWINCE__
1550 ::GetCursorPosWinCE(&pt);
1551#else
1e6feb95 1552 ::GetCursorPos(&pt);
f2325516 1553#endif
1e6feb95
VZ
1554
1555 // find the window which currently has the cursor and go up the window
1556 // chain until we find this window - or exhaust it
1557 HWND hwnd = ::WindowFromPoint(pt);
1558 while ( hwnd && (hwnd != GetHwnd()) )
1559 hwnd = ::GetParent(hwnd);
1560
1561 return hwnd != NULL;
1562}
1563
e39af974 1564void wxWindowMSW::OnInternalIdle()
42e69d6b 1565{
4e5c6c33 1566#ifndef HAVE_TRACKMOUSEEVENT
42e69d6b
VZ
1567 // Check if we need to send a LEAVE event
1568 if ( m_mouseInWindow )
2d0a075d 1569 {
ee74faf9
VZ
1570 // note that we should generate the leave event whether the window has
1571 // or doesn't have mouse capture
1572 if ( !IsMouseInWindow() )
42e69d6b 1573 {
51e4e266 1574 GenerateMouseLeave();
42e69d6b
VZ
1575 }
1576 }
4e5c6c33 1577#endif // !HAVE_TRACKMOUSEEVENT
c085e333 1578
df707c27 1579 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
e39af974 1580 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
42e69d6b 1581}
568cb543 1582
42e69d6b 1583// Set this window to be the child of 'parent'.
1e6feb95 1584bool wxWindowMSW::Reparent(wxWindowBase *parent)
42e69d6b
VZ
1585{
1586 if ( !wxWindowBase::Reparent(parent) )
08158721 1587 return false;
c085e333 1588
42e69d6b
VZ
1589 HWND hWndChild = GetHwnd();
1590 HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
a23fd0e1 1591
42e69d6b 1592 ::SetParent(hWndChild, hWndParent);
a23fd0e1 1593
ee471817 1594#ifndef __WXWINCE__
d66d0500 1595 if ( wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) )
ee471817
VZ
1596 {
1597 EnsureParentHasControlParentStyle(GetParent());
1598 }
1599#endif // !__WXWINCE__
1600
08158721 1601 return true;
42e69d6b 1602}
a23fd0e1 1603
a0e449ff
VZ
1604static inline void SendSetRedraw(HWND hwnd, bool on)
1605{
c67d6888 1606#ifndef __WXMICROWIN__
a0e449ff 1607 ::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)on, 0);
c67d6888 1608#endif
a0e449ff
VZ
1609}
1610
17808a75 1611void wxWindowMSW::DoFreeze()
a0e449ff 1612{
89267fe5
VS
1613 if ( !IsShown() )
1614 return; // no point in freezing hidden window
1615
1616 SendSetRedraw(GetHwnd(), false);
a0e449ff
VZ
1617}
1618
17808a75 1619void wxWindowMSW::DoThaw()
a0e449ff 1620{
89267fe5
VS
1621 if ( !IsShown() )
1622 return; // hidden windows aren't frozen by DoFreeze
a1037371 1623
89267fe5
VS
1624 SendSetRedraw(GetHwnd(), true);
1625
1626 // we need to refresh everything or otherwise the invalidated area
1627 // is not going to be repainted
1628 Refresh();
a0e449ff
VZ
1629}
1630
1e6feb95 1631void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
42e69d6b
VZ
1632{
1633 HWND hWnd = GetHwnd();
1634 if ( hWnd )
1635 {
d181e053
VZ
1636 RECT mswRect;
1637 const RECT *pRect;
42e69d6b
VZ
1638 if ( rect )
1639 {
f9c980f6 1640 wxCopyRectToRECT(*rect, mswRect);
d181e053 1641 pRect = &mswRect;
42e69d6b
VZ
1642 }
1643 else
d181e053
VZ
1644 {
1645 pRect = NULL;
1646 }
1647
82e3664e 1648 // RedrawWindow not available on SmartPhone or eVC++ 3
41527143 1649#if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
d181e053
VZ
1650 UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
1651 if ( eraseBack )
1652 flags |= RDW_ERASE;
1653
1654 ::RedrawWindow(hWnd, pRect, NULL, flags);
480e9098 1655#else
16d652a5 1656 ::InvalidateRect(hWnd, pRect, eraseBack);
480e9098 1657#endif
42e69d6b
VZ
1658 }
1659}
a23fd0e1 1660
1e6feb95
VZ
1661void wxWindowMSW::Update()
1662{
1663 if ( !::UpdateWindow(GetHwnd()) )
1664 {
1665 wxLogLastError(_T("UpdateWindow"));
1666 }
2b5f62a0 1667
7f0586ef 1668#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95
VZ
1669 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1670 // handler needs to be really drawn right now
1671 (void)::GdiFlush();
1672#endif // __WIN32__
1673}
1674
42e69d6b
VZ
1675// ---------------------------------------------------------------------------
1676// drag and drop
1677// ---------------------------------------------------------------------------
a23fd0e1 1678
3febc967
VZ
1679#if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__)
1680
1681#if wxUSE_STATBOX
1682
006b8dff
JG
1683// we need to lower the sibling static boxes so controls contained within can be
1684// a drop target
3febc967 1685static void AdjustStaticBoxZOrder(wxWindow *parent)
006b8dff 1686{
deb0d191
JG
1687 // no sibling static boxes if we have no parent (ie TLW)
1688 if ( !parent )
1689 return;
1690
006b8dff
JG
1691 for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
1692 node;
1693 node = node->GetNext() )
1694 {
1695 wxStaticBox *statbox = wxDynamicCast(node->GetData(), wxStaticBox);
1696 if ( statbox )
1697 {
1698 ::SetWindowPos(GetHwndOf(statbox), HWND_BOTTOM, 0, 0, 0, 0,
1699 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1700 }
1701 }
1702}
a23fd0e1 1703
3febc967
VZ
1704#else // !wxUSE_STATBOX
1705
1706static inline void AdjustStaticBoxZOrder(wxWindow * WXUNUSED(parent))
1707{
1708}
1709
1710#endif // wxUSE_STATBOX/!wxUSE_STATBOX
1711
1712#endif // drag and drop is used
1713
4ce1efe1 1714#if wxUSE_DRAG_AND_DROP
1e6feb95 1715void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
42e69d6b
VZ
1716{
1717 if ( m_dropTarget != 0 ) {
1718 m_dropTarget->Revoke(m_hWnd);
1719 delete m_dropTarget;
1720 }
a23fd0e1 1721
42e69d6b
VZ
1722 m_dropTarget = pDropTarget;
1723 if ( m_dropTarget != 0 )
006b8dff
JG
1724 {
1725 AdjustStaticBoxZOrder(GetParent());
42e69d6b 1726 m_dropTarget->Register(m_hWnd);
006b8dff 1727 }
42e69d6b 1728}
42e69d6b 1729#endif // wxUSE_DRAG_AND_DROP
2a47d3c1 1730
90e572f1 1731// old-style file manager drag&drop support: we retain the old-style
42e69d6b 1732// DragAcceptFiles in parallel with SetDropTarget.
0c0d1521 1733void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept))
42e69d6b 1734{
0c0d1521 1735#ifndef __WXWINCE__
42e69d6b
VZ
1736 HWND hWnd = GetHwnd();
1737 if ( hWnd )
006b8dff
JG
1738 {
1739 AdjustStaticBoxZOrder(GetParent());
42e69d6b 1740 ::DragAcceptFiles(hWnd, (BOOL)accept);
006b8dff 1741 }
7f0586ef 1742#endif
42e69d6b 1743}
a23fd0e1 1744
42e69d6b
VZ
1745// ----------------------------------------------------------------------------
1746// tooltips
1747// ----------------------------------------------------------------------------
dbda9e86 1748
42e69d6b 1749#if wxUSE_TOOLTIPS
2d0a075d 1750
1e6feb95 1751void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
42e69d6b
VZ
1752{
1753 wxWindowBase::DoSetToolTip(tooltip);
839b865d 1754
42e69d6b 1755 if ( m_tooltip )
d4e5272b 1756 m_tooltip->SetWindow((wxWindow *)this);
42e69d6b 1757}
9a05fd8d 1758
42e69d6b 1759#endif // wxUSE_TOOLTIPS
9a05fd8d 1760
42e69d6b
VZ
1761// ---------------------------------------------------------------------------
1762// moving and resizing
1763// ---------------------------------------------------------------------------
839b865d 1764
f7040b5f
VZ
1765bool wxWindowMSW::IsSizeDeferred() const
1766{
1767#if USE_DEFERRED_SIZING
1768 if ( m_pendingPosition != wxDefaultPosition ||
1769 m_pendingSize != wxDefaultSize )
1770 return true;
1771#endif // USE_DEFERRED_SIZING
1772
1773 return false;
1774}
1775
42e69d6b 1776// Get total size
1e6feb95 1777void wxWindowMSW::DoGetSize(int *x, int *y) const
42e69d6b 1778{
0d6fdb3c 1779#if USE_DEFERRED_SIZING
11cfa8ef
VZ
1780 // if SetSize() had been called at wx level but not realized at Windows
1781 // level yet (i.e. EndDeferWindowPos() not called), we still should return
1782 // the new and not the old position to the other wx code
1783 if ( m_pendingSize != wxDefaultSize )
1784 {
1785 if ( x )
1786 *x = m_pendingSize.x;
1787 if ( y )
1788 *y = m_pendingSize.y;
1789 }
1790 else // use current size
0d6fdb3c 1791#endif // USE_DEFERRED_SIZING
11cfa8ef
VZ
1792 {
1793 RECT rect = wxGetWindowRect(GetHwnd());
82c9f85c 1794
11cfa8ef
VZ
1795 if ( x )
1796 *x = rect.right - rect.left;
1797 if ( y )
1798 *y = rect.bottom - rect.top;
1799 }
42e69d6b
VZ
1800}
1801
82c9f85c
VZ
1802// Get size *available for subwindows* i.e. excluding menu bar etc.
1803void wxWindowMSW::DoGetClientSize(int *x, int *y) const
42e69d6b 1804{
f2197644 1805#if USE_DEFERRED_SIZING
0d6fdb3c 1806 if ( m_pendingSize != wxDefaultSize )
0d7f75df 1807 {
0d6fdb3c 1808 // we need to calculate the client size corresponding to pending size
dc497201
JG
1809 RECT rect;
1810 rect.left = m_pendingPosition.x;
1811 rect.top = m_pendingPosition.y;
1812 rect.right = rect.left + m_pendingSize.x;
1813 rect.bottom = rect.top + m_pendingSize.y;
1814
1815 ::SendMessage(GetHwnd(), WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
1816
1817 if ( x )
1818 *x = rect.right - rect.left;
1819 if ( y )
1820 *y = rect.bottom - rect.top;
0d7f75df 1821 }
0d6fdb3c
VZ
1822 else
1823#endif // USE_DEFERRED_SIZING
1824 {
1825 RECT rect = wxGetClientRect(GetHwnd());
1826
1827 if ( x )
1828 *x = rect.right;
1829 if ( y )
1830 *y = rect.bottom;
1831 }
82c9f85c
VZ
1832}
1833
1834void wxWindowMSW::DoGetPosition(int *x, int *y) const
1835{
a7e0e432
VZ
1836 wxWindow * const parent = GetParent();
1837
1838 wxPoint pos;
11cfa8ef
VZ
1839 if ( m_pendingPosition != wxDefaultPosition )
1840 {
a7e0e432 1841 pos = m_pendingPosition;
11cfa8ef
VZ
1842 }
1843 else // use current position
1844 {
1845 RECT rect = wxGetWindowRect(GetHwnd());
42e69d6b 1846
11cfa8ef
VZ
1847 POINT point;
1848 point.x = rect.left;
1849 point.y = rect.top;
42e69d6b 1850
11cfa8ef
VZ
1851 // we do the adjustments with respect to the parent only for the "real"
1852 // children, not for the dialogs/frames
1853 if ( !IsTopLevel() )
92049cd4 1854 {
e5b5af91
VZ
1855 if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
1856 {
967acfb5 1857 // In RTL mode, we want the logical left x-coordinate,
e5b5af91
VZ
1858 // which would be the physical right x-coordinate.
1859 point.x = rect.right;
1860 }
1861
11cfa8ef
VZ
1862 // Since we now have the absolute screen coords, if there's a
1863 // parent we must subtract its top left corner
11cfa8ef
VZ
1864 if ( parent )
1865 {
a7e0e432 1866 ::ScreenToClient(GetHwndOf(parent), &point);
11cfa8ef 1867 }
89e3037c 1868 }
42e69d6b 1869
a7e0e432
VZ
1870 pos.x = point.x;
1871 pos.y = point.y;
1872 }
1873
1874 // we also must adjust by the client area offset: a control which is just
1875 // under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx
1876 if ( parent && !IsTopLevel() )
1877 {
1878 const wxPoint pt(parent->GetClientAreaOrigin());
1879 pos.x -= pt.x;
1880 pos.y -= pt.y;
11cfa8ef 1881 }
a7e0e432
VZ
1882
1883 if ( x )
1884 *x = pos.x;
1885 if ( y )
1886 *y = pos.y;
42e69d6b 1887}
54bdd8b0 1888
1e6feb95 1889void wxWindowMSW::DoScreenToClient(int *x, int *y) const
42e69d6b
VZ
1890{
1891 POINT pt;
1892 if ( x )
1893 pt.x = *x;
1894 if ( y )
1895 pt.y = *y;
54bdd8b0 1896
82c9f85c 1897 ::ScreenToClient(GetHwnd(), &pt);
a23fd0e1 1898
42e69d6b
VZ
1899 if ( x )
1900 *x = pt.x;
1901 if ( y )
1902 *y = pt.y;
1903}
a23fd0e1 1904
1e6feb95 1905void wxWindowMSW::DoClientToScreen(int *x, int *y) const
42e69d6b
VZ
1906{
1907 POINT pt;
1908 if ( x )
1909 pt.x = *x;
1910 if ( y )
1911 pt.y = *y;
54bdd8b0 1912
82c9f85c 1913 ::ClientToScreen(GetHwnd(), &pt);
a23fd0e1 1914
42e69d6b
VZ
1915 if ( x )
1916 *x = pt.x;
1917 if ( y )
1918 *y = pt.y;
1919}
a23fd0e1 1920
86e30911 1921bool
7d86a2d4
VZ
1922wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
1923{
1924#if USE_DEFERRED_SIZING
1925 // if our parent had prepared a defer window handle for us, use it (unless
1926 // we are a top level window)
1927 wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
1928
1929 HDWP hdwp = parent ? (HDWP)parent->m_hDWP : NULL;
1930 if ( hdwp )
1931 {
1932 hdwp = ::DeferWindowPos(hdwp, (HWND)hwnd, NULL, x, y, width, height,
dd28827a 1933 SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
7d86a2d4
VZ
1934 if ( !hdwp )
1935 {
1936 wxLogLastError(_T("DeferWindowPos"));
1937 }
1938 }
1939
1940 if ( parent )
1941 {
1942 // hdwp must be updated as it may have been changed
1943 parent->m_hDWP = (WXHANDLE)hdwp;
1944 }
1945
86e30911
VZ
1946 if ( hdwp )
1947 {
1948 // did deferred move, remember new coordinates of the window as they're
1949 // different from what Windows would return for it
1950 return true;
1951 }
1952
7d86a2d4 1953 // otherwise (or if deferring failed) move the window in place immediately
7d86a2d4 1954#endif // USE_DEFERRED_SIZING
86e30911 1955 if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) )
7d86a2d4 1956 {
86e30911 1957 wxLogLastError(wxT("MoveWindow"));
7d86a2d4 1958 }
86e30911
VZ
1959
1960 // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move,
1961 // ignored otherwise
1962 return false;
7d86a2d4
VZ
1963}
1964
1e6feb95 1965void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
b782f2e0 1966{
62e1ba75
JS
1967 // TODO: is this consistent with other platforms?
1968 // Still, negative width or height shouldn't be allowed
1969 if (width < 0)
1970 width = 0;
1971 if (height < 0)
1972 height = 0;
9b6ae450 1973
86e30911
VZ
1974 if ( DoMoveSibling(m_hWnd, x, y, width, height) )
1975 {
1976#if USE_DEFERRED_SIZING
1977 m_pendingPosition = wxPoint(x, y);
1978 m_pendingSize = wxSize(width, height);
f8cba58b
VZ
1979 }
1980 else // window was moved immediately, without deferring it
1981 {
1982 m_pendingPosition = wxDefaultPosition;
1983 m_pendingSize = wxDefaultSize;
86e30911
VZ
1984#endif // USE_DEFERRED_SIZING
1985 }
b782f2e0
VZ
1986}
1987
4438caf4
VZ
1988// set the size of the window: if the dimensions are positive, just use them,
1989// but if any of them is equal to -1, it means that we must find the value for
1990// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1991// which case -1 is a valid value for x and y)
1992//
1993// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1994// the width/height to best suit our contents, otherwise we reuse the current
1995// width/height
1e6feb95 1996void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
42e69d6b 1997{
4438caf4 1998 // get the current size and position...
42e69d6b 1999 int currentX, currentY;
da78f3b1
RD
2000 int currentW, currentH;
2001
42e69d6b 2002 GetPosition(&currentX, &currentY);
42e69d6b 2003 GetSize(&currentW, &currentH);
a23fd0e1 2004
952f2aaa
VZ
2005 // ... and don't do anything (avoiding flicker) if it's already ok unless
2006 // we're forced to resize the window
4438caf4 2007 if ( x == currentX && y == currentY &&
952f2aaa
VZ
2008 width == currentW && height == currentH &&
2009 !(sizeFlags & wxSIZE_FORCE) )
4438caf4 2010 {
42e69d6b 2011 return;
4438caf4 2012 }
a23fd0e1 2013
422d0ff0 2014 if ( x == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
4438caf4 2015 x = currentX;
422d0ff0 2016 if ( y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
4438caf4 2017 y = currentY;
a23fd0e1 2018
4438caf4 2019 AdjustForParentClientOrigin(x, y, sizeFlags);
a23fd0e1 2020
abb74e0f 2021 wxSize size = wxDefaultSize;
422d0ff0 2022 if ( width == wxDefaultCoord )
4438caf4 2023 {
9e2896e5 2024 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
4438caf4
VZ
2025 {
2026 size = DoGetBestSize();
2027 width = size.x;
2028 }
2029 else
2030 {
2031 // just take the current one
2032 width = currentW;
2033 }
2034 }
2035
422d0ff0 2036 if ( height == wxDefaultCoord )
4438caf4 2037 {
9e2896e5 2038 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
4438caf4 2039 {
422d0ff0 2040 if ( size.x == wxDefaultCoord )
4438caf4 2041 {
b782f2e0 2042 size = DoGetBestSize();
4438caf4
VZ
2043 }
2044 //else: already called DoGetBestSize() above
a23fd0e1 2045
4438caf4
VZ
2046 height = size.y;
2047 }
2048 else
2049 {
2050 // just take the current one
2051 height = currentH;
2052 }
2053 }
2054
b782f2e0 2055 DoMoveWindow(x, y, width, height);
4438caf4
VZ
2056}
2057
1e6feb95 2058void wxWindowMSW::DoSetClientSize(int width, int height)
42e69d6b 2059{
90e572f1 2060 // setting the client size is less obvious than it could have been
d4597e13 2061 // because in the result of changing the total size the window scrollbar
c72b1ad7
VZ
2062 // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect()
2063 // doesn't take neither into account) and so the client size will not be
2064 // correct as the difference between the total and client size changes --
2065 // so we keep changing it until we get it right
d4597e13 2066 //
d6a97306
VZ
2067 // normally this loop shouldn't take more than 3 iterations (usually 1 but
2068 // if scrollbars [dis]appear as the result of the first call, then 2 and it
2069 // may become 3 if the window had 0 size originally and so we didn't
2070 // calculate the scrollbar correction correctly during the first iteration)
2071 // but just to be on the safe side we check for it instead of making it an
d4597e13 2072 // "infinite" loop (i.e. leaving break inside as the only way to get out)
d6a97306 2073 for ( int i = 0; i < 4; i++ )
d4597e13
VZ
2074 {
2075 RECT rectClient;
2076 ::GetClientRect(GetHwnd(), &rectClient);
2bda0e17 2077
b0268daf 2078 // if the size is already ok, stop here (NB: rectClient.left = top = 0)
422d0ff0
WS
2079 if ( (rectClient.right == width || width == wxDefaultCoord) &&
2080 (rectClient.bottom == height || height == wxDefaultCoord) )
d4597e13
VZ
2081 {
2082 break;
2083 }
a23fd0e1 2084
d4597e13
VZ
2085 // Find the difference between the entire window (title bar and all)
2086 // and the client area; add this to the new client size to move the
2087 // window
2088 RECT rectWin;
2089 ::GetWindowRect(GetHwnd(), &rectWin);
2090
b0268daf
VZ
2091 const int widthWin = rectWin.right - rectWin.left,
2092 heightWin = rectWin.bottom - rectWin.top;
387a3b02 2093
d4597e13
VZ
2094 // MoveWindow positions the child windows relative to the parent, so
2095 // adjust if necessary
2096 if ( !IsTopLevel() )
2097 {
2098 wxWindow *parent = GetParent();
2099 if ( parent )
2100 {
b0268daf 2101 ::ScreenToClient(GetHwndOf(parent), (POINT *)&rectWin);
d4597e13
VZ
2102 }
2103 }
a23fd0e1 2104
b0268daf 2105 // don't call DoMoveWindow() because we want to move window immediately
c72b1ad7
VZ
2106 // and not defer it here as otherwise the value returned by
2107 // GetClient/WindowRect() wouldn't change as the window wouldn't be
2108 // really resized
b0268daf
VZ
2109 if ( !::MoveWindow(GetHwnd(),
2110 rectWin.left,
2111 rectWin.top,
2112 width + widthWin - rectClient.right,
2113 height + heightWin - rectClient.bottom,
2114 TRUE) )
2115 {
2116 wxLogLastError(_T("MoveWindow"));
2117 }
d4597e13 2118 }
42e69d6b 2119}
a23fd0e1 2120
42e69d6b
VZ
2121// ---------------------------------------------------------------------------
2122// text metrics
2123// ---------------------------------------------------------------------------
a23fd0e1 2124
1e6feb95 2125int wxWindowMSW::GetCharHeight() const
42e69d6b 2126{
f6bcfd97 2127 return wxGetTextMetrics(this).tmHeight;
42e69d6b 2128}
3eddf563 2129
1e6feb95 2130int wxWindowMSW::GetCharWidth() const
42e69d6b 2131{
f6bcfd97
BP
2132 // +1 is needed because Windows apparently adds it when calculating the
2133 // dialog units size in pixels
2134#if wxDIALOG_UNIT_COMPATIBILITY
1e6feb95 2135 return wxGetTextMetrics(this).tmAveCharWidth;
f6bcfd97
BP
2136#else
2137 return wxGetTextMetrics(this).tmAveCharWidth + 1;
2138#endif
42e69d6b 2139}
f4621a09 2140
1e6feb95 2141void wxWindowMSW::GetTextExtent(const wxString& string,
34636400 2142 int *x, int *y,
42e69d6b 2143 int *descent, int *externalLeading,
e0448413 2144 const wxFont *fontToUse) const
42e69d6b 2145{
e0448413 2146 wxASSERT_MSG( !fontToUse || fontToUse->Ok(),
64869ab7 2147 _T("invalid font in GetTextExtent()") );
634903fd 2148
e0448413
VZ
2149 HFONT hfontToUse;
2150 if ( fontToUse )
2151 hfontToUse = GetHfontOf(*fontToUse);
2d17baae 2152 else
e0448413 2153 hfontToUse = GetHfontOf(GetFont());
634903fd 2154
64869ab7 2155 WindowHDC hdc(GetHwnd());
e0448413 2156 SelectInHDC selectFont(hdc, hfontToUse);
341c92a8 2157
42e69d6b
VZ
2158 SIZE sizeRect;
2159 TEXTMETRIC tm;
e0a050e3 2160 ::GetTextExtentPoint32(hdc, string.wx_str(), string.length(), &sizeRect);
64869ab7 2161 GetTextMetrics(hdc, &tm);
42e69d6b 2162
0655ad29
VZ
2163 if ( x )
2164 *x = sizeRect.cx;
2165 if ( y )
2166 *y = sizeRect.cy;
2167 if ( descent )
2168 *descent = tm.tmDescent;
2169 if ( externalLeading )
2170 *externalLeading = tm.tmExternalLeading;
2bda0e17
KB
2171}
2172
c50f1fb9
VZ
2173// ---------------------------------------------------------------------------
2174// popup menu
2175// ---------------------------------------------------------------------------
2176
2e9f62da
VZ
2177#if wxUSE_MENUS_NATIVE
2178
ed45e263
VZ
2179// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
2180// immediately, without waiting for the next event loop iteration
2181//
2182// NB: this function should probably be made public later as it can almost
2183// surely replace wxYield() elsewhere as well
2184static void wxYieldForCommandsOnly()
2185{
2186 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
2187 // want to process it here)
2188 MSG msg;
1bf77ee5 2189 while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE) )
ed45e263 2190 {
dd7ebf8b 2191 if ( msg.message == WM_QUIT )
1bf77ee5
VZ
2192 {
2193 // if we retrieved a WM_QUIT, insert back into the message queue.
2194 ::PostQuitMessage(0);
2195 break;
2196 }
7de59551 2197
1bf77ee5
VZ
2198 // luckily (as we don't have access to wxEventLoopImpl method from here
2199 // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it
2200 // immediately
2201 ::TranslateMessage(&msg);
2202 ::DispatchMessage(&msg);
2203 }
ed45e263
VZ
2204}
2205
1e6feb95 2206bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
c50f1fb9
VZ
2207{
2208 menu->SetInvokingWindow(this);
2209 menu->UpdateUI();
2210
27d2dbbc 2211 if ( x == wxDefaultCoord && y == wxDefaultCoord )
971562cb
VS
2212 {
2213 wxPoint mouse = ScreenToClient(wxGetMousePosition());
2214 x = mouse.x; y = mouse.y;
2215 }
2216
c50f1fb9
VZ
2217 HWND hWnd = GetHwnd();
2218 HMENU hMenu = GetHmenuOf(menu);
2219 POINT point;
2220 point.x = x;
2221 point.y = y;
2222 ::ClientToScreen(hWnd, &point);
5cb598ae 2223#if defined(__WXWINCE__)
b40bf35c
VZ
2224 static const UINT flags = 0;
2225#else // !__WXWINCE__
2226 UINT flags = TPM_RIGHTBUTTON;
2227 // NT4 doesn't support TPM_RECURSE and simply doesn't show the menu at all
2228 // when it's use, I'm not sure about Win95/98 but prefer to err on the safe
2229 // side and not to use it there neither -- modify the test if it does work
2230 // on these systems
2231 if ( wxGetWinVersion() >= wxWinVersion_5 )
2232 {
2233 // using TPM_RECURSE allows us to show a popup menu while another menu
2234 // is opened which can be useful and is supported by the other
2235 // platforms, so allow it under Windows too
2236 flags |= TPM_RECURSE;
2237 }
2238#endif // __WXWINCE__/!__WXWINCE__
2239
7f0586ef 2240 ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
ed45e263 2241
90e572f1 2242 // we need to do it right now as otherwise the events are never going to be
ed45e263
VZ
2243 // sent to wxCurrentPopupMenu from HandleCommand()
2244 //
2245 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
2246 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
2247 // destroyed as soon as we return (it can be a local variable in the caller
2248 // for example) and so we do need to process the event immediately
2249 wxYieldForCommandsOnly();
2250
c50f1fb9
VZ
2251 menu->SetInvokingWindow(NULL);
2252
08158721 2253 return true;
c50f1fb9
VZ
2254}
2255
1e6feb95
VZ
2256#endif // wxUSE_MENUS_NATIVE
2257
42e69d6b
VZ
2258// ===========================================================================
2259// pre/post message processing
2260// ===========================================================================
2bda0e17 2261
c140b7e7 2262WXLRESULT wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
42e69d6b
VZ
2263{
2264 if ( m_oldWndProc )
2265 return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
2266 else
2267 return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
2268}
2bda0e17 2269
1e6feb95 2270bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
42e69d6b 2271{
1e6feb95
VZ
2272 // wxUniversal implements tab traversal itself
2273#ifndef __WXUNIVERSAL__
42e69d6b 2274 if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) )
2d0a075d 2275 {
42e69d6b
VZ
2276 // intercept dialog navigation keys
2277 MSG *msg = (MSG *)pMsg;
d9317fd4
VZ
2278
2279 // here we try to do all the job which ::IsDialogMessage() usually does
2280 // internally
573a1586 2281 if ( msg->message == WM_KEYDOWN )
42e69d6b 2282 {
3f7bc32b
VZ
2283 bool bCtrlDown = wxIsCtrlDown();
2284 bool bShiftDown = wxIsShiftDown();
a23fd0e1 2285
42e69d6b
VZ
2286 // WM_GETDLGCODE: ask the control if it wants the key for itself,
2287 // don't process it if it's the case (except for Ctrl-Tab/Enter
2288 // combinations which are always processed)
977f50f3
VZ
2289 LONG lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0);
2290
2291 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
2292 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
2293 // it, of course, implies them
2294 if ( lDlgCode & DLGC_WANTALLKEYS )
42e69d6b 2295 {
977f50f3 2296 lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS;
42e69d6b 2297 }
a23fd0e1 2298
08158721 2299 bool bForward = true,
298ca00c
VZ
2300 bWindowChange = false,
2301 bFromTab = false;
a23fd0e1 2302
573a1586 2303 // should we process this message specially?
08158721 2304 bool bProcess = true;
9145664b 2305 switch ( msg->wParam )
42e69d6b
VZ
2306 {
2307 case VK_TAB:
7cc44669
VZ
2308 if ( (lDlgCode & DLGC_WANTTAB) && !bCtrlDown )
2309 {
2310 // let the control have the TAB
08158721 2311 bProcess = false;
42e69d6b 2312 }
7cc44669
VZ
2313 else // use it for navigation
2314 {
42e69d6b
VZ
2315 // Ctrl-Tab cycles thru notebook pages
2316 bWindowChange = bCtrlDown;
319fefa9 2317 bForward = !bShiftDown;
298ca00c 2318 bFromTab = true;
42e69d6b
VZ
2319 }
2320 break;
a23fd0e1 2321
42e69d6b
VZ
2322 case VK_UP:
2323 case VK_LEFT:
2324 if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
08158721 2325 bProcess = false;
42e69d6b 2326 else
08158721 2327 bForward = false;
42e69d6b 2328 break;
a02eb1d2 2329
42e69d6b
VZ
2330 case VK_DOWN:
2331 case VK_RIGHT:
2332 if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
08158721 2333 bProcess = false;
42e69d6b 2334 break;
2bda0e17 2335
efe5e221
VZ
2336 case VK_PRIOR:
2337 bForward = false;
2338 // fall through
2339
2340 case VK_NEXT:
2341 // we treat PageUp/Dn as arrows because chances are that
2342 // a control which needs arrows also needs them for
2343 // navigation (e.g. wxTextCtrl, wxListCtrl, ...)
ada5f90d 2344 if ( (lDlgCode & DLGC_WANTARROWS) && !bCtrlDown )
efe5e221 2345 bProcess = false;
ada5f90d 2346 else // OTOH Ctrl-PageUp/Dn works as [Shift-]Ctrl-Tab
efe5e221
VZ
2347 bWindowChange = true;
2348 break;
2349
42e69d6b
VZ
2350 case VK_RETURN:
2351 {
90c6edd7 2352#if wxUSE_BUTTON
3147bb58 2353 // currently active button should get enter press even
90c6edd7
VZ
2354 // if there is a default button elsewhere so check if
2355 // this window is a button first
2356 wxWindow *btn = NULL;
3147bb58 2357 if ( lDlgCode & DLGC_DEFPUSHBUTTON )
319fefa9 2358 {
3e79ed96
VZ
2359 // let IsDialogMessage() handle this for all
2360 // buttons except the owner-drawn ones which it
2361 // just seems to ignore
2362 long style = ::GetWindowLong(msg->hwnd, GWL_STYLE);
2363 if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
2364 {
2365 // emulate the button click
dca0f651 2366 btn = wxFindWinFromHandle(msg->hwnd);
3e79ed96
VZ
2367 }
2368
08158721 2369 bProcess = false;
319fefa9 2370 }
90c6edd7 2371 else // not a button itself, do we have default button?
c50f1fb9 2372 {
8e86978a
VZ
2373 // check if this window or any of its ancestors
2374 // wants the message for itself (we always reserve
2375 // Ctrl-Enter for dialog navigation though)
2376 wxWindow *win = this;
2377 if ( !bCtrlDown )
2378 {
53b0c2bc 2379 // this will contain the dialog code of this
0075ea22 2380 // window and all of its parent windows in turn
53b0c2bc
VZ
2381 LONG lDlgCode2 = lDlgCode;
2382
0075ea22 2383 while ( win )
8e86978a 2384 {
53b0c2bc 2385 if ( lDlgCode2 & DLGC_WANTMESSAGE )
8e86978a
VZ
2386 {
2387 // as it wants to process Enter itself,
2388 // don't call IsDialogMessage() which
2389 // would consume it
2390 return false;
2391 }
2392
0075ea22
VZ
2393 // don't propagate keyboard messages beyond
2394 // the first top level window parent
2395 if ( win->IsTopLevel() )
2396 break;
2397
2398 win = win->GetParent();
2399
53b0c2bc
VZ
2400 lDlgCode2 = ::SendMessage
2401 (
2402 GetHwndOf(win),
2403 WM_GETDLGCODE,
2404 0,
2405 0
2406 );
8e86978a
VZ
2407 }
2408 }
2409 else // bCtrlDown
2410 {
2411 win = wxGetTopLevelParent(win);
2412 }
2413
2414 wxTopLevelWindow * const
2415 tlw = wxDynamicCast(win, wxTopLevelWindow);
6c20e8f8 2416 if ( tlw )
c50f1fb9 2417 {
90c6edd7
VZ
2418 btn = wxDynamicCast(tlw->GetDefaultItem(),
2419 wxButton);
c50f1fb9 2420 }
90c6edd7
VZ
2421 }
2422
2423 if ( btn && btn->IsEnabled() )
2424 {
2425 btn->MSWCommand(BN_CLICKED, 0 /* unused */);
2426 return true;
2427 }
2428
1e6feb95 2429#endif // wxUSE_BUTTON
90c6edd7 2430
7b504551 2431#ifdef __WXWINCE__
90c6edd7
VZ
2432 // map Enter presses into button presses on PDAs
2433 wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN);
2434 event.SetEventObject(this);
937013e0 2435 if ( HandleWindowEvent(event) )
90c6edd7
VZ
2436 return true;
2437#endif // __WXWINCE__
42e69d6b
VZ
2438 }
2439 break;
2bda0e17 2440
42e69d6b 2441 default:
08158721 2442 bProcess = false;
42e69d6b 2443 }
2bda0e17 2444
42e69d6b
VZ
2445 if ( bProcess )
2446 {
2447 wxNavigationKeyEvent event;
2448 event.SetDirection(bForward);
2449 event.SetWindowChange(bWindowChange);
298ca00c 2450 event.SetFromTab(bFromTab);
42e69d6b 2451 event.SetEventObject(this);
3572173c 2452
937013e0 2453 if ( HandleWindowEvent(event) )
57c0af52 2454 {
d7e0024b
VZ
2455 // as we don't call IsDialogMessage(), which would take of
2456 // this by default, we need to manually send this message
1ca78aa1
JS
2457 // so that controls can change their UI state if needed
2458 MSWUpdateUIState(UIS_CLEAR, UISF_HIDEFOCUS);
d7e0024b 2459
08158721 2460 return true;
57c0af52 2461 }
42e69d6b
VZ
2462 }
2463 }
a23fd0e1 2464
98ebf919 2465 if ( ::IsDialogMessage(GetHwnd(), msg) )
f6bcfd97 2466 {
98ebf919
VZ
2467 // IsDialogMessage() did something...
2468 return true;
f6bcfd97 2469 }
42e69d6b 2470 }
1e6feb95 2471#endif // __WXUNIVERSAL__
a23fd0e1 2472
42e69d6b
VZ
2473#if wxUSE_TOOLTIPS
2474 if ( m_tooltip )
387a3b02 2475 {
42e69d6b
VZ
2476 // relay mouse move events to the tooltip control
2477 MSG *msg = (MSG *)pMsg;
2478 if ( msg->message == WM_MOUSEMOVE )
259a4264 2479 wxToolTip::RelayEvent(pMsg);
387a3b02 2480 }
42e69d6b 2481#endif // wxUSE_TOOLTIPS
a23fd0e1 2482
08158721 2483 return false;
387a3b02
JS
2484}
2485
1e6feb95 2486bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg)
387a3b02 2487{
1e6feb95 2488#if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
c50f1fb9 2489 return m_acceleratorTable.Translate(this, pMsg);
1e6feb95 2490#else
574c939e 2491 (void) pMsg;
08158721 2492 return false;
1e6feb95 2493#endif // wxUSE_ACCEL
387a3b02
JS
2494}
2495
98ebf919 2496bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* msg)
a37d422a 2497{
98ebf919
VZ
2498 // all tests below have to deal with various bugs/misfeatures of
2499 // IsDialogMessage(): we have to prevent it from being called from our
2500 // MSWProcessMessage() in some situations
2501
2502 // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the
2503 // message even when there is no cancel button and when the message is
2504 // needed by the control itself: in particular, it prevents the tree in
2505 // place edit control from being closed with Escape in a dialog
2506 if ( msg->message == WM_KEYDOWN && msg->wParam == VK_ESCAPE )
2507 {
2508 return false;
2509 }
2510
2511 // ::IsDialogMessage() is broken and may sometimes hang the application by
2512 // going into an infinite loop when it tries to find the control to give
2513 // focus to when Alt-<key> is pressed, so we try to detect [some of] the
2514 // situations when this may happen and not call it then
2515 if ( msg->message != WM_SYSCHAR )
2516 return true;
2517
2518 // assume we can call it by default
2519 bool canSafelyCallIsDlgMsg = true;
2520
2521 HWND hwndFocus = ::GetFocus();
2522
2523 // if the currently focused window itself has WS_EX_CONTROLPARENT style,
2524 // ::IsDialogMessage() will also enter an infinite loop, because it will
2525 // recursively check the child windows but not the window itself and so if
2526 // none of the children accepts focus it loops forever (as it only stops
2527 // when it gets back to the window it started from)
2528 //
2529 // while it is very unusual that a window with WS_EX_CONTROLPARENT
2530 // style has the focus, it can happen. One such possibility is if
2531 // all windows are either toplevel, wxDialog, wxPanel or static
2532 // controls and no window can actually accept keyboard input.
2533#if !defined(__WXWINCE__)
2534 if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
2535 {
2536 // pessimistic by default
2537 canSafelyCallIsDlgMsg = false;
2538 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2539 node;
2540 node = node->GetNext() )
2541 {
2542 wxWindow * const win = node->GetData();
ad02525d 2543 if ( win->CanAcceptFocus() &&
d66d0500 2544 !wxHasWindowExStyle(win, WS_EX_CONTROLPARENT) )
98ebf919
VZ
2545 {
2546 // it shouldn't hang...
2547 canSafelyCallIsDlgMsg = true;
2548
2549 break;
2550 }
2551 }
2552 }
2553#endif // !__WXWINCE__
2554
2555 if ( canSafelyCallIsDlgMsg )
2556 {
2557 // ::IsDialogMessage() can enter in an infinite loop when the
2558 // currently focused window is disabled or hidden and its
2559 // parent has WS_EX_CONTROLPARENT style, so don't call it in
2560 // this case
2561 while ( hwndFocus )
2562 {
2563 if ( !::IsWindowEnabled(hwndFocus) ||
2564 !::IsWindowVisible(hwndFocus) )
2565 {
2566 // it would enter an infinite loop if we do this!
2567 canSafelyCallIsDlgMsg = false;
2568
2569 break;
2570 }
2571
2572 if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
2573 {
2574 // it's a top level window, don't go further -- e.g. even
2575 // if the parent of a dialog is disabled, this doesn't
2576 // break navigation inside the dialog
2577 break;
2578 }
2579
2580 hwndFocus = ::GetParent(hwndFocus);
2581 }
2582 }
2583
2584 return canSafelyCallIsDlgMsg;
a37d422a
VZ
2585}
2586
42e69d6b 2587// ---------------------------------------------------------------------------
e39af974 2588// message params unpackers
42e69d6b 2589// ---------------------------------------------------------------------------
2bda0e17 2590
1e6feb95 2591void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b
VZ
2592 WORD *id, WXHWND *hwnd, WORD *cmd)
2593{
2594 *id = LOWORD(wParam);
2595 *hwnd = (WXHWND)lParam;
2596 *cmd = HIWORD(wParam);
2bda0e17
KB
2597}
2598
1e6feb95 2599void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2600 WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
2bda0e17 2601{
42e69d6b
VZ
2602 *state = LOWORD(wParam);
2603 *minimized = HIWORD(wParam);
2604 *hwnd = (WXHWND)lParam;
2bda0e17
KB
2605}
2606
1e6feb95 2607void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2608 WXWORD *code, WXWORD *pos, WXHWND *hwnd)
2bda0e17 2609{
42e69d6b
VZ
2610 *code = LOWORD(wParam);
2611 *pos = HIWORD(wParam);
2612 *hwnd = (WXHWND)lParam;
2613}
a23fd0e1 2614
1e6feb95 2615void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
01c500af 2616 WXHDC *hdc, WXHWND *hwnd)
42e69d6b 2617{
42e69d6b
VZ
2618 *hwnd = (WXHWND)lParam;
2619 *hdc = (WXHDC)wParam;
2bda0e17
KB
2620}
2621
1e6feb95 2622void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2623 WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
2bda0e17 2624{
42e69d6b
VZ
2625 *item = (WXWORD)wParam;
2626 *flags = HIWORD(wParam);
2627 *hmenu = (WXHMENU)lParam;
2628}
c085e333 2629
42e69d6b 2630// ---------------------------------------------------------------------------
77ffb593 2631// Main wxWidgets window proc and the window proc for wxWindow
42e69d6b 2632// ---------------------------------------------------------------------------
2bda0e17 2633
42e69d6b
VZ
2634// Hook for new window just as it's being created, when the window isn't yet
2635// associated with the handle
b225f659
VZ
2636static wxWindowMSW *gs_winBeingCreated = NULL;
2637
2638// implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2639// window being created and insures that it's always unset back later
2640wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW *winBeingCreated)
2641{
2642 gs_winBeingCreated = winBeingCreated;
2643}
2644
2645wxWindowCreationHook::~wxWindowCreationHook()
2646{
2647 gs_winBeingCreated = NULL;
2648}
42e69d6b
VZ
2649
2650// Main window proc
3135f4a7 2651LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2bda0e17 2652{
42e69d6b
VZ
2653 // trace all messages - useful for the debugging
2654#ifdef __WXDEBUG__
13e4c4d9 2655 wxLogTrace(wxTraceMessages,
dca0f651
VZ
2656 wxT("Processing %s(hWnd=%p, wParam=%08lx, lParam=%08lx)"),
2657 wxGetMessageName(message), hWnd, (long)wParam, lParam);
42e69d6b 2658#endif // __WXDEBUG__
2bda0e17 2659
dca0f651 2660 wxWindowMSW *wnd = wxFindWinFromHandle(hWnd);
c085e333 2661
42e69d6b 2662 // when we get the first message for the HWND we just created, we associate
b225f659
VZ
2663 // it with wxWindow stored in gs_winBeingCreated
2664 if ( !wnd && gs_winBeingCreated )
2d0a075d 2665 {
b225f659
VZ
2666 wxAssociateWinWithHandle(hWnd, gs_winBeingCreated);
2667 wnd = gs_winBeingCreated;
2668 gs_winBeingCreated = NULL;
42e69d6b 2669 wnd->SetHWND((WXHWND)hWnd);
2d0a075d 2670 }
2bda0e17 2671
42e69d6b 2672 LRESULT rc;
a23fd0e1 2673
b46b1d59 2674 if ( wnd && wxGUIEventLoop::AllowProcessing(wnd) )
b225f659 2675 rc = wnd->MSWWindowProc(message, wParam, lParam);
a23fd0e1 2676 else
b225f659 2677 rc = ::DefWindowProc(hWnd, message, wParam, lParam);
2bda0e17 2678
42e69d6b 2679 return rc;
f7bd2698
JS
2680}
2681
c140b7e7 2682WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
f7bd2698 2683{
42e69d6b 2684 // did we process the message?
08158721 2685 bool processed = false;
f7bd2698 2686
42e69d6b
VZ
2687 // the return value
2688 union
2bda0e17 2689 {
42e69d6b 2690 bool allow;
c140b7e7 2691 WXLRESULT result;
42e69d6b
VZ
2692 WXHBRUSH hBrush;
2693 } rc;
2bda0e17 2694
42e69d6b
VZ
2695 // for most messages we should return 0 when we do process the message
2696 rc.result = 0;
2bda0e17 2697
42e69d6b 2698 switch ( message )
39136494 2699 {
42e69d6b
VZ
2700 case WM_CREATE:
2701 {
2702 bool mayCreate;
2703 processed = HandleCreate((WXLPCREATESTRUCT)lParam, &mayCreate);
2704 if ( processed )
2705 {
2706 // return 0 to allow window creation
2707 rc.result = mayCreate ? 0 : -1;
2708 }
2709 }
2710 break;
47cbd6da 2711
42e69d6b 2712 case WM_DESTROY:
08158721 2713 // never set processed to true and *always* pass WM_DESTROY to
ad4297f3
VZ
2714 // DefWindowProc() as Windows may do some internal cleanup when
2715 // processing it and failing to pass the message along may cause
2716 // memory and resource leaks!
2717 (void)HandleDestroy();
42e69d6b
VZ
2718 break;
2719
9b6ae450
VZ
2720 case WM_SIZE:
2721 processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
9b6ae450
VZ
2722 break;
2723
42e69d6b 2724 case WM_MOVE:
132cb640 2725 processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
42e69d6b 2726 break;
47cbd6da 2727
7f0586ef 2728#if !defined(__WXWINCE__)
5706de1c 2729 case WM_MOVING:
540b6b09
VZ
2730 {
2731 LPRECT pRect = (LPRECT)lParam;
2732 wxRect rc;
2733 rc.SetLeft(pRect->left);
2734 rc.SetTop(pRect->top);
2735 rc.SetRight(pRect->right);
2736 rc.SetBottom(pRect->bottom);
2737 processed = HandleMoving(rc);
2738 if (processed) {
2739 pRect->left = rc.GetLeft();
2740 pRect->top = rc.GetTop();
2741 pRect->right = rc.GetRight();
2742 pRect->bottom = rc.GetBottom();
2743 }
2744 }
5706de1c 2745 break;
a047aff2 2746#if 0
aa767a45
JS
2747 case WM_ENTERSIZEMOVE:
2748 {
2749 processed = HandleEnterSizeMove();
2750 }
2751 break;
2752
2753 case WM_EXITSIZEMOVE:
2754 {
2755 processed = HandleExitSizeMove();
2756 }
2757 break;
a047aff2 2758#endif
5706de1c
JS
2759 case WM_SIZING:
2760 {
2761 LPRECT pRect = (LPRECT)lParam;
2762 wxRect rc;
2763 rc.SetLeft(pRect->left);
2764 rc.SetTop(pRect->top);
2765 rc.SetRight(pRect->right);
2766 rc.SetBottom(pRect->bottom);
2767 processed = HandleSizing(rc);
2768 if (processed) {
2769 pRect->left = rc.GetLeft();
2770 pRect->top = rc.GetTop();
2771 pRect->right = rc.GetRight();
2772 pRect->bottom = rc.GetBottom();
2773 }
2774 }
2775 break;
9b6ae450 2776#endif // !__WXWINCE__
5706de1c 2777
7f0586ef 2778#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95 2779 case WM_ACTIVATEAPP:
afafd942 2780 // This implicitly sends a wxEVT_ACTIVATE_APP event
1e6feb95 2781 wxTheApp->SetActive(wParam != 0, FindFocus());
42e69d6b 2782 break;
8a46f9b1 2783#endif
47cbd6da 2784
42e69d6b 2785 case WM_ACTIVATE:
341c92a8 2786 {
42e69d6b
VZ
2787 WXWORD state, minimized;
2788 WXHWND hwnd;
2789 UnpackActivate(wParam, lParam, &state, &minimized, &hwnd);
2790
2791 processed = HandleActivate(state, minimized != 0, (WXHWND)hwnd);
341c92a8 2792 }
42e69d6b 2793 break;
341c92a8 2794
42e69d6b 2795 case WM_SETFOCUS:
dca0f651 2796 processed = HandleSetFocus((WXHWND)wParam);
42e69d6b 2797 break;
47cbd6da 2798
42e69d6b 2799 case WM_KILLFOCUS:
dca0f651 2800 processed = HandleKillFocus((WXHWND)wParam);
42e69d6b 2801 break;
47cbd6da 2802
c3732409 2803 case WM_PRINTCLIENT:
1a784dfc 2804 processed = HandlePrintClient((WXHDC)wParam);
07c19327
VZ
2805 break;
2806
c3732409
VZ
2807 case WM_PAINT:
2808 if ( wParam )
5c6c3176 2809 {
5c6c3176 2810 wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
07c19327 2811
5c6c3176
RD
2812 processed = HandlePaint();
2813 }
c3732409
VZ
2814 else // no DC given
2815 {
2816 processed = HandlePaint();
2817 }
5c6c3176
RD
2818 break;
2819
42e69d6b 2820 case WM_CLOSE:
9fd9e47a
JS
2821#ifdef __WXUNIVERSAL__
2822 // Universal uses its own wxFrame/wxDialog, so we don't receive
2823 // close events unless we have this.
2824 Close();
c3732409
VZ
2825#endif // __WXUNIVERSAL__
2826
42e69d6b
VZ
2827 // don't let the DefWindowProc() destroy our window - we'll do it
2828 // ourselves in ~wxWindow
08158721 2829 processed = true;
42e69d6b
VZ
2830 rc.result = TRUE;
2831 break;
47cbd6da 2832
42e69d6b
VZ
2833 case WM_SHOWWINDOW:
2834 processed = HandleShow(wParam != 0, (int)lParam);
2835 break;
3a19e16d 2836
42e69d6b 2837 case WM_MOUSEMOVE:
132cb640
VZ
2838 processed = HandleMouseMove(GET_X_LPARAM(lParam),
2839 GET_Y_LPARAM(lParam),
2840 wParam);
2841 break;
0d0512bd 2842
4e5c6c33 2843#ifdef HAVE_TRACKMOUSEEVENT
e5297b7f 2844 case WM_MOUSELEAVE:
aafb9978
VZ
2845 // filter out excess WM_MOUSELEAVE events sent after PopupMenu()
2846 // (on XP at least)
4e5c6c33 2847 if ( m_mouseInWindow )
e5297b7f 2848 {
4e5c6c33 2849 GenerateMouseLeave();
e5297b7f 2850 }
4e5c6c33
VZ
2851
2852 // always pass processed back as false, this allows the window
2853 // manager to process the message too. This is needed to
2854 // ensure windows XP themes work properly as the mouse moves
2855 // over widgets like buttons. So don't set processed to true here.
51e4e266 2856 break;
4e5c6c33 2857#endif // HAVE_TRACKMOUSEEVENT
35bbb0c6 2858
d2c52078
RD
2859#if wxUSE_MOUSEWHEEL
2860 case WM_MOUSEWHEEL:
2861 processed = HandleMouseWheel(wParam, lParam);
2862 break;
2863#endif
2864
42e69d6b
VZ
2865 case WM_LBUTTONDOWN:
2866 case WM_LBUTTONUP:
2867 case WM_LBUTTONDBLCLK:
2868 case WM_RBUTTONDOWN:
2869 case WM_RBUTTONUP:
2870 case WM_RBUTTONDBLCLK:
2871 case WM_MBUTTONDOWN:
2872 case WM_MBUTTONUP:
2873 case WM_MBUTTONDBLCLK:
2f68482e 2874#ifdef wxHAS_XBUTTON
01101e2d
VZ
2875 case WM_XBUTTONDOWN:
2876 case WM_XBUTTONUP:
2877 case WM_XBUTTONDBLCLK:
2f68482e 2878#endif // wxHAS_XBUTTON
dfafa702 2879 {
98363307 2880#ifdef __WXMICROWIN__
cd4453e5
VZ
2881 // MicroWindows seems to ignore the fact that a window is
2882 // disabled. So catch mouse events and throw them away if
2883 // necessary.
d0a3d109 2884 wxWindowMSW* win = this;
dfafa702 2885 for ( ;; )
d0a3d109
VZ
2886 {
2887 if (!win->IsEnabled())
2888 {
08158721 2889 processed = true;
d0a3d109
VZ
2890 break;
2891 }
dfafa702 2892
d0a3d109 2893 win = win->GetParent();
dfafa702 2894 if ( !win || win->IsTopLevel() )
d0a3d109
VZ
2895 break;
2896 }
dfafa702 2897
03e0b2b1
VZ
2898 if ( processed )
2899 break;
2900
dfafa702 2901#endif // __WXMICROWIN__
03e0b2b1
VZ
2902 int x = GET_X_LPARAM(lParam),
2903 y = GET_Y_LPARAM(lParam);
dfafa702 2904
42b1fb63 2905#ifdef __WXWINCE__
03e0b2b1 2906 // redirect the event to a static control if necessary by
42b1fb63
VZ
2907 // finding one under mouse because under CE the static controls
2908 // don't generate mouse events (even with SS_NOTIFY)
03e0b2b1
VZ
2909 wxWindowMSW *win;
2910 if ( GetCapture() == this )
2911 {
2912 // but don't do it if the mouse is captured by this window
2913 // because then it should really get this event itself
2914 win = this;
d0a3d109 2915 }
03e0b2b1
VZ
2916 else
2917 {
2918 win = FindWindowForMouseEvent(this, &x, &y);
2b5f62a0
VZ
2919
2920 // this should never happen
2921 wxCHECK_MSG( win, 0,
2922 _T("FindWindowForMouseEvent() returned NULL") );
9f011847 2923 }
7d4f65e3
JS
2924#ifdef __POCKETPC__
2925 if (IsContextMenuEnabled() && message == WM_LBUTTONDOWN)
2926 {
2927 SHRGINFO shrgi = {0};
faa94f3e 2928
7d4f65e3
JS
2929 shrgi.cbSize = sizeof(SHRGINFO);
2930 shrgi.hwndClient = (HWND) GetHWND();
2931 shrgi.ptDown.x = x;
2932 shrgi.ptDown.y = y;
faa94f3e 2933
7d4f65e3
JS
2934 shrgi.dwFlags = SHRG_RETURNCMD;
2935 // shrgi.dwFlags = SHRG_NOTIFYPARENT;
faa94f3e 2936
7d4f65e3
JS
2937 if (GN_CONTEXTMENU == ::SHRecognizeGesture(&shrgi))
2938 {
2939 wxPoint pt(x, y);
2940 pt = ClientToScreen(pt);
faa94f3e 2941
7d4f65e3 2942 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
faa94f3e 2943
7d4f65e3 2944 evtCtx.SetEventObject(this);
937013e0 2945 if (HandleWindowEvent(evtCtx))
f350d4b2 2946 {
7d4f65e3 2947 processed = true;
f350d4b2
JS
2948 return true;
2949 }
7d4f65e3
JS
2950 }
2951 }
2952#endif
2953
42b1fb63
VZ
2954#else // !__WXWINCE__
2955 wxWindowMSW *win = this;
2956#endif // __WXWINCE__/!__WXWINCE__
9f011847
VZ
2957
2958 processed = win->HandleMouseEvent(message, x, y, wParam);
2b5f62a0 2959
9f011847
VZ
2960 // if the app didn't eat the event, handle it in the default
2961 // way, that is by giving this window the focus
2962 if ( !processed )
2963 {
2b5f62a0
VZ
2964 // for the standard classes their WndProc sets the focus to
2965 // them anyhow and doing it from here results in some weird
9f011847 2966 // problems, so don't do it for them (unnecessary anyhow)
2b5f62a0
VZ
2967 if ( !win->IsOfStandardClass() )
2968 {
edc09871 2969 if ( message == WM_LBUTTONDOWN && win->IsFocusable() )
2b5f62a0
VZ
2970 win->SetFocus();
2971 }
03e0b2b1 2972 }
98363307 2973 }
dfafa702 2974 break;
d0a3d109 2975
cd4453e5 2976#ifdef MM_JOY1MOVE
42e69d6b
VZ
2977 case MM_JOY1MOVE:
2978 case MM_JOY2MOVE:
2979 case MM_JOY1ZMOVE:
2980 case MM_JOY2ZMOVE:
2981 case MM_JOY1BUTTONDOWN:
2982 case MM_JOY2BUTTONDOWN:
2983 case MM_JOY1BUTTONUP:
2984 case MM_JOY2BUTTONUP:
132cb640
VZ
2985 processed = HandleJoystickEvent(message,
2986 GET_X_LPARAM(lParam),
2987 GET_Y_LPARAM(lParam),
2988 wParam);
42e69d6b 2989 break;
cd4453e5 2990#endif // __WXMICROWIN__
47cbd6da 2991
42e69d6b
VZ
2992 case WM_COMMAND:
2993 {
2994 WORD id, cmd;
2995 WXHWND hwnd;
2996 UnpackCommand(wParam, lParam, &id, &hwnd, &cmd);
47cbd6da 2997
42e69d6b
VZ
2998 processed = HandleCommand(id, cmd, hwnd);
2999 }
3000 break;
7d532b0c 3001
42e69d6b
VZ
3002 case WM_NOTIFY:
3003 processed = HandleNotify((int)wParam, lParam, &rc.result);
3004 break;
2bda0e17 3005
27005f3a
VZ
3006 // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU,
3007 // otherwise DefWindowProc() does it perfectly fine for us, but MSLU
3008 // apparently doesn't always behave properly and needs some help
3009#if wxUSE_UNICODE_MSLU && defined(NF_QUERY)
3010 case WM_NOTIFYFORMAT:
3011 if ( lParam == NF_QUERY )
3012 {
3013 processed = true;
3014 rc.result = NFR_UNICODE;
3015 }
3016 break;
3017#endif // wxUSE_UNICODE_MSLU
3018
08158721 3019 // for these messages we must return true if process the message
cd4453e5 3020#ifdef WM_DRAWITEM
42e69d6b 3021 case WM_DRAWITEM:
dca0f651
VZ
3022 processed = MSWOnDrawItem(wParam, (WXDRAWITEMSTRUCT *)lParam);
3023 if ( processed )
3024 rc.result = TRUE;
3025 break;
57a7b7c1 3026
dca0f651
VZ
3027 case WM_MEASUREITEM:
3028 processed = MSWOnMeasureItem(wParam, (WXMEASUREITEMSTRUCT *)lParam);
3029 if ( processed )
3030 rc.result = TRUE;
42e69d6b 3031 break;
cd4453e5
VZ
3032#endif // defined(WM_DRAWITEM)
3033
9bf84618 3034 case WM_GETDLGCODE:
ff7282e1 3035 if ( !IsOfStandardClass() || HasFlag(wxWANTS_CHARS) )
9bf84618 3036 {
5a403e3f
VZ
3037 // we always want to get the char events
3038 rc.result = DLGC_WANTCHARS;
3039
ff7282e1 3040 if ( HasFlag(wxWANTS_CHARS) )
5a403e3f
VZ
3041 {
3042 // in fact, we want everything
3043 rc.result |= DLGC_WANTARROWS |
3044 DLGC_WANTTAB |
3045 DLGC_WANTALLKEYS;
3046 }
3047
08158721 3048 processed = true;
9bf84618 3049 }
101f488c 3050 //else: get the dlg code from the DefWindowProc()
9bf84618
VZ
3051 break;
3052
4004f41e 3053 case WM_SYSKEYDOWN:
42e69d6b 3054 case WM_KEYDOWN:
9c7df356
VZ
3055 // If this has been processed by an event handler, return 0 now
3056 // (we've handled it).
3057 m_lastKeydownProcessed = HandleKeyDown((WORD) wParam, lParam);
3058 if ( m_lastKeydownProcessed )
2d0a075d 3059 {
08158721 3060 processed = true;
2d0a075d 3061 }
81d66cf3 3062
2b5f62a0 3063 if ( !processed )
42e69d6b 3064 {
2b5f62a0
VZ
3065 switch ( wParam )
3066 {
90e572f1 3067 // we consider these messages "not interesting" to OnChar, so
2b5f62a0
VZ
3068 // just don't do anything more with them
3069 case VK_SHIFT:
3070 case VK_CONTROL:
3071 case VK_MENU:
3072 case VK_CAPITAL:
3073 case VK_NUMLOCK:
3074 case VK_SCROLL:
08158721 3075 processed = true;
2b5f62a0 3076 break;
2bda0e17 3077
2b5f62a0
VZ
3078 // avoid duplicate messages to OnChar for these ASCII keys:
3079 // they will be translated by TranslateMessage() and received
3080 // in WM_CHAR
3081 case VK_ESCAPE:
3082 case VK_SPACE:
3083 case VK_RETURN:
3084 case VK_BACK:
3085 case VK_TAB:
3086 case VK_ADD:
3087 case VK_SUBTRACT:
3088 case VK_MULTIPLY:
3089 case VK_DIVIDE:
3f2174bb
VZ
3090 case VK_NUMPAD0:
3091 case VK_NUMPAD1:
3092 case VK_NUMPAD2:
3093 case VK_NUMPAD3:
3094 case VK_NUMPAD4:
3095 case VK_NUMPAD5:
3096 case VK_NUMPAD6:
3097 case VK_NUMPAD7:
3098 case VK_NUMPAD8:
3099 case VK_NUMPAD9:
2b5f62a0
VZ
3100 case VK_OEM_1:
3101 case VK_OEM_2:
3102 case VK_OEM_3:
3103 case VK_OEM_4:
3104 case VK_OEM_5:
3105 case VK_OEM_6:
3106 case VK_OEM_7:
3107 case VK_OEM_PLUS:
3108 case VK_OEM_COMMA:
3109 case VK_OEM_MINUS:
3110 case VK_OEM_PERIOD:
08158721 3111 // but set processed to false, not true to still pass them
2b5f62a0
VZ
3112 // to the control's default window proc - otherwise
3113 // built-in keyboard handling won't work
08158721 3114 processed = false;
2b5f62a0 3115 break;
2bda0e17 3116
42e69d6b 3117#ifdef VK_APPS
2b5f62a0
VZ
3118 // special case of VK_APPS: treat it the same as right mouse
3119 // click because both usually pop up a context menu
3120 case VK_APPS:
ae177b45 3121 processed = HandleMouseEvent(WM_RBUTTONDOWN, -1, -1, 0);
2b5f62a0 3122 break;
42e69d6b 3123#endif // VK_APPS
2bda0e17 3124
2b5f62a0
VZ
3125 default:
3126 // do generate a CHAR event
3127 processed = HandleChar((WORD)wParam, lParam);
3128 }
42e69d6b 3129 }
2b5f62a0 3130 if (message == WM_SYSKEYDOWN) // Let Windows still handle the SYSKEYs
08158721 3131 processed = false;
42e69d6b 3132 break;
2bda0e17 3133
4004f41e 3134 case WM_SYSKEYUP:
42e69d6b 3135 case WM_KEYUP:
4aff28fc
VZ
3136#ifdef VK_APPS
3137 // special case of VK_APPS: treat it the same as right mouse button
3138 if ( wParam == VK_APPS )
3139 {
ae177b45 3140 processed = HandleMouseEvent(WM_RBUTTONUP, -1, -1, 0);
4aff28fc
VZ
3141 }
3142 else
3143#endif // VK_APPS
3144 {
3145 processed = HandleKeyUp((WORD) wParam, lParam);
3146 }
42e69d6b 3147 break;
debe6624 3148
170cbe33 3149 case WM_SYSCHAR:
42e69d6b 3150 case WM_CHAR: // Always an ASCII character
d9f14e16
RD
3151 if ( m_lastKeydownProcessed )
3152 {
3153 // The key was handled in the EVT_KEY_DOWN and handling
3154 // a key in an EVT_KEY_DOWN handler is meant, by
3155 // design, to prevent EVT_CHARs from happening
08158721
DS
3156 m_lastKeydownProcessed = false;
3157 processed = true;
d9f14e16
RD
3158 }
3159 else
7de5bdf4 3160 {
08158721 3161 processed = HandleChar((WORD)wParam, lParam, true);
7de5bdf4 3162 }
42e69d6b 3163 break;
2bda0e17 3164
5048c832
JS
3165#if wxUSE_HOTKEY
3166 case WM_HOTKEY:
3167 processed = HandleHotKey((WORD)wParam, lParam);
3168 break;
540b6b09 3169#endif // wxUSE_HOTKEY
5048c832 3170
b65f16da
VS
3171 case WM_CUT:
3172 case WM_COPY:
3173 case WM_PASTE:
3174 processed = HandleClipboardEvent(message);
3175 break;
3176
42e69d6b
VZ
3177 case WM_HSCROLL:
3178 case WM_VSCROLL:
a23fd0e1 3179 {
42e69d6b
VZ
3180 WXWORD code, pos;
3181 WXHWND hwnd;
3182 UnpackScroll(wParam, lParam, &code, &pos, &hwnd);
2bda0e17 3183
42e69d6b
VZ
3184 processed = MSWOnScroll(message == WM_HSCROLL ? wxHORIZONTAL
3185 : wxVERTICAL,
3186 code, pos, hwnd);
a23fd0e1 3187 }
42e69d6b 3188 break;
a23fd0e1 3189
42e69d6b 3190 // CTLCOLOR messages are sent by children to query the parent for their
01c500af 3191 // colors
04ef50df 3192#ifndef __WXMICROWIN__
42e69d6b
VZ
3193 case WM_CTLCOLORMSGBOX:
3194 case WM_CTLCOLOREDIT:
3195 case WM_CTLCOLORLISTBOX:
3196 case WM_CTLCOLORBTN:
3197 case WM_CTLCOLORDLG:
3198 case WM_CTLCOLORSCROLLBAR:
3199 case WM_CTLCOLORSTATIC:
a23fd0e1 3200 {
42e69d6b
VZ
3201 WXHDC hdc;
3202 WXHWND hwnd;
01c500af 3203 UnpackCtlColor(wParam, lParam, &hdc, &hwnd);
42e69d6b 3204
48fa6bd3 3205 processed = HandleCtlColor(&rc.hBrush, (WXHDC)hdc, (WXHWND)hwnd);
a23fd0e1 3206 }
42e69d6b 3207 break;
cd4453e5 3208#endif // !__WXMICROWIN__
debe6624 3209
42e69d6b 3210 case WM_SYSCOLORCHANGE:
90c1530a 3211 // the return value for this message is ignored
42e69d6b
VZ
3212 processed = HandleSysColorChange();
3213 break;
2bda0e17 3214
7f0586ef 3215#if !defined(__WXWINCE__)
574c939e
KB
3216 case WM_DISPLAYCHANGE:
3217 processed = HandleDisplayChange();
3218 break;
7f0586ef 3219#endif
574c939e 3220
42e69d6b 3221 case WM_PALETTECHANGED:
dca0f651 3222 processed = HandlePaletteChanged((WXHWND)wParam);
42e69d6b 3223 break;
2bda0e17 3224
a5e84126 3225 case WM_CAPTURECHANGED:
dca0f651 3226 processed = HandleCaptureChanged((WXHWND)lParam);
a5e84126
JS
3227 break;
3228
3c96418b
JG
3229 case WM_SETTINGCHANGE:
3230 processed = HandleSettingChange(wParam, lParam);
3231 break;
3232
42e69d6b
VZ
3233 case WM_QUERYNEWPALETTE:
3234 processed = HandleQueryNewPalette();
3235 break;
2bda0e17 3236
42e69d6b 3237 case WM_ERASEBKGND:
dca0f651 3238 processed = HandleEraseBkgnd((WXHDC)wParam);
42e69d6b
VZ
3239 if ( processed )
3240 {
3241 // we processed the message, i.e. erased the background
3242 rc.result = TRUE;
3243 }
3244 break;
debe6624 3245
7f0586ef 3246#if !defined(__WXWINCE__)
42e69d6b
VZ
3247 case WM_DROPFILES:
3248 processed = HandleDropFiles(wParam);
3249 break;
7f0586ef 3250#endif
2bda0e17 3251
42e69d6b 3252 case WM_INITDIALOG:
dca0f651 3253 processed = HandleInitDialog((WXHWND)wParam);
a23fd0e1 3254
42e69d6b
VZ
3255 if ( processed )
3256 {
3257 // we never set focus from here
3258 rc.result = FALSE;
3259 }
3260 break;
a23fd0e1 3261
7f0586ef 3262#if !defined(__WXWINCE__)
42e69d6b
VZ
3263 case WM_QUERYENDSESSION:
3264 processed = HandleQueryEndSession(lParam, &rc.allow);
3265 break;
2bda0e17 3266
42e69d6b
VZ
3267 case WM_ENDSESSION:
3268 processed = HandleEndSession(wParam != 0, lParam);
3269 break;
2bda0e17 3270
42e69d6b 3271 case WM_GETMINMAXINFO:
25889d3c 3272 processed = HandleGetMinMaxInfo((MINMAXINFO*)lParam);
42e69d6b 3273 break;
7f0586ef 3274#endif
debe6624 3275
42e69d6b 3276 case WM_SETCURSOR:
dca0f651 3277 processed = HandleSetCursor((WXHWND)wParam,
42e69d6b
VZ
3278 LOWORD(lParam), // hit test
3279 HIWORD(lParam)); // mouse msg
3280
3281 if ( processed )
3282 {
3283 // returning TRUE stops the DefWindowProc() from further
3284 // processing this message - exactly what we need because we've
3285 // just set the cursor.
3286 rc.result = TRUE;
3287 }
3288 break;
4cdc2c13 3289
ed5317e5
JS
3290#if wxUSE_ACCESSIBILITY
3291 case WM_GETOBJECT:
3292 {
3293 //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
3294 LPARAM dwObjId = (LPARAM) (DWORD) lParam;
3295
66b9ec3d 3296 if (dwObjId == (LPARAM)OBJID_CLIENT && GetOrCreateAccessible())
ed5317e5
JS
3297 {
3298 return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible());
3299 }
3300 break;
3301 }
3302#endif
3303
e39af974 3304#if defined(WM_HELP)
b96340e6 3305 case WM_HELP:
b96340e6 3306 {
a9c11b71
VZ
3307 // by default, WM_HELP is propagated by DefWindowProc() upwards
3308 // to the window parent but as we do it ourselves already
3309 // (wxHelpEvent is derived from wxCommandEvent), we don't want
3310 // to get the other events if we process this message at all
3311 processed = true;
3312
3313 // WM_HELP doesn't use lParam under CE
7f0586ef 3314#ifndef __WXWINCE__
4cdc2c13 3315 HELPINFO* info = (HELPINFO*) lParam;
a9c11b71 3316 if ( info->iContextType == HELPINFO_WINDOW )
b96340e6 3317 {
a9c11b71
VZ
3318#endif // !__WXWINCE__
3319 wxHelpEvent helpEvent
3320 (
3321 wxEVT_HELP,
3322 GetId(),
7f0586ef 3323#ifdef __WXWINCE__
2d4ec362 3324 wxGetMousePosition() // what else?
7f0586ef 3325#else
a9c11b71 3326 wxPoint(info->MousePos.x, info->MousePos.y)
7f0586ef 3327#endif
a9c11b71 3328 );
b96340e6 3329
a9c11b71 3330 helpEvent.SetEventObject(this);
937013e0 3331 HandleWindowEvent(helpEvent);
7f0586ef 3332#ifndef __WXWINCE__
b96340e6 3333 }
a9c11b71 3334 else if ( info->iContextType == HELPINFO_MENUITEM )
4cdc2c13
VZ
3335 {
3336 wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
3337 helpEvent.SetEventObject(this);
937013e0 3338 HandleWindowEvent(helpEvent);
69231000 3339
4cdc2c13 3340 }
a9c11b71
VZ
3341 else // unknown help event?
3342 {
3343 processed = false;
3344 }
3345#endif // !__WXWINCE__
b96340e6 3346 }
b96340e6 3347 break;
a9c11b71 3348#endif // WM_HELP
4cdc2c13 3349
7f0586ef 3350#if !defined(__WXWINCE__)
69231000 3351 case WM_CONTEXTMENU:
4cdc2c13
VZ
3352 {
3353 // we don't convert from screen to client coordinates as
3354 // the event may be handled by a parent window
3355 wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
3356
3357 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
2d1715aa
VZ
3358
3359 // we could have got an event from our child, reflect it back
3360 // to it if this is the case
d85c53a5 3361 wxWindowMSW *win = NULL;
dca0f651
VZ
3362 WXHWND hWnd = (WXHWND)wParam;
3363 if ( hWnd != m_hWnd )
2d1715aa 3364 {
dca0f651 3365 win = FindItemByHWND(hWnd);
2d1715aa
VZ
3366 }
3367
3368 if ( !win )
3369 win = this;
3370
3371 evtCtx.SetEventObject(win);
937013e0 3372 processed = win->HandleWindowEvent(evtCtx);
4cdc2c13 3373 }
69231000 3374 break;
7f0586ef 3375#endif
b74cce40 3376
53a118d6 3377#if wxUSE_MENUS
b74cce40
VZ
3378 case WM_MENUCHAR:
3379 // we're only interested in our own menus, not MF_SYSMENU
3380 if ( HIWORD(wParam) == MF_POPUP )
3381 {
3382 // handle menu chars for ownerdrawn menu items
3383 int i = HandleMenuChar(toupper(LOWORD(wParam)), lParam);
3384 if ( i != wxNOT_FOUND )
3385 {
3386 rc.result = MAKELRESULT(i, MNC_EXECUTE);
08158721 3387 processed = true;
b74cce40
VZ
3388 }
3389 }
3390 break;
53a118d6 3391#endif // wxUSE_MENUS
355debca 3392
dbc74bcc 3393#ifndef __WXWINCE__
355debca
VZ
3394 case WM_POWERBROADCAST:
3395 {
3396 bool vetoed;
3397 processed = HandlePower(wParam, lParam, &vetoed);
3398 rc.result = processed && vetoed ? BROADCAST_QUERY_DENY : TRUE;
3399 }
3400 break;
dbc74bcc 3401#endif // __WXWINCE__
5acec112 3402
a047aff2
JS
3403#if wxUSE_UXTHEME
3404 // If we want the default themed border then we need to draw it ourselves
3405 case WM_NCCALCSIZE:
3406 {
3407 wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
dc797d8e
JS
3408 const wxBorder border = TranslateBorder(GetBorder());
3409 if (theme && border == wxBORDER_THEME)
a047aff2
JS
3410 {
3411 // first ask the widget to calculate the border size
3412 rc.result = MSWDefWindowProc(message, wParam, lParam);
3413 processed = true;
3414
e822d1bd
VZ
3415 // now alter the client size making room for drawing a
3416 // themed border
dca0f651
VZ
3417 RECT *rect;
3418 if ( wParam )
a047aff2 3419 {
e822d1bd 3420 NCCALCSIZE_PARAMS *csparam = (NCCALCSIZE_PARAMS *)lParam;
dca0f651 3421 rect = &csparam->rgrc[0];
a047aff2
JS
3422 }
3423 else
3424 {
dca0f651 3425 rect = (RECT *)lParam;
a047aff2 3426 }
dca0f651 3427
fe545198 3428 wxUxThemeHandle hTheme((const wxWindow *)this, L"EDIT");
a047aff2 3429 RECT rcClient = { 0, 0, 0, 0 };
d935b421 3430 wxClientDC dc((wxWindow *)this);
888dde65 3431 wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
a047aff2 3432
dca0f651
VZ
3433 if ( theme->GetThemeBackgroundContentRect
3434 (
3435 hTheme,
3436 GetHdcOf(*impl),
3437 EP_EDITTEXT,
3438 ETS_NORMAL,
3439 rect,
3440 &rcClient) == S_OK )
a047aff2
JS
3441 {
3442 InflateRect(&rcClient, -1, -1);
dca0f651 3443 *rect = rcClient;
a047aff2
JS
3444 rc.result = WVR_REDRAW;
3445 }
3446 }
3447 }
3448 break;
3449
3450 case WM_NCPAINT:
3451 {
3452 wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive();
dc797d8e
JS
3453 const wxBorder border = TranslateBorder(GetBorder());
3454 if (theme && border == wxBORDER_THEME)
a047aff2
JS
3455 {
3456 // first ask the widget to paint its non-client area, such as scrollbars, etc.
3457 rc.result = MSWDefWindowProc(message, wParam, lParam);
3458 processed = true;
3459
fe545198 3460 wxUxThemeHandle hTheme((const wxWindow *)this, L"EDIT");
d935b421 3461 wxWindowDC dc((wxWindow *)this);
888dde65 3462 wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
a047aff2
JS
3463
3464 // Clip the DC so that you only draw on the non-client area
3465 RECT rcBorder;
3466 wxCopyRectToRECT(GetSize(), rcBorder);
3467
3468 RECT rcClient;
3469 theme->GetThemeBackgroundContentRect(
888dde65 3470 hTheme, GetHdcOf(*impl), EP_EDITTEXT, ETS_NORMAL, &rcBorder, &rcClient);
a047aff2
JS
3471 InflateRect(&rcClient, -1, -1);
3472
888dde65 3473 ::ExcludeClipRect(GetHdcOf(*impl), rcClient.left, rcClient.top,
a047aff2
JS
3474 rcClient.right, rcClient.bottom);
3475
3476 // Make sure the background is in a proper state
3477 if (theme->IsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL))
3478 {
888dde65 3479 theme->DrawThemeParentBackground(GetHwnd(), GetHdcOf(*impl), &rcBorder);
a047aff2
JS
3480 }
3481
3482 // Draw the border
3483 int nState;
3484 if ( !IsEnabled() )
3485 nState = ETS_DISABLED;
3486 // should we check this?
3487 //else if ( ::GetWindowLong(GetHwnd(), GWL_STYLE) & ES_READONLY)
3488 // nState = ETS_READONLY;
3489 else
3490 nState = ETS_NORMAL;
888dde65 3491 theme->DrawThemeBackground(hTheme, GetHdcOf(*impl), EP_EDITTEXT, nState, &rcBorder, NULL);
a047aff2
JS
3492 }
3493 }
3494 break;
3495
3496#endif // wxUSE_UXTHEME
3497
5acec112
VZ
3498 default:
3499 // try a custom message handler
3500 const MSWMessageHandlers::const_iterator
3501 i = gs_messageHandlers.find(message);
3502 if ( i != gs_messageHandlers.end() )
3503 {
3504 processed = (*i->second)(this, message, wParam, lParam);
3505 }
a23fd0e1 3506 }
2d0a075d 3507
42e69d6b 3508 if ( !processed )
2d0a075d 3509 {
42e69d6b 3510#ifdef __WXDEBUG__
223d09f6 3511 wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
42e69d6b
VZ
3512 wxGetMessageName(message));
3513#endif // __WXDEBUG__
3514 rc.result = MSWDefWindowProc(message, wParam, lParam);
a23fd0e1 3515 }
2bda0e17 3516
42e69d6b 3517 return rc.result;
2bda0e17
KB
3518}
3519
b225f659
VZ
3520// ----------------------------------------------------------------------------
3521// wxWindow <-> HWND map
3522// ----------------------------------------------------------------------------
2bda0e17 3523
dca0f651 3524wxWindow *wxFindWinFromHandle(HWND hwnd)
4ce81a75 3525{
dca0f651
VZ
3526 WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
3527 return i == gs_windowHandles.end() ? NULL : i->second;
42e69d6b 3528}
4ce81a75 3529
dca0f651 3530void wxAssociateWinWithHandle(HWND hwnd, wxWindowMSW *win)
42e69d6b 3531{
dca0f651 3532 // adding NULL hwnd is (first) surely a result of an error and
42e69d6b 3533 // (secondly) breaks menu command processing
dca0f651
VZ
3534 wxCHECK_RET( hwnd != (HWND)NULL,
3535 wxT("attempt to add a NULL hwnd to window list ignored") );
4ce81a75 3536
b225f659 3537#ifdef __WXDEBUG__
dca0f651
VZ
3538 WindowHandles::const_iterator i = gs_windowHandles.find(hwnd);
3539 if ( i != gs_windowHandles.end() )
c7527e3f 3540 {
dca0f651
VZ
3541 if ( i->second != win )
3542 {
3543 wxLogDebug(wxT("HWND %p already associated with another window (%s)"),
3544 hwnd, win->GetClassInfo()->GetClassName());
3545 }
3546 //else: this actually happens currently because we associate the window
3547 // with its HWND during creation (if we create it) and also when
3548 // SubclassWin() is called later, this is ok
c7527e3f 3549 }
b225f659 3550#endif // __WXDEBUG__
dca0f651 3551
936bb82e 3552 gs_windowHandles[hwnd] = (wxWindow *)win;
42e69d6b 3553}
4ce81a75 3554
1e6feb95 3555void wxRemoveHandleAssociation(wxWindowMSW *win)
42e69d6b 3556{
dca0f651 3557 gs_windowHandles.erase(GetHwndOf(win));
4ce81a75
JS
3558}
3559
b225f659
VZ
3560// ----------------------------------------------------------------------------
3561// various MSW speciic class dependent functions
3562// ----------------------------------------------------------------------------
3563
42e69d6b
VZ
3564// Default destroyer - override if you destroy it in some other way
3565// (e.g. with MDI child windows)
1e6feb95 3566void wxWindowMSW::MSWDestroyWindow()
4ce81a75 3567{
42e69d6b 3568}
4ce81a75 3569
b225f659
VZ
3570bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos,
3571 const wxSize& size,
3572 int& x, int& y,
3573 int& w, int& h) const
2bda0e17 3574{
9cb57df4 3575 // yes, those are just some arbitrary hardcoded numbers
2a77c8c4 3576 static const int DEFAULT_Y = 200;
2a77c8c4 3577
08158721 3578 bool nonDefault = false;
c085e333 3579
422d0ff0 3580 if ( pos.x == wxDefaultCoord )
b225f659 3581 {
9cb57df4
VZ
3582 // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we
3583 // can just as well set it to CW_USEDEFAULT as well
b225f659
VZ
3584 x =
3585 y = CW_USEDEFAULT;
3586 }
3587 else
a23fd0e1 3588 {
2a77c8c4
VZ
3589 // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it
3590 // neither because it is not handled as a special value by Windows then
3591 // and so we have to choose some default value for it
b225f659 3592 x = pos.x;
422d0ff0 3593 y = pos.y == wxDefaultCoord ? DEFAULT_Y : pos.y;
c085e333 3594
08158721 3595 nonDefault = true;
42e69d6b 3596 }
2bda0e17 3597
b889a3a2
VZ
3598 /*
3599 NB: there used to be some code here which set the initial size of the
3600 window to the client size of the parent if no explicit size was
77ffb593 3601 specified. This was wrong because wxWidgets programs often assume
b889a3a2
VZ
3602 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
3603 it. To see why, you should understand that Windows sends WM_SIZE from
3604 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
3605 from some base class ctor and so this WM_SIZE is not processed in the
3606 real class' OnSize() (because it's not fully constructed yet and the
3607 event goes to some base class OnSize() instead). So the WM_SIZE we
3608 rely on is the one sent when the parent frame resizes its children
3609 but here is the problem: if the child already has just the right
77ffb593 3610 size, nothing will happen as both wxWidgets and Windows check for
b889a3a2
VZ
3611 this and ignore any attempts to change the window size to the size it
3612 already has - so no WM_SIZE would be sent.
3613 */
b225f659 3614
35bbb0c6 3615
426936d1
RD
3616 // we don't use CW_USEDEFAULT here for several reasons:
3617 //
3618 // 1. it results in huge frames on modern screens (1000*800 is not
3619 // uncommon on my 1280*1024 screen) which is way too big for a half
77ffb593 3620 // empty frame of most of wxWidgets samples for example)
426936d1
RD
3621 //
3622 // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which
3623 // the default is for whatever reason 8*8 which breaks client <->
3624 // window size calculations (it would be nice if it didn't, but it
3625 // does and the simplest way to fix it seemed to change the broken
3626 // default size anyhow)
3627 //
3628 // 3. there is just no advantage in doing it: with x and y it is
3629 // possible that [future versions of] Windows position the new top
3630 // level window in some smart way which we can't do, but we can
3631 // guess a reasonably good size for a new window just as well
3632 // ourselves
960b193e 3633
3a3c8603
DS
3634 // However, on PocketPC devices, we must use the default
3635 // size if possible.
960b193e 3636#ifdef _WIN32_WCE
422d0ff0 3637 if (size.x == wxDefaultCoord)
3a3c8603
DS
3638 w = CW_USEDEFAULT;
3639 else
3640 w = size.x;
422d0ff0 3641 if (size.y == wxDefaultCoord)
3a3c8603
DS
3642 h = CW_USEDEFAULT;
3643 else
3644 h = size.y;
960b193e 3645#else
422d0ff0 3646 if ( size.x == wxDefaultCoord || size.y == wxDefaultCoord)
426936d1 3647 {
08158721 3648 nonDefault = true;
8614c467 3649 }
426936d1
RD
3650 w = WidthDefault(size.x);
3651 h = HeightDefault(size.y);
960b193e 3652#endif
8614c467 3653
4e9d23cd
VZ
3654 AdjustForParentClientOrigin(x, y);
3655
b225f659
VZ
3656 return nonDefault;
3657}
3658
9dfef5ac
VZ
3659WXHWND wxWindowMSW::MSWGetParent() const
3660{
d285d708 3661 return m_parent ? m_parent->GetHWND() : WXHWND(NULL);
9dfef5ac
VZ
3662}
3663
b225f659
VZ
3664bool wxWindowMSW::MSWCreate(const wxChar *wclass,
3665 const wxChar *title,
3666 const wxPoint& pos,
3667 const wxSize& size,
3668 WXDWORD style,
3669 WXDWORD extendedStyle)
3670{
23035521
VZ
3671 // check a common bug in the user code: if the window is created with a
3672 // non-default ctor and Create() is called too, we'd create 2 HWND for a
3673 // single wxWindow object and this results in all sorts of trouble,
3674 // especially for wxTLWs
3675 wxCHECK_MSG( !m_hWnd, true, "window can't be recreated" );
3676
d9698bd4
VZ
3677 // this can happen if this function is called using the return value of
3678 // wxApp::GetRegisteredClassName() which failed
3679 wxCHECK_MSG( wclass, false, "failed to register window class?" );
3680
3681
b225f659
VZ
3682 // choose the position/size for the new window
3683 int x, y, w, h;
3684 (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
3685
b225f659
VZ
3686 // controlId is menu handle for the top level windows, so set it to 0
3687 // unless we're creating a child window
f586fde3 3688 int controlId = style & WS_CHILD ? GetId() : 0;
2bda0e17 3689
b225f659
VZ
3690 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
3691 // which is the same but without CS_[HV]REDRAW class styles so using it
3692 // ensures that the window is not fully repainted on each resize
3693 wxString className(wclass);
e441e1f4 3694 if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
b225f659 3695 {
d9698bd4 3696 className += wxApp::GetNoRedrawClassSuffix();
a23fd0e1 3697 }
c085e333 3698
b225f659
VZ
3699 // do create the window
3700 wxWindowCreationHook hook(this);
b3daa5a3 3701
5e67eb97
VZ
3702 m_hWnd = (WXHWND)::CreateWindowEx
3703 (
3704 extendedStyle,
e0a050e3
VS
3705 className.wx_str(),
3706 title ? title : m_windowName.wx_str(),
5e67eb97
VZ
3707 style,
3708 x, y, w, h,
3709 (HWND)MSWGetParent(),
dca0f651 3710 (HMENU)wxUIntToPtr(controlId),
5e67eb97
VZ
3711 wxGetInstance(),
3712 NULL // no extra data
3713 );
b225f659
VZ
3714
3715 if ( !m_hWnd )
c7527e3f 3716 {
5e67eb97 3717 wxLogSysError(_("Can't create window of class %s"), className.c_str());
b225f659 3718
08158721 3719 return false;
c7527e3f 3720 }
b3daa5a3 3721
b225f659 3722 SubclassWin(m_hWnd);
c085e333 3723
08158721 3724 return true;
2bda0e17
KB
3725}
3726
42e69d6b
VZ
3727// ===========================================================================
3728// MSW message handlers
3729// ===========================================================================
3730
3731// ---------------------------------------------------------------------------
3732// WM_NOTIFY
3733// ---------------------------------------------------------------------------
3734
1e6feb95 3735bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
2bda0e17 3736{
04ef50df 3737#ifndef __WXMICROWIN__
42e69d6b
VZ
3738 LPNMHDR hdr = (LPNMHDR)lParam;
3739 HWND hWnd = hdr->hwndFrom;
dca0f651 3740 wxWindow *win = wxFindWinFromHandle(hWnd);
42e69d6b 3741
2b15b970 3742 // if the control is one of our windows, let it handle the message itself
42e69d6b 3743 if ( win )
564b2609 3744 {
42e69d6b 3745 return win->MSWOnNotify(idCtrl, lParam, result);
564b2609 3746 }
2bda0e17 3747
2b15b970
VZ
3748 // VZ: why did we do it? normally this is unnecessary and, besides, it
3749 // breaks the message processing for the toolbars because the tooltip
3750 // notifications were being forwarded to the toolbar child controls
3751 // (if it had any) before being passed to the toolbar itself, so in my
3752 // example the tooltip for the combobox was always shown instead of the
3753 // correct button tooltips
3754#if 0
42e69d6b 3755 // try all our children
222ed1d6 3756 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
42e69d6b 3757 while ( node )
564b2609 3758 {
42e69d6b
VZ
3759 wxWindow *child = node->GetData();
3760 if ( child->MSWOnNotify(idCtrl, lParam, result) )
3761 {
08158721 3762 return true;
42e69d6b 3763 }
2d0a075d 3764
42e69d6b
VZ
3765 node = node->GetNext();
3766 }
2b15b970 3767#endif // 0
2d0a075d 3768
2b15b970 3769 // by default, handle it ourselves
42e69d6b 3770 return MSWOnNotify(idCtrl, lParam, result);
cd4453e5 3771#else // __WXMICROWIN__
08158721 3772 return false;
04ef50df 3773#endif
42e69d6b 3774}
2d0a075d 3775
bd9cd534
VZ
3776#if wxUSE_TOOLTIPS
3777
3778bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
3779 WXLPARAM lParam,
3780 const wxString& ttip)
3781{
3782 // I don't know why it happens, but the versions of comctl32.dll starting
3783 // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally,
3784 // this message is supposed to be sent to Unicode programs only) -- hence
3785 // we need to handle it as well, otherwise no tooltips will be shown in
3786 // this case
7f0586ef 3787#ifndef __WXWINCE__
118208ac
VZ
3788 if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW)
3789 || ttip.empty() )
bd9cd534
VZ
3790 {
3791 // not a tooltip message or no tooltip to show anyhow
08158721 3792 return false;
bd9cd534 3793 }
7f0586ef 3794#endif
bd9cd534
VZ
3795
3796 LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
3797
118208ac
VZ
3798 // We don't want to use the szText buffer because it has a limit of 80
3799 // bytes and this is not enough, especially for Unicode build where it
3800 // limits the tooltip string length to only 40 characters
3801 //
3802 // The best would be, of course, to not impose any length limitations at
3803 // all but then the buffer would have to be dynamic and someone would have
3804 // to free it and we don't have the tooltip owner object here any more, so
3805 // for now use our own static buffer with a higher fixed max length.
3806 //
3807 // Note that using a static buffer should not be a problem as only a single
3808 // tooltip can be shown at the same time anyhow.
2b5f62a0 3809#if !wxUSE_UNICODE
118208ac 3810 if ( code == (WXUINT) TTN_NEEDTEXTW )
bd9cd534 3811 {
118208ac
VZ
3812 // We need to convert tooltip from multi byte to Unicode on the fly.
3813 static wchar_t buf[513];
25c46fda 3814
118208ac
VZ
3815 // Truncate tooltip length if needed as otherwise we might not have
3816 // enough space for it in the buffer and MultiByteToWideChar() would
3817 // return an error
fec9cc08 3818 size_t tipLength = wxMin(ttip.length(), WXSIZEOF(buf) - 1);
7afebc8c
JS
3819
3820 // Convert to WideChar without adding the NULL character. The NULL
25c46fda 3821 // character is added afterwards (this is more efficient).
118208ac
VZ
3822 int len = ::MultiByteToWideChar
3823 (
3824 CP_ACP,
3825 0, // no flags
b05fde97 3826 ttip.wx_str(),
118208ac
VZ
3827 tipLength,
3828 buf,
3829 WXSIZEOF(buf) - 1
3830 );
3831
3832 if ( !len )
3833 {
3834 wxLogLastError(_T("MultiByteToWideChar()"));
3835 }
7afebc8c 3836
118208ac
VZ
3837 buf[len] = L'\0';
3838 ttText->lpszText = (LPSTR) buf;
3839 }
3840 else // TTN_NEEDTEXTA
3841#endif // !wxUSE_UNICODE
3842 {
3843 // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or
3844 // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
3845 // to copy the string we have into the buffer
3846 static wxChar buf[513];
e408bf52 3847 wxStrlcpy(buf, ttip.c_str(), WXSIZEOF(buf));
118208ac 3848 ttText->lpszText = buf;
bd9cd534
VZ
3849 }
3850
08158721 3851 return true;
bd9cd534
VZ
3852}
3853
3854#endif // wxUSE_TOOLTIPS
3855
1e6feb95 3856bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl),
bd9cd534
VZ
3857 WXLPARAM lParam,
3858 WXLPARAM* WXUNUSED(result))
42e69d6b
VZ
3859{
3860#if wxUSE_TOOLTIPS
bd9cd534 3861 if ( m_tooltip )
42e69d6b 3862 {
bd9cd534
VZ
3863 NMHDR* hdr = (NMHDR *)lParam;
3864 if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip()))
3865 {
3866 // processed
08158721 3867 return true;
bd9cd534 3868 }
42e69d6b 3869 }
f5dd1cf1
WS
3870#else
3871 wxUnusedVar(lParam);
42e69d6b
VZ
3872#endif // wxUSE_TOOLTIPS
3873
08158721 3874 return false;
42e69d6b 3875}
2b15b970 3876
42e69d6b
VZ
3877// ---------------------------------------------------------------------------
3878// end session messages
3879// ---------------------------------------------------------------------------
2d0a075d 3880
1e6feb95 3881bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
42e69d6b 3882{
040e5f77 3883#ifdef ENDSESSION_LOGOFF
abb74e0f 3884 wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY);
42e69d6b 3885 event.SetEventObject(wxTheApp);
08158721 3886 event.SetCanVeto(true);
a17e237f 3887 event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF);
2d0a075d 3888
42e69d6b
VZ
3889 bool rc = wxTheApp->ProcessEvent(event);
3890
3891 if ( rc )
3892 {
3893 // we may end only if the app didn't veto session closing (double
3894 // negation...)
3895 *mayEnd = !event.GetVeto();
2d0a075d
JS
3896 }
3897
42e69d6b 3898 return rc;
7f0586ef 3899#else
040e5f77
VZ
3900 wxUnusedVar(logOff);
3901 wxUnusedVar(mayEnd);
08158721 3902 return false;
7f0586ef 3903#endif
2bda0e17
KB
3904}
3905
1e6feb95 3906bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
2bda0e17 3907{
040e5f77 3908#ifdef ENDSESSION_LOGOFF
42e69d6b
VZ
3909 // do nothing if the session isn't ending
3910 if ( !endSession )
08158721 3911 return false;
a23fd0e1 3912
519dc37f
VZ
3913 // only send once
3914 if ( (this != wxTheApp->GetTopWindow()) )
08158721 3915 return false;
519dc37f 3916
abb74e0f 3917 wxCloseEvent event(wxEVT_END_SESSION, wxID_ANY);
42e69d6b 3918 event.SetEventObject(wxTheApp);
08158721 3919 event.SetCanVeto(false);
f801d19a 3920 event.SetLoggingOff((logOff & ENDSESSION_LOGOFF) != 0);
519dc37f
VZ
3921
3922 return wxTheApp->ProcessEvent(event);
7f0586ef 3923#else
040e5f77
VZ
3924 wxUnusedVar(endSession);
3925 wxUnusedVar(logOff);
08158721 3926 return false;
7f0586ef 3927#endif
2bda0e17
KB
3928}
3929
42e69d6b
VZ
3930// ---------------------------------------------------------------------------
3931// window creation/destruction
3932// ---------------------------------------------------------------------------
3933
0c0d1521
WS
3934bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED_IN_WINCE(cs),
3935 bool *mayCreate)
61179e28 3936{
ee471817
VZ
3937 // VZ: why is this commented out for WinCE? If it doesn't support
3938 // WS_EX_CONTROLPARENT at all it should be somehow handled globally,
3939 // not with multiple #ifdef's!
7f0586ef 3940#ifndef __WXWINCE__
61179e28 3941 if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
ee471817
VZ
3942 EnsureParentHasControlParentStyle(GetParent());
3943#endif // !__WXWINCE__
61179e28 3944
08158721 3945 *mayCreate = true;
42e69d6b 3946
08158721 3947 return true;
2bda0e17
KB
3948}
3949
1e6feb95 3950bool wxWindowMSW::HandleDestroy()
2bda0e17 3951{
7de59551 3952 SendDestroyEvent();
42e69d6b
VZ
3953
3954 // delete our drop target if we've got one
3955#if wxUSE_DRAG_AND_DROP
3956 if ( m_dropTarget != NULL )
2d0a075d 3957 {
42e69d6b
VZ
3958 m_dropTarget->Revoke(m_hWnd);
3959
3960 delete m_dropTarget;
3961 m_dropTarget = NULL;
2d0a075d 3962 }
42e69d6b 3963#endif // wxUSE_DRAG_AND_DROP
2bda0e17 3964
42e69d6b 3965 // WM_DESTROY handled
08158721 3966 return true;
2bda0e17
KB
3967}
3968
42e69d6b
VZ
3969// ---------------------------------------------------------------------------
3970// activation/focus
3971// ---------------------------------------------------------------------------
3972
1e6feb95 3973bool wxWindowMSW::HandleActivate(int state,
42e69d6b
VZ
3974 bool WXUNUSED(minimized),
3975 WXHWND WXUNUSED(activate))
2bda0e17 3976{
42e69d6b
VZ
3977 wxActivateEvent event(wxEVT_ACTIVATE,
3978 (state == WA_ACTIVE) || (state == WA_CLICKACTIVE),
3979 m_windowId);
3980 event.SetEventObject(this);
3981
937013e0 3982 return HandleWindowEvent(event);
42e69d6b
VZ
3983}
3984
1e6feb95 3985bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
42e69d6b 3986{
c7aee865
RD
3987 // Strangly enough, some controls get set focus events when they are being
3988 // deleted, even if they already had focus before.
3989 if ( m_isBeingDeleted )
3990 {
3991 return false;
3992 }
35bbb0c6 3993
456bc6d9
VZ
3994 // notify the parent keeping track of focus for the kbd navigation
3995 // purposes that we got it
e72aa7f5 3996 wxChildFocusEvent eventFocus((wxWindow *)this);
937013e0 3997 (void)HandleWindowEvent(eventFocus);
456bc6d9 3998
789295bf 3999#if wxUSE_CARET
42e69d6b 4000 // Deal with caret
789295bf 4001 if ( m_caret )
2d0a075d 4002 {
789295bf 4003 m_caret->OnSetFocus();
2bda0e17 4004 }
789295bf 4005#endif // wxUSE_CARET
42e69d6b 4006
42e69d6b
VZ
4007 wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
4008 event.SetEventObject(this);
4009
1e6feb95
VZ
4010 // wxFindWinFromHandle() may return NULL, it is ok
4011 event.SetWindow(wxFindWinFromHandle(hwnd));
4012
937013e0 4013 return HandleWindowEvent(event);
2bda0e17
KB
4014}
4015
1e6feb95 4016bool wxWindowMSW::HandleKillFocus(WXHWND hwnd)
2bda0e17 4017{
789295bf 4018#if wxUSE_CARET
42e69d6b 4019 // Deal with caret
789295bf 4020 if ( m_caret )
2d0a075d 4021 {
789295bf 4022 m_caret->OnKillFocus();
2bda0e17 4023 }
789295bf 4024#endif // wxUSE_CARET
42e69d6b 4025
2913e597
RD
4026 // Don't send the event when in the process of being deleted. This can
4027 // only cause problems if the event handler tries to access the object.
4028 if ( m_isBeingDeleted )
4029 {
08158721 4030 return false;
2913e597
RD
4031 }
4032
42e69d6b
VZ
4033 wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
4034 event.SetEventObject(this);
4035
1e6feb95
VZ
4036 // wxFindWinFromHandle() may return NULL, it is ok
4037 event.SetWindow(wxFindWinFromHandle(hwnd));
4038
937013e0 4039 return HandleWindowEvent(event);
2bda0e17
KB
4040}
4041
faa49bfd
WS
4042// ---------------------------------------------------------------------------
4043// labels
4044// ---------------------------------------------------------------------------
4045
4046void wxWindowMSW::SetLabel( const wxString& label)
4047{
4048 SetWindowText(GetHwnd(), label.c_str());
4049}
4050
4051wxString wxWindowMSW::GetLabel() const
4052{
4053 return wxGetWindowText(GetHWND());
4054}
4055
42e69d6b
VZ
4056// ---------------------------------------------------------------------------
4057// miscellaneous
4058// ---------------------------------------------------------------------------
4059
1e6feb95 4060bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status))
2bda0e17 4061{
42e69d6b 4062 wxShowEvent event(GetId(), show);
687706f5 4063 event.SetEventObject(this);
42e69d6b 4064
937013e0 4065 return HandleWindowEvent(event);
2bda0e17
KB
4066}
4067
1e6feb95 4068bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
2bda0e17 4069{
42e69d6b 4070 wxInitDialogEvent event(GetId());
687706f5 4071 event.SetEventObject(this);
42e69d6b 4072
937013e0 4073 return HandleWindowEvent(event);
2bda0e17
KB
4074}
4075
1e6feb95 4076bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
2bda0e17 4077{
7f0586ef 4078#if defined (__WXMICROWIN__) || defined(__WXWINCE__)
35bbb0c6 4079 wxUnusedVar(wParam);
08158721 4080 return false;
4ce1efe1 4081#else // __WXMICROWIN__
42e69d6b 4082 HDROP hFilesInfo = (HDROP) wParam;
42e69d6b
VZ
4083
4084 // Get the total number of files dropped
c3c39620 4085 UINT gwFilesDropped = ::DragQueryFile
f6bcfd97
BP
4086 (
4087 (HDROP)hFilesInfo,
4088 (UINT)-1,
4089 (LPTSTR)0,
4090 (UINT)0
4091 );
42e69d6b
VZ
4092
4093 wxString *files = new wxString[gwFilesDropped];
c3c39620 4094 for ( UINT wIndex = 0; wIndex < gwFilesDropped; wIndex++ )
2d0a075d 4095 {
c3c39620
VZ
4096 // first get the needed buffer length (+1 for terminating NUL)
4097 size_t len = ::DragQueryFile(hFilesInfo, wIndex, NULL, 0) + 1;
4098
4099 // and now get the file name
4100 ::DragQueryFile(hFilesInfo, wIndex,
de564874 4101 wxStringBuffer(files[wIndex], len), len);
2d0a075d 4102 }
2bda0e17 4103
42e69d6b 4104 wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
687706f5 4105 event.SetEventObject(this);
c3c39620
VZ
4106
4107 POINT dropPoint;
4108 DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint);
b3dc8a3e
VZ
4109 event.m_pos.x = dropPoint.x;
4110 event.m_pos.y = dropPoint.y;
42e69d6b 4111
fe8f9ad7
VZ
4112 DragFinish(hFilesInfo);
4113
937013e0 4114 return HandleWindowEvent(event);
04ef50df 4115#endif
2bda0e17
KB
4116}
4117
cc972ac6 4118
1e6feb95
VZ
4119bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
4120 short nHitTest,
4121 int WXUNUSED(mouseMsg))
2bda0e17 4122{
04ef50df 4123#ifndef __WXMICROWIN__
bfbd6dc1 4124 // the logic is as follows:
46753a7c
VZ
4125 // 0. if we're busy, set the busy cursor (even for non client elements)
4126 // 1. don't set custom cursor for non client area of enabled windows
4127 // 2. ask user EVT_SET_CURSOR handler for the cursor
4128 // 3. if still no cursor but we're in a TLW, set the global cursor
42e69d6b 4129
46753a7c
VZ
4130 HCURSOR hcursor = 0;
4131 if ( wxIsBusy() )
43b5058d 4132 {
46753a7c 4133 hcursor = wxGetCurrentBusyCursor();
43b5058d 4134 }
46753a7c
VZ
4135 else // not busy
4136 {
4137 if ( nHitTest != HTCLIENT )
4138 return false;
43b5058d 4139
46753a7c
VZ
4140 // first ask the user code - it may wish to set the cursor in some very
4141 // specific way (for example, depending on the current position)
4142 POINT pt;
f2325516 4143#ifdef __WXWINCE__
46753a7c 4144 if ( !::GetCursorPosWinCE(&pt))
f2325516 4145#else
46753a7c 4146 if ( !::GetCursorPos(&pt) )
3fca879c 4147#endif
46753a7c
VZ
4148 {
4149 wxLogLastError(wxT("GetCursorPos"));
4150 }
43b5058d 4151
46753a7c
VZ
4152 int x = pt.x,
4153 y = pt.y;
4154 ScreenToClient(&x, &y);
4155 wxSetCursorEvent event(x, y);
42e69d6b 4156
937013e0 4157 bool processedEvtSetCursor = HandleWindowEvent(event);
46753a7c 4158 if ( processedEvtSetCursor && event.HasCursor() )
bfbd6dc1 4159 {
46753a7c 4160 hcursor = GetHcursorOf(event.GetCursor());
bfbd6dc1 4161 }
43b5058d 4162
46753a7c 4163 if ( !hcursor )
bfbd6dc1 4164 {
46753a7c
VZ
4165 // the test for processedEvtSetCursor is here to prevent using
4166 // m_cursor if the user code caught EVT_SET_CURSOR() and returned
4167 // nothing from it - this is a way to say that our cursor shouldn't
4168 // be used for this point
4169 if ( !processedEvtSetCursor && m_cursor.Ok() )
42e69d6b 4170 {
46753a7c 4171 hcursor = GetHcursorOf(m_cursor);
43b5058d 4172 }
46753a7c
VZ
4173
4174 if ( !hcursor && !GetParent() )
43b5058d
VZ
4175 {
4176 const wxCursor *cursor = wxGetGlobalCursor();
4177 if ( cursor && cursor->Ok() )
4178 {
4179 hcursor = GetHcursorOf(*cursor);
4180 }
42e69d6b
VZ
4181 }
4182 }
4183 }
4184
46753a7c 4185
bfbd6dc1
VZ
4186 if ( hcursor )
4187 {
4188 ::SetCursor(hcursor);
4189
4190 // cursor set, stop here
08158721 4191 return true;
bfbd6dc1 4192 }
cd4453e5
VZ
4193#endif // __WXMICROWIN__
4194
3ca6a5f0 4195 // pass up the window chain
08158721 4196 return false;
2bda0e17
KB
4197}
4198
dbc74bcc 4199bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
355debca 4200 WXLPARAM WXUNUSED(lParam),
dbc74bcc 4201 bool *WXUNUSED_IN_WINCE(vetoed))
355debca 4202{
dbc74bcc
WS
4203#ifdef __WXWINCE__
4204 // FIXME
4205 return false;
4206#else
355debca
VZ
4207 wxEventType evtType;
4208 switch ( wParam )
4209 {
4210 case PBT_APMQUERYSUSPEND:
4211 evtType = wxEVT_POWER_SUSPENDING;
4212 break;
4213
4214 case PBT_APMQUERYSUSPENDFAILED:
4215 evtType = wxEVT_POWER_SUSPEND_CANCEL;
4216 break;
4217
4218 case PBT_APMSUSPEND:
4219 evtType = wxEVT_POWER_SUSPENDED;
4220 break;
4221
4222 case PBT_APMRESUMESUSPEND:
4223 evtType = wxEVT_POWER_RESUME;
4224 break;
4225
4226 default:
4227 wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam);
4228 // fall through
4229
4230 // these messages are currently not mapped to wx events
4231 case PBT_APMQUERYSTANDBY:
4232 case PBT_APMQUERYSTANDBYFAILED:
4233 case PBT_APMSTANDBY:
4234 case PBT_APMRESUMESTANDBY:
4235 case PBT_APMBATTERYLOW:
4236 case PBT_APMPOWERSTATUSCHANGE:
4237 case PBT_APMOEMEVENT:
355debca 4238 case PBT_APMRESUMECRITICAL:
55cd5d10
VZ
4239#ifdef PBT_APMRESUMEAUTOMATIC
4240 case PBT_APMRESUMEAUTOMATIC:
4241#endif
355debca
VZ
4242 evtType = wxEVT_NULL;
4243 break;
4244 }
4245
4246 // don't handle unknown messages
4247 if ( evtType == wxEVT_NULL )
4248 return false;
4249
4250 // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events?
4251
4252 wxPowerEvent event(evtType);
937013e0 4253 if ( !HandleWindowEvent(event) )
355debca
VZ
4254 return false;
4255
4256 *vetoed = event.IsVetoed();
4257
4258 return true;
dbc74bcc 4259#endif
355debca
VZ
4260}
4261
2e992e06
VZ
4262bool wxWindowMSW::IsDoubleBuffered() const
4263{
75e8e6dc 4264 for ( const wxWindowMSW *win = this; win; win = win->GetParent() )
d66d0500 4265 {
75e8e6dc 4266 if ( wxHasWindowExStyle(win, WS_EX_COMPOSITED) )
2e992e06 4267 return true;
75e8e6dc
VZ
4268
4269 if ( win->IsTopLevel() )
4270 break;
4271 }
d66d0500 4272
2e992e06
VZ
4273 return false;
4274}
4275
f60ca3e2
RD
4276void wxWindowMSW::SetDoubleBuffered(bool on)
4277{
4278 // Get the current extended style bits
d66d0500 4279 long exstyle = wxGetWindowExStyle(this);
f60ca3e2
RD
4280
4281 // Twiddle the bit as needed
4282 if ( on )
4283 exstyle |= WS_EX_COMPOSITED;
4284 else
4285 exstyle &= ~WS_EX_COMPOSITED;
4286
4287 // put it back
d66d0500 4288 wxSetWindowExStyle(this, exstyle);
f60ca3e2
RD
4289}
4290
42e69d6b
VZ
4291// ---------------------------------------------------------------------------
4292// owner drawn stuff
4293// ---------------------------------------------------------------------------
4294
61fef19b
VZ
4295#if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \
4296 (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__))
4297 #define WXUNUSED_UNLESS_ODRAWN(param) param
4298#else
4299 #define WXUNUSED_UNLESS_ODRAWN(param)
4300#endif
4301
4302bool
4303wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id),
4304 WXDRAWITEMSTRUCT * WXUNUSED_UNLESS_ODRAWN(itemStruct))
2bda0e17 4305{
4286a5b5 4306#if wxUSE_OWNER_DRAWN
1e6feb95
VZ
4307
4308#if wxUSE_MENUS_NATIVE
42e69d6b 4309 // is it a menu item?
6f806543
VZ
4310 DRAWITEMSTRUCT *pDrawStruct = (DRAWITEMSTRUCT *)itemStruct;
4311 if ( id == 0 && pDrawStruct->CtlType == ODT_MENU )
42e69d6b 4312 {
42e69d6b 4313 wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
03cef643 4314
2d29bf54
JS
4315 // see comment before the same test in MSWOnMeasureItem() below
4316 if ( !pMenuItem )
4317 return false;
4318
4319 wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
42f25dcf 4320 false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
42e69d6b 4321
7561aacd
VZ
4322 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
4323 // the DC from being released
4324 wxDCTemp dc((WXHDC)pDrawStruct->hDC);
42e69d6b
VZ
4325 wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top,
4326 pDrawStruct->rcItem.right - pDrawStruct->rcItem.left,
4327 pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top);
4328
4329 return pMenuItem->OnDrawItem
7561aacd
VZ
4330 (
4331 dc,
4332 rect,
4333 (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
4334 (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
4335 );
42e69d6b 4336 }
1e6feb95 4337#endif // wxUSE_MENUS_NATIVE
42e69d6b 4338
c8e4fa8b
JS
4339#endif // USE_OWNER_DRAWN
4340
6a89f9ee 4341#if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)
c8e4fa8b 4342
c8e4fa8b 4343#if wxUSE_OWNER_DRAWN
1384636d 4344 wxControl *item = wxDynamicCast(FindItem(id), wxControl);
567be187 4345#else // !wxUSE_OWNER_DRAWN
1384636d
VS
4346 // we may still have owner-drawn buttons internally because we have to make
4347 // them owner-drawn to support colour change
35bbb0c6 4348 wxControl *item =
095b80e2
WS
4349# if wxUSE_BUTTON
4350 wxDynamicCast(FindItem(id), wxButton)
4351# else
4352 NULL
4353# endif
4354 ;
cd0b1709 4355#endif // USE_OWNER_DRAWN
567be187
VZ
4356
4357 if ( item )
4358 {
4359 return item->MSWOnDraw(itemStruct);
4360 }
4286a5b5 4361
c8e4fa8b
JS
4362#endif // wxUSE_CONTROLS
4363
08158721 4364 return false;
2bda0e17
KB
4365}
4366
61fef19b 4367bool
d1d276f2 4368wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
2bda0e17 4369{
61fef19b 4370#if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
42e69d6b 4371 // is it a menu item?
6f806543
VZ
4372 MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct;
4373 if ( id == 0 && pMeasureStruct->CtlType == ODT_MENU )
2d0a075d 4374 {
42e69d6b
VZ
4375 wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
4376
b6afa1a3
VZ
4377 // according to Carsten Fuchs the pointer may be NULL under XP if an
4378 // MDI child frame is initially maximized, see this for more info:
4379 // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745
4380 //
4381 // so silently ignore it instead of asserting
4382 if ( !pMenuItem )
4383 return false;
4384
4385 wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
42f25dcf 4386 false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
42e69d6b 4387
975b6bcf
VZ
4388 size_t w, h;
4389 bool rc = pMenuItem->OnMeasureItem(&w, &h);
4390
4391 pMeasureStruct->itemWidth = w;
4392 pMeasureStruct->itemHeight = h;
4393
4394 return rc;
2d0a075d 4395 }
42e69d6b 4396
567be187
VZ
4397 wxControl *item = wxDynamicCast(FindItem(id), wxControl);
4398 if ( item )
42e69d6b 4399 {
567be187 4400 return item->MSWOnMeasure(itemStruct);
42e69d6b 4401 }
d1d276f2
WS
4402#else
4403 wxUnusedVar(id);
4404 wxUnusedVar(itemStruct);
4405#endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
567be187 4406
08158721 4407 return false;
2bda0e17
KB
4408}
4409
42e69d6b
VZ
4410// ---------------------------------------------------------------------------
4411// colours and palettes
4412// ---------------------------------------------------------------------------
2bda0e17 4413
1e6feb95 4414bool wxWindowMSW::HandleSysColorChange()
2bda0e17 4415{
42e69d6b
VZ
4416 wxSysColourChangedEvent event;
4417 event.SetEventObject(this);
4418
937013e0 4419 (void)HandleWindowEvent(event);
23895080
VZ
4420
4421 // always let the system carry on the default processing to allow the
4422 // native controls to react to the colours update
08158721 4423 return false;
42e69d6b
VZ
4424}
4425
574c939e
KB
4426bool wxWindowMSW::HandleDisplayChange()
4427{
4428 wxDisplayChangedEvent event;
4429 event.SetEventObject(this);
4430
937013e0 4431 return HandleWindowEvent(event);
574c939e
KB
4432}
4433
04ef50df 4434#ifndef __WXMICROWIN__
42e69d6b 4435
1a784dfc 4436bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC hDC, WXHWND hWnd)
01c500af 4437{
3d74a760 4438#if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
43bfb798 4439 wxUnusedVar(hDC);
3d74a760
WS
4440 wxUnusedVar(hWnd);
4441#else
2bae4332 4442 wxControl *item = wxDynamicCast(FindItemByHWND(hWnd, true), wxControl);
c3732409 4443
01c500af 4444 if ( item )
1a784dfc 4445 *brush = item->MSWControlColor(hDC, hWnd);
2d0a075d 4446 else
1e6feb95 4447#endif // wxUSE_CONTROLS
01c500af 4448 *brush = NULL;
42e69d6b 4449
01c500af 4450 return *brush != NULL;
2bda0e17
KB
4451}
4452
01c500af
VZ
4453#endif // __WXMICROWIN__
4454
1e6feb95 4455bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
42e69d6b 4456{
574c939e 4457#if wxUSE_PALETTE
b95edd47
VZ
4458 // same as below except we don't respond to our own messages
4459 if ( hWndPalChange != GetHWND() )
4460 {
574c939e 4461 // check to see if we our our parents have a custom palette
fa21d338 4462 wxWindowMSW *win = this;
b95edd47
VZ
4463 while ( win && !win->HasCustomPalette() )
4464 {
4465 win = win->GetParent();
4466 }
4467
4468 if ( win && win->HasCustomPalette() )
4469 {
4470 // realize the palette to see whether redrawing is needed
4471 HDC hdc = ::GetDC((HWND) hWndPalChange);
4472 win->m_palette.SetHPALETTE((WXHPALETTE)
4473 ::SelectPalette(hdc, GetHpaletteOf(win->m_palette), FALSE));
574c939e
KB
4474
4475 int result = ::RealizePalette(hdc);
b95edd47
VZ
4476
4477 // restore the palette (before releasing the DC)
4478 win->m_palette.SetHPALETTE((WXHPALETTE)
4479 ::SelectPalette(hdc, GetHpaletteOf(win->m_palette), FALSE));
4480 ::RealizePalette(hdc);
4481 ::ReleaseDC((HWND) hWndPalChange, hdc);
4482
4483 // now check for the need to redraw
574c939e 4484 if (result > 0)
08158721 4485 ::InvalidateRect((HWND) hWndPalChange, NULL, TRUE);
574c939e 4486 }
b95edd47
VZ
4487
4488 }
4489#endif // wxUSE_PALETTE
574c939e 4490
42e69d6b
VZ
4491 wxPaletteChangedEvent event(GetId());
4492 event.SetEventObject(this);
4493 event.SetChangedWindow(wxFindWinFromHandle(hWndPalChange));
2d0a075d 4494
937013e0 4495 return HandleWindowEvent(event);
42e69d6b
VZ
4496}
4497
a5e84126
JS
4498bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
4499{
63e819f2
VS
4500 // notify windows on the capture stack about lost capture
4501 // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
72f8c792 4502 wxWindowBase::NotifyCaptureLost();
a5e84126 4503
72f8c792 4504 wxWindow *win = wxFindWinFromHandle(hWndGainedCapture);
63e819f2
VS
4505 wxMouseCaptureChangedEvent event(GetId(), win);
4506 event.SetEventObject(this);
937013e0 4507 return HandleWindowEvent(event);
a5e84126
JS
4508}
4509
3c96418b
JG
4510bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam, WXLPARAM lParam)
4511{
4512 // despite MSDN saying "(This message cannot be sent directly to a window.)"
4513 // we need to send this to child windows (it is only sent to top-level
4514 // windows) so {list,tree}ctrls can adjust their font size if necessary
4515 // this is exactly how explorer does it to enable the font size changes
4516
4517 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
4518 while ( node )
4519 {
4520 // top-level windows already get this message from the system
4521 wxWindow *win = node->GetData();
4522 if ( !win->IsTopLevel() )
4523 {
4524 ::SendMessage(GetHwndOf(win), WM_SETTINGCHANGE, wParam, lParam);
4525 }
4526
4527 node = node->GetNext();
4528 }
4529
3c96418b
JG
4530 // let the system handle it
4531 return false;
4532}
4533
1e6feb95 4534bool wxWindowMSW::HandleQueryNewPalette()
42e69d6b 4535{
574c939e
KB
4536
4537#if wxUSE_PALETTE
4538 // check to see if we our our parents have a custom palette
fa21d338 4539 wxWindowMSW *win = this;
574c939e
KB
4540 while (!win->HasCustomPalette() && win->GetParent()) win = win->GetParent();
4541 if (win->HasCustomPalette()) {
4542 /* realize the palette to see whether redrawing is needed */
3a3c8603 4543 HDC hdc = ::GetDC((HWND) GetHWND());
574c939e 4544 win->m_palette.SetHPALETTE( (WXHPALETTE)
b95edd47 4545 ::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), FALSE) );
574c939e
KB
4546
4547 int result = ::RealizePalette(hdc);
4548 /* restore the palette (before releasing the DC) */
4549 win->m_palette.SetHPALETTE( (WXHPALETTE)
b95edd47 4550 ::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), TRUE) );
574c939e
KB
4551 ::RealizePalette(hdc);
4552 ::ReleaseDC((HWND) GetHWND(), hdc);
4553 /* now check for the need to redraw */
4554 if (result > 0)
4555 ::InvalidateRect((HWND) GetHWND(), NULL, TRUE);
4556 }
b95edd47 4557#endif // wxUSE_PALETTE
574c939e 4558
42e69d6b
VZ
4559 wxQueryNewPaletteEvent event(GetId());
4560 event.SetEventObject(this);
4561
937013e0 4562 return HandleWindowEvent(event) && event.GetPaletteRealized();
42e69d6b
VZ
4563}
4564
4565// Responds to colour changes: passes event on to children.
574c939e 4566void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
42e69d6b 4567{
90c1530a
VZ
4568 // the top level window also reset the standard colour map as it might have
4569 // changed (there is no need to do it for the non top level windows as we
4570 // only have to do it once)
4571 if ( IsTopLevel() )
4572 {
4573 // FIXME-MT
08158721 4574 gs_hasStdCmap = false;
90c1530a 4575 }
222ed1d6 4576 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
42e69d6b
VZ
4577 while ( node )
4578 {
23895080
VZ
4579 // Only propagate to non-top-level windows because Windows already
4580 // sends this event to all top-level ones
4581 wxWindow *win = node->GetData();
4582 if ( !win->IsTopLevel() )
42e69d6b 4583 {
23895080
VZ
4584 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
4585 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
4586 // the standard controls
4587 ::SendMessage(GetHwndOf(win), WM_SYSCOLORCHANGE, 0, 0);
564b2609 4588 }
42e69d6b 4589
23895080
VZ
4590 node = node->GetNext();
4591 }
2bda0e17
KB
4592}
4593
90c1530a
VZ
4594extern wxCOLORMAP *wxGetStdColourMap()
4595{
4596 static COLORREF s_stdColours[wxSTD_COL_MAX];
4597 static wxCOLORMAP s_cmap[wxSTD_COL_MAX];
4598
4599 if ( !gs_hasStdCmap )
4600 {
08158721 4601 static bool s_coloursInit = false;
90c1530a
VZ
4602
4603 if ( !s_coloursInit )
4604 {
4605 // When a bitmap is loaded, the RGB values can change (apparently
4606 // because Windows adjusts them to care for the old programs always
4607 // using 0xc0c0c0 while the transparent colour for the new Windows
4608 // versions is different). But we do this adjustment ourselves so
4609 // we want to avoid Windows' "help" and for this we need to have a
4610 // reference bitmap which can tell us what the RGB values change
4611 // to.
e5dbcb50 4612 wxLogNull logNo; // suppress error if we couldn't load the bitmap
90c1530a
VZ
4613 wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
4614 if ( stdColourBitmap.Ok() )
4615 {
4616 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
4617 wxASSERT_MSG( stdColourBitmap.GetWidth() == wxSTD_COL_MAX,
4618 _T("forgot to update wxBITMAP_STD_COLOURS!") );
4619
4620 wxMemoryDC memDC;
4621 memDC.SelectObject(stdColourBitmap);
4622
4623 wxColour colour;
4624 for ( size_t i = 0; i < WXSIZEOF(s_stdColours); i++ )
4625 {
4626 memDC.GetPixel(i, 0, &colour);
4627 s_stdColours[i] = wxColourToRGB(colour);
4628 }
4629 }
4630 else // wxBITMAP_STD_COLOURS couldn't be loaded
4631 {
4632 s_stdColours[0] = RGB(000,000,000); // black
4633 s_stdColours[1] = RGB(128,128,128); // dark grey
4634 s_stdColours[2] = RGB(192,192,192); // light grey
4635 s_stdColours[3] = RGB(255,255,255); // white
4636 //s_stdColours[4] = RGB(000,000,255); // blue
4637 //s_stdColours[5] = RGB(255,000,255); // magenta
4638 }
4639
08158721 4640 s_coloursInit = true;
90c1530a
VZ
4641 }
4642
08158721 4643 gs_hasStdCmap = true;
90c1530a
VZ
4644
4645 // create the colour map
4646#define INIT_CMAP_ENTRY(col) \
4647 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
4648 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
4649
4650 INIT_CMAP_ENTRY(BTNTEXT);
4651 INIT_CMAP_ENTRY(BTNSHADOW);
4652 INIT_CMAP_ENTRY(BTNFACE);
4653 INIT_CMAP_ENTRY(BTNHIGHLIGHT);
4654
4655#undef INIT_CMAP_ENTRY
4656 }
4657
4658 return s_cmap;
4659}
4660
42e69d6b
VZ
4661// ---------------------------------------------------------------------------
4662// painting
4663// ---------------------------------------------------------------------------
4664
1e6feb95 4665bool wxWindowMSW::HandlePaint()
2bda0e17 4666{
42e69d6b
VZ
4667 HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
4668 if ( !hRegion )
f6bcfd97 4669 wxLogLastError(wxT("CreateRectRgn"));
42e69d6b 4670 if ( ::GetUpdateRgn(GetHwnd(), hRegion, FALSE) == ERROR )
f6bcfd97 4671 wxLogLastError(wxT("GetUpdateRgn"));
c085e333 4672
42e69d6b 4673 m_updateRegion = wxRegion((WXHRGN) hRegion);
c085e333 4674
42e69d6b
VZ
4675 wxPaintEvent event(m_windowId);
4676 event.SetEventObject(this);
2bda0e17 4677
937013e0 4678 bool processed = HandleWindowEvent(event);
1e6feb95
VZ
4679
4680 // note that we must generate NC event after the normal one as otherwise
4681 // BeginPaint() will happily overwrite our decorations with the background
4682 // colour
4683 wxNcPaintEvent eventNc(m_windowId);
4684 eventNc.SetEventObject(this);
937013e0 4685 HandleWindowEvent(eventNc);
1e6feb95 4686
90df6033
VZ
4687 // don't keep an HRGN we don't need any longer (GetUpdateRegion() can only
4688 // be called from inside the event handlers called above)
4689 m_updateRegion.Clear();
4690
1e6feb95 4691 return processed;
2bda0e17
KB
4692}
4693
63da7df7 4694// Can be called from an application's OnPaint handler
1e6feb95 4695void wxWindowMSW::OnPaint(wxPaintEvent& event)
63da7df7 4696{
1e6feb95
VZ
4697#ifdef __WXUNIVERSAL__
4698 event.Skip();
4699#else
888dde65 4700 HDC hDC = (HDC) wxPaintDCImpl::FindDCInCache((wxWindow*) event.GetEventObject());
63da7df7
JS
4701 if (hDC != 0)
4702 {
4703 MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0);
4704 }
1e6feb95 4705#endif
63da7df7
JS
4706}
4707
1e6feb95 4708bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
a23fd0e1 4709{
e0e6ac8a 4710 wxDCTemp dc(hdc, GetClientSize());
888dde65 4711 wxDCTempImpl *impl = (wxDCTempImpl*) dc.GetImpl();
c085e333 4712
888dde65
RR
4713 impl->SetHDC(hdc);
4714 impl->SetWindow((wxWindow *)this);
c085e333 4715
2bda0e17 4716 wxEraseEvent event(m_windowId, &dc);
42e69d6b 4717 event.SetEventObject(this);
937013e0 4718 bool rc = HandleWindowEvent(event);
c085e333 4719
7561aacd 4720 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
888dde65 4721 impl->SelectOldObjects(hdc);
a23fd0e1
VZ
4722
4723 return rc;
2bda0e17
KB
4724}
4725
8681b094
VZ
4726void wxWindowMSW::OnEraseBackground(wxEraseEvent& event)
4727{
52c3e064
VZ
4728 // standard non top level controls (i.e. except the dialogs) always erase
4729 // their background themselves in HandleCtlColor() or have some control-
4730 // specific ways to set the colours (common controls)
4731 if ( IsOfStandardClass() && !IsTopLevel() )
b8335252 4732 {
c5bd3c62
VZ
4733 event.Skip();
4734 return;
4735 }
b8335252 4736
06d7ed27 4737 if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM )
c5bd3c62 4738 {
06d7ed27
VZ
4739 // don't skip the event here, custom background means that the app
4740 // is drawing it itself in its OnPaint(), so don't draw it at all
4741 // now to avoid flicker
4742 return;
4743 }
8681b094 4744
888dde65
RR
4745 wxDC *dc = event.GetDC();
4746 if (!dc) return;
4747 wxMSWDCImpl *impl = (wxMSWDCImpl*) dc->GetImpl();
90df6033 4748
06d7ed27 4749 // do default background painting
888dde65 4750 if ( !DoEraseBackground(GetHdcOf(*impl)) )
06d7ed27
VZ
4751 {
4752 // let the system paint the background
4753 event.Skip();
c5bd3c62
VZ
4754 }
4755}
4756
c3732409 4757bool wxWindowMSW::DoEraseBackground(WXHDC hDC)
c581abbc 4758{
c3732409
VZ
4759 HBRUSH hbr = (HBRUSH)MSWGetBgBrush(hDC);
4760 if ( !hbr )
c581abbc
VZ
4761 return false;
4762
c3732409 4763 wxFillRect(GetHwnd(), (HDC)hDC, hbr);
c581abbc
VZ
4764
4765 return true;
4766}
4767
c3732409 4768WXHBRUSH
2bae4332 4769wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), WXHWND hWnd)
c5bd3c62 4770{
accbb1e7
VZ
4771 if ( m_hasBgCol )
4772 {
8d075f8d
VZ
4773 // our background colour applies to:
4774 // 1. this window itself, always
4775 // 2. all children unless the colour is "not inheritable"
c3732409
VZ
4776 // 3. even if it is not inheritable, our immediate transparent
4777 // children should still inherit it -- but not any transparent
4778 // children because it would look wrong if a child of non
4779 // transparent child would show our bg colour when the child itself
4780 // does not
2bae4332
VZ
4781 wxWindow *win = wxFindWinFromHandle(hWnd);
4782 if ( win == this ||
c3732409 4783 m_inheritBgCol ||
2bae4332
VZ
4784 (win && win->HasTransparentBackground() &&
4785 win->GetParent() == this) )
accbb1e7 4786 {
c3732409
VZ
4787 // draw children with the same colour as the parent
4788 wxBrush *
4789 brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour());
4790
4791 return (WXHBRUSH)GetHbrushOf(*brush);
accbb1e7
VZ
4792 }
4793 }
4794
c3732409 4795 return 0;
c5bd3c62 4796}
8681b094 4797
2bae4332 4798WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, WXHWND hWndToPaint)
bdd1a35d 4799{
2bae4332
VZ
4800 if ( !hWndToPaint )
4801 hWndToPaint = GetHWND();
bdd1a35d 4802
c3732409 4803 for ( wxWindowMSW *win = this; win; win = win->GetParent() )
c5bd3c62 4804 {
2bae4332 4805 WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, hWndToPaint);
c5bd3c62
VZ
4806 if ( hBrush )
4807 return hBrush;
24cb4019 4808
c3732409
VZ
4809 // background is not inherited beyond top level windows
4810 if ( win->IsTopLevel() )
24cb4019 4811 break;
01c500af 4812 }
c5bd3c62
VZ
4813
4814 return 0;
8681b094
VZ
4815}
4816
b728a212 4817bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
1a784dfc 4818{
b728a212
JG
4819 // we receive this message when DrawThemeParentBackground() is
4820 // called from def window proc of several controls under XP and we
4821 // must draw properly themed background here
4822 //
4823 // note that naively I'd expect filling the client rect with the
4824 // brush returned by MSWGetBgBrush() work -- but for some reason it
4825 // doesn't and we have to call parents MSWPrintChild() which is
4826 // supposed to call DrawThemeBackground() with appropriate params
4827 //
4828 // also note that in this case lParam == PRF_CLIENT but we're
4829 // clearly expected to paint the background and nothing else!
4830
4831 if ( IsTopLevel() || InheritsBackgroundColour() )
4832 return false;
4833
4834 // sometimes we don't want the parent to handle it at all, instead
4835 // return whatever value this window wants
4836 if ( !MSWShouldPropagatePrintChild() )
4837 return MSWPrintChild(hDC, (wxWindow *)this);
4838
4839 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
4840 {
4841 if ( win->MSWPrintChild(hDC, (wxWindow *)this) )
4842 return true;
4843
4844 if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
4845 break;
4846 }
4847
1a784dfc
VZ
4848 return false;
4849}
4850
42e69d6b
VZ
4851// ---------------------------------------------------------------------------
4852// moving and resizing
4853// ---------------------------------------------------------------------------
4854
1e6feb95 4855bool wxWindowMSW::HandleMinimize()
42e69d6b
VZ
4856{
4857 wxIconizeEvent event(m_windowId);
4858 event.SetEventObject(this);
2d0a075d 4859
937013e0 4860 return HandleWindowEvent(event);
2bda0e17
KB
4861}
4862
1e6feb95 4863bool wxWindowMSW::HandleMaximize()
2bda0e17 4864{
42e69d6b
VZ
4865 wxMaximizeEvent event(m_windowId);
4866 event.SetEventObject(this);
c085e333 4867
937013e0 4868 return HandleWindowEvent(event);
42e69d6b 4869}
2bda0e17 4870
1e6feb95 4871bool wxWindowMSW::HandleMove(int x, int y)
42e69d6b 4872{
907173e5
WS
4873 wxPoint point(x,y);
4874 wxMoveEvent event(point, m_windowId);
42e69d6b
VZ
4875 event.SetEventObject(this);
4876
937013e0 4877 return HandleWindowEvent(event);
42e69d6b
VZ
4878}
4879
5706de1c
JS
4880bool wxWindowMSW::HandleMoving(wxRect& rect)
4881{
4882 wxMoveEvent event(rect, m_windowId);
4883 event.SetEventObject(this);
577baeef 4884
937013e0 4885 bool rc = HandleWindowEvent(event);
5706de1c
JS
4886 if (rc)
4887 rect = event.GetRect();
4888 return rc;
4889}
4890
aa767a45
JS
4891bool wxWindowMSW::HandleEnterSizeMove()
4892{
66e2ba91 4893 wxMoveEvent event(wxPoint(0,0), m_windowId);
aa767a45
JS
4894 event.SetEventType(wxEVT_MOVE_START);
4895 event.SetEventObject(this);
4896
937013e0 4897 return HandleWindowEvent(event);
aa767a45
JS
4898}
4899
4900bool wxWindowMSW::HandleExitSizeMove()
4901{
66e2ba91 4902 wxMoveEvent event(wxPoint(0,0), m_windowId);
aa767a45
JS
4903 event.SetEventType(wxEVT_MOVE_END);
4904 event.SetEventObject(this);
4905
937013e0 4906 return HandleWindowEvent(event);
aa767a45
JS
4907}
4908
4bc0f25e 4909bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
42e69d6b 4910{
c3723477
JS
4911#if USE_DEFERRED_SIZING
4912 // when we resize this window, its children are probably going to be
4913 // repositioned as well, prepare to use DeferWindowPos() for them
4914 int numChildren = 0;
4915 for ( HWND child = ::GetWindow(GetHwndOf(this), GW_CHILD);
4916 child;
4917 child = ::GetWindow(child, GW_HWNDNEXT) )
4918 {
4919 numChildren ++;
4920 }
4921
3fca879c 4922 // Protect against valid m_hDWP being overwritten
c3723477
JS
4923 bool useDefer = false;
4924
3f48c8e2
VZ
4925 if ( numChildren > 1 )
4926 {
c3723477 4927 if (!m_hDWP)
3fca879c 4928 {
c3723477
JS
4929 m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
4930 if ( !m_hDWP )
4931 {
4932 wxLogLastError(_T("BeginDeferWindowPos"));
4933 }
4934 if (m_hDWP)
4935 useDefer = true;
3f48c8e2
VZ
4936 }
4937 }
f7040b5f 4938#endif // USE_DEFERRED_SIZING
42e69d6b 4939
3f48c8e2
VZ
4940 // update this window size
4941 bool processed = false;
4bc0f25e
VZ
4942 switch ( wParam )
4943 {
4944 default:
4945 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
4946 // fall through nevertheless
4947
4948 case SIZE_MAXHIDE:
4949 case SIZE_MAXSHOW:
4950 // we're not interested in these messages at all
4951 break;
4952
4953 case SIZE_MINIMIZED:
4954 processed = HandleMinimize();
4955 break;
4956
4957 case SIZE_MAXIMIZED:
a4d1972d 4958 /* processed = */ HandleMaximize();
4bc0f25e
VZ
4959 // fall through to send a normal size event as well
4960
4961 case SIZE_RESTORED:
4962 // don't use w and h parameters as they specify the client size
4963 // while according to the docs EVT_SIZE handler is supposed to
4964 // receive the total size
4965 wxSizeEvent event(GetSize(), m_windowId);
4966 event.SetEventObject(this);
4967
937013e0 4968 processed = HandleWindowEvent(event);
4bc0f25e
VZ
4969 }
4970
c3723477 4971#if USE_DEFERRED_SIZING
3f48c8e2 4972 // and finally change the positions of all child windows at once
c3723477 4973 if ( useDefer && m_hDWP )
3f48c8e2
VZ
4974 {
4975 // reset m_hDWP to NULL so that child windows don't try to use our
4976 // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
4977 // happen anyhow normally but who knows what weird flow of control we
4978 // may have depending on what the users EVT_SIZE handler does...)
4979 HDWP hDWP = (HDWP)m_hDWP;
4980 m_hDWP = NULL;
3fca879c 4981
3f48c8e2
VZ
4982 // do put all child controls in place at once
4983 if ( !::EndDeferWindowPos(hDWP) )
4984 {
4985 wxLogLastError(_T("EndDeferWindowPos"));
4986 }
c3723477 4987
da78f3b1 4988 // Reset our children's pending pos/size values.
c3723477
JS
4989 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
4990 node;
4991 node = node->GetNext() )
4992 {
82e3664e 4993 wxWindowMSW *child = node->GetData();
67644c1d
RD
4994 child->m_pendingPosition = wxDefaultPosition;
4995 child->m_pendingSize = wxDefaultSize;
c3723477 4996 }
3f48c8e2 4997 }
7d86a2d4 4998#endif // USE_DEFERRED_SIZING
3f48c8e2 4999
4bc0f25e 5000 return processed;
42e69d6b
VZ
5001}
5002
5706de1c
JS
5003bool wxWindowMSW::HandleSizing(wxRect& rect)
5004{
5005 wxSizeEvent event(rect, m_windowId);
5006 event.SetEventObject(this);
577baeef 5007
937013e0 5008 bool rc = HandleWindowEvent(event);
5706de1c
JS
5009 if (rc)
5010 rect = event.GetRect();
5011 return rc;
5012}
5013
0c0d1521 5014bool wxWindowMSW::HandleGetMinMaxInfo(void *WXUNUSED_IN_WINCE(mmInfo))
42e69d6b 5015{
7f0586ef 5016#ifdef __WXWINCE__
08158721 5017 return false;
7f0586ef 5018#else
42e69d6b
VZ
5019 MINMAXINFO *info = (MINMAXINFO *)mmInfo;
5020
08158721 5021 bool rc = false;
b2d5a7ee 5022
e7dda1ff
VS
5023 int minWidth = GetMinWidth(),
5024 minHeight = GetMinHeight(),
5025 maxWidth = GetMaxWidth(),
5026 maxHeight = GetMaxHeight();
42e69d6b 5027
422d0ff0 5028 if ( minWidth != wxDefaultCoord )
2d0a075d 5029 {
e7dda1ff 5030 info->ptMinTrackSize.x = minWidth;
08158721 5031 rc = true;
2d0a075d 5032 }
2bda0e17 5033
422d0ff0 5034 if ( minHeight != wxDefaultCoord )
42e69d6b 5035 {
e7dda1ff 5036 info->ptMinTrackSize.y = minHeight;
08158721 5037 rc = true;
42e69d6b 5038 }
2bda0e17 5039
422d0ff0 5040 if ( maxWidth != wxDefaultCoord )
42e69d6b 5041 {
e7dda1ff 5042 info->ptMaxTrackSize.x = maxWidth;
08158721 5043 rc = true;
2d0a075d 5044 }
2bda0e17 5045
422d0ff0 5046 if ( maxHeight != wxDefaultCoord )
42e69d6b 5047 {
e7dda1ff 5048 info->ptMaxTrackSize.y = maxHeight;
08158721 5049 rc = true;
42e69d6b 5050 }
2bda0e17 5051
42e69d6b 5052 return rc;
7f0586ef 5053#endif
42e69d6b 5054}
2d0a075d 5055
42e69d6b
VZ
5056// ---------------------------------------------------------------------------
5057// command messages
5058// ---------------------------------------------------------------------------
5059
0edeeb6d 5060bool wxWindowMSW::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND control)
42e69d6b 5061{
0edeeb6d
VZ
5062 // sign extend to int from short before comparing with the other int ids
5063 int id = (signed short)id_;
5064
1e6feb95 5065#if wxUSE_MENUS_NATIVE
8c290175 5066 if ( !cmd && wxCurrentPopupMenu )
42e69d6b
VZ
5067 {
5068 wxMenu *popupMenu = wxCurrentPopupMenu;
5069 wxCurrentPopupMenu = NULL;
5070
5071 return popupMenu->MSWCommand(cmd, id);
5072 }
1e6feb95 5073#endif // wxUSE_MENUS_NATIVE
42e69d6b 5074
8c290175 5075 wxWindow *win = NULL;
71292fab
VZ
5076
5077 // first try to find it from HWND - this works even with the broken
5078 // programs using the same ids for different controls
5079 if ( control )
42e69d6b 5080 {
71292fab 5081 win = wxFindWinFromHandle(control);
b853f898 5082 }
2f4ef631 5083
71292fab
VZ
5084 // try the id
5085 if ( !win )
b853f898 5086 {
0edeeb6d 5087 win = FindItem(id);
42e69d6b
VZ
5088 }
5089
5090 if ( win )
b94ae1ea 5091 {
42e69d6b 5092 return win->MSWCommand(cmd, id);
b94ae1ea
VZ
5093 }
5094
5095 // the messages sent from the in-place edit control used by the treectrl
5096 // for label editing have id == 0, but they should _not_ be treated as menu
5097 // messages (they are EN_XXX ones, in fact) so don't translate anything
5098 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
5099 if ( !control )
a84fc80b 5100 {
a6ac49b1 5101 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
a84fc80b 5102 event.SetEventObject(this);
a84fc80b 5103 event.SetInt(id);
b94ae1ea 5104
937013e0 5105 return HandleWindowEvent(event);
a84fc80b 5106 }
6fe19057
VZ
5107 else
5108 {
01d2bf4d 5109#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
6fe19057
VZ
5110 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
5111 // notifications to its parent which we want to reflect back to
5112 // wxSpinCtrl
5113 wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control);
5114 if ( spin && spin->ProcessTextCommand(cmd, id) )
08158721 5115 return true;
6fe19057 5116#endif // wxUSE_SPINCTRL
42e69d6b 5117
01d2bf4d
WS
5118#if wxUSE_CHOICE && defined(__SMARTPHONE__)
5119 // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND
5120 // notifications to its parent which we want to reflect back to
5121 // wxChoice
5122 wxChoice *choice = wxChoice::GetChoiceForListBox(control);
5123 if ( choice && choice->MSWCommand(cmd, id) )
5124 return true;
5125#endif
5126 }
5127
08158721 5128 return false;
2bda0e17
KB
5129}
5130
42e69d6b
VZ
5131// ---------------------------------------------------------------------------
5132// mouse events
5133// ---------------------------------------------------------------------------
5134
1e6feb95
VZ
5135void wxWindowMSW::InitMouseEvent(wxMouseEvent& event,
5136 int x, int y,
5137 WXUINT flags)
42e69d6b 5138{
1e6feb95
VZ
5139 // our client coords are not quite the same as Windows ones
5140 wxPoint pt = GetClientAreaOrigin();
5141 event.m_x = x - pt.x;
5142 event.m_y = y - pt.y;
5143
5144 event.m_shiftDown = (flags & MK_SHIFT) != 0;
5145 event.m_controlDown = (flags & MK_CONTROL) != 0;
5146 event.m_leftDown = (flags & MK_LBUTTON) != 0;
5147 event.m_middleDown = (flags & MK_MBUTTON) != 0;
5148 event.m_rightDown = (flags & MK_RBUTTON) != 0;
2f68482e 5149#ifdef wxHAS_XBUTTON
01101e2d
VZ
5150 event.m_aux1Down = (flags & MK_XBUTTON1) != 0;
5151 event.m_aux2Down = (flags & MK_XBUTTON2) != 0;
2f68482e 5152#endif // wxHAS_XBUTTON
6719c06a 5153 event.m_altDown = ::wxIsAltDown();
1e6feb95 5154
f0b1ccde 5155#ifndef __WXWINCE__
1bf77ee5 5156 event.SetTimestamp(::GetMessageTime());
f0b1ccde
JS
5157#endif
5158
687706f5 5159 event.SetEventObject(this);
fb35f0c7 5160 event.SetId(GetId());
42e69d6b
VZ
5161
5162#if wxUSE_MOUSEEVENT_HACK
c358ea41
VZ
5163 gs_lastMouseEvent.pos = ClientToScreen(wxPoint(x, y));
5164 gs_lastMouseEvent.type = event.GetEventType();
42e69d6b 5165#endif // wxUSE_MOUSEEVENT_HACK
2bda0e17
KB
5166}
5167
42b1fb63 5168#ifdef __WXWINCE__
dfafa702
VZ
5169// Windows doesn't send the mouse events to the static controls (which are
5170// transparent in the sense that their WM_NCHITTEST handler returns
5171// HTTRANSPARENT) at all but we want all controls to receive the mouse events
5172// and so we manually check if we don't have a child window under mouse and if
5173// we do, send the event to it instead of the window Windows had sent WM_XXX
5174// to.
5175//
5176// Notice that this is not done for the mouse move events because this could
5177// (would?) be too slow, but only for clicks which means that the static texts
5178// still don't get move, enter nor leave events.
42b1fb63 5179static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y)
dfafa702
VZ
5180{
5181 wxCHECK_MSG( x && y, win, _T("NULL pointer in FindWindowForMouseEvent") );
5182
5183 // first try to find a non transparent child: this allows us to send events
5184 // to a static text which is inside a static box, for example
5185 POINT pt = { *x, *y };
5186 HWND hwnd = GetHwndOf(win),
5187 hwndUnderMouse;
5188
7f0586ef
JS
5189#ifdef __WXWINCE__
5190 hwndUnderMouse = ::ChildWindowFromPoint
5191 (
5192 hwnd,
5193 pt
5194 );
5195#else
dfafa702
VZ
5196 hwndUnderMouse = ::ChildWindowFromPointEx
5197 (
5198 hwnd,
5199 pt,
5200 CWP_SKIPINVISIBLE |
5201 CWP_SKIPDISABLED |
5202 CWP_SKIPTRANSPARENT
5203 );
7f0586ef 5204#endif
dfafa702
VZ
5205
5206 if ( !hwndUnderMouse || hwndUnderMouse == hwnd )
dfafa702
VZ
5207 {
5208 // now try any child window at all
5209 hwndUnderMouse = ::ChildWindowFromPoint(hwnd, pt);
5210 }
5211
5212 // check that we have a child window which is susceptible to receive mouse
5213 // events: for this it must be shown and enabled
5214 if ( hwndUnderMouse &&
5215 hwndUnderMouse != hwnd &&
5216 ::IsWindowVisible(hwndUnderMouse) &&
5217 ::IsWindowEnabled(hwndUnderMouse) )
5218 {
dca0f651 5219 wxWindow *winUnderMouse = wxFindWinFromHandle(hwndUnderMouse);
dfafa702
VZ
5220 if ( winUnderMouse )
5221 {
5222 // translate the mouse coords to the other window coords
5223 win->ClientToScreen(x, y);
5224 winUnderMouse->ScreenToClient(x, y);
5225
5226 win = winUnderMouse;
5227 }
5228 }
5229
5230 return win;
5231}
42b1fb63 5232#endif // __WXWINCE__
dfafa702 5233
1e6feb95 5234bool wxWindowMSW::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
2bda0e17 5235{
42e69d6b 5236 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
34621cc5 5237 // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST
42e69d6b
VZ
5238 // from the message id and take the value in the table to get wxWin event
5239 // id
5240 static const wxEventType eventsMouse[] =
5241 {
5242 wxEVT_MOTION,
5243 wxEVT_LEFT_DOWN,
5244 wxEVT_LEFT_UP,
5245 wxEVT_LEFT_DCLICK,
5246 wxEVT_RIGHT_DOWN,
5247 wxEVT_RIGHT_UP,
5248 wxEVT_RIGHT_DCLICK,
5249 wxEVT_MIDDLE_DOWN,
5250 wxEVT_MIDDLE_UP,
01101e2d
VZ
5251 wxEVT_MIDDLE_DCLICK,
5252 0, // this one is for wxEVT_MOTION which is not used here
5253 wxEVT_AUX1_DOWN,
5254 wxEVT_AUX1_UP,
5255 wxEVT_AUX1_DCLICK,
5256 wxEVT_AUX2_DOWN,
5257 wxEVT_AUX2_UP,
5258 wxEVT_AUX2_DCLICK
42e69d6b 5259 };
2bda0e17 5260
2f68482e 5261#ifdef wxHAS_XBUTTON
01101e2d
VZ
5262 // the same messages are used for both auxillary mouse buttons so we need
5263 // to adjust the index manually
5264 switch ( msg )
5265 {
5266 case WM_XBUTTONDOWN:
5267 case WM_XBUTTONUP:
5268 case WM_XBUTTONDBLCLK:
5269 if ( flags & MK_XBUTTON2 )
5270 msg += wxEVT_AUX2_DOWN - wxEVT_AUX1_DOWN;
5271 }
2f68482e 5272#endif // wxHAS_XBUTTON
01101e2d 5273
42e69d6b
VZ
5274 wxMouseEvent event(eventsMouse[msg - WM_MOUSEMOVE]);
5275 InitMouseEvent(event, x, y, flags);
5276
937013e0 5277 return HandleWindowEvent(event);
42e69d6b
VZ
5278}
5279
1e6feb95 5280bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
42e69d6b
VZ
5281{
5282 if ( !m_mouseInWindow )
2bda0e17 5283 {
1e6feb95
VZ
5284 // it would be wrong to assume that just because we get a mouse move
5285 // event that the mouse is inside the window: although this is usually
5286 // true, it is not if we had captured the mouse, so we need to check
5287 // the mouse coordinates here
5288 if ( !HasCapture() || IsMouseInWindow() )
5289 {
5290 // Generate an ENTER event
08158721 5291 m_mouseInWindow = true;
e5297b7f 5292
4e5c6c33 5293#ifdef HAVE_TRACKMOUSEEVENT
aafb9978
VZ
5294 typedef BOOL (WINAPI *_TrackMouseEvent_t)(LPTRACKMOUSEEVENT);
5295#ifdef __WXWINCE__
5296 static const _TrackMouseEvent_t
5297 s_pfn_TrackMouseEvent = _TrackMouseEvent;
5298#else // !__WXWINCE__
5299 static _TrackMouseEvent_t s_pfn_TrackMouseEvent;
5300 static bool s_initDone = false;
5301 if ( !s_initDone )
5302 {
e2d4ce7d 5303 // see comment in wxApp::GetComCtl32Version() explaining the
5a9379d7
VZ
5304 // use of wxLoadedDLL
5305 wxLoadedDLL dllComCtl32(_T("comctl32.dll"));
aafb9978
VZ
5306 if ( dllComCtl32.IsLoaded() )
5307 {
5308 s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
e2d4ce7d 5309 dllComCtl32.RawGetSymbol(_T("_TrackMouseEvent"));
aafb9978
VZ
5310 }
5311
5312 s_initDone = true;
aafb9978
VZ
5313 }
5314
5315 if ( s_pfn_TrackMouseEvent )
5316#endif // __WXWINCE__/!__WXWINCE__
5317 {
5318 WinStruct<TRACKMOUSEEVENT> trackinfo;
4e5c6c33 5319
aafb9978
VZ
5320 trackinfo.dwFlags = TME_LEAVE;
5321 trackinfo.hwndTrack = GetHwnd();
5322
5323 (*s_pfn_TrackMouseEvent)(&trackinfo);
5324 }
4e5c6c33
VZ
5325#endif // HAVE_TRACKMOUSEEVENT
5326
1e6feb95
VZ
5327 wxMouseEvent event(wxEVT_ENTER_WINDOW);
5328 InitMouseEvent(event, x, y, flags);
42e69d6b 5329
937013e0 5330 (void)HandleWindowEvent(event);
1e6feb95 5331 }
42e69d6b 5332 }
cff58b52 5333#ifdef HAVE_TRACKMOUSEEVENT
aafb9978 5334 else // mouse not in window
cff58b52
KH
5335 {
5336 // Check if we need to send a LEAVE event
5337 // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so
5338 // send it here if we are using native mouse leave tracking
5339 if ( HasCapture() && !IsMouseInWindow() )
5340 {
5341 GenerateMouseLeave();
5342 }
5343 }
1ca78aa1 5344#endif // HAVE_TRACKMOUSEEVENT
42e69d6b
VZ
5345
5346#if wxUSE_MOUSEEVENT_HACK
c358ea41
VZ
5347 // Windows often generates mouse events even if mouse position hasn't
5348 // changed (http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/66576)
5349 //
5350 // Filter this out as it can result in unexpected behaviour compared to
5351 // other platforms
5352 if ( gs_lastMouseEvent.type == wxEVT_RIGHT_DOWN ||
5353 gs_lastMouseEvent.type == wxEVT_LEFT_DOWN ||
5354 gs_lastMouseEvent.type == wxEVT_MIDDLE_DOWN ||
5355 gs_lastMouseEvent.type == wxEVT_MOTION )
5356 {
5357 if ( ClientToScreen(wxPoint(x, y)) == gs_lastMouseEvent.pos )
5358 {
5359 gs_lastMouseEvent.type = wxEVT_MOTION;
42e69d6b 5360
c358ea41
VZ
5361 return false;
5362 }
42e69d6b
VZ
5363 }
5364#endif // wxUSE_MOUSEEVENT_HACK
5365
5366 return HandleMouseEvent(WM_MOUSEMOVE, x, y, flags);
5367}
5368
d2c52078 5369
24ce4c18 5370bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
d2c52078
RD
5371{
5372#if wxUSE_MOUSEWHEEL
3c297348
VZ
5373 // notice that WM_MOUSEWHEEL position is in screen coords (as it's
5374 // forwarded up to the parent by DefWindowProc()) and not in the client
5375 // ones as all the other messages, translate them to the client coords for
5376 // consistency
5377 const wxPoint
5378 pt = ScreenToClient(wxPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
d2c52078 5379 wxMouseEvent event(wxEVT_MOUSEWHEEL);
3c297348 5380 InitMouseEvent(event, pt.x, pt.y, LOWORD(wParam));
d2c52078
RD
5381 event.m_wheelRotation = (short)HIWORD(wParam);
5382 event.m_wheelDelta = WHEEL_DELTA;
5383
0f7a546d
RD
5384 static int s_linesPerRotation = -1;
5385 if ( s_linesPerRotation == -1 )
5386 {
5387 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
5388 &s_linesPerRotation, 0))
5389 {
5390 // this is not supposed to happen
5391 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
5392
5393 // the default is 3, so use it if SystemParametersInfo() failed
5394 s_linesPerRotation = 3;
5395 }
5396 }
d2c52078 5397
0f7a546d 5398 event.m_linesPerAction = s_linesPerRotation;
937013e0 5399 return HandleWindowEvent(event);
0f7a546d 5400
51e4e266
VZ
5401#else // !wxUSE_MOUSEWHEEL
5402 wxUnusedVar(wParam);
5403 wxUnusedVar(lParam);
38caaa61 5404
08158721 5405 return false;
51e4e266 5406#endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL
d2c52078
RD
5407}
5408
51e4e266
VZ
5409void wxWindowMSW::GenerateMouseLeave()
5410{
5411 m_mouseInWindow = false;
5412
5413 int state = 0;
5414 if ( wxIsShiftDown() )
5415 state |= MK_SHIFT;
5416 if ( wxIsCtrlDown() )
5417 state |= MK_CONTROL;
5418
5419 // Only the high-order bit should be tested
5420 if ( GetKeyState( VK_LBUTTON ) & (1<<15) )
5421 state |= MK_LBUTTON;
5422 if ( GetKeyState( VK_MBUTTON ) & (1<<15) )
5423 state |= MK_MBUTTON;
5424 if ( GetKeyState( VK_RBUTTON ) & (1<<15) )
5425 state |= MK_RBUTTON;
5426
5427 POINT pt;
f2325516
JS
5428#ifdef __WXWINCE__
5429 if ( !::GetCursorPosWinCE(&pt) )
5430#else
51e4e266 5431 if ( !::GetCursorPos(&pt) )
f2325516 5432#endif
51e4e266
VZ
5433 {
5434 wxLogLastError(_T("GetCursorPos"));
5435 }
5436
5437 // we need to have client coordinates here for symmetry with
5438 // wxEVT_ENTER_WINDOW
5439 RECT rect = wxGetWindowRect(GetHwnd());
5440 pt.x -= rect.left;
5441 pt.y -= rect.top;
5442
5443 wxMouseEvent event(wxEVT_LEAVE_WINDOW);
5444 InitMouseEvent(event, pt.x, pt.y, state);
5445
937013e0 5446 (void)HandleWindowEvent(event);
51e4e266 5447}
d2c52078 5448
42e69d6b
VZ
5449// ---------------------------------------------------------------------------
5450// keyboard handling
5451// ---------------------------------------------------------------------------
5452
c42404a5
VZ
5453// create the key event of the given type for the given key - used by
5454// HandleChar and HandleKeyDown/Up
1e6feb95 5455wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType,
b09bda68 5456 int id,
9c7df356
VZ
5457 WXLPARAM lParam,
5458 WXWPARAM wParam) const
c42404a5
VZ
5459{
5460 wxKeyEvent event(evType);
5461 event.SetId(GetId());
3f7bc32b
VZ
5462 event.m_shiftDown = wxIsShiftDown();
5463 event.m_controlDown = wxIsCtrlDown();
c42404a5
VZ
5464 event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN;
5465
687706f5 5466 event.SetEventObject((wxWindow *)this); // const_cast
c42404a5 5467 event.m_keyCode = id;
0d9b2c16 5468#if wxUSE_UNICODE
32b13913 5469 event.m_uniChar = (wxChar) wParam;
0d9b2c16 5470#endif
9c7df356
VZ
5471 event.m_rawCode = (wxUint32) wParam;
5472 event.m_rawFlags = (wxUint32) lParam;
f0b1ccde 5473#ifndef __WXWINCE__
1bf77ee5 5474 event.SetTimestamp(::GetMessageTime());
f0b1ccde 5475#endif
c42404a5
VZ
5476
5477 // translate the position to client coords
5478 POINT pt;
f2325516
JS
5479#ifdef __WXWINCE__
5480 GetCursorPosWinCE(&pt);
5481#else
c42404a5 5482 GetCursorPos(&pt);
f2325516 5483#endif
c42404a5
VZ
5484 RECT rect;
5485 GetWindowRect(GetHwnd(),&rect);
5486 pt.x -= rect.left;
5487 pt.y -= rect.top;
5488
5489 event.m_x = pt.x;
5490 event.m_y = pt.y;
5491
5492 return event;
5493}
5494
08158721 5495// isASCII is true only when we're called from WM_CHAR handler and not from
42e69d6b 5496// WM_KEYDOWN one
1e6feb95 5497bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
42e69d6b
VZ
5498{
5499 int id;
42e69d6b
VZ
5500 if ( isASCII )
5501 {
42e69d6b 5502 id = wParam;
2d0a075d 5503 }
9c7df356 5504 else // we're called from WM_KEYDOWN
c42404a5 5505 {
6121a198
VZ
5506 // don't pass lParam to wxCharCodeMSWToWX() here because we don't want
5507 // to get numpad key codes: CHAR events should use the logical keys
5508 // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events
5509 id = wxCharCodeMSWToWX(wParam);
9c7df356 5510 if ( id == 0 )
c42404a5 5511 {
9c7df356 5512 // it's ASCII and will be processed here only when called from
08158721
DS
5513 // WM_CHAR (i.e. when isASCII = true), don't process it now
5514 return false;
c42404a5 5515 }
9c7df356 5516 }
42e69d6b 5517
9c7df356 5518 wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam, wParam));
2b5f62a0
VZ
5519
5520 // the alphanumeric keys produced by pressing AltGr+something on European
5521 // keyboards have both Ctrl and Alt modifiers which may confuse the user
5522 // code as, normally, keys with Ctrl and/or Alt don't result in anything
5523 // alphanumeric, so pretend that there are no modifiers at all (the
5524 // KEY_DOWN event would still have the correct modifiers if they're really
5525 // needed)
5526 if ( event.m_controlDown && event.m_altDown &&
5527 (id >= 32 && id < 256) )
9c7df356 5528 {
2b5f62a0 5529 event.m_controlDown =
08158721 5530 event.m_altDown = false;
2d0a075d 5531 }
c42404a5 5532
937013e0 5533 return HandleWindowEvent(event);
2bda0e17
KB
5534}
5535
1e6feb95 5536bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
2bda0e17 5537{
ff792344 5538 int id = wxCharCodeMSWToWX(wParam, lParam);
2bda0e17 5539
c42404a5
VZ
5540 if ( !id )
5541 {
5542 // normal ASCII char
42e69d6b
VZ
5543 id = wParam;
5544 }
5545
b60978b2 5546 wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
937013e0 5547 return HandleWindowEvent(event);
2bda0e17
KB
5548}
5549
1e6feb95 5550bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
2bda0e17 5551{
ff792344 5552 int id = wxCharCodeMSWToWX(wParam, lParam);
2bda0e17 5553
c42404a5
VZ
5554 if ( !id )
5555 {
5556 // normal ASCII char
42e69d6b 5557 id = wParam;
2d0a075d 5558 }
2bda0e17 5559
b60978b2 5560 wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
937013e0 5561 return HandleWindowEvent(event);
2bda0e17
KB
5562}
5563
53a118d6 5564#if wxUSE_MENUS
0c0d1521
WS
5565int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
5566 WXLPARAM WXUNUSED_IN_WINCE(lParam))
b74cce40 5567{
7f0586ef
JS
5568 // FIXME: implement GetMenuItemCount for WinCE, possibly
5569 // in terms of GetMenuItemInfo
5570#ifndef __WXWINCE__
b74cce40
VZ
5571 const HMENU hmenu = (HMENU)lParam;
5572
5573 MENUITEMINFO mii;
5574 wxZeroMemory(mii);
5575 mii.cbSize = sizeof(MENUITEMINFO);
c70ffbdb
VZ
5576
5577 // we could use MIIM_FTYPE here as we only need to know if the item is
5578 // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but
5579 // MIIM_FTYPE is not supported under Win95
b74cce40
VZ
5580 mii.fMask = MIIM_TYPE | MIIM_DATA;
5581
5582 // find if we have this letter in any owner drawn item
5583 const int count = ::GetMenuItemCount(hmenu);
5584 for ( int i = 0; i < count; i++ )
5585 {
c70ffbdb
VZ
5586 // previous loop iteration could modify it, reset it back before
5587 // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData
5588 mii.cch = 0;
5589
b74cce40
VZ
5590 if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) )
5591 {
5592 if ( mii.fType == MFT_OWNERDRAW )
5593 {
5594 // dwItemData member of the MENUITEMINFO is a
5595 // pointer to the associated wxMenuItem -- see the
5596 // menu creation code
5597 wxMenuItem *item = (wxMenuItem*)mii.dwItemData;
5598
967d3d97 5599 const wxChar *p = wxStrchr(item->GetItemLabel().wx_str(), _T('&'));
b74cce40
VZ
5600 while ( p++ )
5601 {
5602 if ( *p == _T('&') )
5603 {
5604 // this is not the accel char, find the real one
5605 p = wxStrchr(p + 1, _T('&'));
5606 }
5607 else // got the accel char
5608 {
5609 // FIXME-UNICODE: this comparison doesn't risk to work
5610 // for non ASCII accelerator characters I'm afraid, but
5611 // what can we do?
907173e5 5612 if ( (wchar_t)wxToupper(*p) == (wchar_t)chAccel )
b74cce40
VZ
5613 {
5614 return i;
5615 }
5616 else
5617 {
5618 // this one doesn't match
5619 break;
5620 }
5621 }
5622 }
5623 }
5624 }
e39af974 5625 else // failed to get the menu text?
b74cce40 5626 {
c70ffbdb 5627 // it's not fatal, so don't show error, but still log it
b74cce40
VZ
5628 wxLogLastError(_T("GetMenuItemInfo"));
5629 }
5630 }
7f0586ef 5631#endif
b74cce40
VZ
5632 return wxNOT_FOUND;
5633}
5634
17a04304
VZ
5635#endif // wxUSE_MENUS
5636
5637bool wxWindowMSW::HandleClipboardEvent(WXUINT nMsg)
78c91815 5638{
17a04304
VZ
5639 const wxEventType type = nMsg == WM_CUT ? wxEVT_COMMAND_TEXT_CUT
5640 : nMsg == WM_COPY ? wxEVT_COMMAND_TEXT_COPY
5641 : /* nMsg == WM_PASTE */ wxEVT_COMMAND_TEXT_PASTE;
78c91815
VZ
5642 wxClipboardTextEvent evt(type, GetId());
5643
5644 evt.SetEventObject(this);
5645
937013e0 5646 return HandleWindowEvent(evt);
78c91815
VZ
5647}
5648
42e69d6b
VZ
5649// ---------------------------------------------------------------------------
5650// joystick
5651// ---------------------------------------------------------------------------
5652
1e6feb95 5653bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags)
2bda0e17 5654{
8cb172b4 5655#ifdef JOY_BUTTON1
42e69d6b
VZ
5656 int change = 0;
5657 if ( flags & JOY_BUTTON1CHG )
5658 change = wxJOY_BUTTON1;
5659 if ( flags & JOY_BUTTON2CHG )
5660 change = wxJOY_BUTTON2;
5661 if ( flags & JOY_BUTTON3CHG )
5662 change = wxJOY_BUTTON3;
5663 if ( flags & JOY_BUTTON4CHG )
5664 change = wxJOY_BUTTON4;
2bda0e17 5665
42e69d6b
VZ
5666 int buttons = 0;
5667 if ( flags & JOY_BUTTON1 )
5668 buttons |= wxJOY_BUTTON1;
5669 if ( flags & JOY_BUTTON2 )
5670 buttons |= wxJOY_BUTTON2;
5671 if ( flags & JOY_BUTTON3 )
5672 buttons |= wxJOY_BUTTON3;
5673 if ( flags & JOY_BUTTON4 )
5674 buttons |= wxJOY_BUTTON4;
c085e333 5675
42e69d6b
VZ
5676 // the event ids aren't consecutive so we can't use table based lookup
5677 int joystick;
5678 wxEventType eventType;
5679 switch ( msg )
5680 {
5681 case MM_JOY1MOVE:
5682 joystick = 1;
5683 eventType = wxEVT_JOY_MOVE;
5684 break;
2bda0e17 5685
42e69d6b
VZ
5686 case MM_JOY2MOVE:
5687 joystick = 2;
5688 eventType = wxEVT_JOY_MOVE;
5689 break;
2bda0e17 5690
42e69d6b
VZ
5691 case MM_JOY1ZMOVE:
5692 joystick = 1;
5693 eventType = wxEVT_JOY_ZMOVE;
5694 break;
2bda0e17 5695
42e69d6b
VZ
5696 case MM_JOY2ZMOVE:
5697 joystick = 2;
5698 eventType = wxEVT_JOY_ZMOVE;
5699 break;
2bda0e17 5700
42e69d6b
VZ
5701 case MM_JOY1BUTTONDOWN:
5702 joystick = 1;
5703 eventType = wxEVT_JOY_BUTTON_DOWN;
5704 break;
2bda0e17 5705
42e69d6b
VZ
5706 case MM_JOY2BUTTONDOWN:
5707 joystick = 2;
5708 eventType = wxEVT_JOY_BUTTON_DOWN;
5709 break;
2bda0e17 5710
42e69d6b
VZ
5711 case MM_JOY1BUTTONUP:
5712 joystick = 1;
5713 eventType = wxEVT_JOY_BUTTON_UP;
5714 break;
5715
5716 case MM_JOY2BUTTONUP:
5717 joystick = 2;
5718 eventType = wxEVT_JOY_BUTTON_UP;
5719 break;
5720
5721 default:
223d09f6 5722 wxFAIL_MSG(wxT("no such joystick event"));
2d0a075d 5723
08158721 5724 return false;
2d0a075d 5725 }
2bda0e17 5726
42e69d6b
VZ
5727 wxJoystickEvent event(eventType, buttons, joystick, change);
5728 event.SetPosition(wxPoint(x, y));
5729 event.SetEventObject(this);
c085e333 5730
937013e0 5731 return HandleWindowEvent(event);
8cb172b4 5732#else
991420e6
WS
5733 wxUnusedVar(msg);
5734 wxUnusedVar(x);
5735 wxUnusedVar(y);
5736 wxUnusedVar(flags);
08158721 5737 return false;
8cb172b4 5738#endif
2bda0e17
KB
5739}
5740
42e69d6b
VZ
5741// ---------------------------------------------------------------------------
5742// scrolling
5743// ---------------------------------------------------------------------------
5744
1e6feb95 5745bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
f4f734c1 5746 WXWORD pos, WXHWND control)
35bbb0c6 5747{
a0d924c6 5748 if ( control && control != m_hWnd ) // Prevent infinite recursion
cc2b7472 5749 {
42e69d6b
VZ
5750 wxWindow *child = wxFindWinFromHandle(control);
5751 if ( child )
5752 return child->MSWOnScroll(orientation, wParam, pos, control);
cc2b7472 5753 }
2bda0e17 5754
9145664b 5755 wxScrollWinEvent event;
42e69d6b
VZ
5756 event.SetPosition(pos);
5757 event.SetOrientation(orientation);
687706f5 5758 event.SetEventObject(this);
cc2b7472 5759
42e69d6b
VZ
5760 switch ( wParam )
5761 {
5762 case SB_TOP:
687706f5 5763 event.SetEventType(wxEVT_SCROLLWIN_TOP);
42e69d6b 5764 break;
cc2b7472 5765
42e69d6b 5766 case SB_BOTTOM:
687706f5 5767 event.SetEventType(wxEVT_SCROLLWIN_BOTTOM);
42e69d6b 5768 break;
cc2b7472 5769
42e69d6b 5770 case SB_LINEUP:
687706f5 5771 event.SetEventType(wxEVT_SCROLLWIN_LINEUP);
42e69d6b 5772 break;
2bda0e17 5773
42e69d6b 5774 case SB_LINEDOWN:
687706f5 5775 event.SetEventType(wxEVT_SCROLLWIN_LINEDOWN);
42e69d6b 5776 break;
a02eb1d2 5777
42e69d6b 5778 case SB_PAGEUP:
687706f5 5779 event.SetEventType(wxEVT_SCROLLWIN_PAGEUP);
42e69d6b 5780 break;
2bda0e17 5781
42e69d6b 5782 case SB_PAGEDOWN:
687706f5 5783 event.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN);
42e69d6b 5784 break;
2bda0e17 5785
42e69d6b 5786 case SB_THUMBPOSITION:
feda3011 5787 case SB_THUMBTRACK:
f6bcfd97
BP
5788 // under Win32, the scrollbar range and position are 32 bit integers,
5789 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
5790 // explicitly query the scrollbar for the correct position (this must
5791 // be done only for these two SB_ events as they are the only one
5792 // carrying the scrollbar position)
5793 {
0cf5de11 5794 WinStruct<SCROLLINFO> scrollInfo;
f6bcfd97
BP
5795 scrollInfo.fMask = SIF_TRACKPOS;
5796
5797 if ( !::GetScrollInfo(GetHwnd(),
1ddb6d28 5798 WXOrientToSB(orientation),
f6bcfd97
BP
5799 &scrollInfo) )
5800 {
3103e8a9 5801 // Not necessarily an error, if there are no scrollbars yet.
f676b387 5802 // wxLogLastError(_T("GetScrollInfo"));
f6bcfd97
BP
5803 }
5804
5805 event.SetPosition(scrollInfo.nTrackPos);
5806 }
f6bcfd97 5807
687706f5 5808 event.SetEventType( wParam == SB_THUMBPOSITION
f6bcfd97 5809 ? wxEVT_SCROLLWIN_THUMBRELEASE
687706f5 5810 : wxEVT_SCROLLWIN_THUMBTRACK );
42e69d6b 5811 break;
c085e333 5812
42e69d6b 5813 default:
08158721 5814 return false;
564b2609 5815 }
2bda0e17 5816
937013e0 5817 return HandleWindowEvent(event);
2bda0e17
KB
5818}
5819
5acec112
VZ
5820// ----------------------------------------------------------------------------
5821// custom message handlers
5822// ----------------------------------------------------------------------------
5823
5824/* static */ bool
5825wxWindowMSW::MSWRegisterMessageHandler(int msg, MSWMessageHandler handler)
5826{
5827 wxCHECK_MSG( gs_messageHandlers.find(msg) == gs_messageHandlers.end(),
5828 false, _T("registering handler for the same message twice") );
5829
5830 gs_messageHandlers[msg] = handler;
5831 return true;
5832}
5833
5834/* static */ void
5835wxWindowMSW::MSWUnregisterMessageHandler(int msg, MSWMessageHandler handler)
5836{
5837 const MSWMessageHandlers::iterator i = gs_messageHandlers.find(msg);
5838 wxCHECK_RET( i != gs_messageHandlers.end() && i->second == handler,
5839 _T("unregistering non-registered handler?") );
5840
5841 gs_messageHandlers.erase(i);
5842}
5843
42e69d6b
VZ
5844// ===========================================================================
5845// global functions
5846// ===========================================================================
5847
7a5e53ab 5848void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont& the_font)
2bda0e17 5849{
42e69d6b
VZ
5850 TEXTMETRIC tm;
5851 HDC dc = ::GetDC((HWND) wnd);
42e69d6b 5852 HFONT was = 0;
35bbb0c6 5853
7a5e53ab
VS
5854 // the_font.UseResource();
5855 // the_font.RealizeResource();
c57c2993 5856 HFONT fnt = (HFONT)the_font.GetResourceHandle(); // const_cast
7a5e53ab
VS
5857 if ( fnt )
5858 was = (HFONT) SelectObject(dc,fnt);
35bbb0c6 5859
42e69d6b 5860 GetTextMetrics(dc, &tm);
7a5e53ab 5861 if ( fnt && was )
2d0a075d 5862 {
42e69d6b 5863 SelectObject(dc,was);
2d0a075d 5864 }
42e69d6b 5865 ReleaseDC((HWND)wnd, dc);
0655ad29
VZ
5866
5867 if ( x )
5868 *x = tm.tmAveCharWidth;
5869 if ( y )
5870 *y = tm.tmHeight + tm.tmExternalLeading;
2bda0e17 5871
7a5e53ab 5872 // the_font.ReleaseResource();
42e69d6b 5873}
c085e333 5874
5004c3ad
JG
5875// use the "extended" bit (24) of lParam to distinguish extended keys
5876// from normal keys as the same key is sent
ed5bc8f1
VZ
5877static inline
5878int ChooseNormalOrExtended(int lParam, int keyNormal, int keyExtended)
5004c3ad 5879{
ed5bc8f1
VZ
5880 // except that if lParam is 0, it means we don't have real lParam from
5881 // WM_KEYDOWN but are just translating just a VK constant (e.g. done from
5882 // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a
5883 // non-numpad (hence extended) key as this is a more common case
5884 return !lParam || (lParam & (1 << 24)) ? keyExtended : keyNormal;
5004c3ad
JG
5885}
5886
d5c21b02
VZ
5887// this array contains the Windows virtual key codes which map one to one to
5888// WXK_xxx constants and is used in wxCharCodeMSWToWX/WXToMSW() below
5889//
5890// note that keys having a normal and numpad version (e.g. WXK_HOME and
5891// WXK_NUMPAD_HOME) are not included in this table as the mapping is not 1-to-1
5892static const struct wxKeyMapping
5893{
5894 int vk;
5895 wxKeyCode wxk;
5896} gs_specialKeys[] =
5897{
5898 { VK_CANCEL, WXK_CANCEL },
5899 { VK_BACK, WXK_BACK },
5900 { VK_TAB, WXK_TAB },
5901 { VK_CLEAR, WXK_CLEAR },
5902 { VK_SHIFT, WXK_SHIFT },
5903 { VK_CONTROL, WXK_CONTROL },
5904 { VK_MENU , WXK_ALT },
5905 { VK_PAUSE, WXK_PAUSE },
5906 { VK_CAPITAL, WXK_CAPITAL },
5907 { VK_SPACE, WXK_SPACE },
5908 { VK_ESCAPE, WXK_ESCAPE },
5909 { VK_SELECT, WXK_SELECT },
5910 { VK_PRINT, WXK_PRINT },
5911 { VK_EXECUTE, WXK_EXECUTE },
e59c2b2d
VZ
5912 { VK_SNAPSHOT, WXK_SNAPSHOT },
5913 { VK_HELP, WXK_HELP },
d5c21b02
VZ
5914
5915 { VK_NUMPAD0, WXK_NUMPAD0 },
5916 { VK_NUMPAD1, WXK_NUMPAD1 },
5917 { VK_NUMPAD2, WXK_NUMPAD2 },
5918 { VK_NUMPAD3, WXK_NUMPAD3 },
5919 { VK_NUMPAD4, WXK_NUMPAD4 },
5920 { VK_NUMPAD5, WXK_NUMPAD5 },
5921 { VK_NUMPAD6, WXK_NUMPAD6 },
5922 { VK_NUMPAD7, WXK_NUMPAD7 },
5923 { VK_NUMPAD8, WXK_NUMPAD8 },
5924 { VK_NUMPAD9, WXK_NUMPAD9 },
5925 { VK_MULTIPLY, WXK_NUMPAD_MULTIPLY },
5926 { VK_ADD, WXK_NUMPAD_ADD },
5927 { VK_SUBTRACT, WXK_NUMPAD_SUBTRACT },
5928 { VK_DECIMAL, WXK_NUMPAD_DECIMAL },
5929 { VK_DIVIDE, WXK_NUMPAD_DIVIDE },
5930
5931 { VK_F1, WXK_F1 },
5932 { VK_F2, WXK_F2 },
5933 { VK_F3, WXK_F3 },
5934 { VK_F4, WXK_F4 },
5935 { VK_F5, WXK_F5 },
5936 { VK_F6, WXK_F6 },
5937 { VK_F7, WXK_F7 },
5938 { VK_F8, WXK_F8 },
5939 { VK_F9, WXK_F9 },
5940 { VK_F10, WXK_F10 },
5941 { VK_F11, WXK_F11 },
5942 { VK_F12, WXK_F12 },
5943 { VK_F13, WXK_F13 },
5944 { VK_F14, WXK_F14 },
5945 { VK_F15, WXK_F15 },
5946 { VK_F16, WXK_F16 },
5947 { VK_F17, WXK_F17 },
5948 { VK_F18, WXK_F18 },
5949 { VK_F19, WXK_F19 },
5950 { VK_F20, WXK_F20 },
5951 { VK_F21, WXK_F21 },
5952 { VK_F22, WXK_F22 },
5953 { VK_F23, WXK_F23 },
5954 { VK_F24, WXK_F24 },
5955
5956 { VK_NUMLOCK, WXK_NUMLOCK },
5957 { VK_SCROLL, WXK_SCROLL },
5958
5959#ifdef VK_APPS
5960 { VK_LWIN, WXK_WINDOWS_LEFT },
5961 { VK_RWIN, WXK_WINDOWS_RIGHT },
5962 { VK_APPS, WXK_WINDOWS_MENU },
5963#endif // VK_APPS defined
5964};
5965
42e69d6b
VZ
5966// Returns 0 if was a normal ASCII value, not a special key. This indicates that
5967// the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
d5c21b02 5968int wxCharCodeMSWToWX(int vk, WXLPARAM lParam)
42e69d6b 5969{
d5c21b02
VZ
5970 // check the table first
5971 for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ )
5972 {
5973 if ( gs_specialKeys[n].vk == vk )
5974 return gs_specialKeys[n].wxk;
5975 }
9c7df356 5976
d5c21b02
VZ
5977 // keys requiring special handling
5978 int wxk;
5979 switch ( vk )
5980 {
e77c5d96
VZ
5981 // the mapping for these keys may be incorrect on non-US keyboards so
5982 // maybe we shouldn't map them to ASCII values at all
d5c21b02
VZ
5983 case VK_OEM_1: wxk = ';'; break;
5984 case VK_OEM_PLUS: wxk = '+'; break;
5985 case VK_OEM_COMMA: wxk = ','; break;
5986 case VK_OEM_MINUS: wxk = '-'; break;
5987 case VK_OEM_PERIOD: wxk = '.'; break;
5988 case VK_OEM_2: wxk = '/'; break;
5989 case VK_OEM_3: wxk = '~'; break;
5990 case VK_OEM_4: wxk = '['; break;
5991 case VK_OEM_5: wxk = '\\'; break;
5992 case VK_OEM_6: wxk = ']'; break;
5993 case VK_OEM_7: wxk = '\''; break;
702c4208 5994
5004c3ad 5995 // handle extended keys
413553cc 5996 case VK_PRIOR:
d5c21b02 5997 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEUP, WXK_PAGEUP);
413553cc 5998 break;
d5c21b02 5999
413553cc 6000 case VK_NEXT:
d5c21b02 6001 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEDOWN, WXK_PAGEDOWN);
413553cc 6002 break;
d5c21b02 6003
413553cc 6004 case VK_END:
d5c21b02 6005 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_END, WXK_END);
413553cc 6006 break;
d5c21b02 6007
413553cc 6008 case VK_HOME:
d5c21b02 6009 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_HOME, WXK_HOME);
413553cc 6010 break;
d5c21b02 6011
413553cc 6012 case VK_LEFT:
d5c21b02 6013 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_LEFT, WXK_LEFT);
413553cc 6014 break;
d5c21b02 6015
413553cc 6016 case VK_UP:
d5c21b02 6017 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_UP, WXK_UP);
413553cc 6018 break;
d5c21b02 6019
413553cc 6020 case VK_RIGHT:
d5c21b02 6021 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_RIGHT, WXK_RIGHT);
413553cc 6022 break;
d5c21b02 6023
413553cc 6024 case VK_DOWN:
d5c21b02 6025 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DOWN, WXK_DOWN);
413553cc 6026 break;
d5c21b02 6027
413553cc 6028 case VK_INSERT:
d5c21b02 6029 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_INSERT, WXK_INSERT);
413553cc 6030 break;
d5c21b02 6031
413553cc 6032 case VK_DELETE:
d5c21b02 6033 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE);
413553cc 6034 break;
d5c21b02 6035
ff792344 6036 case VK_RETURN:
ed5bc8f1
VZ
6037 // don't use ChooseNormalOrExtended() here as the keys are reversed
6038 // here: numpad enter is the extended one
d5c21b02 6039 wxk = lParam && (lParam & (1 << 24)) ? WXK_NUMPAD_ENTER : WXK_RETURN;
ff792344
VZ
6040 break;
6041
f6bcfd97 6042 default:
d5c21b02
VZ
6043 wxk = 0;
6044 }
6045
6046 return wxk;
6047}
6048
6049WXWORD wxCharCodeWXToMSW(int wxk, bool *isVirtual)
6050{
6051 if ( isVirtual )
6052 *isVirtual = true;
6053
6054 // check the table first
6055 for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ )
6056 {
6057 if ( gs_specialKeys[n].wxk == wxk )
6058 return gs_specialKeys[n].vk;
6059 }
6060
6061 // and then check for special keys not included in the table
6062 WXWORD vk;
6063 switch ( wxk )
6064 {
71403278
VZ
6065 case WXK_PAGEUP:
6066 case WXK_NUMPAD_PAGEUP:
6067 vk = VK_PRIOR;
6068 break;
6069
6070 case WXK_PAGEDOWN:
6071 case WXK_NUMPAD_PAGEDOWN:
6072 vk = VK_NEXT;
6073 break;
6074
6075 case WXK_END:
6076 case WXK_NUMPAD_END:
6077 vk = VK_END;
6078 break;
6079
6080 case WXK_HOME:
6081 case WXK_NUMPAD_HOME:
6082 vk = VK_HOME;
6083 break;
6084
6085 case WXK_LEFT:
6086 case WXK_NUMPAD_LEFT:
6087 vk = VK_LEFT;
6088 break;
6089
6090 case WXK_UP:
6091 case WXK_NUMPAD_UP:
6092 vk = VK_UP;
6093 break;
6094
6095 case WXK_RIGHT:
6096 case WXK_NUMPAD_RIGHT:
6097 vk = VK_RIGHT;
6098 break;
6099
6100 case WXK_DOWN:
6101 case WXK_NUMPAD_DOWN:
6102 vk = VK_DOWN;
6103 break;
6104
6105 case WXK_INSERT:
6106 case WXK_NUMPAD_INSERT:
6107 vk = VK_INSERT;
6108 break;
6109
6110 case WXK_DELETE:
6111 case WXK_NUMPAD_DELETE:
6112 vk = VK_DELETE;
6113 break;
d5c21b02
VZ
6114
6115 default:
d9fda37b
VZ
6116 // no VkKeyScan() under CE unfortunately, we need to test how does
6117 // it handle OEM keys
6118#ifndef __WXWINCE__
ad294cb8
VZ
6119 // check to see if its one of the OEM key codes.
6120 BYTE vks = LOBYTE(VkKeyScan(wxk));
6e3e6c8e 6121 if ( vks != 0xff )
ad294cb8
VZ
6122 {
6123 vk = vks;
6124 }
6125 else
d9fda37b 6126#endif // !__WXWINCE__
ad294cb8
VZ
6127 {
6128 if ( isVirtual )
6129 *isVirtual = false;
6130 vk = (WXWORD)wxk;
6131 }
2bda0e17 6132 }
d5c21b02
VZ
6133
6134 return vk;
6135}
6136
6137// small helper for wxGetKeyState() and wxGetMouseState()
6138static inline bool wxIsKeyDown(WXWORD vk)
6139{
d9fda37b
VZ
6140 // SM_SWAPBUTTON is not available under CE, so don't swap buttons there
6141#ifdef SM_SWAPBUTTON
6142 if ( vk == VK_LBUTTON || vk == VK_RBUTTON )
b8f434e7 6143 {
d9fda37b
VZ
6144 if ( ::GetSystemMetrics(SM_SWAPBUTTON) )
6145 {
6146 if ( vk == VK_LBUTTON )
6147 vk = VK_RBUTTON;
6148 else // vk == VK_RBUTTON
6149 vk = VK_LBUTTON;
6150 }
b8f434e7 6151 }
d9fda37b
VZ
6152#endif // SM_SWAPBUTTON
6153
d5c21b02
VZ
6154 // the low order bit indicates whether the key was pressed since the last
6155 // call and the high order one indicates whether it is down right now and
6156 // we only want that one
b8f434e7 6157 return (GetAsyncKeyState(vk) & (1<<15)) != 0;
2bda0e17
KB
6158}
6159
1751226c 6160bool wxGetKeyState(wxKeyCode key)
6ed892f3 6161{
d5c21b02
VZ
6162 // although this does work under Windows, it is not supported under other
6163 // platforms so don't allow it, you must use wxGetMouseState() instead
6164 wxASSERT_MSG( key != VK_LBUTTON &&
6165 key != VK_RBUTTON &&
6166 key != VK_MBUTTON,
6167 wxT("can't use wxGetKeyState() for mouse buttons") );
6ed892f3 6168
d5c21b02 6169 const WXWORD vk = wxCharCodeWXToMSW(key);
44353523 6170
d5c21b02
VZ
6171 // if the requested key is a LED key, return true if the led is pressed
6172 if ( key == WXK_NUMLOCK || key == WXK_CAPITAL || key == WXK_SCROLL )
fdec2c05 6173 {
d5c21b02
VZ
6174 // low order bit means LED is highlighted and high order one means the
6175 // key is down; for compatibility with the other ports return true if
6176 // either one is set
b8f434e7 6177 return GetKeyState(vk) != 0;
35bbb0c6 6178
fdec2c05 6179 }
d5c21b02 6180 else // normal key
84c51ddf 6181 {
d5c21b02 6182 return wxIsKeyDown(vk);
84c51ddf 6183 }
6ed892f3
RN
6184}
6185
7dd40b6f
RD
6186
6187wxMouseState wxGetMouseState()
6188{
6189 wxMouseState ms;
6190 POINT pt;
6191 GetCursorPos( &pt );
6192
6193 ms.SetX(pt.x);
6194 ms.SetY(pt.y);
d5c21b02
VZ
6195 ms.SetLeftDown(wxIsKeyDown(VK_LBUTTON));
6196 ms.SetMiddleDown(wxIsKeyDown(VK_MBUTTON));
6197 ms.SetRightDown(wxIsKeyDown(VK_RBUTTON));
2f68482e 6198#ifdef wxHAS_XBUTTON
01101e2d
VZ
6199 ms.SetAux1Down(wxIsKeyDown(VK_XBUTTON1));
6200 ms.SetAux2Down(wxIsKeyDown(VK_XBUTTON2));
2f68482e 6201#endif // wxHAS_XBUTTON
dd28827a 6202
6719c06a
VZ
6203 ms.SetControlDown(wxIsCtrlDown ());
6204 ms.SetShiftDown (wxIsShiftDown());
6205 ms.SetAltDown (wxIsAltDown ());
7dd40b6f 6206// ms.SetMetaDown();
dd28827a 6207
7dd40b6f
RD
6208 return ms;
6209}
6210
6211
42e69d6b 6212wxWindow *wxGetActiveWindow()
2bda0e17 6213{
42e69d6b
VZ
6214 HWND hWnd = GetActiveWindow();
6215 if ( hWnd != 0 )
2d0a075d 6216 {
dca0f651 6217 return wxFindWinFromHandle(hWnd);
2d0a075d 6218 }
42e69d6b 6219 return NULL;
2bda0e17
KB
6220}
6221
8614c467
VZ
6222extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
6223{
6224 HWND hwnd = (HWND)hWnd;
6225
6226 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
6227 // by code in msw/radiobox.cpp), for all the others we just search up the
6228 // window hierarchy
6229 wxWindow *win = (wxWindow *)NULL;
6230 if ( hwnd )
6231 {
dca0f651 6232 win = wxFindWinFromHandle(hwnd);
8614c467
VZ
6233 if ( !win )
6234 {
a2242341 6235#if wxUSE_RADIOBOX
8614c467
VZ
6236 // native radiobuttons return DLGC_RADIOBUTTON here and for any
6237 // wxWindow class which overrides WM_GETDLGCODE processing to
6238 // do it as well, win would be already non NULL
a2242341 6239 if ( ::SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_RADIOBUTTON )
8614c467 6240 {
975b6bcf 6241 win = (wxWindow *)wxGetWindowUserData(hwnd);
8614c467 6242 }
a2242341
VZ
6243 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
6244#endif // wxUSE_RADIOBOX
6245
6246 // spin control text buddy window should be mapped to spin ctrl
6247 // itself so try it too
24ce4c18 6248#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
a2242341
VZ
6249 if ( !win )
6250 {
6251 win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
6252 }
6253#endif // wxUSE_SPINCTRL
8614c467 6254 }
8614c467
VZ
6255 }
6256
6257 while ( hwnd && !win )
6258 {
761989ff
VZ
6259 // this is a really ugly hack needed to avoid mistakenly returning the
6260 // parent frame wxWindow for the find/replace modeless dialog HWND -
6261 // this, in turn, is needed to call IsDialogMessage() from
6262 // wxApp::ProcessMessage() as for this we must return NULL from here
6263 //
6264 // FIXME: this is clearly not the best way to do it but I think we'll
6265 // need to change HWND <-> wxWindow code more heavily than I can
6266 // do it now to fix it
c67d6888 6267#ifndef __WXMICROWIN__
761989ff
VZ
6268 if ( ::GetWindow(hwnd, GW_OWNER) )
6269 {
6270 // it's a dialog box, don't go upwards
6271 break;
6272 }
c67d6888 6273#endif
761989ff 6274
8614c467 6275 hwnd = ::GetParent(hwnd);
dca0f651 6276 win = wxFindWinFromHandle(hwnd);
8614c467
VZ
6277 }
6278
6279 return win;
6280}
6281
7f0586ef 6282#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
04ef50df 6283
42e69d6b
VZ
6284// Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
6285// in active frames and dialogs, regardless of where the focus is.
6286static HHOOK wxTheKeyboardHook = 0;
6287static FARPROC wxTheKeyboardHookProc = 0;
6288int APIENTRY _EXPORT
6289wxKeyboardHook(int nCode, WORD wParam, DWORD lParam);
2bda0e17 6290
42e69d6b 6291void wxSetKeyboardHook(bool doIt)
2bda0e17 6292{
42e69d6b 6293 if ( doIt )
2d0a075d 6294 {
42e69d6b
VZ
6295 wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
6296 wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
c7527e3f 6297
8614c467 6298 GetCurrentThreadId()
42e69d6b 6299 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
8614c467 6300 );
2d0a075d 6301 }
2d0a075d 6302 else
2d0a075d 6303 {
42e69d6b 6304 UnhookWindowsHookEx(wxTheKeyboardHook);
2d0a075d 6305 }
2bda0e17
KB
6306}
6307
42e69d6b
VZ
6308int APIENTRY _EXPORT
6309wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
2bda0e17 6310{
42e69d6b
VZ
6311 DWORD hiWord = HIWORD(lParam);
6312 if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) )
43d811ea 6313 {
ff792344 6314 int id = wxCharCodeMSWToWX(wParam, lParam);
32de7d24 6315 if ( id != 0 )
43d811ea 6316 {
42e69d6b
VZ
6317 wxKeyEvent event(wxEVT_CHAR_HOOK);
6318 if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN )
08158721 6319 event.m_altDown = true;
c085e333 6320
687706f5 6321 event.SetEventObject(NULL);
42e69d6b 6322 event.m_keyCode = id;
3f7bc32b
VZ
6323 event.m_shiftDown = wxIsShiftDown();
6324 event.m_controlDown = wxIsCtrlDown();
f0b1ccde 6325#ifndef __WXWINCE__
1bf77ee5 6326 event.SetTimestamp(::GetMessageTime());
f0b1ccde 6327#endif
42e69d6b 6328 wxWindow *win = wxGetActiveWindow();
32de7d24 6329 wxEvtHandler *handler;
42e69d6b
VZ
6330 if ( win )
6331 {
32de7d24
VZ
6332 handler = win->GetEventHandler();
6333 event.SetId(win->GetId());
42e69d6b
VZ
6334 }
6335 else
6336 {
32de7d24 6337 handler = wxTheApp;
abb74e0f 6338 event.SetId(wxID_ANY);
32de7d24
VZ
6339 }
6340
6341 if ( handler && handler->ProcessEvent(event) )
6342 {
6343 // processed
6344 return 1;
42e69d6b 6345 }
43d811ea
JS
6346 }
6347 }
32de7d24 6348
42e69d6b 6349 return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam);
4fabb575 6350}
cd4453e5
VZ
6351
6352#endif // !__WXMICROWIN__
4fabb575 6353
b2aef89b 6354#ifdef __WXDEBUG__
4a712ba3 6355const wxChar *wxGetMessageName(int message)
47cbd6da 6356{
42e69d6b
VZ
6357 switch ( message )
6358 {
4a712ba3
VZ
6359 case 0x0000: return wxT("WM_NULL");
6360 case 0x0001: return wxT("WM_CREATE");
6361 case 0x0002: return wxT("WM_DESTROY");
6362 case 0x0003: return wxT("WM_MOVE");
6363 case 0x0005: return wxT("WM_SIZE");
6364 case 0x0006: return wxT("WM_ACTIVATE");
6365 case 0x0007: return wxT("WM_SETFOCUS");
6366 case 0x0008: return wxT("WM_KILLFOCUS");
6367 case 0x000A: return wxT("WM_ENABLE");
6368 case 0x000B: return wxT("WM_SETREDRAW");
6369 case 0x000C: return wxT("WM_SETTEXT");
6370 case 0x000D: return wxT("WM_GETTEXT");
6371 case 0x000E: return wxT("WM_GETTEXTLENGTH");
6372 case 0x000F: return wxT("WM_PAINT");
6373 case 0x0010: return wxT("WM_CLOSE");
6374 case 0x0011: return wxT("WM_QUERYENDSESSION");
6375 case 0x0012: return wxT("WM_QUIT");
6376 case 0x0013: return wxT("WM_QUERYOPEN");
6377 case 0x0014: return wxT("WM_ERASEBKGND");
6378 case 0x0015: return wxT("WM_SYSCOLORCHANGE");
6379 case 0x0016: return wxT("WM_ENDSESSION");
6380 case 0x0017: return wxT("WM_SYSTEMERROR");
6381 case 0x0018: return wxT("WM_SHOWWINDOW");
6382 case 0x0019: return wxT("WM_CTLCOLOR");
6383 case 0x001A: return wxT("WM_WININICHANGE");
6384 case 0x001B: return wxT("WM_DEVMODECHANGE");
6385 case 0x001C: return wxT("WM_ACTIVATEAPP");
6386 case 0x001D: return wxT("WM_FONTCHANGE");
6387 case 0x001E: return wxT("WM_TIMECHANGE");
6388 case 0x001F: return wxT("WM_CANCELMODE");
6389 case 0x0020: return wxT("WM_SETCURSOR");
6390 case 0x0021: return wxT("WM_MOUSEACTIVATE");
6391 case 0x0022: return wxT("WM_CHILDACTIVATE");
6392 case 0x0023: return wxT("WM_QUEUESYNC");
6393 case 0x0024: return wxT("WM_GETMINMAXINFO");
6394 case 0x0026: return wxT("WM_PAINTICON");
6395 case 0x0027: return wxT("WM_ICONERASEBKGND");
6396 case 0x0028: return wxT("WM_NEXTDLGCTL");
6397 case 0x002A: return wxT("WM_SPOOLERSTATUS");
6398 case 0x002B: return wxT("WM_DRAWITEM");
6399 case 0x002C: return wxT("WM_MEASUREITEM");
6400 case 0x002D: return wxT("WM_DELETEITEM");
6401 case 0x002E: return wxT("WM_VKEYTOITEM");
6402 case 0x002F: return wxT("WM_CHARTOITEM");
6403 case 0x0030: return wxT("WM_SETFONT");
6404 case 0x0031: return wxT("WM_GETFONT");
6405 case 0x0037: return wxT("WM_QUERYDRAGICON");
6406 case 0x0039: return wxT("WM_COMPAREITEM");
6407 case 0x0041: return wxT("WM_COMPACTING");
6408 case 0x0044: return wxT("WM_COMMNOTIFY");
6409 case 0x0046: return wxT("WM_WINDOWPOSCHANGING");
6410 case 0x0047: return wxT("WM_WINDOWPOSCHANGED");
6411 case 0x0048: return wxT("WM_POWER");
6412
6413 case 0x004A: return wxT("WM_COPYDATA");
6414 case 0x004B: return wxT("WM_CANCELJOURNAL");
6415 case 0x004E: return wxT("WM_NOTIFY");
6416 case 0x0050: return wxT("WM_INPUTLANGCHANGEREQUEST");
6417 case 0x0051: return wxT("WM_INPUTLANGCHANGE");
6418 case 0x0052: return wxT("WM_TCARD");
6419 case 0x0053: return wxT("WM_HELP");
6420 case 0x0054: return wxT("WM_USERCHANGED");
6421 case 0x0055: return wxT("WM_NOTIFYFORMAT");
6422 case 0x007B: return wxT("WM_CONTEXTMENU");
6423 case 0x007C: return wxT("WM_STYLECHANGING");
6424 case 0x007D: return wxT("WM_STYLECHANGED");
6425 case 0x007E: return wxT("WM_DISPLAYCHANGE");
6426 case 0x007F: return wxT("WM_GETICON");
6427 case 0x0080: return wxT("WM_SETICON");
6428
6429 case 0x0081: return wxT("WM_NCCREATE");
6430 case 0x0082: return wxT("WM_NCDESTROY");
6431 case 0x0083: return wxT("WM_NCCALCSIZE");
6432 case 0x0084: return wxT("WM_NCHITTEST");
6433 case 0x0085: return wxT("WM_NCPAINT");
6434 case 0x0086: return wxT("WM_NCACTIVATE");
6435 case 0x0087: return wxT("WM_GETDLGCODE");
6436 case 0x00A0: return wxT("WM_NCMOUSEMOVE");
6437 case 0x00A1: return wxT("WM_NCLBUTTONDOWN");
6438 case 0x00A2: return wxT("WM_NCLBUTTONUP");
6439 case 0x00A3: return wxT("WM_NCLBUTTONDBLCLK");
6440 case 0x00A4: return wxT("WM_NCRBUTTONDOWN");
6441 case 0x00A5: return wxT("WM_NCRBUTTONUP");
6442 case 0x00A6: return wxT("WM_NCRBUTTONDBLCLK");
6443 case 0x00A7: return wxT("WM_NCMBUTTONDOWN");
6444 case 0x00A8: return wxT("WM_NCMBUTTONUP");
6445 case 0x00A9: return wxT("WM_NCMBUTTONDBLCLK");
609da8bb
VZ
6446
6447 case 0x00B0: return wxT("EM_GETSEL");
6448 case 0x00B1: return wxT("EM_SETSEL");
6449 case 0x00B2: return wxT("EM_GETRECT");
6450 case 0x00B3: return wxT("EM_SETRECT");
6451 case 0x00B4: return wxT("EM_SETRECTNP");
6452 case 0x00B5: return wxT("EM_SCROLL");
6453 case 0x00B6: return wxT("EM_LINESCROLL");
6454 case 0x00B7: return wxT("EM_SCROLLCARET");
6455 case 0x00B8: return wxT("EM_GETMODIFY");
6456 case 0x00B9: return wxT("EM_SETMODIFY");
6457 case 0x00BA: return wxT("EM_GETLINECOUNT");
6458 case 0x00BB: return wxT("EM_LINEINDEX");
6459 case 0x00BC: return wxT("EM_SETHANDLE");
6460 case 0x00BD: return wxT("EM_GETHANDLE");
6461 case 0x00BE: return wxT("EM_GETTHUMB");
6462 case 0x00C1: return wxT("EM_LINELENGTH");
6463 case 0x00C2: return wxT("EM_REPLACESEL");
6464 case 0x00C4: return wxT("EM_GETLINE");
6465 case 0x00C5: return wxT("EM_LIMITTEXT/EM_SETLIMITTEXT"); /* ;win40 Name change */
6466 case 0x00C6: return wxT("EM_CANUNDO");
6467 case 0x00C7: return wxT("EM_UNDO");
6468 case 0x00C8: return wxT("EM_FMTLINES");
6469 case 0x00C9: return wxT("EM_LINEFROMCHAR");
6470 case 0x00CB: return wxT("EM_SETTABSTOPS");
6471 case 0x00CC: return wxT("EM_SETPASSWORDCHAR");
6472 case 0x00CD: return wxT("EM_EMPTYUNDOBUFFER");
6473 case 0x00CE: return wxT("EM_GETFIRSTVISIBLELINE");
6474 case 0x00CF: return wxT("EM_SETREADONLY");
6475 case 0x00D0: return wxT("EM_SETWORDBREAKPROC");
6476 case 0x00D1: return wxT("EM_GETWORDBREAKPROC");
6477 case 0x00D2: return wxT("EM_GETPASSWORDCHAR");
6478 case 0x00D3: return wxT("EM_SETMARGINS");
6479 case 0x00D4: return wxT("EM_GETMARGINS");
6480 case 0x00D5: return wxT("EM_GETLIMITTEXT");
6481 case 0x00D6: return wxT("EM_POSFROMCHAR");
6482 case 0x00D7: return wxT("EM_CHARFROMPOS");
6483 case 0x00D8: return wxT("EM_SETIMESTATUS");
6484 case 0x00D9: return wxT("EM_GETIMESTATUS");
6485
4a712ba3
VZ
6486 case 0x0100: return wxT("WM_KEYDOWN");
6487 case 0x0101: return wxT("WM_KEYUP");
6488 case 0x0102: return wxT("WM_CHAR");
6489 case 0x0103: return wxT("WM_DEADCHAR");
6490 case 0x0104: return wxT("WM_SYSKEYDOWN");
6491 case 0x0105: return wxT("WM_SYSKEYUP");
6492 case 0x0106: return wxT("WM_SYSCHAR");
6493 case 0x0107: return wxT("WM_SYSDEADCHAR");
6494 case 0x0108: return wxT("WM_KEYLAST");
6495
6496 case 0x010D: return wxT("WM_IME_STARTCOMPOSITION");
6497 case 0x010E: return wxT("WM_IME_ENDCOMPOSITION");
6498 case 0x010F: return wxT("WM_IME_COMPOSITION");
6499
6500 case 0x0110: return wxT("WM_INITDIALOG");
6501 case 0x0111: return wxT("WM_COMMAND");
6502 case 0x0112: return wxT("WM_SYSCOMMAND");
6503 case 0x0113: return wxT("WM_TIMER");
6504 case 0x0114: return wxT("WM_HSCROLL");
6505 case 0x0115: return wxT("WM_VSCROLL");
6506 case 0x0116: return wxT("WM_INITMENU");
6507 case 0x0117: return wxT("WM_INITMENUPOPUP");
6508 case 0x011F: return wxT("WM_MENUSELECT");
6509 case 0x0120: return wxT("WM_MENUCHAR");
6510 case 0x0121: return wxT("WM_ENTERIDLE");
609da8bb
VZ
6511
6512 case 0x0132: return wxT("WM_CTLCOLORMSGBOX");
6513 case 0x0133: return wxT("WM_CTLCOLOREDIT");
6514 case 0x0134: return wxT("WM_CTLCOLORLISTBOX");
6515 case 0x0135: return wxT("WM_CTLCOLORBTN");
6516 case 0x0136: return wxT("WM_CTLCOLORDLG");
6517 case 0x0137: return wxT("WM_CTLCOLORSCROLLBAR");
6518 case 0x0138: return wxT("WM_CTLCOLORSTATIC");
6519 case 0x01E1: return wxT("MN_GETHMENU");
6520
4a712ba3
VZ
6521 case 0x0200: return wxT("WM_MOUSEMOVE");
6522 case 0x0201: return wxT("WM_LBUTTONDOWN");
6523 case 0x0202: return wxT("WM_LBUTTONUP");
6524 case 0x0203: return wxT("WM_LBUTTONDBLCLK");
6525 case 0x0204: return wxT("WM_RBUTTONDOWN");
6526 case 0x0205: return wxT("WM_RBUTTONUP");
6527 case 0x0206: return wxT("WM_RBUTTONDBLCLK");
6528 case 0x0207: return wxT("WM_MBUTTONDOWN");
6529 case 0x0208: return wxT("WM_MBUTTONUP");
6530 case 0x0209: return wxT("WM_MBUTTONDBLCLK");
6531 case 0x020A: return wxT("WM_MOUSEWHEEL");
01101e2d
VZ
6532 case 0x020B: return wxT("WM_XBUTTONDOWN");
6533 case 0x020C: return wxT("WM_XBUTTONUP");
6534 case 0x020D: return wxT("WM_XBUTTONDBLCLK");
4a712ba3
VZ
6535 case 0x0210: return wxT("WM_PARENTNOTIFY");
6536 case 0x0211: return wxT("WM_ENTERMENULOOP");
6537 case 0x0212: return wxT("WM_EXITMENULOOP");
6538
6539 case 0x0213: return wxT("WM_NEXTMENU");
6540 case 0x0214: return wxT("WM_SIZING");
6541 case 0x0215: return wxT("WM_CAPTURECHANGED");
6542 case 0x0216: return wxT("WM_MOVING");
6543 case 0x0218: return wxT("WM_POWERBROADCAST");
6544 case 0x0219: return wxT("WM_DEVICECHANGE");
6545
6546 case 0x0220: return wxT("WM_MDICREATE");
6547 case 0x0221: return wxT("WM_MDIDESTROY");
6548 case 0x0222: return wxT("WM_MDIACTIVATE");
6549 case 0x0223: return wxT("WM_MDIRESTORE");
6550 case 0x0224: return wxT("WM_MDINEXT");
6551 case 0x0225: return wxT("WM_MDIMAXIMIZE");
6552 case 0x0226: return wxT("WM_MDITILE");
6553 case 0x0227: return wxT("WM_MDICASCADE");
6554 case 0x0228: return wxT("WM_MDIICONARRANGE");
6555 case 0x0229: return wxT("WM_MDIGETACTIVE");
6556 case 0x0230: return wxT("WM_MDISETMENU");
6557 case 0x0233: return wxT("WM_DROPFILES");
6558
6559 case 0x0281: return wxT("WM_IME_SETCONTEXT");
6560 case 0x0282: return wxT("WM_IME_NOTIFY");
6561 case 0x0283: return wxT("WM_IME_CONTROL");
6562 case 0x0284: return wxT("WM_IME_COMPOSITIONFULL");
6563 case 0x0285: return wxT("WM_IME_SELECT");
6564 case 0x0286: return wxT("WM_IME_CHAR");
6565 case 0x0290: return wxT("WM_IME_KEYDOWN");
6566 case 0x0291: return wxT("WM_IME_KEYUP");
6567
609da8bb
VZ
6568 case 0x02A0: return wxT("WM_NCMOUSEHOVER");
6569 case 0x02A1: return wxT("WM_MOUSEHOVER");
6570 case 0x02A2: return wxT("WM_NCMOUSELEAVE");
6571 case 0x02A3: return wxT("WM_MOUSELEAVE");
6572
4a712ba3
VZ
6573 case 0x0300: return wxT("WM_CUT");
6574 case 0x0301: return wxT("WM_COPY");
6575 case 0x0302: return wxT("WM_PASTE");
6576 case 0x0303: return wxT("WM_CLEAR");
6577 case 0x0304: return wxT("WM_UNDO");
6578 case 0x0305: return wxT("WM_RENDERFORMAT");
6579 case 0x0306: return wxT("WM_RENDERALLFORMATS");
6580 case 0x0307: return wxT("WM_DESTROYCLIPBOARD");
6581 case 0x0308: return wxT("WM_DRAWCLIPBOARD");
6582 case 0x0309: return wxT("WM_PAINTCLIPBOARD");
6583 case 0x030A: return wxT("WM_VSCROLLCLIPBOARD");
6584 case 0x030B: return wxT("WM_SIZECLIPBOARD");
6585 case 0x030C: return wxT("WM_ASKCBFORMATNAME");
6586 case 0x030D: return wxT("WM_CHANGECBCHAIN");
6587 case 0x030E: return wxT("WM_HSCROLLCLIPBOARD");
6588 case 0x030F: return wxT("WM_QUERYNEWPALETTE");
6589 case 0x0310: return wxT("WM_PALETTEISCHANGING");
6590 case 0x0311: return wxT("WM_PALETTECHANGED");
4a712ba3 6591 case 0x0312: return wxT("WM_HOTKEY");
609da8bb
VZ
6592
6593 case 0x0317: return wxT("WM_PRINT");
6594 case 0x0318: return wxT("WM_PRINTCLIENT");
c085e333 6595
2d0a075d
JS
6596 // common controls messages - although they're not strictly speaking
6597 // standard, it's nice to decode them nevertheless
a02eb1d2 6598
2d0a075d 6599 // listview
4a712ba3
VZ
6600 case 0x1000 + 0: return wxT("LVM_GETBKCOLOR");
6601 case 0x1000 + 1: return wxT("LVM_SETBKCOLOR");
6602 case 0x1000 + 2: return wxT("LVM_GETIMAGELIST");
6603 case 0x1000 + 3: return wxT("LVM_SETIMAGELIST");
6604 case 0x1000 + 4: return wxT("LVM_GETITEMCOUNT");
6605 case 0x1000 + 5: return wxT("LVM_GETITEMA");
6606 case 0x1000 + 75: return wxT("LVM_GETITEMW");
6607 case 0x1000 + 6: return wxT("LVM_SETITEMA");
6608 case 0x1000 + 76: return wxT("LVM_SETITEMW");
6609 case 0x1000 + 7: return wxT("LVM_INSERTITEMA");
6610 case 0x1000 + 77: return wxT("LVM_INSERTITEMW");
6611 case 0x1000 + 8: return wxT("LVM_DELETEITEM");
6612 case 0x1000 + 9: return wxT("LVM_DELETEALLITEMS");
6613 case 0x1000 + 10: return wxT("LVM_GETCALLBACKMASK");
6614 case 0x1000 + 11: return wxT("LVM_SETCALLBACKMASK");
6615 case 0x1000 + 12: return wxT("LVM_GETNEXTITEM");
6616 case 0x1000 + 13: return wxT("LVM_FINDITEMA");
6617 case 0x1000 + 83: return wxT("LVM_FINDITEMW");
6618 case 0x1000 + 14: return wxT("LVM_GETITEMRECT");
6619 case 0x1000 + 15: return wxT("LVM_SETITEMPOSITION");
6620 case 0x1000 + 16: return wxT("LVM_GETITEMPOSITION");
6621 case 0x1000 + 17: return wxT("LVM_GETSTRINGWIDTHA");
6622 case 0x1000 + 87: return wxT("LVM_GETSTRINGWIDTHW");
6623 case 0x1000 + 18: return wxT("LVM_HITTEST");
6624 case 0x1000 + 19: return wxT("LVM_ENSUREVISIBLE");
6625 case 0x1000 + 20: return wxT("LVM_SCROLL");
6626 case 0x1000 + 21: return wxT("LVM_REDRAWITEMS");
6627 case 0x1000 + 22: return wxT("LVM_ARRANGE");
6628 case 0x1000 + 23: return wxT("LVM_EDITLABELA");
6629 case 0x1000 + 118: return wxT("LVM_EDITLABELW");
6630 case 0x1000 + 24: return wxT("LVM_GETEDITCONTROL");
6631 case 0x1000 + 25: return wxT("LVM_GETCOLUMNA");
6632 case 0x1000 + 95: return wxT("LVM_GETCOLUMNW");
6633 case 0x1000 + 26: return wxT("LVM_SETCOLUMNA");
6634 case 0x1000 + 96: return wxT("LVM_SETCOLUMNW");
6635 case 0x1000 + 27: return wxT("LVM_INSERTCOLUMNA");
6636 case 0x1000 + 97: return wxT("LVM_INSERTCOLUMNW");
6637 case 0x1000 + 28: return wxT("LVM_DELETECOLUMN");
6638 case 0x1000 + 29: return wxT("LVM_GETCOLUMNWIDTH");
6639 case 0x1000 + 30: return wxT("LVM_SETCOLUMNWIDTH");
6640 case 0x1000 + 31: return wxT("LVM_GETHEADER");
6641 case 0x1000 + 33: return wxT("LVM_CREATEDRAGIMAGE");
6642 case 0x1000 + 34: return wxT("LVM_GETVIEWRECT");
6643 case 0x1000 + 35: return wxT("LVM_GETTEXTCOLOR");
6644 case 0x1000 + 36: return wxT("LVM_SETTEXTCOLOR");
6645 case 0x1000 + 37: return wxT("LVM_GETTEXTBKCOLOR");
6646 case 0x1000 + 38: return wxT("LVM_SETTEXTBKCOLOR");
6647 case 0x1000 + 39: return wxT("LVM_GETTOPINDEX");
6648 case 0x1000 + 40: return wxT("LVM_GETCOUNTPERPAGE");
6649 case 0x1000 + 41: return wxT("LVM_GETORIGIN");
6650 case 0x1000 + 42: return wxT("LVM_UPDATE");
6651 case 0x1000 + 43: return wxT("LVM_SETITEMSTATE");
6652 case 0x1000 + 44: return wxT("LVM_GETITEMSTATE");
6653 case 0x1000 + 45: return wxT("LVM_GETITEMTEXTA");
6654 case 0x1000 + 115: return wxT("LVM_GETITEMTEXTW");
6655 case 0x1000 + 46: return wxT("LVM_SETITEMTEXTA");
6656 case 0x1000 + 116: return wxT("LVM_SETITEMTEXTW");
6657 case 0x1000 + 47: return wxT("LVM_SETITEMCOUNT");
6658 case 0x1000 + 48: return wxT("LVM_SORTITEMS");
6659 case 0x1000 + 49: return wxT("LVM_SETITEMPOSITION32");
6660 case 0x1000 + 50: return wxT("LVM_GETSELECTEDCOUNT");
6661 case 0x1000 + 51: return wxT("LVM_GETITEMSPACING");
6662 case 0x1000 + 52: return wxT("LVM_GETISEARCHSTRINGA");
6663 case 0x1000 + 117: return wxT("LVM_GETISEARCHSTRINGW");
6664 case 0x1000 + 53: return wxT("LVM_SETICONSPACING");
6665 case 0x1000 + 54: return wxT("LVM_SETEXTENDEDLISTVIEWSTYLE");
6666 case 0x1000 + 55: return wxT("LVM_GETEXTENDEDLISTVIEWSTYLE");
6667 case 0x1000 + 56: return wxT("LVM_GETSUBITEMRECT");
6668 case 0x1000 + 57: return wxT("LVM_SUBITEMHITTEST");
6669 case 0x1000 + 58: return wxT("LVM_SETCOLUMNORDERARRAY");
6670 case 0x1000 + 59: return wxT("LVM_GETCOLUMNORDERARRAY");
6671 case 0x1000 + 60: return wxT("LVM_SETHOTITEM");
6672 case 0x1000 + 61: return wxT("LVM_GETHOTITEM");
6673 case 0x1000 + 62: return wxT("LVM_SETHOTCURSOR");
6674 case 0x1000 + 63: return wxT("LVM_GETHOTCURSOR");
6675 case 0x1000 + 64: return wxT("LVM_APPROXIMATEVIEWRECT");
6676 case 0x1000 + 65: return wxT("LVM_SETWORKAREA");
c085e333 6677
2d0a075d 6678 // tree view
4a712ba3
VZ
6679 case 0x1100 + 0: return wxT("TVM_INSERTITEMA");
6680 case 0x1100 + 50: return wxT("TVM_INSERTITEMW");
6681 case 0x1100 + 1: return wxT("TVM_DELETEITEM");
6682 case 0x1100 + 2: return wxT("TVM_EXPAND");
6683 case 0x1100 + 4: return wxT("TVM_GETITEMRECT");
6684 case 0x1100 + 5: return wxT("TVM_GETCOUNT");
6685 case 0x1100 + 6: return wxT("TVM_GETINDENT");
6686 case 0x1100 + 7: return wxT("TVM_SETINDENT");
6687 case 0x1100 + 8: return wxT("TVM_GETIMAGELIST");
6688 case 0x1100 + 9: return wxT("TVM_SETIMAGELIST");
6689 case 0x1100 + 10: return wxT("TVM_GETNEXTITEM");
6690 case 0x1100 + 11: return wxT("TVM_SELECTITEM");
6691 case 0x1100 + 12: return wxT("TVM_GETITEMA");
6692 case 0x1100 + 62: return wxT("TVM_GETITEMW");
6693 case 0x1100 + 13: return wxT("TVM_SETITEMA");
6694 case 0x1100 + 63: return wxT("TVM_SETITEMW");
6695 case 0x1100 + 14: return wxT("TVM_EDITLABELA");
6696 case 0x1100 + 65: return wxT("TVM_EDITLABELW");
6697 case 0x1100 + 15: return wxT("TVM_GETEDITCONTROL");
6698 case 0x1100 + 16: return wxT("TVM_GETVISIBLECOUNT");
6699 case 0x1100 + 17: return wxT("TVM_HITTEST");
6700 case 0x1100 + 18: return wxT("TVM_CREATEDRAGIMAGE");
6701 case 0x1100 + 19: return wxT("TVM_SORTCHILDREN");
6702 case 0x1100 + 20: return wxT("TVM_ENSUREVISIBLE");
6703 case 0x1100 + 21: return wxT("TVM_SORTCHILDRENCB");
6704 case 0x1100 + 22: return wxT("TVM_ENDEDITLABELNOW");
6705 case 0x1100 + 23: return wxT("TVM_GETISEARCHSTRINGA");
6706 case 0x1100 + 64: return wxT("TVM_GETISEARCHSTRINGW");
6707 case 0x1100 + 24: return wxT("TVM_SETTOOLTIPS");
6708 case 0x1100 + 25: return wxT("TVM_GETTOOLTIPS");
c085e333 6709
2d0a075d 6710 // header
4a712ba3
VZ
6711 case 0x1200 + 0: return wxT("HDM_GETITEMCOUNT");
6712 case 0x1200 + 1: return wxT("HDM_INSERTITEMA");
6713 case 0x1200 + 10: return wxT("HDM_INSERTITEMW");
6714 case 0x1200 + 2: return wxT("HDM_DELETEITEM");
6715 case 0x1200 + 3: return wxT("HDM_GETITEMA");
6716 case 0x1200 + 11: return wxT("HDM_GETITEMW");
6717 case 0x1200 + 4: return wxT("HDM_SETITEMA");
6718 case 0x1200 + 12: return wxT("HDM_SETITEMW");
6719 case 0x1200 + 5: return wxT("HDM_LAYOUT");
6720 case 0x1200 + 6: return wxT("HDM_HITTEST");
6721 case 0x1200 + 7: return wxT("HDM_GETITEMRECT");
6722 case 0x1200 + 8: return wxT("HDM_SETIMAGELIST");
6723 case 0x1200 + 9: return wxT("HDM_GETIMAGELIST");
6724 case 0x1200 + 15: return wxT("HDM_ORDERTOINDEX");
6725 case 0x1200 + 16: return wxT("HDM_CREATEDRAGIMAGE");
6726 case 0x1200 + 17: return wxT("HDM_GETORDERARRAY");
6727 case 0x1200 + 18: return wxT("HDM_SETORDERARRAY");
6728 case 0x1200 + 19: return wxT("HDM_SETHOTDIVIDER");
c085e333 6729
2d0a075d 6730 // tab control
4a712ba3
VZ
6731 case 0x1300 + 2: return wxT("TCM_GETIMAGELIST");
6732 case 0x1300 + 3: return wxT("TCM_SETIMAGELIST");
6733 case 0x1300 + 4: return wxT("TCM_GETITEMCOUNT");
6734 case 0x1300 + 5: return wxT("TCM_GETITEMA");
6735 case 0x1300 + 60: return wxT("TCM_GETITEMW");
6736 case 0x1300 + 6: return wxT("TCM_SETITEMA");
6737 case 0x1300 + 61: return wxT("TCM_SETITEMW");
6738 case 0x1300 + 7: return wxT("TCM_INSERTITEMA");
6739 case 0x1300 + 62: return wxT("TCM_INSERTITEMW");
6740 case 0x1300 + 8: return wxT("TCM_DELETEITEM");
6741 case 0x1300 + 9: return wxT("TCM_DELETEALLITEMS");
6742 case 0x1300 + 10: return wxT("TCM_GETITEMRECT");
6743 case 0x1300 + 11: return wxT("TCM_GETCURSEL");
6744 case 0x1300 + 12: return wxT("TCM_SETCURSEL");
6745 case 0x1300 + 13: return wxT("TCM_HITTEST");
6746 case 0x1300 + 14: return wxT("TCM_SETITEMEXTRA");
6747 case 0x1300 + 40: return wxT("TCM_ADJUSTRECT");
6748 case 0x1300 + 41: return wxT("TCM_SETITEMSIZE");
6749 case 0x1300 + 42: return wxT("TCM_REMOVEIMAGE");
6750 case 0x1300 + 43: return wxT("TCM_SETPADDING");
6751 case 0x1300 + 44: return wxT("TCM_GETROWCOUNT");
6752 case 0x1300 + 45: return wxT("TCM_GETTOOLTIPS");
6753 case 0x1300 + 46: return wxT("TCM_SETTOOLTIPS");
6754 case 0x1300 + 47: return wxT("TCM_GETCURFOCUS");
6755 case 0x1300 + 48: return wxT("TCM_SETCURFOCUS");
6756 case 0x1300 + 49: return wxT("TCM_SETMINTABWIDTH");
6757 case 0x1300 + 50: return wxT("TCM_DESELECTALL");
c085e333 6758
2d0a075d 6759 // toolbar
4a712ba3
VZ
6760 case WM_USER+1: return wxT("TB_ENABLEBUTTON");
6761 case WM_USER+2: return wxT("TB_CHECKBUTTON");
6762 case WM_USER+3: return wxT("TB_PRESSBUTTON");
6763 case WM_USER+4: return wxT("TB_HIDEBUTTON");
6764 case WM_USER+5: return wxT("TB_INDETERMINATE");
6765 case WM_USER+9: return wxT("TB_ISBUTTONENABLED");
6766 case WM_USER+10: return wxT("TB_ISBUTTONCHECKED");
6767 case WM_USER+11: return wxT("TB_ISBUTTONPRESSED");
6768 case WM_USER+12: return wxT("TB_ISBUTTONHIDDEN");
6769 case WM_USER+13: return wxT("TB_ISBUTTONINDETERMINATE");
6770 case WM_USER+17: return wxT("TB_SETSTATE");
6771 case WM_USER+18: return wxT("TB_GETSTATE");
6772 case WM_USER+19: return wxT("TB_ADDBITMAP");
6773 case WM_USER+20: return wxT("TB_ADDBUTTONS");
6774 case WM_USER+21: return wxT("TB_INSERTBUTTON");
6775 case WM_USER+22: return wxT("TB_DELETEBUTTON");
6776 case WM_USER+23: return wxT("TB_GETBUTTON");
6777 case WM_USER+24: return wxT("TB_BUTTONCOUNT");
6778 case WM_USER+25: return wxT("TB_COMMANDTOINDEX");
6779 case WM_USER+26: return wxT("TB_SAVERESTOREA");
6780 case WM_USER+76: return wxT("TB_SAVERESTOREW");
6781 case WM_USER+27: return wxT("TB_CUSTOMIZE");
6782 case WM_USER+28: return wxT("TB_ADDSTRINGA");
6783 case WM_USER+77: return wxT("TB_ADDSTRINGW");
6784 case WM_USER+29: return wxT("TB_GETITEMRECT");
6785 case WM_USER+30: return wxT("TB_BUTTONSTRUCTSIZE");
6786 case WM_USER+31: return wxT("TB_SETBUTTONSIZE");
6787 case WM_USER+32: return wxT("TB_SETBITMAPSIZE");
6788 case WM_USER+33: return wxT("TB_AUTOSIZE");
6789 case WM_USER+35: return wxT("TB_GETTOOLTIPS");
6790 case WM_USER+36: return wxT("TB_SETTOOLTIPS");
6791 case WM_USER+37: return wxT("TB_SETPARENT");
6792 case WM_USER+39: return wxT("TB_SETROWS");
6793 case WM_USER+40: return wxT("TB_GETROWS");
6794 case WM_USER+42: return wxT("TB_SETCMDID");
6795 case WM_USER+43: return wxT("TB_CHANGEBITMAP");
6796 case WM_USER+44: return wxT("TB_GETBITMAP");
6797 case WM_USER+45: return wxT("TB_GETBUTTONTEXTA");
6798 case WM_USER+75: return wxT("TB_GETBUTTONTEXTW");
6799 case WM_USER+46: return wxT("TB_REPLACEBITMAP");
6800 case WM_USER+47: return wxT("TB_SETINDENT");
6801 case WM_USER+48: return wxT("TB_SETIMAGELIST");
6802 case WM_USER+49: return wxT("TB_GETIMAGELIST");
6803 case WM_USER+50: return wxT("TB_LOADIMAGES");
6804 case WM_USER+51: return wxT("TB_GETRECT");
6805 case WM_USER+52: return wxT("TB_SETHOTIMAGELIST");
6806 case WM_USER+53: return wxT("TB_GETHOTIMAGELIST");
6807 case WM_USER+54: return wxT("TB_SETDISABLEDIMAGELIST");
6808 case WM_USER+55: return wxT("TB_GETDISABLEDIMAGELIST");
6809 case WM_USER+56: return wxT("TB_SETSTYLE");
6810 case WM_USER+57: return wxT("TB_GETSTYLE");
6811 case WM_USER+58: return wxT("TB_GETBUTTONSIZE");
6812 case WM_USER+59: return wxT("TB_SETBUTTONWIDTH");
6813 case WM_USER+60: return wxT("TB_SETMAXTEXTROWS");
6814 case WM_USER+61: return wxT("TB_GETTEXTROWS");
6815 case WM_USER+41: return wxT("TB_GETBITMAPFLAGS");
c085e333 6816
42e69d6b 6817 default:
4a712ba3
VZ
6818 static wxString s_szBuf;
6819 s_szBuf.Printf(wxT("<unknown message = %d>"), message);
6820 return s_szBuf.c_str();
42e69d6b 6821 }
47cbd6da 6822}
ea57084d 6823#endif //__WXDEBUG__
4aff28fc 6824
1e6feb95 6825static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
f6bcfd97
BP
6826{
6827 // prepare the DC
6828 TEXTMETRIC tm;
6829 HWND hwnd = GetHwndOf(win);
6830 HDC hdc = ::GetDC(hwnd);
6831
6832#if !wxDIALOG_UNIT_COMPATIBILITY
6833 // and select the current font into it
6834 HFONT hfont = GetHfontOf(win->GetFont());
6835 if ( hfont )
6836 {
6837 hfont = (HFONT)::SelectObject(hdc, hfont);
6838 }
6839#endif
6840
6841 // finally retrieve the text metrics from it
6842 GetTextMetrics(hdc, &tm);
6843
6844#if !wxDIALOG_UNIT_COMPATIBILITY
6845 // and clean up
6846 if ( hfont )
6847 {
6848 (void)::SelectObject(hdc, hfont);
6849 }
6850#endif
6851
6852 ::ReleaseDC(hwnd, hdc);
6853
6854 return tm;
6855}
3723b7b1
JS
6856
6857// Find the wxWindow at the current mouse position, returning the mouse
6858// position.
2b5f62a0 6859wxWindow* wxFindWindowAtPointer(wxPoint& pt)
3723b7b1 6860{
2b5f62a0
VZ
6861 pt = wxGetMousePosition();
6862 return wxFindWindowAtPoint(pt);
57591e0e
JS
6863}
6864
6865wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
6866{
6867 POINT pt2;
6868 pt2.x = pt.x;
6869 pt2.y = pt.y;
3723b7b1 6870
ab3eae34 6871 HWND hWnd = ::WindowFromPoint(pt2);
3723b7b1 6872
ab3eae34 6873 return wxGetWindowFromHWND((WXHWND)hWnd);
3723b7b1
JS
6874}
6875
6876// Get the current mouse position.
6877wxPoint wxGetMousePosition()
6878{
1772ead0 6879 POINT pt;
f2325516
JS
6880#ifdef __WXWINCE__
6881 GetCursorPosWinCE(&pt);
6882#else
1772ead0 6883 GetCursorPos( & pt );
f2325516 6884#endif
5cd16c0c 6885
1772ead0 6886 return wxPoint(pt.x, pt.y);
3723b7b1
JS
6887}
6888
5048c832 6889#if wxUSE_HOTKEY
540b6b09 6890
afafd942
JS
6891#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6892static void WinCEUnregisterHotKey(int modifiers, int id)
6893{
6894 // Register hotkeys for the hardware buttons
6895 HINSTANCE hCoreDll;
6896 typedef BOOL (WINAPI *UnregisterFunc1Proc)(UINT, UINT);
6897
6898 UnregisterFunc1Proc procUnregisterFunc;
6899 hCoreDll = LoadLibrary(_T("coredll.dll"));
6900 if (hCoreDll)
6901 {
6902 procUnregisterFunc = (UnregisterFunc1Proc)GetProcAddress(hCoreDll, _T("UnregisterFunc1"));
6903 if (procUnregisterFunc)
6904 procUnregisterFunc(modifiers, id);
6905 FreeLibrary(hCoreDll);
6906 }
6907}
6908#endif
6909
540b6b09 6910bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
5048c832
JS
6911{
6912 UINT win_modifiers=0;
540b6b09
VZ
6913 if ( modifiers & wxMOD_ALT )
6914 win_modifiers |= MOD_ALT;
6915 if ( modifiers & wxMOD_SHIFT )
6916 win_modifiers |= MOD_SHIFT;
6917 if ( modifiers & wxMOD_CONTROL )
6918 win_modifiers |= MOD_CONTROL;
6919 if ( modifiers & wxMOD_WIN )
6920 win_modifiers |= MOD_WIN;
6921
afafd942
JS
6922#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6923 // Required for PPC and Smartphone hardware buttons
6924 if (keycode >= WXK_SPECIAL1 && keycode <= WXK_SPECIAL20)
6925 WinCEUnregisterHotKey(win_modifiers, hotkeyId);
6926#endif
6927
540b6b09
VZ
6928 if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) )
6929 {
6930 wxLogLastError(_T("RegisterHotKey"));
5048c832 6931
08158721 6932 return false;
540b6b09
VZ
6933 }
6934
08158721 6935 return true;
5048c832
JS
6936}
6937
6938bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
6939{
afafd942
JS
6940#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6941 WinCEUnregisterHotKey(MOD_WIN, hotkeyId);
6942#endif
6943
540b6b09
VZ
6944 if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) )
6945 {
6946 wxLogLastError(_T("UnregisterHotKey"));
6947
08158721 6948 return false;
540b6b09
VZ
6949 }
6950
08158721 6951 return true;
5048c832
JS
6952}
6953
0b4f47a3
DS
6954#if wxUSE_ACCEL
6955
5048c832
JS
6956bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
6957{
540b6b09
VZ
6958 int hotkeyId = wParam;
6959 int virtualKey = HIWORD(lParam);
6960 int win_modifiers = LOWORD(lParam);
6961
5048c832
JS
6962 wxKeyEvent event(CreateKeyEvent(wxEVT_HOTKEY, virtualKey, wParam, lParam));
6963 event.SetId(hotkeyId);
6964 event.m_shiftDown = (win_modifiers & MOD_SHIFT) != 0;
6965 event.m_controlDown = (win_modifiers & MOD_CONTROL) != 0;
6966 event.m_altDown = (win_modifiers & MOD_ALT) != 0;
6967 event.m_metaDown = (win_modifiers & MOD_WIN) != 0;
540b6b09 6968
937013e0 6969 return HandleWindowEvent(event);
5048c832 6970}
540b6b09 6971
0b4f47a3
DS
6972#endif // wxUSE_ACCEL
6973
540b6b09 6974#endif // wxUSE_HOTKEY
5048c832 6975
550049c2 6976// Not tested under WinCE
d79df32c 6977#ifndef __WXWINCE__
d79df32c 6978
550049c2
VZ
6979// this class installs a message hook which really wakes up our idle processing
6980// each time a WM_NULL is received (wxWakeUpIdle does this), even if we're
6981// sitting inside a local modal loop (e.g. a menu is opened or scrollbar is
6982// being dragged or even inside ::MessageBox()) and so don't control message
6983// dispatching otherwise
6984class wxIdleWakeUpModule : public wxModule
6985{
d79df32c 6986public:
3a3c8603 6987 virtual bool OnInit()
550049c2 6988 {
3a3c8603 6989 ms_hMsgHookProc = ::SetWindowsHookEx
550049c2
VZ
6990 (
6991 WH_GETMESSAGE,
6992 &wxIdleWakeUpModule::MsgHookProc,
6993 NULL,
6994 GetCurrentThreadId()
6995 );
d79df32c 6996
550049c2
VZ
6997 if ( !ms_hMsgHookProc )
6998 {
6999 wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)"));
7000
7001 return false;
7002 }
7003
7004 return true;
3a3c8603 7005 }
550049c2 7006
3a3c8603 7007 virtual void OnExit()
550049c2 7008 {
3a3c8603
DS
7009 ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc);
7010 }
550049c2 7011
3a3c8603 7012 static LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
550049c2 7013 {
3a3c8603 7014 MSG *msg = (MSG*)lParam;
34ea3c74
VZ
7015
7016 // only process the message if it is actually going to be removed from
7017 // the message queue, this prevents that the same event from being
7018 // processed multiple times if now someone just called PeekMessage()
7019 if ( msg->message == WM_NULL && wParam == PM_REMOVE )
3a3c8603 7020 {
550049c2 7021 wxTheApp->ProcessPendingEvents();
3a3c8603 7022 }
550049c2 7023
3a3c8603 7024 return CallNextHookEx(ms_hMsgHookProc, nCode, wParam, lParam);
47b378bd 7025 }
550049c2 7026
d79df32c 7027private:
3a3c8603 7028 static HHOOK ms_hMsgHookProc;
550049c2
VZ
7029
7030 DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule)
d79df32c 7031};
d79df32c 7032
550049c2
VZ
7033HHOOK wxIdleWakeUpModule::ms_hMsgHookProc = 0;
7034
7035IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule, wxModule)
7036
7037#endif // __WXWINCE__
3a3c8603 7038
d26e1ab2
JS
7039#ifdef __WXWINCE__
7040
7041#if wxUSE_STATBOX
7042static void wxAdjustZOrder(wxWindow* parent)
7043{
7044 if (parent->IsKindOf(CLASSINFO(wxStaticBox)))
7045 {
7046 // Set the z-order correctly
7047 SetWindowPos((HWND) parent->GetHWND(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
7048 }
35bbb0c6 7049
d26e1ab2
JS
7050 wxWindowList::compatibility_iterator current = parent->GetChildren().GetFirst();
7051 while (current)
7052 {
7053 wxWindow *childWin = current->GetData();
7054 wxAdjustZOrder(childWin);
7055 current = current->GetNext();
7056 }
7057}
7058#endif
7059
7060// We need to adjust the z-order of static boxes in WinCE, to
7061// make 'contained' controls visible
7062void wxWindowMSW::OnInitDialog( wxInitDialogEvent& event )
7063{
7064#if wxUSE_STATBOX
7065 wxAdjustZOrder(this);
7066#endif
35bbb0c6 7067
d26e1ab2
JS
7068 event.Skip();
7069}
7070#endif