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