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