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