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