]> git.saurik.com Git - wxWidgets.git/blame - src/msw/window.cpp
attempt to fix compilation for old imagehlp.h header
[wxWidgets.git] / src / msw / window.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
1e6feb95 2// Name: src/msw/windows.cpp
2bda0e17
KB
3// Purpose: wxWindow
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
JS
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
a23fd0e1
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
a23fd0e1 21 #pragma implementation "window.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
09914df7 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
9ed0d735 32 #include "wx/msw/wrapwin.h"
4e938f5b 33 #include "wx/window.h"
0c589ad0 34 #include "wx/accel.h"
3a19e16d
VZ
35 #include "wx/setup.h"
36 #include "wx/menu.h"
37 #include "wx/dc.h"
38 #include "wx/dcclient.h"
8e92ccef 39 #include "wx/dcmemory.h"
3a19e16d
VZ
40 #include "wx/utils.h"
41 #include "wx/app.h"
3a19e16d
VZ
42 #include "wx/layout.h"
43 #include "wx/dialog.h"
44 #include "wx/frame.h"
45 #include "wx/listbox.h"
46 #include "wx/button.h"
3a19e16d 47 #include "wx/msgdlg.h"
1f3943e0 48 #include "wx/settings.h"
8d753488 49 #include "wx/statbox.h"
2bda0e17
KB
50#endif
51
f6bcfd97 52#if wxUSE_OWNER_DRAWN
09914df7 53 #include "wx/ownerdrw.h"
2bda0e17
KB
54#endif
55
9e2896e5
VZ
56#if wxUSE_DRAG_AND_DROP
57 #include "wx/dnd.h"
2bda0e17
KB
58#endif
59
ed5317e5
JS
60#if wxUSE_ACCESSIBILITY
61 #include "wx/access.h"
bef8d481 62 #include <ole2.h>
ed5317e5
JS
63 #include <oleacc.h>
64 #ifndef WM_GETOBJECT
65 #define WM_GETOBJECT 0x003D
66 #endif
67 #ifndef OBJID_CLIENT
68 #define OBJID_CLIENT 0xFFFFFFFC
69 #endif
70#endif
71
2bda0e17 72#include "wx/menuitem.h"
47cbd6da 73#include "wx/log.h"
750b78ba 74
0c589ad0
BM
75#include "wx/msw/private.h"
76
750b78ba 77#if wxUSE_TOOLTIPS
42e69d6b 78 #include "wx/tooltip.h"
750b78ba
JS
79#endif
80
789295bf
VZ
81#if wxUSE_CARET
82 #include "wx/caret.h"
83#endif // wxUSE_CARET
84
6fe19057
VZ
85#if wxUSE_SPINCTRL
86 #include "wx/spinctrl.h"
87#endif // wxUSE_SPINCTRL
88
dbda9e86
JS
89#include "wx/intl.h"
90#include "wx/log.h"
3a19e16d 91
2a47d3c1 92#include "wx/textctrl.h"
d9317fd4 93#include "wx/notebook.h"
2a47d3c1 94
2bda0e17
KB
95#include <string.h>
96
7f0586ef 97#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__)
3a19e16d
VZ
98 #include <shellapi.h>
99 #include <mmsystem.h>
2bda0e17
KB
100#endif
101
102#ifdef __WIN32__
3a19e16d 103 #include <windowsx.h>
2bda0e17
KB
104#endif
105
7f0586ef 106#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__)
310df81b 107 #ifdef __WIN95__
c42404a5
VZ
108 #include <commctrl.h>
109 #endif
7f0586ef 110#elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler
b39dbf34 111 #include "wx/msw/gnuwin32/extra.h"
57c208c5 112#endif
2bda0e17 113
13c4e406
JS
114#if defined(__GNUG__)
115#include "wx/msw/missing.h"
116#endif
aedcc0dc 117
7f0586ef
JS
118#if defined(__WXWINCE__)
119#include "wx/msw/wince/missing.h"
120#endif
121
9c7df356
VZ
122// ----------------------------------------------------------------------------
123// standard constants not available with all compilers/headers
124// ----------------------------------------------------------------------------
125
f6bcfd97
BP
126// This didn't appear in mingw until 2.95.2
127#ifndef SIF_TRACKPOS
128#define SIF_TRACKPOS 16
129#endif
130
d2c52078
RD
131#if wxUSE_MOUSEWHEEL
132 #ifndef WM_MOUSEWHEEL
133 #define WM_MOUSEWHEEL 0x020A
c9d4f881
RD
134 #endif
135 #ifndef WHEEL_DELTA
d2c52078 136 #define WHEEL_DELTA 120
c9d4f881
RD
137 #endif
138 #ifndef SPI_GETWHEELSCROLLLINES
d2c52078
RD
139 #define SPI_GETWHEELSCROLLLINES 104
140 #endif
9c7df356
VZ
141#endif // wxUSE_MOUSEWHEEL
142
143#ifndef VK_OEM_1
144 #define VK_OEM_1 0xBA
9c7df356
VZ
145 #define VK_OEM_2 0xBF
146 #define VK_OEM_3 0xC0
147 #define VK_OEM_4 0xDB
148 #define VK_OEM_5 0xDC
149 #define VK_OEM_6 0xDD
150 #define VK_OEM_7 0xDE
d2c52078
RD
151#endif
152
3f3071dc
MB
153#ifndef VK_OEM_COMMA
154 #define VK_OEM_PLUS 0xBB
155 #define VK_OEM_COMMA 0xBC
156 #define VK_OEM_MINUS 0xBD
157 #define VK_OEM_PERIOD 0xBE
158#endif
159
a23fd0e1 160// ---------------------------------------------------------------------------
42e69d6b 161// global variables
a23fd0e1 162// ---------------------------------------------------------------------------
47cbd6da 163
90c1530a 164// the last Windows message we got (FIXME-MT)
42e69d6b 165extern MSG s_currentMsg;
2bda0e17 166
1e6feb95 167#if wxUSE_MENUS_NATIVE
2bda0e17 168wxMenu *wxCurrentPopupMenu = NULL;
1e6feb95
VZ
169#endif // wxUSE_MENUS_NATIVE
170
2ffa221c 171extern const wxChar *wxCanvasClassName;
42e69d6b 172
90c1530a
VZ
173// true if we had already created the std colour map, used by
174// wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
175static bool gs_hasStdCmap = FALSE;
176
42e69d6b
VZ
177// ---------------------------------------------------------------------------
178// private functions
179// ---------------------------------------------------------------------------
180
181// the window proc for all our windows
3135f4a7 182LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
42e69d6b 183 WPARAM wParam, LPARAM lParam);
577baeef 184
42e69d6b
VZ
185
186#ifdef __WXDEBUG__
187 const char *wxGetMessageName(int message);
188#endif //__WXDEBUG__
2bda0e17 189
1e6feb95 190void wxRemoveHandleAssociation(wxWindowMSW *win);
cc972ac6 191extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
2bda0e17
KB
192wxWindow *wxFindWinFromHandle(WXHWND hWnd);
193
4aff28fc
VZ
194// this magical function is used to translate VK_APPS key presses to right
195// mouse clicks
1e6feb95
VZ
196static void TranslateKbdEventToMouse(wxWindowMSW *win,
197 int *x, int *y, WPARAM *flags);
4aff28fc 198
f6bcfd97 199// get the text metrics for the current font
1e6feb95
VZ
200static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
201
dfafa702 202// find the window for the mouse event at the specified position
abcbaea7 203static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y); //TW:REQ:Univ
dfafa702 204
c48926e1 205// wrapper around BringWindowToTop() API
44d5b352 206static inline void wxBringWindowToTop(HWND hwnd)
c48926e1
VZ
207{
208#ifdef __WXMICROWIN__
209 // It seems that MicroWindows brings the _parent_ of the window to the top,
210 // which can be the wrong one.
211
212 // activate (set focus to) specified window
213 ::SetFocus(hwnd);
313901f3 214#endif
c48926e1
VZ
215
216 // raise top level parent to top of z order
313901f3 217 if (!::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE))
c48926e1 218 {
313901f3 219 wxLogLastError(_T("SetWindowPos"));
c48926e1 220 }
c48926e1 221}
f6bcfd97 222
a23fd0e1
VZ
223// ---------------------------------------------------------------------------
224// event tables
225// ---------------------------------------------------------------------------
226
1e6feb95
VZ
227// in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
228// method
229#ifdef __WXUNIVERSAL__
230 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW, wxWindowBase)
231#else // __WXMSW__
232 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
233#endif // __WXUNIVERSAL__/__WXMSW__
234
235BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase)
236 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
237 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged)
238 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
2bda0e17
KB
239END_EVENT_TABLE()
240
a23fd0e1
VZ
241// ===========================================================================
242// implementation
243// ===========================================================================
244
42e69d6b
VZ
245// ---------------------------------------------------------------------------
246// wxWindow utility functions
247// ---------------------------------------------------------------------------
248
2bda0e17 249// Find an item given the MS Windows id
1e6feb95 250wxWindow *wxWindowMSW::FindItem(long id) const
2bda0e17 251{
1e6feb95 252#if wxUSE_CONTROLS
f7637829 253 wxControl *item = wxDynamicCastThis(wxControl);
f048e32f
VZ
254 if ( item )
255 {
1e6feb95
VZ
256 // is it we or one of our "internal" children?
257 if ( item->GetId() == id
258#ifndef __WXUNIVERSAL__
259 || (item->GetSubcontrols().Index(id) != wxNOT_FOUND)
260#endif // __WXUNIVERSAL__
261 )
f048e32f
VZ
262 {
263 return item;
264 }
265 }
1e6feb95 266#endif // wxUSE_CONTROLS
f048e32f 267
222ed1d6 268 wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
2d0a075d
JS
269 while (current)
270 {
42e69d6b 271 wxWindow *childWin = current->GetData();
2bda0e17 272
42e69d6b 273 wxWindow *wnd = childWin->FindItem(id);
cc2b7472 274 if ( wnd )
42e69d6b 275 return wnd;
2bda0e17 276
42e69d6b 277 current = current->GetNext();
2bda0e17 278 }
42e69d6b 279
2d0a075d 280 return NULL;
2bda0e17
KB
281}
282
283// Find an item given the MS Windows handle
1e6feb95 284wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const
2bda0e17 285{
222ed1d6 286 wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
2d0a075d 287 while (current)
2bda0e17 288 {
42e69d6b
VZ
289 wxWindow *parent = current->GetData();
290
2d0a075d 291 // Do a recursive search.
42e69d6b 292 wxWindow *wnd = parent->FindItemByHWND(hWnd);
cc2b7472 293 if ( wnd )
42e69d6b 294 return wnd;
2d0a075d 295
1e6feb95
VZ
296 if ( !controlOnly
297#if wxUSE_CONTROLS
298 || parent->IsKindOf(CLASSINFO(wxControl))
299#endif // wxUSE_CONTROLS
300 )
2d0a075d 301 {
42e69d6b
VZ
302 wxWindow *item = current->GetData();
303 if ( item->GetHWND() == hWnd )
2d0a075d
JS
304 return item;
305 else
306 {
307 if ( item->ContainsHWND(hWnd) )
308 return item;
309 }
310 }
42e69d6b
VZ
311
312 current = current->GetNext();
2bda0e17 313 }
2d0a075d 314 return NULL;
2bda0e17
KB
315}
316
317// Default command handler
1e6feb95 318bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id))
2bda0e17 319{
2d0a075d 320 return FALSE;
2bda0e17
KB
321}
322
fd3f686c
VZ
323// ----------------------------------------------------------------------------
324// constructors and such
325// ----------------------------------------------------------------------------
326
1e6feb95 327void wxWindowMSW::Init()
2bda0e17 328{
cc2b7472
VZ
329 // generic
330 InitBase();
634903fd 331
cc2b7472 332 // MSW specific
2d0a075d 333 m_isBeingDeleted = FALSE;
5a403e3f 334 m_oldWndProc = NULL;
fd3f686c 335 m_mouseInWindow = FALSE;
68304caf 336 m_lastKeydownProcessed = FALSE;
2bda0e17 337
d7cbabe0
VZ
338 m_childrenDisabled = NULL;
339
2d0a075d 340 // wxWnd
2d0a075d 341 m_hMenu = 0;
2bda0e17 342
319fefa9
VZ
343 m_hWnd = 0;
344
2d0a075d
JS
345 m_xThumbSize = 0;
346 m_yThumbSize = 0;
2bda0e17 347
85d10d9b
VZ
348 // as all windows are created with WS_VISIBLE style...
349 m_isShown = TRUE;
350
a23fd0e1 351#if wxUSE_MOUSEEVENT_HACK
cc2b7472
VZ
352 m_lastMouseX =
353 m_lastMouseY = -1;
354 m_lastMouseEvent = -1;
a23fd0e1 355#endif // wxUSE_MOUSEEVENT_HACK
fd3f686c
VZ
356}
357
2bda0e17 358// Destructor
1e6feb95 359wxWindowMSW::~wxWindowMSW()
2bda0e17 360{
2d0a075d 361 m_isBeingDeleted = TRUE;
2bda0e17 362
2e9f62da 363#ifndef __WXUNIVERSAL__
4a41c655 364 // VS: make sure there's no wxFrame with last focus set to us:
2e9f62da 365 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
4a41c655 366 {
085ad686 367 wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
4a41c655
VS
368 if ( frame )
369 {
c5053639 370 if ( frame->GetLastFocus() == this )
2e9f62da 371 {
085ad686 372 frame->SetLastFocus(NULL);
2e9f62da 373 }
cc0c7cd8 374 break;
4a41c655
VS
375 }
376 }
2e9f62da 377#endif // __WXUNIVERSAL__
2bda0e17 378
cc0c7cd8
VS
379 // VS: destroy children first and _then_ detach *this from its parent.
380 // If we'd do it the other way around, children wouldn't be able
381 // find their parent frame (see above).
382 DestroyChildren();
383
a23fd0e1
VZ
384 if ( m_parent )
385 m_parent->RemoveChild(this);
386
cc2b7472 387 if ( m_hWnd )
42e69d6b 388 {
98440bc3
VZ
389 // VZ: test temp removed to understand what really happens here
390 //if (::IsWindow(GetHwnd()))
df61c009
JS
391 {
392 if ( !::DestroyWindow(GetHwnd()) )
f6bcfd97 393 wxLogLastError(wxT("DestroyWindow"));
df61c009 394 }
2bda0e17 395
c50f1fb9
VZ
396 // remove hWnd <-> wxWindow association
397 wxRemoveHandleAssociation(this);
398 }
d7cbabe0
VZ
399
400 delete m_childrenDisabled;
2bda0e17
KB
401}
402
fd3f686c 403// real construction (Init() must have been called before!)
1e6feb95
VZ
404bool wxWindowMSW::Create(wxWindow *parent,
405 wxWindowID id,
406 const wxPoint& pos,
407 const wxSize& size,
408 long style,
409 const wxString& name)
2d0a075d 410{
223d09f6 411 wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") );
2bda0e17 412
8d99be5f
VZ
413 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
414 return FALSE;
42e69d6b 415
fd3f686c 416 parent->AddChild(this);
2bda0e17 417
b2d5a7ee 418 WXDWORD exstyle;
e49d97e6 419 DWORD msflags = MSWGetCreateWindowFlags(&exstyle);
1e6feb95
VZ
420
421#ifdef __WXUNIVERSAL__
d1fe917b 422 // no borders, we draw them ourselves
76c79ff4
VZ
423 exstyle &= ~(WS_EX_DLGMODALFRAME |
424 WS_EX_STATICEDGE |
425 WS_EX_CLIENTEDGE |
426 WS_EX_WINDOWEDGE);
d1fe917b 427 msflags &= ~WS_BORDER;
b2d5a7ee 428#endif // wxUniversal
1e6feb95 429
e49d97e6
VZ
430 // all windows are created visible by default except popup ones (which are
431 // like the wxTopLevelWindows in this aspect)
1e6feb95
VZ
432 if ( style & wxPOPUP_WINDOW )
433 {
1e6feb95
VZ
434 msflags &= ~WS_VISIBLE;
435 m_isShown = FALSE;
436 }
e49d97e6
VZ
437 else
438 {
439 msflags |= WS_VISIBLE;
440 }
1e6feb95 441
42cfcc58 442 return MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle);
2bda0e17
KB
443}
444
42e69d6b
VZ
445// ---------------------------------------------------------------------------
446// basic operations
447// ---------------------------------------------------------------------------
448
1e6feb95 449void wxWindowMSW::SetFocus()
2bda0e17 450{
a23fd0e1 451 HWND hWnd = GetHwnd();
1e6feb95
VZ
452 wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
453
7f0586ef 454#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95 455 ::SetLastError(0);
8cb172b4 456#endif
d0a3d109 457
1e6feb95
VZ
458 if ( !::SetFocus(hWnd) )
459 {
5262eb0a 460#if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
1e6feb95
VZ
461 // was there really an error?
462 DWORD dwRes = ::GetLastError();
463 if ( dwRes )
464 {
5262eb0a
VZ
465 HWND hwndFocus = ::GetFocus();
466 if ( hwndFocus != hWnd )
467 {
468 wxLogApiError(_T("SetFocus"), dwRes);
469 }
1e6feb95 470 }
5262eb0a 471#endif // Debug
1e6feb95 472 }
2bda0e17
KB
473}
474
ddf9d04f
VZ
475void wxWindowMSW::SetFocusFromKbd()
476{
ddf9d04f
VZ
477 // when the focus is given to the control with DLGC_HASSETSEL style from
478 // keyboard its contents should be entirely selected: this is what
479 // ::IsDialogMessage() does and so we should do it as well to provide the
480 // same LNF as the native programs
481 if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE, 0, 0) & DLGC_HASSETSEL )
482 {
483 ::SendMessage(GetHwnd(), EM_SETSEL, 0, -1);
484 }
1b1ca07a
VZ
485
486 // do this after (maybe) setting the selection as like this when
487 // wxEVT_SET_FOCUS handler is called, the selection would have been already
488 // set correctly -- this may be important
489 wxWindowBase::SetFocusFromKbd();
ddf9d04f
VZ
490}
491
42e69d6b
VZ
492// Get the window with the focus
493wxWindow *wxWindowBase::FindFocus()
494{
495 HWND hWnd = ::GetFocus();
496 if ( hWnd )
497 {
a2242341 498 return wxGetWindowFromHWND((WXHWND)hWnd);
42e69d6b
VZ
499 }
500
501 return NULL;
502}
503
1e6feb95 504bool wxWindowMSW::Enable(bool enable)
2bda0e17 505{
cc2b7472
VZ
506 if ( !wxWindowBase::Enable(enable) )
507 return FALSE;
508
a23fd0e1 509 HWND hWnd = GetHwnd();
cc2b7472 510 if ( hWnd )
2d0a075d 511 ::EnableWindow(hWnd, (BOOL)enable);
cc2b7472 512
83a16cfa
VZ
513 // the logic below doesn't apply to the top level windows -- otherwise
514 // showing a modal dialog would result in total greying out (and ungreying
515 // out later) of everything which would be really ugly
516 if ( IsTopLevel() )
517 return TRUE;
518
d7cbabe0
VZ
519 // when the parent is disabled, all of its children should be disabled as
520 // well but when it is enabled back, only those of the children which
521 // hadn't been already disabled in the beginning should be enabled again,
522 // so we have to keep the list of those children
222ed1d6 523 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
fa3d9b4e
VZ
524 node;
525 node = node->GetNext() )
87a1e308
VZ
526 {
527 wxWindow *child = node->GetData();
fa3d9b4e
VZ
528 if ( child->IsTopLevel() )
529 {
530 // the logic below doesn't apply to top level children
531 continue;
532 }
d7cbabe0
VZ
533
534 if ( enable )
535 {
536 // enable the child back unless it had been disabled before us
537 if ( !m_childrenDisabled || !m_childrenDisabled->Find(child) )
538 child->Enable();
539 }
540 else // we're being disabled
541 {
542 if ( child->IsEnabled() )
543 {
544 // disable it as children shouldn't stay enabled while the
545 // parent is not
546 child->Disable();
547 }
548 else // child already disabled, remember it
549 {
550 // have we created the list of disabled children already?
551 if ( !m_childrenDisabled )
552 m_childrenDisabled = new wxWindowList;
553
554 m_childrenDisabled->Append(child);
555 }
556 }
87a1e308 557 }
d7cbabe0
VZ
558
559 if ( enable && m_childrenDisabled )
560 {
561 // we don't need this list any more, don't keep unused memory
562 delete m_childrenDisabled;
563 m_childrenDisabled = NULL;
564 }
87a1e308 565
cc2b7472 566 return TRUE;
2bda0e17
KB
567}
568
1e6feb95 569bool wxWindowMSW::Show(bool show)
42e69d6b
VZ
570{
571 if ( !wxWindowBase::Show(show) )
572 return FALSE;
573
574 HWND hWnd = GetHwnd();
575 int cshow = show ? SW_SHOW : SW_HIDE;
576 ::ShowWindow(hWnd, cshow);
577
1c844232 578 if ( show && IsTopLevel() )
42e69d6b 579 {
c48926e1 580 wxBringWindowToTop(hWnd);
42e69d6b
VZ
581 }
582
583 return TRUE;
584}
585
586// Raise the window to the top of the Z order
1e6feb95 587void wxWindowMSW::Raise()
42e69d6b 588{
c48926e1 589 wxBringWindowToTop(GetHwnd());
42e69d6b
VZ
590}
591
592// Lower the window to the bottom of the Z order
1e6feb95 593void wxWindowMSW::Lower()
42e69d6b
VZ
594{
595 ::SetWindowPos(GetHwnd(), HWND_BOTTOM, 0, 0, 0, 0,
596 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
597}
598
1e6feb95 599void wxWindowMSW::SetTitle( const wxString& title)
42e69d6b
VZ
600{
601 SetWindowText(GetHwnd(), title.c_str());
602}
603
1e6feb95 604wxString wxWindowMSW::GetTitle() const
42e69d6b
VZ
605{
606 return wxGetWindowText(GetHWND());
607}
608
94633ad9 609void wxWindowMSW::DoCaptureMouse()
2bda0e17 610{
a23fd0e1 611 HWND hWnd = GetHwnd();
1e6feb95 612 if ( hWnd )
2d0a075d 613 {
1e6feb95 614 ::SetCapture(hWnd);
2d0a075d 615 }
2bda0e17
KB
616}
617
94633ad9 618void wxWindowMSW::DoReleaseMouse()
2bda0e17 619{
1e6feb95 620 if ( !::ReleaseCapture() )
2d0a075d 621 {
1e6feb95 622 wxLogLastError(_T("ReleaseCapture"));
2d0a075d 623 }
2bda0e17
KB
624}
625
1e6feb95
VZ
626/* static */ wxWindow *wxWindowBase::GetCapture()
627{
628 HWND hwnd = ::GetCapture();
629 return hwnd ? wxFindWinFromHandle((WXHWND)hwnd) : (wxWindow *)NULL;
630}
631
632bool wxWindowMSW::SetFont(const wxFont& font)
2bda0e17 633{
42e69d6b
VZ
634 if ( !wxWindowBase::SetFont(font) )
635 {
636 // nothing to do
637 return FALSE;
2d0a075d 638 }
195896c7 639
42e69d6b
VZ
640 HWND hWnd = GetHwnd();
641 if ( hWnd != 0 )
642 {
643 WXHANDLE hFont = m_font.GetResourceHandle();
2bda0e17 644
223d09f6 645 wxASSERT_MSG( hFont, wxT("should have valid font") );
3a19e16d 646
c50f1fb9 647 ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
42e69d6b 648 }
2bda0e17 649
42e69d6b
VZ
650 return TRUE;
651}
1e6feb95 652bool wxWindowMSW::SetCursor(const wxCursor& cursor)
2bda0e17 653{
42e69d6b
VZ
654 if ( !wxWindowBase::SetCursor(cursor) )
655 {
656 // no change
657 return FALSE;
658 }
659
8a9c2246
VZ
660 if ( m_cursor.Ok() )
661 {
662 HWND hWnd = GetHwnd();
42e69d6b 663
8a9c2246
VZ
664 // Change the cursor NOW if we're within the correct window
665 POINT point;
666 ::GetCursorPos(&point);
2bda0e17 667
82c9f85c 668 RECT rect = wxGetWindowRect(hWnd);
3a19e16d 669
8a9c2246
VZ
670 if ( ::PtInRect(&rect, point) && !wxIsBusy() )
671 ::SetCursor(GetHcursorOf(m_cursor));
672 }
3a19e16d 673
42e69d6b 674 return TRUE;
3a19e16d
VZ
675}
676
1e6feb95 677void wxWindowMSW::WarpPointer (int x, int y)
2bda0e17 678{
1e6feb95 679 ClientToScreen(&x, &y);
42e69d6b 680
1e6feb95
VZ
681 if ( !::SetCursorPos(x, y) )
682 {
683 wxLogLastError(_T("SetCursorPos"));
684 }
2bda0e17
KB
685}
686
42e69d6b 687#if WXWIN_COMPATIBILITY
1e6feb95 688void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const
2bda0e17 689{
42e69d6b
VZ
690}
691#endif // WXWIN_COMPATIBILITY
81d66cf3 692
42e69d6b
VZ
693// ---------------------------------------------------------------------------
694// scrolling stuff
695// ---------------------------------------------------------------------------
2d0a075d 696
0cf5de11 697// convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT
3f3071dc 698static inline int wxDirToWinStyle(int orient)
0cf5de11
VZ
699{
700 return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
701}
702
42e69d6b 703#if WXWIN_COMPATIBILITY
1e6feb95 704void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh)
42e69d6b 705{
42e69d6b
VZ
706 int range1 = range;
707
708 // Try to adjust the range to cope with page size > 1
709 // - a Windows API quirk
710 int pageSize = GetScrollPage(orient);
711 if ( pageSize > 1 && range > 0)
2d0a075d 712 {
42e69d6b 713 range1 += (pageSize - 1);
2d0a075d
JS
714 }
715
0cf5de11 716 WinStruct<SCROLLINFO> info;
42e69d6b
VZ
717 info.nPage = pageSize; // Have to set this, or scrollbar goes awry
718 info.nMin = 0;
719 info.nMax = range1;
42e69d6b
VZ
720 info.fMask = SIF_RANGE | SIF_PAGE;
721
722 HWND hWnd = GetHwnd();
723 if ( hWnd )
0cf5de11 724 ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh);
2bda0e17
KB
725}
726
1e6feb95 727void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh)
2bda0e17 728{
0cf5de11 729 WinStruct<SCROLLINFO> info;
42e69d6b 730 info.nPage = page;
42e69d6b
VZ
731 info.fMask = SIF_PAGE;
732
733 HWND hWnd = GetHwnd();
734 if ( hWnd )
0cf5de11 735 ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh);
42e69d6b 736}
2bda0e17 737
1e6feb95 738int wxWindowMSW::GetScrollPage(int orient) const
42e69d6b 739{
0cf5de11 740 return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
2bda0e17
KB
741}
742
42e69d6b
VZ
743#endif // WXWIN_COMPATIBILITY
744
9cd6d737
VZ
745inline int GetScrollPosition(HWND hWnd, int wOrient)
746{
747#ifdef __WXMICROWIN__
748 return ::GetScrollPosWX(hWnd, wOrient);
749#else
7f0586ef 750 SCROLLINFO scrollInfo;
4676948b 751 scrollInfo.cbSize = sizeof(SCROLLINFO);
7f0586ef
JS
752 scrollInfo.fMask = SIF_POS;
753 if ( !::GetScrollInfo(hWnd,
754 wOrient,
755 &scrollInfo) )
756 {
757 wxLogLastError(_T("GetScrollInfo"));
758 }
759 return scrollInfo.nPos;
760// return ::GetScrollPos(hWnd, wOrient);
9cd6d737
VZ
761#endif
762}
763
1e6feb95 764int wxWindowMSW::GetScrollPos(int orient) const
2bda0e17 765{
42e69d6b 766 HWND hWnd = GetHwnd();
9cd6d737
VZ
767 wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
768
0cf5de11 769 return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT);
42e69d6b 770}
2bda0e17 771
42e69d6b
VZ
772// This now returns the whole range, not just the number
773// of positions that we can scroll.
1e6feb95 774int wxWindowMSW::GetScrollRange(int orient) const
42e69d6b 775{
7f0586ef 776 int maxPos;
a23fd0e1 777 HWND hWnd = GetHwnd();
0cf5de11 778 if ( !hWnd )
42e69d6b 779 return 0;
7f0586ef 780#if 0
0cf5de11
VZ
781 ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
782 &minPos, &maxPos);
7f0586ef
JS
783#endif
784 SCROLLINFO scrollInfo;
785 scrollInfo.fMask = SIF_RANGE;
786 if ( !::GetScrollInfo(hWnd,
787 orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
788 &scrollInfo) )
789 {
790 wxLogLastError(_T("GetScrollInfo"));
791 }
792 maxPos = scrollInfo.nMax;
0cf5de11
VZ
793
794 // undo "range - 1" done in SetScrollbar()
795 return maxPos + 1;
cc2b7472 796}
2bda0e17 797
1e6feb95 798int wxWindowMSW::GetScrollThumb(int orient) const
2bda0e17 799{
0cf5de11 800 return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
2bda0e17
KB
801}
802
1e6feb95 803void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
2bda0e17 804{
5f3286d1
VZ
805 HWND hWnd = GetHwnd();
806 wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") );
72fd19a1 807
0cf5de11 808 WinStruct<SCROLLINFO> info;
42e69d6b
VZ
809 info.nPage = 0;
810 info.nMin = 0;
811 info.nPos = pos;
812 info.fMask = SIF_POS;
a647d42a
VZ
813 if ( HasFlag(wxALWAYS_SHOW_SB) )
814 {
815 // disable scrollbar instead of removing it then
816 info.fMask |= SIF_DISABLENOSCROLL;
817 }
2d0a075d 818
0cf5de11
VZ
819 ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
820 &info, refresh);
2bda0e17
KB
821}
822
42e69d6b 823// New function that will replace some of the above.
0cf5de11
VZ
824void wxWindowMSW::SetScrollbar(int orient,
825 int pos,
826 int pageSize,
827 int range,
828 bool refresh)
829{
830 WinStruct<SCROLLINFO> info;
831 info.nPage = pageSize;
832 info.nMin = 0; // range is nMax - nMin + 1
833 info.nMax = range - 1; // as both nMax and nMax are inclusive
42e69d6b
VZ
834 info.nPos = pos;
835 info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
a647d42a
VZ
836 if ( HasFlag(wxALWAYS_SHOW_SB) )
837 {
838 // disable scrollbar instead of removing it then
839 info.fMask |= SIF_DISABLENOSCROLL;
840 }
2bda0e17 841
42e69d6b
VZ
842 HWND hWnd = GetHwnd();
843 if ( hWnd )
81d66cf3 844 {
0cf5de11
VZ
845 ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
846 &info, refresh);
81d66cf3 847 }
0cf5de11
VZ
848
849 *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
81d66cf3
JS
850}
851
1e6feb95 852void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
2bda0e17 853{
574c939e
KB
854 RECT rect;
855 RECT *pr;
1e6feb95 856 if ( prect )
2d0a075d 857 {
1e6feb95
VZ
858 rect.left = prect->x;
859 rect.top = prect->y;
860 rect.right = prect->x + prect->width;
861 rect.bottom = prect->y + prect->height;
f797e53d
VZ
862 pr = &rect;
863 }
864 else
865 {
866 pr = NULL;
2d0a075d 867 }
2bda0e17 868
7f0586ef
JS
869#ifdef __WXWINCE__
870 // FIXME: is this the exact equivalent of the line below?
871 ::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_ERASE|SW_INVALIDATE);
872#else
f797e53d 873 ::ScrollWindow(GetHwnd(), dx, dy, pr, pr);
7f0586ef 874#endif
2bda0e17
KB
875}
876
9cd6d737 877static bool ScrollVertically(HWND hwnd, int kind, int count)
b9b3393e 878{
9cd6d737
VZ
879 int posStart = GetScrollPosition(hwnd, SB_VERT);
880
881 int pos = posStart;
c0cdd6cc
VZ
882 for ( int n = 0; n < count; n++ )
883 {
884 ::SendMessage(hwnd, WM_VSCROLL, kind, 0);
9cd6d737
VZ
885
886 int posNew = GetScrollPosition(hwnd, SB_VERT);
887 if ( posNew == pos )
888 {
889 // don't bother to continue, we're already at top/bottom
890 break;
891 }
892
893 pos = posNew;
c0cdd6cc 894 }
9cd6d737
VZ
895
896 return pos != posStart;
b9b3393e
VZ
897}
898
9cd6d737 899bool wxWindowMSW::ScrollLines(int lines)
b9b3393e
VZ
900{
901 bool down = lines > 0;
902
9cd6d737
VZ
903 return ScrollVertically(GetHwnd(),
904 down ? SB_LINEDOWN : SB_LINEUP,
905 down ? lines : -lines);
b9b3393e
VZ
906}
907
9cd6d737 908bool wxWindowMSW::ScrollPages(int pages)
b9b3393e
VZ
909{
910 bool down = pages > 0;
911
9cd6d737
VZ
912 return ScrollVertically(GetHwnd(),
913 down ? SB_PAGEDOWN : SB_PAGEUP,
914 down ? pages : -pages);
b9b3393e
VZ
915}
916
42e69d6b
VZ
917// ---------------------------------------------------------------------------
918// subclassing
919// ---------------------------------------------------------------------------
920
1e6feb95 921void wxWindowMSW::SubclassWin(WXHWND hWnd)
2bda0e17 922{
223d09f6 923 wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") );
2bda0e17 924
c50f1fb9 925 HWND hwnd = (HWND)hWnd;
223d09f6 926 wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") );
c50f1fb9
VZ
927
928 wxAssociateWinWithHandle(hwnd, this);
2bda0e17 929
eb5e4d9a 930 m_oldWndProc = (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC);
b2d5a7ee 931
b225f659
VZ
932 // we don't need to subclass the window of our own class (in the Windows
933 // sense of the word)
eb5e4d9a 934 if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
b225f659
VZ
935 {
936 ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc);
937 }
938 else
939 {
5a403e3f
VZ
940 // don't bother restoring it neither: this also makes it easy to
941 // implement IsOfStandardClass() method which returns TRUE for the
942 // standard controls and FALSE for the wxWindows own windows as it can
943 // simply check m_oldWndProc
b225f659
VZ
944 m_oldWndProc = NULL;
945 }
2bda0e17
KB
946}
947
1e6feb95 948void wxWindowMSW::UnsubclassWin()
2bda0e17 949{
42e69d6b 950 wxRemoveHandleAssociation(this);
2bda0e17 951
42e69d6b 952 // Restore old Window proc
c50f1fb9
VZ
953 HWND hwnd = GetHwnd();
954 if ( hwnd )
42e69d6b 955 {
c50f1fb9
VZ
956 m_hWnd = 0;
957
223d09f6 958 wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
c50f1fb9 959
b225f659 960 if ( m_oldWndProc )
42e69d6b 961 {
eb5e4d9a 962 if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) )
b225f659
VZ
963 {
964 ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc);
965 }
966
967 m_oldWndProc = NULL;
42e69d6b 968 }
42e69d6b 969 }
2bda0e17
KB
970}
971
eb5e4d9a
VS
972bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc)
973{
42cfcc58
VZ
974 // Unicows note: the code below works, but only because WNDCLASS contains
975 // original window handler rather that the unicows fake one. This may not
976 // be on purpose, though; if it stops working with future versions of
977 // unicows.dll, we can override unicows hooks by setting
978 // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own
979 // versions that keep track of fake<->real wnd proc mapping.
980 WNDCLASS cls;
981 if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) )
136cb3c7 982 {
42cfcc58 983 wxLogLastError(_T("GetClassInfo"));
eb5e4d9a 984
42cfcc58 985 return FALSE;
136cb3c7 986 }
42cfcc58
VZ
987
988 return wndProc == (WXFARPROC)cls.lpfnWndProc;
eb5e4d9a
VS
989}
990
b2d5a7ee
VZ
991// ----------------------------------------------------------------------------
992// Style handling
993// ----------------------------------------------------------------------------
994
995void wxWindowMSW::SetWindowStyleFlag(long flags)
996{
997 long flagsOld = GetWindowStyleFlag();
998 if ( flags == flagsOld )
999 return;
1000
1001 // update the internal variable
1002 wxWindowBase::SetWindowStyleFlag(flags);
1003
5b2f31eb
VZ
1004 // now update the Windows style as well if needed - and if the window had
1005 // been already created
1006 if ( !GetHwnd() )
1007 return;
1008
b2d5a7ee
VZ
1009 WXDWORD exstyle, exstyleOld;
1010 long style = MSWGetStyle(flags, &exstyle),
1011 styleOld = MSWGetStyle(flagsOld, &exstyleOld);
1012
1013 if ( style != styleOld )
1014 {
1015 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1016 // this function so instead of simply setting the style to the new
1017 // value we clear the bits which were set in styleOld but are set in
1018 // the new one and set the ones which were not set before
1019 long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE);
1020 styleReal &= ~styleOld;
1021 styleReal |= style;
1022
1023 ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
1024 }
1025
1026 // and the extended style
1027 if ( exstyle != exstyleOld )
1028 {
1029 long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
1030 exstyleReal &= ~exstyleOld;
1031 exstyleReal |= exstyle;
1032
1033 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
1034
1035 // we must call SetWindowPos() to flash the cached extended style and
1036 // also to make the change to wxSTAY_ON_TOP style take effect: just
1037 // setting the style simply doesn't work
1038 if ( !::SetWindowPos(GetHwnd(),
1039 exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
1040 : HWND_NOTOPMOST,
1041 0, 0, 0, 0,
1042 SWP_NOMOVE | SWP_NOSIZE) )
1043 {
1044 wxLogLastError(_T("SetWindowPos"));
1045 }
1046 }
1047}
1048
1049WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
1050{
1051 // translate the style
6ae0daf6 1052 WXDWORD style = WS_CHILD | WS_VISIBLE;
b2d5a7ee
VZ
1053
1054 if ( flags & wxCLIP_CHILDREN )
1055 style |= WS_CLIPCHILDREN;
1056
1057 if ( flags & wxCLIP_SIBLINGS )
1058 style |= WS_CLIPSIBLINGS;
1059
f9007c32
JS
1060 if ( flags & wxVSCROLL )
1061 style |= WS_VSCROLL;
1062
1063 if ( flags & wxHSCROLL )
1064 style |= WS_HSCROLL;
1065
65bc172c 1066 const wxBorder border = GetBorder(flags);
577baeef 1067
65bc172c
VZ
1068 // WS_BORDER is only required for wxBORDER_SIMPLE
1069 if ( border == wxBORDER_SIMPLE )
b2d5a7ee 1070 style |= WS_BORDER;
577baeef 1071
b2d5a7ee
VZ
1072 // now deal with ext style if the caller wants it
1073 if ( exstyle )
1074 {
1075 *exstyle = 0;
1076
7f0586ef 1077#ifndef __WXWINCE__
b2d5a7ee
VZ
1078 if ( flags & wxTRANSPARENT_WINDOW )
1079 *exstyle |= WS_EX_TRANSPARENT;
7f0586ef 1080#endif
b2d5a7ee 1081
fe3d9123 1082 switch ( border )
b2d5a7ee
VZ
1083 {
1084 default:
65bc172c 1085 case wxBORDER_DEFAULT:
b2d5a7ee
VZ
1086 wxFAIL_MSG( _T("unknown border style") );
1087 // fall through
1088
1089 case wxBORDER_NONE:
1090 case wxBORDER_SIMPLE:
1091 break;
1092
1093 case wxBORDER_STATIC:
1094 *exstyle |= WS_EX_STATICEDGE;
1095 break;
1096
1097 case wxBORDER_RAISED:
7699361c 1098 *exstyle |= WS_EX_DLGMODALFRAME;
b2d5a7ee
VZ
1099 break;
1100
b2d5a7ee
VZ
1101 case wxBORDER_SUNKEN:
1102 *exstyle |= WS_EX_CLIENTEDGE;
fe3d9123 1103 style &= ~WS_BORDER;
b2d5a7ee
VZ
1104 break;
1105
1106 case wxBORDER_DOUBLE:
1107 *exstyle |= WS_EX_DLGMODALFRAME;
1108 break;
1109 }
d515c32d 1110
09168de7 1111 // wxUniv doesn't use Windows dialog navigation functions at all
7f0586ef 1112#if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
5b9c12e1 1113 // to make the dialog navigation work with the nested panels we must
09168de7
VZ
1114 // use this style (top level windows such as dialogs don't need it)
1115 if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
d515c32d
VZ
1116 {
1117 *exstyle |= WS_EX_CONTROLPARENT;
1118 }
09168de7 1119#endif // __WXUNIVERSAL__
b2d5a7ee
VZ
1120 }
1121
1122 return style;
1123}
eb5e4d9a 1124
c455ab93 1125#if WXWIN_COMPATIBILITY
42e69d6b
VZ
1126// If nothing defined for this, try the parent.
1127// E.g. we may be a button loaded from a resource, with no callback function
1128// defined.
1e6feb95 1129void wxWindowMSW::OnCommand(wxWindow& win, wxCommandEvent& event)
2bda0e17 1130{
42e69d6b
VZ
1131 if ( GetEventHandler()->ProcessEvent(event) )
1132 return;
1133 if ( m_parent )
1134 m_parent->GetEventHandler()->OnCommand(win, event);
1135}
1136#endif // WXWIN_COMPATIBILITY_2
c085e333 1137
42e69d6b 1138#if WXWIN_COMPATIBILITY
1e6feb95 1139wxObject* wxWindowMSW::GetChild(int number) const
42e69d6b
VZ
1140{
1141 // Return a pointer to the Nth object in the Panel
1142 wxNode *node = GetChildren().First();
1143 int n = number;
1144 while (node && n--)
1145 node = node->Next();
1146 if ( node )
1147 {
1148 wxObject *obj = (wxObject *)node->Data();
1149 return(obj);
1150 }
1151 else
1152 return NULL;
1153}
1154#endif // WXWIN_COMPATIBILITY
2bda0e17 1155
42e69d6b 1156// Setup background and foreground colours correctly
1e6feb95 1157void wxWindowMSW::SetupColours()
42e69d6b
VZ
1158{
1159 if ( GetParent() )
1160 SetBackgroundColour(GetParent()->GetBackgroundColour());
1161}
a23fd0e1 1162
1e6feb95
VZ
1163bool wxWindowMSW::IsMouseInWindow() const
1164{
1165 // get the mouse position
1166 POINT pt;
1167 ::GetCursorPos(&pt);
1168
1169 // find the window which currently has the cursor and go up the window
1170 // chain until we find this window - or exhaust it
1171 HWND hwnd = ::WindowFromPoint(pt);
1172 while ( hwnd && (hwnd != GetHwnd()) )
1173 hwnd = ::GetParent(hwnd);
1174
1175 return hwnd != NULL;
1176}
1177
e39af974 1178void wxWindowMSW::OnInternalIdle()
42e69d6b
VZ
1179{
1180 // Check if we need to send a LEAVE event
1181 if ( m_mouseInWindow )
2d0a075d 1182 {
ee74faf9
VZ
1183 // note that we should generate the leave event whether the window has
1184 // or doesn't have mouse capture
1185 if ( !IsMouseInWindow() )
42e69d6b
VZ
1186 {
1187 // Generate a LEAVE event
1188 m_mouseInWindow = FALSE;
2bda0e17 1189
1e6feb95 1190 // Unfortunately the mouse button and keyboard state may have
e39af974 1191 // changed by the time the OnInternalIdle function is called, so 'state'
1e6feb95 1192 // may be meaningless.
42e69d6b 1193 int state = 0;
3f7bc32b 1194 if ( wxIsShiftDown() )
42e69d6b 1195 state |= MK_SHIFT;
3f7bc32b 1196 if ( wxIsCtrlDown() )
42e69d6b 1197 state |= MK_CONTROL;
54ca0d12
GRG
1198 if ( GetKeyState( VK_LBUTTON ) )
1199 state |= MK_LBUTTON;
1200 if ( GetKeyState( VK_MBUTTON ) )
1201 state |= MK_MBUTTON;
1202 if ( GetKeyState( VK_RBUTTON ) )
1203 state |= MK_RBUTTON;
33ac7e6f 1204
1e6feb95
VZ
1205 POINT pt;
1206 if ( !::GetCursorPos(&pt) )
1207 {
1208 wxLogLastError(_T("GetCursorPos"));
1209 }
c085e333 1210
1e6feb95
VZ
1211 // we need to have client coordinates here for symmetry with
1212 // wxEVT_ENTER_WINDOW
82c9f85c 1213 RECT rect = wxGetWindowRect(GetHwnd());
1e6feb95
VZ
1214 pt.x -= rect.left;
1215 pt.y -= rect.top;
1216
1217 wxMouseEvent event2(wxEVT_LEAVE_WINDOW);
1218 InitMouseEvent(event2, pt.x, pt.y, state);
1219
1220 (void)GetEventHandler()->ProcessEvent(event2);
42e69d6b
VZ
1221 }
1222 }
c085e333 1223
e39af974
JS
1224 if (wxUpdateUIEvent::CanUpdate(this))
1225 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
42e69d6b 1226}
568cb543 1227
42e69d6b 1228// Set this window to be the child of 'parent'.
1e6feb95 1229bool wxWindowMSW::Reparent(wxWindowBase *parent)
42e69d6b
VZ
1230{
1231 if ( !wxWindowBase::Reparent(parent) )
1232 return FALSE;
c085e333 1233
42e69d6b
VZ
1234 HWND hWndChild = GetHwnd();
1235 HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
a23fd0e1 1236
42e69d6b 1237 ::SetParent(hWndChild, hWndParent);
a23fd0e1 1238
42e69d6b
VZ
1239 return TRUE;
1240}
a23fd0e1 1241
1e6feb95 1242void wxWindowMSW::Clear()
42e69d6b 1243{
1e6feb95 1244 wxClientDC dc((wxWindow *)this);
42e69d6b
VZ
1245 wxBrush brush(GetBackgroundColour(), wxSOLID);
1246 dc.SetBackground(brush);
1247 dc.Clear();
1248}
a23fd0e1 1249
a0e449ff
VZ
1250static inline void SendSetRedraw(HWND hwnd, bool on)
1251{
c67d6888 1252#ifndef __WXMICROWIN__
a0e449ff 1253 ::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)on, 0);
c67d6888 1254#endif
a0e449ff
VZ
1255}
1256
1257void wxWindowMSW::Freeze()
1258{
94589c3f 1259 SendSetRedraw(GetHwnd(), FALSE);
a0e449ff
VZ
1260}
1261
1262void wxWindowMSW::Thaw()
1263{
94589c3f 1264 SendSetRedraw(GetHwnd(), TRUE);
c0cdd6cc
VZ
1265
1266 // we need to refresh everything or otherwise he invalidated area is not
1267 // repainted
1268 Refresh();
a0e449ff
VZ
1269}
1270
1e6feb95 1271void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
42e69d6b
VZ
1272{
1273 HWND hWnd = GetHwnd();
1274 if ( hWnd )
1275 {
1276 if ( rect )
1277 {
1278 RECT mswRect;
1279 mswRect.left = rect->x;
1280 mswRect.top = rect->y;
1281 mswRect.right = rect->x + rect->width;
1282 mswRect.bottom = rect->y + rect->height;
a23fd0e1 1283
42e69d6b
VZ
1284 ::InvalidateRect(hWnd, &mswRect, eraseBack);
1285 }
1286 else
1287 ::InvalidateRect(hWnd, NULL, eraseBack);
1288 }
1289}
a23fd0e1 1290
1e6feb95
VZ
1291void wxWindowMSW::Update()
1292{
1293 if ( !::UpdateWindow(GetHwnd()) )
1294 {
1295 wxLogLastError(_T("UpdateWindow"));
1296 }
2b5f62a0 1297
7f0586ef 1298#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95
VZ
1299 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1300 // handler needs to be really drawn right now
1301 (void)::GdiFlush();
1302#endif // __WIN32__
1303}
1304
42e69d6b
VZ
1305// ---------------------------------------------------------------------------
1306// drag and drop
1307// ---------------------------------------------------------------------------
a23fd0e1 1308
a23fd0e1 1309
4ce1efe1 1310#if wxUSE_DRAG_AND_DROP
1e6feb95 1311void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
42e69d6b
VZ
1312{
1313 if ( m_dropTarget != 0 ) {
1314 m_dropTarget->Revoke(m_hWnd);
1315 delete m_dropTarget;
1316 }
a23fd0e1 1317
42e69d6b
VZ
1318 m_dropTarget = pDropTarget;
1319 if ( m_dropTarget != 0 )
1320 m_dropTarget->Register(m_hWnd);
1321}
42e69d6b 1322#endif // wxUSE_DRAG_AND_DROP
2a47d3c1 1323
42e69d6b
VZ
1324// old style file-manager drag&drop support: we retain the old-style
1325// DragAcceptFiles in parallel with SetDropTarget.
1e6feb95 1326void wxWindowMSW::DragAcceptFiles(bool accept)
42e69d6b 1327{
7f0586ef 1328#if !defined(__WXWINCE__)
42e69d6b
VZ
1329 HWND hWnd = GetHwnd();
1330 if ( hWnd )
1331 ::DragAcceptFiles(hWnd, (BOOL)accept);
7f0586ef 1332#endif
42e69d6b 1333}
a23fd0e1 1334
42e69d6b
VZ
1335// ----------------------------------------------------------------------------
1336// tooltips
1337// ----------------------------------------------------------------------------
dbda9e86 1338
42e69d6b 1339#if wxUSE_TOOLTIPS
2d0a075d 1340
1e6feb95 1341void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
42e69d6b
VZ
1342{
1343 wxWindowBase::DoSetToolTip(tooltip);
839b865d 1344
42e69d6b 1345 if ( m_tooltip )
d4e5272b 1346 m_tooltip->SetWindow((wxWindow *)this);
42e69d6b 1347}
9a05fd8d 1348
42e69d6b 1349#endif // wxUSE_TOOLTIPS
9a05fd8d 1350
42e69d6b
VZ
1351// ---------------------------------------------------------------------------
1352// moving and resizing
1353// ---------------------------------------------------------------------------
839b865d 1354
42e69d6b 1355// Get total size
1e6feb95 1356void wxWindowMSW::DoGetSize(int *x, int *y) const
42e69d6b 1357{
82c9f85c
VZ
1358 RECT rect = wxGetWindowRect(GetHwnd());
1359
42e69d6b
VZ
1360 if ( x )
1361 *x = rect.right - rect.left;
1362 if ( y )
1363 *y = rect.bottom - rect.top;
1364}
1365
82c9f85c
VZ
1366// Get size *available for subwindows* i.e. excluding menu bar etc.
1367void wxWindowMSW::DoGetClientSize(int *x, int *y) const
42e69d6b 1368{
82c9f85c 1369 RECT rect = wxGetClientRect(GetHwnd());
42e69d6b 1370
82c9f85c
VZ
1371 if ( x )
1372 *x = rect.right;
1373 if ( y )
1374 *y = rect.bottom;
1375}
1376
1377void wxWindowMSW::DoGetPosition(int *x, int *y) const
1378{
1379 RECT rect = wxGetWindowRect(GetHwnd());
42e69d6b 1380
42e69d6b
VZ
1381 POINT point;
1382 point.x = rect.left;
1383 point.y = rect.top;
42e69d6b 1384
92049cd4
VZ
1385 // we do the adjustments with respect to the parent only for the "real"
1386 // children, not for the dialogs/frames
1387 if ( !IsTopLevel() )
42e69d6b 1388 {
92049cd4
VZ
1389 HWND hParentWnd = 0;
1390 wxWindow *parent = GetParent();
1391 if ( parent )
1392 hParentWnd = GetWinHwnd(parent);
1393
1394 // Since we now have the absolute screen coords, if there's a parent we
1395 // must subtract its top left corner
1396 if ( hParentWnd )
1397 {
1398 ::ScreenToClient(hParentWnd, &point);
1399 }
1400
89e3037c
GT
1401 if ( parent )
1402 {
1403 // We may be faking the client origin. So a window that's really at (0,
1404 // 30) may appear (to wxWin apps) to be at (0, 0).
1405 wxPoint pt(parent->GetClientAreaOrigin());
1406 point.x -= pt.x;
1407 point.y -= pt.y;
1408 }
42e69d6b
VZ
1409 }
1410
1411 if ( x )
1412 *x = point.x;
1413 if ( y )
1414 *y = point.y;
1415}
54bdd8b0 1416
1e6feb95 1417void wxWindowMSW::DoScreenToClient(int *x, int *y) const
42e69d6b
VZ
1418{
1419 POINT pt;
1420 if ( x )
1421 pt.x = *x;
1422 if ( y )
1423 pt.y = *y;
54bdd8b0 1424
82c9f85c 1425 ::ScreenToClient(GetHwnd(), &pt);
a23fd0e1 1426
42e69d6b
VZ
1427 if ( x )
1428 *x = pt.x;
1429 if ( y )
1430 *y = pt.y;
1431}
a23fd0e1 1432
1e6feb95 1433void wxWindowMSW::DoClientToScreen(int *x, int *y) const
42e69d6b
VZ
1434{
1435 POINT pt;
1436 if ( x )
1437 pt.x = *x;
1438 if ( y )
1439 pt.y = *y;
54bdd8b0 1440
82c9f85c 1441 ::ClientToScreen(GetHwnd(), &pt);
a23fd0e1 1442
42e69d6b
VZ
1443 if ( x )
1444 *x = pt.x;
1445 if ( y )
1446 *y = pt.y;
1447}
a23fd0e1 1448
1e6feb95 1449void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
b782f2e0 1450{
62e1ba75
JS
1451 // TODO: is this consistent with other platforms?
1452 // Still, negative width or height shouldn't be allowed
1453 if (width < 0)
1454 width = 0;
1455 if (height < 0)
1456 height = 0;
b782f2e0
VZ
1457 if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
1458 {
f6bcfd97 1459 wxLogLastError(wxT("MoveWindow"));
b782f2e0
VZ
1460 }
1461}
1462
4438caf4
VZ
1463// set the size of the window: if the dimensions are positive, just use them,
1464// but if any of them is equal to -1, it means that we must find the value for
1465// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1466// which case -1 is a valid value for x and y)
1467//
1468// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1469// the width/height to best suit our contents, otherwise we reuse the current
1470// width/height
1e6feb95 1471void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
42e69d6b 1472{
4438caf4 1473 // get the current size and position...
42e69d6b
VZ
1474 int currentX, currentY;
1475 GetPosition(&currentX, &currentY);
1476 int currentW,currentH;
1477 GetSize(&currentW, &currentH);
a23fd0e1 1478
4438caf4
VZ
1479 // ... and don't do anything (avoiding flicker) if it's already ok
1480 if ( x == currentX && y == currentY &&
1481 width == currentW && height == currentH )
1482 {
42e69d6b 1483 return;
4438caf4 1484 }
a23fd0e1 1485
f8c03547 1486 if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
4438caf4 1487 x = currentX;
f8c03547 1488 if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
4438caf4 1489 y = currentY;
a23fd0e1 1490
4438caf4 1491 AdjustForParentClientOrigin(x, y, sizeFlags);
a23fd0e1 1492
4438caf4 1493 wxSize size(-1, -1);
42e69d6b 1494 if ( width == -1 )
4438caf4 1495 {
9e2896e5 1496 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
4438caf4
VZ
1497 {
1498 size = DoGetBestSize();
1499 width = size.x;
1500 }
1501 else
1502 {
1503 // just take the current one
1504 width = currentW;
1505 }
1506 }
1507
42e69d6b 1508 if ( height == -1 )
4438caf4 1509 {
9e2896e5 1510 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
4438caf4
VZ
1511 {
1512 if ( size.x == -1 )
1513 {
b782f2e0 1514 size = DoGetBestSize();
4438caf4
VZ
1515 }
1516 //else: already called DoGetBestSize() above
a23fd0e1 1517
4438caf4
VZ
1518 height = size.y;
1519 }
1520 else
1521 {
1522 // just take the current one
1523 height = currentH;
1524 }
1525 }
1526
b782f2e0 1527 DoMoveWindow(x, y, width, height);
4438caf4
VZ
1528}
1529
1e6feb95 1530void wxWindowMSW::DoSetClientSize(int width, int height)
42e69d6b 1531{
d4597e13
VZ
1532 // setting the client size is less obvious than it it could have been
1533 // because in the result of changing the total size the window scrollbar
1534 // may [dis]appear and/or its menubar may [un]wrap and so the client size
1535 // will not be correct as the difference between the total and client size
1536 // changes - so we keep changing it until we get it right
1537 //
d6a97306
VZ
1538 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1539 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1540 // may become 3 if the window had 0 size originally and so we didn't
1541 // calculate the scrollbar correction correctly during the first iteration)
1542 // but just to be on the safe side we check for it instead of making it an
d4597e13 1543 // "infinite" loop (i.e. leaving break inside as the only way to get out)
d6a97306 1544 for ( int i = 0; i < 4; i++ )
d4597e13
VZ
1545 {
1546 RECT rectClient;
1547 ::GetClientRect(GetHwnd(), &rectClient);
2bda0e17 1548
d4597e13 1549 // if the size is already ok, stop here (rectClient.left = top = 0)
9fce8d2e
JS
1550 if ( (rectClient.right == width || width == -1) &&
1551 (rectClient.bottom == height || height == -1) )
d4597e13
VZ
1552 {
1553 break;
1554 }
a23fd0e1 1555
d4597e13
VZ
1556 int widthClient = width,
1557 heightClient = height;
a23fd0e1 1558
d4597e13
VZ
1559 // Find the difference between the entire window (title bar and all)
1560 // and the client area; add this to the new client size to move the
1561 // window
1562 RECT rectWin;
1563 ::GetWindowRect(GetHwnd(), &rectWin);
1564
1565 widthClient += rectWin.right - rectWin.left - rectClient.right;
1566 heightClient += rectWin.bottom - rectWin.top - rectClient.bottom;
1567
1568 POINT point;
1569 point.x = rectWin.left;
1570 point.y = rectWin.top;
387a3b02 1571
d4597e13
VZ
1572 // MoveWindow positions the child windows relative to the parent, so
1573 // adjust if necessary
1574 if ( !IsTopLevel() )
1575 {
1576 wxWindow *parent = GetParent();
1577 if ( parent )
1578 {
1579 ::ScreenToClient(GetHwndOf(parent), &point);
1580 }
1581 }
a23fd0e1 1582
d4597e13
VZ
1583 DoMoveWindow(point.x, point.y, widthClient, heightClient);
1584 }
42e69d6b 1585}
a23fd0e1 1586
42e69d6b
VZ
1587// For implementation purposes - sometimes decorations make the client area
1588// smaller
1e6feb95 1589wxPoint wxWindowMSW::GetClientAreaOrigin() const
42e69d6b
VZ
1590{
1591 return wxPoint(0, 0);
1592}
a23fd0e1 1593
42e69d6b
VZ
1594// ---------------------------------------------------------------------------
1595// text metrics
1596// ---------------------------------------------------------------------------
a23fd0e1 1597
1e6feb95 1598int wxWindowMSW::GetCharHeight() const
42e69d6b 1599{
f6bcfd97 1600 return wxGetTextMetrics(this).tmHeight;
42e69d6b 1601}
3eddf563 1602
1e6feb95 1603int wxWindowMSW::GetCharWidth() const
42e69d6b 1604{
f6bcfd97
BP
1605 // +1 is needed because Windows apparently adds it when calculating the
1606 // dialog units size in pixels
1607#if wxDIALOG_UNIT_COMPATIBILITY
1e6feb95 1608 return wxGetTextMetrics(this).tmAveCharWidth;
f6bcfd97
BP
1609#else
1610 return wxGetTextMetrics(this).tmAveCharWidth + 1;
1611#endif
42e69d6b 1612}
f4621a09 1613
1e6feb95 1614void wxWindowMSW::GetTextExtent(const wxString& string,
34636400 1615 int *x, int *y,
42e69d6b
VZ
1616 int *descent, int *externalLeading,
1617 const wxFont *theFont) const
1618{
1619 const wxFont *fontToUse = theFont;
1620 if ( !fontToUse )
1621 fontToUse = &m_font;
634903fd 1622
42e69d6b
VZ
1623 HWND hWnd = GetHwnd();
1624 HDC dc = ::GetDC(hWnd);
634903fd 1625
42e69d6b
VZ
1626 HFONT fnt = 0;
1627 HFONT hfontOld = 0;
1628 if ( fontToUse && fontToUse->Ok() )
1629 {
1630 fnt = (HFONT)((wxFont *)fontToUse)->GetResourceHandle(); // const_cast
1631 if ( fnt )
1632 hfontOld = (HFONT)SelectObject(dc,fnt);
2bda0e17 1633 }
341c92a8 1634
42e69d6b
VZ
1635 SIZE sizeRect;
1636 TEXTMETRIC tm;
4438caf4 1637 GetTextExtentPoint(dc, string, (int)string.Length(), &sizeRect);
42e69d6b
VZ
1638 GetTextMetrics(dc, &tm);
1639
1640 if ( fontToUse && fnt && hfontOld )
1641 SelectObject(dc, hfontOld);
1642
1643 ReleaseDC(hWnd, dc);
1644
0655ad29
VZ
1645 if ( x )
1646 *x = sizeRect.cx;
1647 if ( y )
1648 *y = sizeRect.cy;
1649 if ( descent )
1650 *descent = tm.tmDescent;
1651 if ( externalLeading )
1652 *externalLeading = tm.tmExternalLeading;
2bda0e17
KB
1653}
1654
c455ab93 1655#if wxUSE_CARET && WXWIN_COMPATIBILITY
42e69d6b
VZ
1656// ---------------------------------------------------------------------------
1657// Caret manipulation
1658// ---------------------------------------------------------------------------
1659
1e6feb95 1660void wxWindowMSW::CreateCaret(int w, int h)
2bda0e17 1661{
789295bf 1662 SetCaret(new wxCaret(this, w, h));
2bda0e17
KB
1663}
1664
1e6feb95 1665void wxWindowMSW::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
2bda0e17 1666{
789295bf 1667 wxFAIL_MSG("not implemented");
2bda0e17
KB
1668}
1669
1e6feb95 1670void wxWindowMSW::ShowCaret(bool show)
2bda0e17 1671{
789295bf
VZ
1672 wxCHECK_RET( m_caret, "no caret to show" );
1673
1674 m_caret->Show(show);
2bda0e17
KB
1675}
1676
1e6feb95 1677void wxWindowMSW::DestroyCaret()
2bda0e17 1678{
789295bf 1679 SetCaret(NULL);
2bda0e17
KB
1680}
1681
1e6feb95 1682void wxWindowMSW::SetCaretPos(int x, int y)
2bda0e17 1683{
789295bf
VZ
1684 wxCHECK_RET( m_caret, "no caret to move" );
1685
1686 m_caret->Move(x, y);
2bda0e17
KB
1687}
1688
1e6feb95 1689void wxWindowMSW::GetCaretPos(int *x, int *y) const
2d0a075d 1690{
789295bf
VZ
1691 wxCHECK_RET( m_caret, "no caret to get position of" );
1692
1693 m_caret->GetPosition(x, y);
42e69d6b 1694}
789295bf 1695#endif // wxUSE_CARET
2bda0e17 1696
c50f1fb9
VZ
1697// ---------------------------------------------------------------------------
1698// popup menu
1699// ---------------------------------------------------------------------------
1700
2e9f62da
VZ
1701#if wxUSE_MENUS_NATIVE
1702
ed45e263
VZ
1703// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
1704// immediately, without waiting for the next event loop iteration
1705//
1706// NB: this function should probably be made public later as it can almost
1707// surely replace wxYield() elsewhere as well
1708static void wxYieldForCommandsOnly()
1709{
1710 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
1711 // want to process it here)
1712 MSG msg;
1713 while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE)
1714 && msg.message != WM_QUIT )
1715 {
1716 wxTheApp->DoMessage((WXMSG *)&msg);
1717 }
7de59551 1718
2b5f62a0
VZ
1719 // If we retrieved a WM_QUIT, insert back into the message queue.
1720 if (msg.message == WM_QUIT)
1721 ::PostQuitMessage(0);
ed45e263
VZ
1722}
1723
1e6feb95 1724bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
c50f1fb9
VZ
1725{
1726 menu->SetInvokingWindow(this);
1727 menu->UpdateUI();
1728
1729 HWND hWnd = GetHwnd();
1730 HMENU hMenu = GetHmenuOf(menu);
1731 POINT point;
1732 point.x = x;
1733 point.y = y;
1734 ::ClientToScreen(hWnd, &point);
1735 wxCurrentPopupMenu = menu;
7f0586ef
JS
1736 UINT flags = 0;
1737#if !defined(__WXWINCE__)
1738 flags = TPM_RIGHTBUTTON;
1739#endif
1740 ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
ed45e263
VZ
1741
1742 // we need to do it righ now as otherwise the events are never going to be
1743 // sent to wxCurrentPopupMenu from HandleCommand()
1744 //
1745 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
1746 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
1747 // destroyed as soon as we return (it can be a local variable in the caller
1748 // for example) and so we do need to process the event immediately
1749 wxYieldForCommandsOnly();
1750
c50f1fb9
VZ
1751 wxCurrentPopupMenu = NULL;
1752
1753 menu->SetInvokingWindow(NULL);
1754
1755 return TRUE;
1756}
1757
1e6feb95
VZ
1758#endif // wxUSE_MENUS_NATIVE
1759
42e69d6b
VZ
1760// ===========================================================================
1761// pre/post message processing
1762// ===========================================================================
2bda0e17 1763
1e6feb95 1764long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
42e69d6b
VZ
1765{
1766 if ( m_oldWndProc )
1767 return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
1768 else
1769 return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
1770}
2bda0e17 1771
1e6feb95 1772bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
42e69d6b 1773{
1e6feb95
VZ
1774 // wxUniversal implements tab traversal itself
1775#ifndef __WXUNIVERSAL__
42e69d6b 1776 if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) )
2d0a075d 1777 {
42e69d6b
VZ
1778 // intercept dialog navigation keys
1779 MSG *msg = (MSG *)pMsg;
d9317fd4
VZ
1780
1781 // here we try to do all the job which ::IsDialogMessage() usually does
1782 // internally
d9506e77 1783#if 1
573a1586 1784 if ( msg->message == WM_KEYDOWN )
42e69d6b 1785 {
3f7bc32b
VZ
1786 bool bCtrlDown = wxIsCtrlDown();
1787 bool bShiftDown = wxIsShiftDown();
a23fd0e1 1788
42e69d6b
VZ
1789 // WM_GETDLGCODE: ask the control if it wants the key for itself,
1790 // don't process it if it's the case (except for Ctrl-Tab/Enter
1791 // combinations which are always processed)
1792 LONG lDlgCode = 0;
1793 if ( !bCtrlDown )
1794 {
1795 lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0);
2b5f62a0
VZ
1796
1797 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
1798 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
1799 // it, of course, implies them
1800 if ( lDlgCode & DLGC_WANTALLKEYS )
1801 {
1802 lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS;
1803 }
42e69d6b 1804 }
a23fd0e1 1805
42e69d6b
VZ
1806 bool bForward = TRUE,
1807 bWindowChange = FALSE;
a23fd0e1 1808
573a1586
VZ
1809 // should we process this message specially?
1810 bool bProcess = TRUE;
9145664b 1811 switch ( msg->wParam )
42e69d6b
VZ
1812 {
1813 case VK_TAB:
319fefa9
VZ
1814 // assume that nobody wants Shift-TAB for himself - if we
1815 // don't do it there is no easy way for a control to grab
1816 // TABs but still let Shift-TAB work as navugation key
1817 if ( (lDlgCode & DLGC_WANTTAB) && !bShiftDown ) {
42e69d6b
VZ
1818 bProcess = FALSE;
1819 }
1820 else {
1821 // Ctrl-Tab cycles thru notebook pages
1822 bWindowChange = bCtrlDown;
319fefa9 1823 bForward = !bShiftDown;
42e69d6b
VZ
1824 }
1825 break;
a23fd0e1 1826
42e69d6b
VZ
1827 case VK_UP:
1828 case VK_LEFT:
1829 if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
1830 bProcess = FALSE;
1831 else
1832 bForward = FALSE;
1833 break;
a02eb1d2 1834
42e69d6b
VZ
1835 case VK_DOWN:
1836 case VK_RIGHT:
1837 if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
1838 bProcess = FALSE;
1839 break;
2bda0e17 1840
42e69d6b
VZ
1841 case VK_RETURN:
1842 {
edccf428 1843 if ( (lDlgCode & DLGC_WANTMESSAGE) && !bCtrlDown )
42e69d6b
VZ
1844 {
1845 // control wants to process Enter itself, don't
1846 // call IsDialogMessage() which would interpret
1847 // it
1848 return FALSE;
1849 }
319fefa9
VZ
1850 else if ( lDlgCode & DLGC_BUTTON )
1851 {
3e79ed96
VZ
1852 // let IsDialogMessage() handle this for all
1853 // buttons except the owner-drawn ones which it
1854 // just seems to ignore
1855 long style = ::GetWindowLong(msg->hwnd, GWL_STYLE);
1856 if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
1857 {
1858 // emulate the button click
1859 wxWindow *btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
1860 if ( btn )
1861 btn->MSWCommand(BN_CLICKED, 0 /* unused */);
1862 }
1863
319fefa9
VZ
1864 bProcess = FALSE;
1865 }
456bc6d9
VZ
1866 // FIXME: this should be handled by
1867 // wxNavigationKeyEvent handler and not here!!
c50f1fb9
VZ
1868 else
1869 {
91a62137 1870#if wxUSE_BUTTON
456bc6d9
VZ
1871 wxButton *btn = wxDynamicCast(GetDefaultItem(),
1872 wxButton);
73927f8b 1873 if ( btn && btn->IsEnabled() )
c50f1fb9
VZ
1874 {
1875 // if we do have a default button, do press it
1876 btn->MSWCommand(BN_CLICKED, 0 /* unused */);
1877
1878 return TRUE;
1879 }
a6e67b55
VZ
1880 else // no default button
1881 {
1e6feb95 1882#endif // wxUSE_BUTTON
a6e67b55
VZ
1883 // this is a quick and dirty test for a text
1884 // control
1885 if ( !(lDlgCode & DLGC_HASSETSEL) )
1886 {
1887 // don't process Enter, the control might
1888 // need it for itself and don't let
1889 // ::IsDialogMessage() have it as it can
1890 // eat the Enter events sometimes
1891 return FALSE;
1892 }
2b5f62a0
VZ
1893 else if (!IsTopLevel())
1894 {
1895 // if not a top level window, let parent
1896 // handle it
1897 return FALSE;
1898 }
a6e67b55
VZ
1899 //else: treat Enter as TAB: pass to the next
1900 // control as this is the best thing to do
1901 // if the text doesn't handle Enter itself
1902 }
91a62137 1903 }
42e69d6b
VZ
1904 }
1905 break;
2bda0e17 1906
42e69d6b
VZ
1907 default:
1908 bProcess = FALSE;
1909 }
2bda0e17 1910
42e69d6b
VZ
1911 if ( bProcess )
1912 {
1913 wxNavigationKeyEvent event;
1914 event.SetDirection(bForward);
1915 event.SetWindowChange(bWindowChange);
1916 event.SetEventObject(this);
3572173c 1917
42e69d6b 1918 if ( GetEventHandler()->ProcessEvent(event) )
57c0af52 1919 {
42e69d6b 1920 return TRUE;
57c0af52 1921 }
42e69d6b
VZ
1922 }
1923 }
91a62137 1924#else // 0
d9317fd4
VZ
1925 // let ::IsDialogMessage() do almost everything and handle just the
1926 // things it doesn't here: Ctrl-TAB for switching notebook pages
1927 if ( msg->message == WM_KEYDOWN )
1928 {
1929 // don't process system keys here
1930 if ( !(HIWORD(msg->lParam) & KF_ALTDOWN) )
1931 {
3f7bc32b 1932 if ( (msg->wParam == VK_TAB) && wxIsCtrlDown() )
d9317fd4
VZ
1933 {
1934 // find the first notebook parent and change its page
1935 wxWindow *win = this;
1936 wxNotebook *nbook = NULL;
1937 while ( win && !nbook )
1938 {
1939 nbook = wxDynamicCast(win, wxNotebook);
1940 win = win->GetParent();
1941 }
1942
1943 if ( nbook )
1944 {
3f7bc32b 1945 bool forward = !wxIsShiftDown();
d9317fd4
VZ
1946
1947 nbook->AdvanceSelection(forward);
1948 }
1949 }
1950 }
1951 }
91a62137 1952#endif // 1/0
a23fd0e1 1953
aae032a0
VZ
1954 // we handle VK_ESCAPE ourselves in wxDialog::OnCharHook() and we
1955 // shouldn't let IsDialogMessage() get it as it _always_ eats the
1956 // message even when there is no cancel button and when the message is
1957 // needed by the control itself: in particular, it prevents the tree in
1958 // place edit control from being closed with Escape in a dialog
1959 if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE )
f6bcfd97 1960 {
ae79d315
VZ
1961 // ::IsDialogMessage() is broken and may sometimes hang the
1962 // application by going into an infinite loop, so we try to detect
1963 // [some of] the situatations when this may happen and not call it
1964 // then
1965
1966 // assume we can call it by default
085ad686
VZ
1967 bool canSafelyCallIsDlgMsg = TRUE;
1968
48c61225 1969 HWND hwndFocus = ::GetFocus();
ae79d315
VZ
1970
1971 // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter
1972 // an infinite loop, because it will recursively check the child
1973 // windows but not the window itself and so if none of the children
1974 // accepts focus it loops forever (as it only stops when it gets
1975 // back to the window it started from)
1976 //
1977 // while it is very unusual that a window with WS_EX_CONTROLPARENT
1978 // style has the focus, it can happen. One such possibility is if
1979 // all windows are either toplevel, wxDialog, wxPanel or static
1980 // controls and no window can actually accept keyboard input.
7f0586ef 1981#if !defined(__WXWINCE__)
ae79d315 1982 if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
aae032a0 1983 {
ae79d315
VZ
1984 // passimistic by default
1985 canSafelyCallIsDlgMsg = FALSE;
222ed1d6 1986 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
ae79d315
VZ
1987 node;
1988 node = node->GetNext() )
70a5eef8 1989 {
ae79d315
VZ
1990 if ( node->GetData()->AcceptsFocus() )
1991 {
1992 // it shouldn't hang...
1993 canSafelyCallIsDlgMsg = TRUE;
48c61225 1994
ae79d315
VZ
1995 break;
1996 }
48c61225 1997 }
ae79d315 1998 }
7f0586ef 1999#endif
48c61225 2000
ae79d315
VZ
2001 if ( canSafelyCallIsDlgMsg )
2002 {
2003 // ::IsDialogMessage() can enter in an infinite loop when the
2004 // currently focused window is disabled or hidden and its
2005 // parent has WS_EX_CONTROLPARENT style, so don't call it in
2006 // this case
2007 while ( hwndFocus )
48c61225 2008 {
ae79d315
VZ
2009 if ( !::IsWindowEnabled(hwndFocus) ||
2010 !::IsWindowVisible(hwndFocus) )
2011 {
2012 // it would enter an infinite loop if we do this!
2013 canSafelyCallIsDlgMsg = FALSE;
2014
2015 break;
2016 }
48c61225 2017
ae79d315
VZ
2018 if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
2019 {
2020 // it's a top level window, don't go further -- e.g. even
2021 // if the parent of a dialog is disabled, this doesn't
2022 // break navigation inside the dialog
2023 break;
2024 }
2025
2026 hwndFocus = ::GetParent(hwndFocus);
2027 }
085ad686
VZ
2028 }
2029
ae79d315 2030 // let IsDialogMessage() have the message if it's safe to call it
085ad686
VZ
2031 if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
2032 {
2033 // IsDialogMessage() did something...
2034 return TRUE;
aae032a0 2035 }
f6bcfd97 2036 }
42e69d6b 2037 }
1e6feb95 2038#endif // __WXUNIVERSAL__
a23fd0e1 2039
42e69d6b
VZ
2040#if wxUSE_TOOLTIPS
2041 if ( m_tooltip )
387a3b02 2042 {
42e69d6b
VZ
2043 // relay mouse move events to the tooltip control
2044 MSG *msg = (MSG *)pMsg;
2045 if ( msg->message == WM_MOUSEMOVE )
2046 m_tooltip->RelayEvent(pMsg);
387a3b02 2047 }
42e69d6b 2048#endif // wxUSE_TOOLTIPS
a23fd0e1 2049
42e69d6b 2050 return FALSE;
387a3b02
JS
2051}
2052
1e6feb95 2053bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg)
387a3b02 2054{
1e6feb95 2055#if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
c50f1fb9 2056 return m_acceleratorTable.Translate(this, pMsg);
1e6feb95 2057#else
574c939e 2058 (void) pMsg;
1e6feb95
VZ
2059 return FALSE;
2060#endif // wxUSE_ACCEL
387a3b02
JS
2061}
2062
574c939e 2063bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* WXUNUSED(pMsg))
a37d422a
VZ
2064{
2065 // preprocess all messages by default
2066 return TRUE;
2067}
2068
42e69d6b 2069// ---------------------------------------------------------------------------
e39af974 2070// message params unpackers
42e69d6b 2071// ---------------------------------------------------------------------------
2bda0e17 2072
1e6feb95 2073void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b
VZ
2074 WORD *id, WXHWND *hwnd, WORD *cmd)
2075{
2076 *id = LOWORD(wParam);
2077 *hwnd = (WXHWND)lParam;
2078 *cmd = HIWORD(wParam);
2bda0e17
KB
2079}
2080
1e6feb95 2081void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2082 WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
2bda0e17 2083{
42e69d6b
VZ
2084 *state = LOWORD(wParam);
2085 *minimized = HIWORD(wParam);
2086 *hwnd = (WXHWND)lParam;
2bda0e17
KB
2087}
2088
1e6feb95 2089void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2090 WXWORD *code, WXWORD *pos, WXHWND *hwnd)
2bda0e17 2091{
42e69d6b
VZ
2092 *code = LOWORD(wParam);
2093 *pos = HIWORD(wParam);
2094 *hwnd = (WXHWND)lParam;
2095}
a23fd0e1 2096
1e6feb95 2097void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b
VZ
2098 WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd)
2099{
04ef50df 2100#ifndef __WXMICROWIN__
42e69d6b
VZ
2101 *nCtlColor = CTLCOLOR_BTN;
2102 *hwnd = (WXHWND)lParam;
2103 *hdc = (WXHDC)wParam;
04ef50df 2104#endif
2bda0e17
KB
2105}
2106
1e6feb95 2107void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2108 WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
2bda0e17 2109{
42e69d6b
VZ
2110 *item = (WXWORD)wParam;
2111 *flags = HIWORD(wParam);
2112 *hmenu = (WXHMENU)lParam;
2113}
c085e333 2114
42e69d6b
VZ
2115// ---------------------------------------------------------------------------
2116// Main wxWindows window proc and the window proc for wxWindow
2117// ---------------------------------------------------------------------------
2bda0e17 2118
42e69d6b
VZ
2119// Hook for new window just as it's being created, when the window isn't yet
2120// associated with the handle
b225f659
VZ
2121static wxWindowMSW *gs_winBeingCreated = NULL;
2122
2123// implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2124// window being created and insures that it's always unset back later
2125wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW *winBeingCreated)
2126{
2127 gs_winBeingCreated = winBeingCreated;
2128}
2129
2130wxWindowCreationHook::~wxWindowCreationHook()
2131{
2132 gs_winBeingCreated = NULL;
2133}
42e69d6b
VZ
2134
2135// Main window proc
3135f4a7 2136LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2bda0e17 2137{
42e69d6b
VZ
2138 // trace all messages - useful for the debugging
2139#ifdef __WXDEBUG__
13e4c4d9
VZ
2140 wxLogTrace(wxTraceMessages,
2141 wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
2142 wxGetMessageName(message), (long)hWnd, (long)wParam, lParam);
42e69d6b 2143#endif // __WXDEBUG__
2bda0e17 2144
1e6feb95 2145 wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
c085e333 2146
42e69d6b 2147 // when we get the first message for the HWND we just created, we associate
b225f659
VZ
2148 // it with wxWindow stored in gs_winBeingCreated
2149 if ( !wnd && gs_winBeingCreated )
2d0a075d 2150 {
b225f659
VZ
2151 wxAssociateWinWithHandle(hWnd, gs_winBeingCreated);
2152 wnd = gs_winBeingCreated;
2153 gs_winBeingCreated = NULL;
42e69d6b 2154 wnd->SetHWND((WXHWND)hWnd);
2d0a075d 2155 }
2bda0e17 2156
42e69d6b 2157 LRESULT rc;
a23fd0e1 2158
b225f659
VZ
2159 if ( wnd )
2160 rc = wnd->MSWWindowProc(message, wParam, lParam);
a23fd0e1 2161 else
b225f659 2162 rc = ::DefWindowProc(hWnd, message, wParam, lParam);
2bda0e17 2163
42e69d6b 2164 return rc;
f7bd2698
JS
2165}
2166
1e6feb95 2167long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
f7bd2698 2168{
42e69d6b
VZ
2169 // did we process the message?
2170 bool processed = FALSE;
f7bd2698 2171
42e69d6b
VZ
2172 // the return value
2173 union
2bda0e17 2174 {
42e69d6b
VZ
2175 bool allow;
2176 long result;
2177 WXHICON hIcon;
2178 WXHBRUSH hBrush;
2179 } rc;
2bda0e17 2180
42e69d6b
VZ
2181 // for most messages we should return 0 when we do process the message
2182 rc.result = 0;
2bda0e17 2183
42e69d6b 2184 switch ( message )
39136494 2185 {
42e69d6b
VZ
2186 case WM_CREATE:
2187 {
2188 bool mayCreate;
2189 processed = HandleCreate((WXLPCREATESTRUCT)lParam, &mayCreate);
2190 if ( processed )
2191 {
2192 // return 0 to allow window creation
2193 rc.result = mayCreate ? 0 : -1;
2194 }
2195 }
2196 break;
47cbd6da 2197
42e69d6b 2198 case WM_DESTROY:
ad4297f3
VZ
2199 // never set processed to TRUE and *always* pass WM_DESTROY to
2200 // DefWindowProc() as Windows may do some internal cleanup when
2201 // processing it and failing to pass the message along may cause
2202 // memory and resource leaks!
2203 (void)HandleDestroy();
42e69d6b
VZ
2204 break;
2205
2206 case WM_MOVE:
132cb640 2207 processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
42e69d6b 2208 break;
47cbd6da 2209
7f0586ef 2210#if !defined(__WXWINCE__)
5706de1c 2211 case WM_MOVING:
540b6b09
VZ
2212 {
2213 LPRECT pRect = (LPRECT)lParam;
2214 wxRect rc;
2215 rc.SetLeft(pRect->left);
2216 rc.SetTop(pRect->top);
2217 rc.SetRight(pRect->right);
2218 rc.SetBottom(pRect->bottom);
2219 processed = HandleMoving(rc);
2220 if (processed) {
2221 pRect->left = rc.GetLeft();
2222 pRect->top = rc.GetTop();
2223 pRect->right = rc.GetRight();
2224 pRect->bottom = rc.GetBottom();
2225 }
2226 }
5706de1c 2227 break;
7f0586ef 2228#endif
5706de1c 2229
42e69d6b 2230 case WM_SIZE:
1e6feb95
VZ
2231 switch ( wParam )
2232 {
2233 case SIZE_MAXHIDE:
2234 case SIZE_MAXSHOW:
2235 // we're not interested in these messages at all
2236 break;
2237
2238 case SIZE_MINIMIZED:
2239 // we shouldn't send sizev events for these messages as the
2240 // client size may be negative which breaks existing code
2241 //
2242 // OTOH we might send another (wxMinimizedEvent?) one or
2243 // add an additional parameter to wxSizeEvent if this is
2244 // useful to anybody
2245 break;
2246
2247 default:
2248 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
2249 // fall through nevertheless
2250
2251 case SIZE_MAXIMIZED:
2252 case SIZE_RESTORED:
2253 processed = HandleSize(LOWORD(lParam), HIWORD(lParam),
2254 wParam);
2255 }
2256 break;
2257
7f0586ef 2258#if !defined(__WXWINCE__)
5706de1c
JS
2259 case WM_SIZING:
2260 {
2261 LPRECT pRect = (LPRECT)lParam;
2262 wxRect rc;
2263 rc.SetLeft(pRect->left);
2264 rc.SetTop(pRect->top);
2265 rc.SetRight(pRect->right);
2266 rc.SetBottom(pRect->bottom);
2267 processed = HandleSizing(rc);
2268 if (processed) {
2269 pRect->left = rc.GetLeft();
2270 pRect->top = rc.GetTop();
2271 pRect->right = rc.GetRight();
2272 pRect->bottom = rc.GetBottom();
2273 }
2274 }
2275 break;
7f0586ef 2276#endif
5706de1c 2277
7f0586ef 2278#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95
VZ
2279 case WM_ACTIVATEAPP:
2280 wxTheApp->SetActive(wParam != 0, FindFocus());
42e69d6b 2281 break;
8a46f9b1 2282#endif
47cbd6da 2283
42e69d6b 2284 case WM_ACTIVATE:
341c92a8 2285 {
42e69d6b
VZ
2286 WXWORD state, minimized;
2287 WXHWND hwnd;
2288 UnpackActivate(wParam, lParam, &state, &minimized, &hwnd);
2289
2290 processed = HandleActivate(state, minimized != 0, (WXHWND)hwnd);
341c92a8 2291 }
42e69d6b 2292 break;
341c92a8 2293
42e69d6b
VZ
2294 case WM_SETFOCUS:
2295 processed = HandleSetFocus((WXHWND)(HWND)wParam);
2296 break;
47cbd6da 2297
42e69d6b
VZ
2298 case WM_KILLFOCUS:
2299 processed = HandleKillFocus((WXHWND)(HWND)wParam);
2300 break;
47cbd6da 2301
42e69d6b
VZ
2302 case WM_PAINT:
2303 processed = HandlePaint();
2304 break;
47cbd6da 2305
42e69d6b 2306 case WM_CLOSE:
9fd9e47a
JS
2307#ifdef __WXUNIVERSAL__
2308 // Universal uses its own wxFrame/wxDialog, so we don't receive
2309 // close events unless we have this.
2310 Close();
2311 processed = TRUE;
2312 rc.result = TRUE;
2313#else
42e69d6b
VZ
2314 // don't let the DefWindowProc() destroy our window - we'll do it
2315 // ourselves in ~wxWindow
2316 processed = TRUE;
2317 rc.result = TRUE;
9fd9e47a 2318#endif
42e69d6b 2319 break;
47cbd6da 2320
42e69d6b
VZ
2321 case WM_SHOWWINDOW:
2322 processed = HandleShow(wParam != 0, (int)lParam);
2323 break;
3a19e16d 2324
42e69d6b 2325 case WM_MOUSEMOVE:
132cb640
VZ
2326 processed = HandleMouseMove(GET_X_LPARAM(lParam),
2327 GET_Y_LPARAM(lParam),
2328 wParam);
2329 break;
0d0512bd 2330
d2c52078
RD
2331#if wxUSE_MOUSEWHEEL
2332 case WM_MOUSEWHEEL:
2333 processed = HandleMouseWheel(wParam, lParam);
2334 break;
2335#endif
2336
42e69d6b
VZ
2337 case WM_LBUTTONDOWN:
2338 case WM_LBUTTONUP:
2339 case WM_LBUTTONDBLCLK:
2340 case WM_RBUTTONDOWN:
2341 case WM_RBUTTONUP:
2342 case WM_RBUTTONDBLCLK:
2343 case WM_MBUTTONDOWN:
2344 case WM_MBUTTONUP:
2345 case WM_MBUTTONDBLCLK:
dfafa702 2346 {
98363307 2347#ifdef __WXMICROWIN__
cd4453e5
VZ
2348 // MicroWindows seems to ignore the fact that a window is
2349 // disabled. So catch mouse events and throw them away if
2350 // necessary.
d0a3d109 2351 wxWindowMSW* win = this;
dfafa702 2352 for ( ;; )
d0a3d109
VZ
2353 {
2354 if (!win->IsEnabled())
2355 {
2356 processed = TRUE;
2357 break;
2358 }
dfafa702 2359
d0a3d109 2360 win = win->GetParent();
dfafa702 2361 if ( !win || win->IsTopLevel() )
d0a3d109
VZ
2362 break;
2363 }
dfafa702 2364
03e0b2b1
VZ
2365 if ( processed )
2366 break;
2367
dfafa702 2368#endif // __WXMICROWIN__
03e0b2b1
VZ
2369 int x = GET_X_LPARAM(lParam),
2370 y = GET_Y_LPARAM(lParam);
dfafa702 2371
03e0b2b1
VZ
2372 // redirect the event to a static control if necessary by
2373 // finding one under mouse
2374 wxWindowMSW *win;
2375 if ( GetCapture() == this )
2376 {
2377 // but don't do it if the mouse is captured by this window
2378 // because then it should really get this event itself
2379 win = this;
d0a3d109 2380 }
03e0b2b1
VZ
2381 else
2382 {
2383 win = FindWindowForMouseEvent(this, &x, &y);
2b5f62a0
VZ
2384
2385 // this should never happen
2386 wxCHECK_MSG( win, 0,
2387 _T("FindWindowForMouseEvent() returned NULL") );
2388
2389 // for the standard classes their WndProc sets the focus to
2390 // them anyhow and doing it from here results in some weird
2391 // problems, but for our windows we want them to acquire
2392 // focus when clicked
2393 if ( !win->IsOfStandardClass() )
2394 {
2395 if ( message == WM_LBUTTONDOWN && win->AcceptsFocus() )
2396 win->SetFocus();
2397 }
03e0b2b1
VZ
2398 }
2399
2400 processed = win->HandleMouseEvent(message, x, y, wParam);
98363307 2401 }
dfafa702 2402 break;
d0a3d109 2403
cd4453e5 2404#ifdef MM_JOY1MOVE
42e69d6b
VZ
2405 case MM_JOY1MOVE:
2406 case MM_JOY2MOVE:
2407 case MM_JOY1ZMOVE:
2408 case MM_JOY2ZMOVE:
2409 case MM_JOY1BUTTONDOWN:
2410 case MM_JOY2BUTTONDOWN:
2411 case MM_JOY1BUTTONUP:
2412 case MM_JOY2BUTTONUP:
132cb640
VZ
2413 processed = HandleJoystickEvent(message,
2414 GET_X_LPARAM(lParam),
2415 GET_Y_LPARAM(lParam),
2416 wParam);
42e69d6b 2417 break;
cd4453e5 2418#endif // __WXMICROWIN__
47cbd6da 2419
42e69d6b
VZ
2420 case WM_SYSCOMMAND:
2421 processed = HandleSysCommand(wParam, lParam);
2422 break;
2a47d3c1 2423
42e69d6b
VZ
2424 case WM_COMMAND:
2425 {
2426 WORD id, cmd;
2427 WXHWND hwnd;
2428 UnpackCommand(wParam, lParam, &id, &hwnd, &cmd);
47cbd6da 2429
42e69d6b
VZ
2430 processed = HandleCommand(id, cmd, hwnd);
2431 }
2432 break;
7d532b0c 2433
42e69d6b
VZ
2434 case WM_NOTIFY:
2435 processed = HandleNotify((int)wParam, lParam, &rc.result);
2436 break;
2bda0e17 2437
42e69d6b 2438 // for these messages we must return TRUE if process the message
cd4453e5 2439#ifdef WM_DRAWITEM
42e69d6b
VZ
2440 case WM_DRAWITEM:
2441 case WM_MEASUREITEM:
2442 {
2443 int idCtrl = (UINT)wParam;
2444 if ( message == WM_DRAWITEM )
2445 {
2446 processed = MSWOnDrawItem(idCtrl,
2447 (WXDRAWITEMSTRUCT *)lParam);
2448 }
2449 else
2450 {
2451 processed = MSWOnMeasureItem(idCtrl,
2452 (WXMEASUREITEMSTRUCT *)lParam);
2453 }
57a7b7c1 2454
42e69d6b
VZ
2455 if ( processed )
2456 rc.result = TRUE;
2457 }
2458 break;
cd4453e5
VZ
2459#endif // defined(WM_DRAWITEM)
2460
9bf84618 2461 case WM_GETDLGCODE:
5a403e3f 2462 if ( !IsOfStandardClass() )
9bf84618 2463 {
5a403e3f
VZ
2464 // we always want to get the char events
2465 rc.result = DLGC_WANTCHARS;
2466
2467 if ( GetWindowStyleFlag() & wxWANTS_CHARS )
2468 {
2469 // in fact, we want everything
2470 rc.result |= DLGC_WANTARROWS |
2471 DLGC_WANTTAB |
2472 DLGC_WANTALLKEYS;
2473 }
2474
9bf84618
VZ
2475 processed = TRUE;
2476 }
101f488c 2477 //else: get the dlg code from the DefWindowProc()
9bf84618
VZ
2478 break;
2479
4004f41e 2480 case WM_SYSKEYDOWN:
42e69d6b 2481 case WM_KEYDOWN:
9c7df356
VZ
2482 // If this has been processed by an event handler, return 0 now
2483 // (we've handled it).
2484 m_lastKeydownProcessed = HandleKeyDown((WORD) wParam, lParam);
2485 if ( m_lastKeydownProcessed )
2d0a075d 2486 {
42e69d6b 2487 processed = TRUE;
2d0a075d 2488 }
81d66cf3 2489
2b5f62a0 2490 if ( !processed )
42e69d6b 2491 {
2b5f62a0
VZ
2492 switch ( wParam )
2493 {
2494 // we consider these message "not interesting" to OnChar, so
2495 // just don't do anything more with them
2496 case VK_SHIFT:
2497 case VK_CONTROL:
2498 case VK_MENU:
2499 case VK_CAPITAL:
2500 case VK_NUMLOCK:
2501 case VK_SCROLL:
2502 processed = TRUE;
2503 break;
2bda0e17 2504
2b5f62a0
VZ
2505 // avoid duplicate messages to OnChar for these ASCII keys:
2506 // they will be translated by TranslateMessage() and received
2507 // in WM_CHAR
2508 case VK_ESCAPE:
2509 case VK_SPACE:
2510 case VK_RETURN:
2511 case VK_BACK:
2512 case VK_TAB:
2513 case VK_ADD:
2514 case VK_SUBTRACT:
2515 case VK_MULTIPLY:
2516 case VK_DIVIDE:
2517 case VK_OEM_1:
2518 case VK_OEM_2:
2519 case VK_OEM_3:
2520 case VK_OEM_4:
2521 case VK_OEM_5:
2522 case VK_OEM_6:
2523 case VK_OEM_7:
2524 case VK_OEM_PLUS:
2525 case VK_OEM_COMMA:
2526 case VK_OEM_MINUS:
2527 case VK_OEM_PERIOD:
2528 // but set processed to FALSE, not TRUE to still pass them
2529 // to the control's default window proc - otherwise
2530 // built-in keyboard handling won't work
2531 processed = FALSE;
2532 break;
2bda0e17 2533
42e69d6b 2534#ifdef VK_APPS
2b5f62a0
VZ
2535 // special case of VK_APPS: treat it the same as right mouse
2536 // click because both usually pop up a context menu
2537 case VK_APPS:
2538 {
2539 WPARAM flags;
2540 int x, y;
4aff28fc 2541
2b5f62a0
VZ
2542 TranslateKbdEventToMouse(this, &x, &y, &flags);
2543 processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags);
2544 }
2545 break;
42e69d6b 2546#endif // VK_APPS
2bda0e17 2547
2b5f62a0
VZ
2548 default:
2549 // do generate a CHAR event
2550 processed = HandleChar((WORD)wParam, lParam);
2551 }
42e69d6b 2552 }
2b5f62a0
VZ
2553 if (message == WM_SYSKEYDOWN) // Let Windows still handle the SYSKEYs
2554 processed = FALSE;
42e69d6b 2555 break;
2bda0e17 2556
4004f41e 2557 case WM_SYSKEYUP:
42e69d6b 2558 case WM_KEYUP:
4aff28fc
VZ
2559#ifdef VK_APPS
2560 // special case of VK_APPS: treat it the same as right mouse button
2561 if ( wParam == VK_APPS )
2562 {
2563 WPARAM flags;
2564 int x, y;
2565
2566 TranslateKbdEventToMouse(this, &x, &y, &flags);
2567 processed = HandleMouseEvent(WM_RBUTTONUP, x, y, flags);
2568 }
2569 else
2570#endif // VK_APPS
2571 {
2572 processed = HandleKeyUp((WORD) wParam, lParam);
2573 }
42e69d6b 2574 break;
debe6624 2575
170cbe33 2576 case WM_SYSCHAR:
42e69d6b 2577 case WM_CHAR: // Always an ASCII character
d9f14e16
RD
2578 if ( m_lastKeydownProcessed )
2579 {
2580 // The key was handled in the EVT_KEY_DOWN and handling
2581 // a key in an EVT_KEY_DOWN handler is meant, by
2582 // design, to prevent EVT_CHARs from happening
2583 m_lastKeydownProcessed = FALSE;
2584 processed = TRUE;
2585 }
2586 else
7de5bdf4 2587 {
d9f14e16 2588 processed = HandleChar((WORD)wParam, lParam, TRUE);
7de5bdf4 2589 }
42e69d6b 2590 break;
2bda0e17 2591
5048c832
JS
2592#if wxUSE_HOTKEY
2593 case WM_HOTKEY:
2594 processed = HandleHotKey((WORD)wParam, lParam);
2595 break;
540b6b09 2596#endif // wxUSE_HOTKEY
5048c832 2597
42e69d6b
VZ
2598 case WM_HSCROLL:
2599 case WM_VSCROLL:
a23fd0e1 2600 {
42e69d6b
VZ
2601 WXWORD code, pos;
2602 WXHWND hwnd;
2603 UnpackScroll(wParam, lParam, &code, &pos, &hwnd);
2bda0e17 2604
42e69d6b
VZ
2605 processed = MSWOnScroll(message == WM_HSCROLL ? wxHORIZONTAL
2606 : wxVERTICAL,
2607 code, pos, hwnd);
a23fd0e1 2608 }
42e69d6b 2609 break;
a23fd0e1 2610
42e69d6b 2611 // CTLCOLOR messages are sent by children to query the parent for their
04ef50df
JS
2612 // colors#ifndef __WXMICROWIN__
2613#ifndef __WXMICROWIN__
42e69d6b
VZ
2614 case WM_CTLCOLORMSGBOX:
2615 case WM_CTLCOLOREDIT:
2616 case WM_CTLCOLORLISTBOX:
2617 case WM_CTLCOLORBTN:
2618 case WM_CTLCOLORDLG:
2619 case WM_CTLCOLORSCROLLBAR:
2620 case WM_CTLCOLORSTATIC:
a23fd0e1 2621 {
42e69d6b
VZ
2622 WXWORD nCtlColor;
2623 WXHDC hdc;
2624 WXHWND hwnd;
2625 UnpackCtlColor(wParam, lParam, &nCtlColor, &hdc, &hwnd);
2626
2627 processed = HandleCtlColor(&rc.hBrush,
2628 (WXHDC)hdc,
2629 (WXHWND)hwnd,
2630 nCtlColor,
2631 message,
2632 wParam,
2633 lParam);
a23fd0e1 2634 }
42e69d6b 2635 break;
cd4453e5 2636#endif // !__WXMICROWIN__
debe6624 2637
42e69d6b 2638 case WM_SYSCOLORCHANGE:
90c1530a 2639 // the return value for this message is ignored
42e69d6b
VZ
2640 processed = HandleSysColorChange();
2641 break;
2bda0e17 2642
7f0586ef 2643#if !defined(__WXWINCE__)
574c939e
KB
2644 case WM_DISPLAYCHANGE:
2645 processed = HandleDisplayChange();
2646 break;
7f0586ef 2647#endif
574c939e 2648
42e69d6b
VZ
2649 case WM_PALETTECHANGED:
2650 processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
2651 break;
2bda0e17 2652
a5e84126
JS
2653 case WM_CAPTURECHANGED:
2654 processed = HandleCaptureChanged((WXHWND) (HWND) lParam);
2655 break;
2656
42e69d6b
VZ
2657 case WM_QUERYNEWPALETTE:
2658 processed = HandleQueryNewPalette();
2659 break;
2bda0e17 2660
42e69d6b
VZ
2661 case WM_ERASEBKGND:
2662 processed = HandleEraseBkgnd((WXHDC)(HDC)wParam);
2663 if ( processed )
2664 {
2665 // we processed the message, i.e. erased the background
2666 rc.result = TRUE;
2667 }
2668 break;
debe6624 2669
7f0586ef 2670#if !defined(__WXWINCE__)
42e69d6b
VZ
2671 case WM_DROPFILES:
2672 processed = HandleDropFiles(wParam);
2673 break;
7f0586ef 2674#endif
2bda0e17 2675
42e69d6b
VZ
2676 case WM_INITDIALOG:
2677 processed = HandleInitDialog((WXHWND)(HWND)wParam);
a23fd0e1 2678
42e69d6b
VZ
2679 if ( processed )
2680 {
2681 // we never set focus from here
2682 rc.result = FALSE;
2683 }
2684 break;
a23fd0e1 2685
7f0586ef 2686#if !defined(__WXWINCE__)
42e69d6b
VZ
2687 case WM_QUERYENDSESSION:
2688 processed = HandleQueryEndSession(lParam, &rc.allow);
2689 break;
2bda0e17 2690
42e69d6b
VZ
2691 case WM_ENDSESSION:
2692 processed = HandleEndSession(wParam != 0, lParam);
2693 break;
2bda0e17 2694
42e69d6b 2695 case WM_GETMINMAXINFO:
25889d3c 2696 processed = HandleGetMinMaxInfo((MINMAXINFO*)lParam);
42e69d6b 2697 break;
7f0586ef 2698#endif
debe6624 2699
42e69d6b
VZ
2700 case WM_SETCURSOR:
2701 processed = HandleSetCursor((WXHWND)(HWND)wParam,
2702 LOWORD(lParam), // hit test
2703 HIWORD(lParam)); // mouse msg
2704
2705 if ( processed )
2706 {
2707 // returning TRUE stops the DefWindowProc() from further
2708 // processing this message - exactly what we need because we've
2709 // just set the cursor.
2710 rc.result = TRUE;
2711 }
2712 break;
4cdc2c13 2713
ed5317e5
JS
2714#if wxUSE_ACCESSIBILITY
2715 case WM_GETOBJECT:
2716 {
2717 //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
2718 LPARAM dwObjId = (LPARAM) (DWORD) lParam;
2719
2720 if (dwObjId == OBJID_CLIENT && GetOrCreateAccessible())
2721 {
2722 return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible());
2723 }
2724 break;
2725 }
2726#endif
2727
e39af974 2728#if defined(WM_HELP)
b96340e6 2729 case WM_HELP:
b96340e6 2730 {
7f0586ef
JS
2731 // HELPINFO doesn't seem to be supported on WinCE.
2732#ifndef __WXWINCE__
4cdc2c13
VZ
2733 HELPINFO* info = (HELPINFO*) lParam;
2734 // Don't yet process menu help events, just windows
2735 if (info->iContextType == HELPINFO_WINDOW)
b96340e6 2736 {
7f0586ef 2737#endif
24ce4c18 2738 wxWindowMSW* subjectOfHelp = this;
4cdc2c13
VZ
2739 bool eventProcessed = FALSE;
2740 while (subjectOfHelp && !eventProcessed)
2741 {
2742 wxHelpEvent helpEvent(wxEVT_HELP,
2743 subjectOfHelp->GetId(),
7f0586ef
JS
2744#ifdef __WXWINCE__
2745 wxPoint(0, 0)
2746#else
2747 wxPoint(info->MousePos.x, info->MousePos.y)
2748#endif
2749 );
2750
4cdc2c13
VZ
2751 helpEvent.SetEventObject(this);
2752 eventProcessed =
2753 GetEventHandler()->ProcessEvent(helpEvent);
2754
2755 // Go up the window hierarchy until the event is
2756 // handled (or not)
2757 subjectOfHelp = subjectOfHelp->GetParent();
2758 }
b96340e6 2759
4cdc2c13 2760 processed = eventProcessed;
7f0586ef 2761#ifndef __WXWINCE__
b96340e6 2762 }
4cdc2c13
VZ
2763 else if (info->iContextType == HELPINFO_MENUITEM)
2764 {
2765 wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
2766 helpEvent.SetEventObject(this);
2767 processed = GetEventHandler()->ProcessEvent(helpEvent);
69231000 2768
4cdc2c13
VZ
2769 }
2770 //else: processed is already FALSE
7f0586ef 2771#endif
b96340e6 2772 }
b96340e6 2773 break;
7f0586ef 2774#endif
4cdc2c13 2775
7f0586ef 2776#if !defined(__WXWINCE__)
69231000 2777 case WM_CONTEXTMENU:
4cdc2c13
VZ
2778 {
2779 // we don't convert from screen to client coordinates as
2780 // the event may be handled by a parent window
2781 wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
2782
2783 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
0d6ae333 2784 processed = GetEventHandler()->ProcessEvent(evtCtx);
4cdc2c13 2785 }
69231000 2786 break;
7f0586ef 2787#endif
b74cce40
VZ
2788
2789 case WM_MENUCHAR:
2790 // we're only interested in our own menus, not MF_SYSMENU
2791 if ( HIWORD(wParam) == MF_POPUP )
2792 {
2793 // handle menu chars for ownerdrawn menu items
2794 int i = HandleMenuChar(toupper(LOWORD(wParam)), lParam);
2795 if ( i != wxNOT_FOUND )
2796 {
2797 rc.result = MAKELRESULT(i, MNC_EXECUTE);
2798 processed = TRUE;
2799 }
2800 }
2801 break;
a23fd0e1 2802 }
2d0a075d 2803
42e69d6b 2804 if ( !processed )
2d0a075d 2805 {
42e69d6b 2806#ifdef __WXDEBUG__
223d09f6 2807 wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
42e69d6b
VZ
2808 wxGetMessageName(message));
2809#endif // __WXDEBUG__
2810 rc.result = MSWDefWindowProc(message, wParam, lParam);
a23fd0e1 2811 }
2bda0e17 2812
42e69d6b 2813 return rc.result;
2bda0e17
KB
2814}
2815
b225f659
VZ
2816// ----------------------------------------------------------------------------
2817// wxWindow <-> HWND map
2818// ----------------------------------------------------------------------------
2bda0e17 2819
1bffa913 2820wxWinHashTable *wxWinHandleHash = NULL;
b225f659 2821
42e69d6b 2822wxWindow *wxFindWinFromHandle(WXHWND hWnd)
4ce81a75 2823{
1bffa913 2824 return wxWinHandleHash->Get((long)hWnd);
42e69d6b 2825}
4ce81a75 2826
1e6feb95 2827void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
42e69d6b
VZ
2828{
2829 // adding NULL hWnd is (first) surely a result of an error and
2830 // (secondly) breaks menu command processing
2831 wxCHECK_RET( hWnd != (HWND)NULL,
223d09f6 2832 wxT("attempt to add a NULL hWnd to window list ignored") );
4ce81a75 2833
c7527e3f 2834 wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd);
b225f659 2835#ifdef __WXDEBUG__
c7527e3f
JS
2836 if ( oldWin && (oldWin != win) )
2837 {
b225f659 2838 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
9b601c24 2839 (int) hWnd, win->GetClassInfo()->GetClassName());
c7527e3f 2840 }
b225f659
VZ
2841 else
2842#endif // __WXDEBUG__
2843 if (!oldWin)
c7527e3f 2844 {
d2d14464 2845 wxWinHandleHash->Put((long)hWnd, (wxWindow *)win);
c7527e3f 2846 }
42e69d6b 2847}
4ce81a75 2848
1e6feb95 2849void wxRemoveHandleAssociation(wxWindowMSW *win)
42e69d6b 2850{
1bffa913 2851 wxWinHandleHash->Delete((long)win->GetHWND());
4ce81a75
JS
2852}
2853
b225f659
VZ
2854// ----------------------------------------------------------------------------
2855// various MSW speciic class dependent functions
2856// ----------------------------------------------------------------------------
2857
42e69d6b
VZ
2858// Default destroyer - override if you destroy it in some other way
2859// (e.g. with MDI child windows)
1e6feb95 2860void wxWindowMSW::MSWDestroyWindow()
4ce81a75 2861{
42e69d6b 2862}
4ce81a75 2863
b225f659
VZ
2864bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos,
2865 const wxSize& size,
2866 int& x, int& y,
2867 int& w, int& h) const
2bda0e17 2868{
2a77c8c4
VZ
2869 static const int DEFAULT_Y = 200;
2870 static const int DEFAULT_H = 250;
2871
b225f659 2872 bool nonDefault = FALSE;
c085e333 2873
b225f659
VZ
2874 if ( pos.x == -1 )
2875 {
2876 // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
2877 // just as well set it to CW_USEDEFAULT as well
2878 x =
2879 y = CW_USEDEFAULT;
2880 }
2881 else
a23fd0e1 2882 {
2a77c8c4
VZ
2883 // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it
2884 // neither because it is not handled as a special value by Windows then
2885 // and so we have to choose some default value for it
b225f659 2886 x = pos.x;
2a77c8c4 2887 y = pos.y == -1 ? DEFAULT_Y : pos.y;
c085e333 2888
b225f659 2889 nonDefault = TRUE;
42e69d6b 2890 }
2bda0e17 2891
b889a3a2
VZ
2892 /*
2893 NB: there used to be some code here which set the initial size of the
2894 window to the client size of the parent if no explicit size was
2895 specified. This was wrong because wxWindows programs often assume
2896 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
2897 it. To see why, you should understand that Windows sends WM_SIZE from
2898 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
2899 from some base class ctor and so this WM_SIZE is not processed in the
2900 real class' OnSize() (because it's not fully constructed yet and the
2901 event goes to some base class OnSize() instead). So the WM_SIZE we
2902 rely on is the one sent when the parent frame resizes its children
2903 but here is the problem: if the child already has just the right
2904 size, nothing will happen as both wxWindows and Windows check for
2905 this and ignore any attempts to change the window size to the size it
2906 already has - so no WM_SIZE would be sent.
2907 */
2908 if ( size.x == -1 )
b225f659 2909 {
2a77c8c4 2910 // as above, h is not used at all in this case anyhow
b889a3a2
VZ
2911 w =
2912 h = CW_USEDEFAULT;
b225f659
VZ
2913 }
2914 else
8614c467 2915 {
2a77c8c4 2916 // and, again as above, we can't set the height to CW_USEDEFAULT here
b225f659 2917 w = size.x;
2a77c8c4 2918 h = size.y == -1 ? DEFAULT_H : size.y;
b225f659
VZ
2919
2920 nonDefault = TRUE;
8614c467
VZ
2921 }
2922
b225f659
VZ
2923 return nonDefault;
2924}
2925
9dfef5ac
VZ
2926WXHWND wxWindowMSW::MSWGetParent() const
2927{
d285d708 2928 return m_parent ? m_parent->GetHWND() : WXHWND(NULL);
9dfef5ac
VZ
2929}
2930
b225f659
VZ
2931bool wxWindowMSW::MSWCreate(const wxChar *wclass,
2932 const wxChar *title,
2933 const wxPoint& pos,
2934 const wxSize& size,
2935 WXDWORD style,
2936 WXDWORD extendedStyle)
2937{
2938 // choose the position/size for the new window
2939 int x, y, w, h;
2940 (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
2941
b225f659
VZ
2942 // controlId is menu handle for the top level windows, so set it to 0
2943 // unless we're creating a child window
f586fde3 2944 int controlId = style & WS_CHILD ? GetId() : 0;
2bda0e17 2945
b225f659
VZ
2946 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
2947 // which is the same but without CS_[HV]REDRAW class styles so using it
2948 // ensures that the window is not fully repainted on each resize
2949 wxString className(wclass);
2950 if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
2951 {
2952 className += wxT("NR");
a23fd0e1 2953 }
c085e333 2954
b225f659
VZ
2955 // do create the window
2956 wxWindowCreationHook hook(this);
b3daa5a3 2957
b225f659 2958 m_hWnd = (WXHWND)::CreateWindowEx
9dfef5ac
VZ
2959 (
2960 extendedStyle,
2961 className,
fda7962d 2962 title ? title : wxEmptyString,
9dfef5ac
VZ
2963 style,
2964 x, y, w, h,
2965 (HWND)MSWGetParent(),
2966 (HMENU)controlId,
2967 wxGetInstance(),
2968 NULL // no extra data
2969 );
b225f659
VZ
2970
2971 if ( !m_hWnd )
c7527e3f 2972 {
b225f659
VZ
2973 wxLogSysError(_("Can't create window of class %s"), wclass);
2974
2975 return FALSE;
c7527e3f 2976 }
b3daa5a3 2977
b225f659 2978 SubclassWin(m_hWnd);
c085e333 2979
a756f210 2980 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
8bf30fe9 2981
42e69d6b 2982 return TRUE;
2bda0e17
KB
2983}
2984
42e69d6b
VZ
2985// ===========================================================================
2986// MSW message handlers
2987// ===========================================================================
2988
2989// ---------------------------------------------------------------------------
2990// WM_NOTIFY
2991// ---------------------------------------------------------------------------
2992
2993#ifdef __WIN95__
2b15b970 2994
1e6feb95 2995bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
2bda0e17 2996{
04ef50df 2997#ifndef __WXMICROWIN__
42e69d6b
VZ
2998 LPNMHDR hdr = (LPNMHDR)lParam;
2999 HWND hWnd = hdr->hwndFrom;
3000 wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd);
3001
2b15b970 3002 // if the control is one of our windows, let it handle the message itself
42e69d6b 3003 if ( win )
564b2609 3004 {
42e69d6b 3005 return win->MSWOnNotify(idCtrl, lParam, result);
564b2609 3006 }
2bda0e17 3007
2b15b970
VZ
3008 // VZ: why did we do it? normally this is unnecessary and, besides, it
3009 // breaks the message processing for the toolbars because the tooltip
3010 // notifications were being forwarded to the toolbar child controls
3011 // (if it had any) before being passed to the toolbar itself, so in my
3012 // example the tooltip for the combobox was always shown instead of the
3013 // correct button tooltips
3014#if 0
42e69d6b 3015 // try all our children
222ed1d6 3016 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
42e69d6b 3017 while ( node )
564b2609 3018 {
42e69d6b
VZ
3019 wxWindow *child = node->GetData();
3020 if ( child->MSWOnNotify(idCtrl, lParam, result) )
3021 {
3022 return TRUE;
42e69d6b 3023 }
2d0a075d 3024
42e69d6b
VZ
3025 node = node->GetNext();
3026 }
2b15b970 3027#endif // 0
2d0a075d 3028
2b15b970 3029 // by default, handle it ourselves
42e69d6b 3030 return MSWOnNotify(idCtrl, lParam, result);
cd4453e5 3031#else // __WXMICROWIN__
04ef50df
JS
3032 return FALSE;
3033#endif
42e69d6b 3034}
2d0a075d 3035
bd9cd534
VZ
3036#if wxUSE_TOOLTIPS
3037
3038bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
3039 WXLPARAM lParam,
3040 const wxString& ttip)
3041{
3042 // I don't know why it happens, but the versions of comctl32.dll starting
3043 // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally,
3044 // this message is supposed to be sent to Unicode programs only) -- hence
3045 // we need to handle it as well, otherwise no tooltips will be shown in
3046 // this case
7f0586ef 3047#ifndef __WXWINCE__
b40e2278 3048 if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) || ttip.empty() )
bd9cd534
VZ
3049 {
3050 // not a tooltip message or no tooltip to show anyhow
3051 return FALSE;
3052 }
7f0586ef 3053#endif
bd9cd534
VZ
3054
3055 LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
3056
2b5f62a0 3057#if !wxUSE_UNICODE
b40e2278 3058 if ( code == (WXUINT) TTN_NEEDTEXTA )
bd9cd534 3059 {
2b5f62a0
VZ
3060 // we pass just the pointer as we store the string internally anyhow
3061 ttText->lpszText = (char *)ttip.c_str();
bd9cd534 3062 }
2b5f62a0
VZ
3063 else // TTN_NEEDTEXTW
3064#endif // !Unicode
bd9cd534
VZ
3065 {
3066#if wxUSE_UNICODE
2b5f62a0 3067 // in Unicode mode this is just what we need
bd9cd534
VZ
3068 ttText->lpszText = (wxChar *)ttip.c_str();
3069#else // !Unicode
5571f3d3
VS
3070 MultiByteToWideChar(CP_ACP, 0, ttip, ttip.length()+1,
3071 (wchar_t *)ttText->szText,
3072 sizeof(ttText->szText) / sizeof(wchar_t));
bd9cd534
VZ
3073#endif // Unicode/!Unicode
3074 }
3075
3076 return TRUE;
3077}
3078
3079#endif // wxUSE_TOOLTIPS
3080
1e6feb95 3081bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl),
bd9cd534
VZ
3082 WXLPARAM lParam,
3083 WXLPARAM* WXUNUSED(result))
42e69d6b
VZ
3084{
3085#if wxUSE_TOOLTIPS
bd9cd534 3086 if ( m_tooltip )
42e69d6b 3087 {
bd9cd534
VZ
3088 NMHDR* hdr = (NMHDR *)lParam;
3089 if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip()))
3090 {
3091 // processed
3092 return TRUE;
3093 }
42e69d6b
VZ
3094 }
3095#endif // wxUSE_TOOLTIPS
3096
3097 return FALSE;
3098}
2b15b970 3099
42e69d6b
VZ
3100#endif // __WIN95__
3101
3102// ---------------------------------------------------------------------------
3103// end session messages
3104// ---------------------------------------------------------------------------
2d0a075d 3105
1e6feb95 3106bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
42e69d6b 3107{
7f0586ef 3108#ifndef __WXWINCE__
42e69d6b
VZ
3109 wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1);
3110 event.SetEventObject(wxTheApp);
3111 event.SetCanVeto(TRUE);
a17e237f 3112 event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF);
2d0a075d 3113
42e69d6b
VZ
3114 bool rc = wxTheApp->ProcessEvent(event);
3115
3116 if ( rc )
3117 {
3118 // we may end only if the app didn't veto session closing (double
3119 // negation...)
3120 *mayEnd = !event.GetVeto();
2d0a075d
JS
3121 }
3122
42e69d6b 3123 return rc;
7f0586ef
JS
3124#else
3125 return FALSE;
3126#endif
2bda0e17
KB
3127}
3128
1e6feb95 3129bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
2bda0e17 3130{
7f0586ef 3131#ifndef __WXWINCE__
42e69d6b
VZ
3132 // do nothing if the session isn't ending
3133 if ( !endSession )
3134 return FALSE;
a23fd0e1 3135
519dc37f
VZ
3136 // only send once
3137 if ( (this != wxTheApp->GetTopWindow()) )
3138 return FALSE;
3139
42e69d6b
VZ
3140 wxCloseEvent event(wxEVT_END_SESSION, -1);
3141 event.SetEventObject(wxTheApp);
3142 event.SetCanVeto(FALSE);
a17e237f 3143 event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
519dc37f
VZ
3144
3145 return wxTheApp->ProcessEvent(event);
7f0586ef
JS
3146#else
3147 return FALSE;
3148#endif
2bda0e17
KB
3149}
3150
42e69d6b
VZ
3151// ---------------------------------------------------------------------------
3152// window creation/destruction
3153// ---------------------------------------------------------------------------
3154
61179e28
VZ
3155bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
3156{
3157 // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
3158 // parent as well as otherwise several Win32 functions using
3159 // GetNextDlgTabItem() to iterate over all controls such as
3160 // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
3161 // all of them iterate over all the controls starting from the focus and
3162 // stop iterating when they get back to the focus but unless all parents
3163 // have WS_EX_CONTROLPARENT bit set, they would never get back to focus
7f0586ef 3164#ifndef __WXWINCE__
61179e28
VZ
3165 if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
3166 {
3167 // there is no need to do anything for the top level windows
3168 const wxWindow *parent = GetParent();
5624b2a1 3169 while ( parent && !parent->IsTopLevel() )
61179e28
VZ
3170 {
3171 LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
3172 if ( !(exStyle & WS_EX_CONTROLPARENT) )
3173 {
3174 // force the parent to have this style
3175 ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
3176 exStyle | WS_EX_CONTROLPARENT);
3177 }
5624b2a1
VZ
3178
3179 parent = parent->GetParent();
61179e28
VZ
3180 }
3181 }
7f0586ef 3182#endif
61179e28 3183
42e69d6b 3184 // TODO: should generate this event from WM_NCCREATE
1e6feb95 3185 wxWindowCreateEvent event((wxWindow *)this);
42e69d6b 3186 (void)GetEventHandler()->ProcessEvent(event);
a23fd0e1 3187
42e69d6b
VZ
3188 *mayCreate = TRUE;
3189
3190 return TRUE;
2bda0e17
KB
3191}
3192
1e6feb95 3193bool wxWindowMSW::HandleDestroy()
2bda0e17 3194{
7de59551 3195 SendDestroyEvent();
42e69d6b
VZ
3196
3197 // delete our drop target if we've got one
3198#if wxUSE_DRAG_AND_DROP
3199 if ( m_dropTarget != NULL )
2d0a075d 3200 {
42e69d6b
VZ
3201 m_dropTarget->Revoke(m_hWnd);
3202
3203 delete m_dropTarget;
3204 m_dropTarget = NULL;
2d0a075d 3205 }
42e69d6b 3206#endif // wxUSE_DRAG_AND_DROP
2bda0e17 3207
42e69d6b
VZ
3208 // WM_DESTROY handled
3209 return TRUE;
2bda0e17
KB
3210}
3211
42e69d6b
VZ
3212// ---------------------------------------------------------------------------
3213// activation/focus
3214// ---------------------------------------------------------------------------
3215
1e6feb95 3216bool wxWindowMSW::HandleActivate(int state,
42e69d6b
VZ
3217 bool WXUNUSED(minimized),
3218 WXHWND WXUNUSED(activate))
2bda0e17 3219{
42e69d6b
VZ
3220 wxActivateEvent event(wxEVT_ACTIVATE,
3221 (state == WA_ACTIVE) || (state == WA_CLICKACTIVE),
3222 m_windowId);
3223 event.SetEventObject(this);
3224
3225 return GetEventHandler()->ProcessEvent(event);
3226}
3227
1e6feb95 3228bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
42e69d6b 3229{
456bc6d9
VZ
3230 // notify the parent keeping track of focus for the kbd navigation
3231 // purposes that we got it
e72aa7f5 3232 wxChildFocusEvent eventFocus((wxWindow *)this);
456bc6d9
VZ
3233 (void)GetEventHandler()->ProcessEvent(eventFocus);
3234
789295bf 3235#if wxUSE_CARET
42e69d6b 3236 // Deal with caret
789295bf 3237 if ( m_caret )
2d0a075d 3238 {
789295bf 3239 m_caret->OnSetFocus();
2bda0e17 3240 }
789295bf 3241#endif // wxUSE_CARET
42e69d6b 3242
ab93a576
RD
3243#if wxUSE_TEXTCTRL
3244 // If it's a wxTextCtrl don't send the event as it will be done
456bc6d9
VZ
3245 // after the control gets to process it from EN_FOCUS handler
3246 if ( wxDynamicCastThis(wxTextCtrl) )
ab93a576
RD
3247 {
3248 return FALSE;
3249 }
456bc6d9 3250#endif // wxUSE_TEXTCTRL
ab93a576 3251
42e69d6b
VZ
3252 wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
3253 event.SetEventObject(this);
3254
1e6feb95
VZ
3255 // wxFindWinFromHandle() may return NULL, it is ok
3256 event.SetWindow(wxFindWinFromHandle(hwnd));
3257
42e69d6b 3258 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3259}
3260
1e6feb95 3261bool wxWindowMSW::HandleKillFocus(WXHWND hwnd)
2bda0e17 3262{
789295bf 3263#if wxUSE_CARET
42e69d6b 3264 // Deal with caret
789295bf 3265 if ( m_caret )
2d0a075d 3266 {
789295bf 3267 m_caret->OnKillFocus();
2bda0e17 3268 }
789295bf 3269#endif // wxUSE_CARET
42e69d6b 3270
ab93a576
RD
3271#if wxUSE_TEXTCTRL
3272 // If it's a wxTextCtrl don't send the event as it will be done
3273 // after the control gets to process it.
3274 wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl);
3275 if ( ctrl )
3276 {
3277 return FALSE;
3278 }
3279#endif
3280
2913e597
RD
3281 // Don't send the event when in the process of being deleted. This can
3282 // only cause problems if the event handler tries to access the object.
3283 if ( m_isBeingDeleted )
3284 {
3285 return FALSE;
3286 }
3287
42e69d6b
VZ
3288 wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
3289 event.SetEventObject(this);
3290
1e6feb95
VZ
3291 // wxFindWinFromHandle() may return NULL, it is ok
3292 event.SetWindow(wxFindWinFromHandle(hwnd));
3293
42e69d6b 3294 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3295}
3296
42e69d6b
VZ
3297// ---------------------------------------------------------------------------
3298// miscellaneous
3299// ---------------------------------------------------------------------------
3300
1e6feb95 3301bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status))
2bda0e17 3302{
42e69d6b
VZ
3303 wxShowEvent event(GetId(), show);
3304 event.m_eventObject = this;
3305
3306 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3307}
3308
1e6feb95 3309bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
2bda0e17 3310{
42e69d6b
VZ
3311 wxInitDialogEvent event(GetId());
3312 event.m_eventObject = this;
3313
3314 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3315}
3316
1e6feb95 3317bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
2bda0e17 3318{
7f0586ef 3319#if defined (__WXMICROWIN__) || defined(__WXWINCE__)
4ce1efe1
CE
3320 return FALSE;
3321#else // __WXMICROWIN__
42e69d6b 3322 HDROP hFilesInfo = (HDROP) wParam;
42e69d6b
VZ
3323
3324 // Get the total number of files dropped
c3c39620 3325 UINT gwFilesDropped = ::DragQueryFile
f6bcfd97
BP
3326 (
3327 (HDROP)hFilesInfo,
3328 (UINT)-1,
3329 (LPTSTR)0,
3330 (UINT)0
3331 );
42e69d6b
VZ
3332
3333 wxString *files = new wxString[gwFilesDropped];
c3c39620 3334 for ( UINT wIndex = 0; wIndex < gwFilesDropped; wIndex++ )
2d0a075d 3335 {
c3c39620
VZ
3336 // first get the needed buffer length (+1 for terminating NUL)
3337 size_t len = ::DragQueryFile(hFilesInfo, wIndex, NULL, 0) + 1;
3338
3339 // and now get the file name
3340 ::DragQueryFile(hFilesInfo, wIndex,
3341 files[wIndex].GetWriteBuf(len), len);
3342
3343 files[wIndex].UngetWriteBuf();
2d0a075d 3344 }
42e69d6b 3345 DragFinish (hFilesInfo);
2bda0e17 3346
42e69d6b
VZ
3347 wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
3348 event.m_eventObject = this;
c3c39620
VZ
3349
3350 POINT dropPoint;
3351 DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint);
b3dc8a3e
VZ
3352 event.m_pos.x = dropPoint.x;
3353 event.m_pos.y = dropPoint.y;
42e69d6b 3354
c3c39620 3355 return GetEventHandler()->ProcessEvent(event);
04ef50df 3356#endif
2bda0e17
KB
3357}
3358
cc972ac6 3359
1e6feb95
VZ
3360bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
3361 short nHitTest,
3362 int WXUNUSED(mouseMsg))
2bda0e17 3363{
04ef50df 3364#ifndef __WXMICROWIN__
bfbd6dc1 3365 // the logic is as follows:
43b5058d
VZ
3366 // -1. don't set cursor for non client area, including but not limited to
3367 // the title bar, scrollbars, &c
3368 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
bfbd6dc1
VZ
3369 // 1. if we have the cursor set it unless wxIsBusy()
3370 // 2. if we're a top level window, set some cursor anyhow
3371 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
42e69d6b 3372
43b5058d
VZ
3373 if ( nHitTest != HTCLIENT )
3374 {
3375 return FALSE;
3376 }
3377
bfbd6dc1 3378 HCURSOR hcursor = 0;
43b5058d
VZ
3379
3380 // first ask the user code - it may wish to set the cursor in some very
3381 // specific way (for example, depending on the current position)
3382 POINT pt;
3383 if ( !::GetCursorPos(&pt) )
3384 {
f6bcfd97 3385 wxLogLastError(wxT("GetCursorPos"));
43b5058d
VZ
3386 }
3387
3388 int x = pt.x,
3389 y = pt.y;
3390 ScreenToClient(&x, &y);
3391 wxSetCursorEvent event(x, y);
3392
3393 bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event);
3394 if ( processedEvtSetCursor && event.HasCursor() )
bfbd6dc1 3395 {
43b5058d 3396 hcursor = GetHcursorOf(event.GetCursor());
bfbd6dc1 3397 }
42e69d6b 3398
43b5058d 3399 if ( !hcursor )
bfbd6dc1 3400 {
43b5058d
VZ
3401 bool isBusy = wxIsBusy();
3402
3403 // the test for processedEvtSetCursor is here to prevent using m_cursor
3404 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3405 // it - this is a way to say that our cursor shouldn't be used for this
3406 // point
3407 if ( !processedEvtSetCursor && m_cursor.Ok() )
bfbd6dc1 3408 {
43b5058d 3409 hcursor = GetHcursorOf(m_cursor);
bfbd6dc1 3410 }
43b5058d
VZ
3411
3412 if ( !GetParent() )
bfbd6dc1 3413 {
43b5058d 3414 if ( isBusy )
42e69d6b 3415 {
43b5058d
VZ
3416 hcursor = wxGetCurrentBusyCursor();
3417 }
3418 else if ( !hcursor )
3419 {
3420 const wxCursor *cursor = wxGetGlobalCursor();
3421 if ( cursor && cursor->Ok() )
3422 {
3423 hcursor = GetHcursorOf(*cursor);
3424 }
42e69d6b
VZ
3425 }
3426 }
3427 }
3428
bfbd6dc1
VZ
3429 if ( hcursor )
3430 {
2b5f62a0
VZ
3431// wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor);
3432
bfbd6dc1
VZ
3433 ::SetCursor(hcursor);
3434
3435 // cursor set, stop here
3436 return TRUE;
3437 }
cd4453e5
VZ
3438#endif // __WXMICROWIN__
3439
3ca6a5f0
BP
3440 // pass up the window chain
3441 return FALSE;
2bda0e17
KB
3442}
3443
42e69d6b
VZ
3444// ---------------------------------------------------------------------------
3445// owner drawn stuff
3446// ---------------------------------------------------------------------------
3447
1e6feb95 3448bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct)
2bda0e17 3449{
4286a5b5 3450#if wxUSE_OWNER_DRAWN
1e6feb95
VZ
3451
3452#if wxUSE_MENUS_NATIVE
42e69d6b 3453 // is it a menu item?
6f806543
VZ
3454 DRAWITEMSTRUCT *pDrawStruct = (DRAWITEMSTRUCT *)itemStruct;
3455 if ( id == 0 && pDrawStruct->CtlType == ODT_MENU )
42e69d6b 3456 {
42e69d6b
VZ
3457 wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
3458
3459 wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
3460
7561aacd
VZ
3461 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3462 // the DC from being released
3463 wxDCTemp dc((WXHDC)pDrawStruct->hDC);
42e69d6b
VZ
3464 wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top,
3465 pDrawStruct->rcItem.right - pDrawStruct->rcItem.left,
3466 pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top);
3467
3468 return pMenuItem->OnDrawItem
7561aacd
VZ
3469 (
3470 dc,
3471 rect,
3472 (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
3473 (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
3474 );
42e69d6b 3475 }
1e6feb95 3476#endif // wxUSE_MENUS_NATIVE
42e69d6b 3477
c8e4fa8b
JS
3478#endif // USE_OWNER_DRAWN
3479
1e6feb95 3480#if wxUSE_CONTROLS
c8e4fa8b 3481
c8e4fa8b 3482#if wxUSE_OWNER_DRAWN
9f522551 3483 wxWindow *item = FindItem(id);
42e69d6b 3484 if ( item && item->IsKindOf(CLASSINFO(wxControl)) )
42e69d6b 3485 return ((wxControl *)item)->MSWOnDraw(itemStruct);
9f522551
VZ
3486#elif !defined(__WXUNIVERSAL__)
3487 // we may still have owner-drawn buttons internally because we have to make
3488 // them owner-drawn to support colour change
3489 wxWindow *item = FindItem(id);
c8e4fa8b
JS
3490 if ( item && item->IsKindOf(CLASSINFO(wxButton)) )
3491 return ((wxButton *)item)->MSWOnDraw(itemStruct);
cd0b1709 3492#endif // USE_OWNER_DRAWN
4286a5b5 3493
c8e4fa8b
JS
3494#endif // wxUSE_CONTROLS
3495
cd0b1709 3496 return FALSE;
2bda0e17
KB
3497}
3498
1e6feb95 3499bool wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
2bda0e17 3500{
4286a5b5 3501#if wxUSE_OWNER_DRAWN
42e69d6b 3502 // is it a menu item?
6f806543
VZ
3503 MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct;
3504 if ( id == 0 && pMeasureStruct->CtlType == ODT_MENU )
2d0a075d 3505 {
42e69d6b
VZ
3506 wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
3507
3508 wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
3509
3510 return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth,
3511 &pMeasureStruct->itemHeight);
2d0a075d 3512 }
42e69d6b
VZ
3513
3514 wxWindow *item = FindItem(id);
3515 if ( item && item->IsKindOf(CLASSINFO(wxControl)) )
3516 {
3517 return ((wxControl *)item)->MSWOnMeasure(itemStruct);
3518 }
4286a5b5 3519#endif // owner-drawn menus
42e69d6b 3520 return FALSE;
2bda0e17
KB
3521}
3522
42e69d6b
VZ
3523// ---------------------------------------------------------------------------
3524// colours and palettes
3525// ---------------------------------------------------------------------------
2bda0e17 3526
1e6feb95 3527bool wxWindowMSW::HandleSysColorChange()
2bda0e17 3528{
42e69d6b
VZ
3529 wxSysColourChangedEvent event;
3530 event.SetEventObject(this);
3531
23895080
VZ
3532 (void)GetEventHandler()->ProcessEvent(event);
3533
3534 // always let the system carry on the default processing to allow the
3535 // native controls to react to the colours update
3536 return FALSE;
42e69d6b
VZ
3537}
3538
574c939e
KB
3539bool wxWindowMSW::HandleDisplayChange()
3540{
3541 wxDisplayChangedEvent event;
3542 event.SetEventObject(this);
3543
3544 return GetEventHandler()->ProcessEvent(event);
3545}
3546
1e6feb95 3547bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush,
42e69d6b
VZ
3548 WXHDC pDC,
3549 WXHWND pWnd,
3550 WXUINT nCtlColor,
3551 WXUINT message,
3552 WXWPARAM wParam,
3553 WXLPARAM lParam)
3554{
04ef50df 3555#ifndef __WXMICROWIN__
42e69d6b
VZ
3556 WXHBRUSH hBrush = 0;
3557
7f0586ef
JS
3558#ifdef __WXWINCE__
3559 if (FALSE)
3560#else
42e69d6b 3561 if ( nCtlColor == CTLCOLOR_DLG )
7f0586ef 3562#endif
2d0a075d 3563 {
42e69d6b 3564 hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
2d0a075d 3565 }
1e6feb95 3566#if wxUSE_CONTROLS
2d0a075d
JS
3567 else
3568 {
42e69d6b
VZ
3569 wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE);
3570 if ( item )
3571 hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
2d0a075d 3572 }
1e6feb95 3573#endif // wxUSE_CONTROLS
42e69d6b
VZ
3574
3575 if ( hBrush )
3576 *brush = hBrush;
3577
3578 return hBrush != 0;
cd4453e5 3579#else // __WXMICROWIN__
04ef50df
JS
3580 return FALSE;
3581#endif
2bda0e17
KB
3582}
3583
42e69d6b 3584// Define for each class of dialog and control
1e6feb95
VZ
3585WXHBRUSH wxWindowMSW::OnCtlColor(WXHDC WXUNUSED(hDC),
3586 WXHWND WXUNUSED(hWnd),
3587 WXUINT WXUNUSED(nCtlColor),
3588 WXUINT WXUNUSED(message),
3589 WXWPARAM WXUNUSED(wParam),
3590 WXLPARAM WXUNUSED(lParam))
2bda0e17 3591{
42e69d6b
VZ
3592 return (WXHBRUSH)0;
3593}
2d0a075d 3594
1e6feb95 3595bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
42e69d6b 3596{
574c939e 3597#if wxUSE_PALETTE
b95edd47
VZ
3598 // same as below except we don't respond to our own messages
3599 if ( hWndPalChange != GetHWND() )
3600 {
574c939e 3601 // check to see if we our our parents have a custom palette
fa21d338 3602 wxWindowMSW *win = this;
b95edd47
VZ
3603 while ( win && !win->HasCustomPalette() )
3604 {
3605 win = win->GetParent();
3606 }
3607
3608 if ( win && win->HasCustomPalette() )
3609 {
3610 // realize the palette to see whether redrawing is needed
3611 HDC hdc = ::GetDC((HWND) hWndPalChange);
3612 win->m_palette.SetHPALETTE((WXHPALETTE)
3613 ::SelectPalette(hdc, GetHpaletteOf(win->m_palette), FALSE));
574c939e
KB
3614
3615 int result = ::RealizePalette(hdc);
b95edd47
VZ
3616
3617 // restore the palette (before releasing the DC)
3618 win->m_palette.SetHPALETTE((WXHPALETTE)
3619 ::SelectPalette(hdc, GetHpaletteOf(win->m_palette), FALSE));
3620 ::RealizePalette(hdc);
3621 ::ReleaseDC((HWND) hWndPalChange, hdc);
3622
3623 // now check for the need to redraw
574c939e
KB
3624 if (result > 0)
3625 InvalidateRect((HWND) hWndPalChange, NULL, TRUE);
574c939e 3626 }
b95edd47
VZ
3627
3628 }
3629#endif // wxUSE_PALETTE
574c939e 3630
42e69d6b
VZ
3631 wxPaletteChangedEvent event(GetId());
3632 event.SetEventObject(this);
3633 event.SetChangedWindow(wxFindWinFromHandle(hWndPalChange));
2d0a075d 3634
42e69d6b
VZ
3635 return GetEventHandler()->ProcessEvent(event);
3636}
3637
a5e84126
JS
3638bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
3639{
3640 wxMouseCaptureChangedEvent event(GetId(), wxFindWinFromHandle(hWndGainedCapture));
3641 event.SetEventObject(this);
3642
3643 return GetEventHandler()->ProcessEvent(event);
3644}
3645
1e6feb95 3646bool wxWindowMSW::HandleQueryNewPalette()
42e69d6b 3647{
574c939e
KB
3648
3649#if wxUSE_PALETTE
3650 // check to see if we our our parents have a custom palette
fa21d338 3651 wxWindowMSW *win = this;
574c939e
KB
3652 while (!win->HasCustomPalette() && win->GetParent()) win = win->GetParent();
3653 if (win->HasCustomPalette()) {
3654 /* realize the palette to see whether redrawing is needed */
3655 HDC hdc = GetDC((HWND) GetHWND());
3656 win->m_palette.SetHPALETTE( (WXHPALETTE)
b95edd47 3657 ::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), FALSE) );
574c939e
KB
3658
3659 int result = ::RealizePalette(hdc);
3660 /* restore the palette (before releasing the DC) */
3661 win->m_palette.SetHPALETTE( (WXHPALETTE)
b95edd47 3662 ::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), TRUE) );
574c939e
KB
3663 ::RealizePalette(hdc);
3664 ::ReleaseDC((HWND) GetHWND(), hdc);
3665 /* now check for the need to redraw */
3666 if (result > 0)
3667 ::InvalidateRect((HWND) GetHWND(), NULL, TRUE);
3668 }
b95edd47 3669#endif // wxUSE_PALETTE
574c939e 3670
42e69d6b
VZ
3671 wxQueryNewPaletteEvent event(GetId());
3672 event.SetEventObject(this);
3673
3674 return GetEventHandler()->ProcessEvent(event) && event.GetPaletteRealized();
3675}
3676
3677// Responds to colour changes: passes event on to children.
574c939e 3678void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
42e69d6b 3679{
90c1530a
VZ
3680 // the top level window also reset the standard colour map as it might have
3681 // changed (there is no need to do it for the non top level windows as we
3682 // only have to do it once)
3683 if ( IsTopLevel() )
3684 {
3685 // FIXME-MT
3686 gs_hasStdCmap = FALSE;
3687 }
222ed1d6 3688 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
42e69d6b
VZ
3689 while ( node )
3690 {
23895080
VZ
3691 // Only propagate to non-top-level windows because Windows already
3692 // sends this event to all top-level ones
3693 wxWindow *win = node->GetData();
3694 if ( !win->IsTopLevel() )
42e69d6b 3695 {
23895080
VZ
3696 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
3697 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
3698 // the standard controls
3699 ::SendMessage(GetHwndOf(win), WM_SYSCOLORCHANGE, 0, 0);
564b2609 3700 }
42e69d6b 3701
23895080
VZ
3702 node = node->GetNext();
3703 }
3704
3705 // update the colours we use if they were not set explicitly by the user:
3706 // this must be done or OnCtlColor() would continue to use the old colours
3707 if ( !m_hasFgCol )
3708 {
3709 m_foregroundColour = wxSystemSettings::
3710 GetSystemColour(wxSYS_COLOUR_WINDOWTEXT);
3711 }
3712
3713 if ( !m_hasBgCol )
3714 {
3715 m_backgroundColour = wxSystemSettings::
3716 GetSystemColour(wxSYS_COLOUR_BTNFACE);
2bda0e17 3717 }
2bda0e17
KB
3718}
3719
90c1530a
VZ
3720extern wxCOLORMAP *wxGetStdColourMap()
3721{
3722 static COLORREF s_stdColours[wxSTD_COL_MAX];
3723 static wxCOLORMAP s_cmap[wxSTD_COL_MAX];
3724
3725 if ( !gs_hasStdCmap )
3726 {
3727 static bool s_coloursInit = FALSE;
3728
3729 if ( !s_coloursInit )
3730 {
3731 // When a bitmap is loaded, the RGB values can change (apparently
3732 // because Windows adjusts them to care for the old programs always
3733 // using 0xc0c0c0 while the transparent colour for the new Windows
3734 // versions is different). But we do this adjustment ourselves so
3735 // we want to avoid Windows' "help" and for this we need to have a
3736 // reference bitmap which can tell us what the RGB values change
3737 // to.
3738 wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
3739 if ( stdColourBitmap.Ok() )
3740 {
3741 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
3742 wxASSERT_MSG( stdColourBitmap.GetWidth() == wxSTD_COL_MAX,
3743 _T("forgot to update wxBITMAP_STD_COLOURS!") );
3744
3745 wxMemoryDC memDC;
3746 memDC.SelectObject(stdColourBitmap);
3747
3748 wxColour colour;
3749 for ( size_t i = 0; i < WXSIZEOF(s_stdColours); i++ )
3750 {
3751 memDC.GetPixel(i, 0, &colour);
3752 s_stdColours[i] = wxColourToRGB(colour);
3753 }
3754 }
3755 else // wxBITMAP_STD_COLOURS couldn't be loaded
3756 {
3757 s_stdColours[0] = RGB(000,000,000); // black
3758 s_stdColours[1] = RGB(128,128,128); // dark grey
3759 s_stdColours[2] = RGB(192,192,192); // light grey
3760 s_stdColours[3] = RGB(255,255,255); // white
3761 //s_stdColours[4] = RGB(000,000,255); // blue
3762 //s_stdColours[5] = RGB(255,000,255); // magenta
3763 }
3764
3765 s_coloursInit = TRUE;
3766 }
3767
3768 gs_hasStdCmap = TRUE;
3769
3770 // create the colour map
3771#define INIT_CMAP_ENTRY(col) \
3772 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
3773 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
3774
3775 INIT_CMAP_ENTRY(BTNTEXT);
3776 INIT_CMAP_ENTRY(BTNSHADOW);
3777 INIT_CMAP_ENTRY(BTNFACE);
3778 INIT_CMAP_ENTRY(BTNHIGHLIGHT);
3779
3780#undef INIT_CMAP_ENTRY
3781 }
3782
3783 return s_cmap;
3784}
3785
42e69d6b
VZ
3786// ---------------------------------------------------------------------------
3787// painting
3788// ---------------------------------------------------------------------------
3789
1e6feb95 3790bool wxWindowMSW::HandlePaint()
2bda0e17 3791{
85b43fbf
JS
3792// if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
3793// return FALSE;
577baeef 3794
42e69d6b
VZ
3795 HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
3796 if ( !hRegion )
f6bcfd97 3797 wxLogLastError(wxT("CreateRectRgn"));
42e69d6b 3798 if ( ::GetUpdateRgn(GetHwnd(), hRegion, FALSE) == ERROR )
f6bcfd97 3799 wxLogLastError(wxT("GetUpdateRgn"));
c085e333 3800
42e69d6b 3801 m_updateRegion = wxRegion((WXHRGN) hRegion);
c085e333 3802
42e69d6b
VZ
3803 wxPaintEvent event(m_windowId);
3804 event.SetEventObject(this);
2bda0e17 3805
1e6feb95
VZ
3806 bool processed = GetEventHandler()->ProcessEvent(event);
3807
3808 // note that we must generate NC event after the normal one as otherwise
3809 // BeginPaint() will happily overwrite our decorations with the background
3810 // colour
3811 wxNcPaintEvent eventNc(m_windowId);
3812 eventNc.SetEventObject(this);
3813 GetEventHandler()->ProcessEvent(eventNc);
3814
3815 return processed;
2bda0e17
KB
3816}
3817
63da7df7 3818// Can be called from an application's OnPaint handler
1e6feb95 3819void wxWindowMSW::OnPaint(wxPaintEvent& event)
63da7df7 3820{
1e6feb95
VZ
3821#ifdef __WXUNIVERSAL__
3822 event.Skip();
3823#else
63da7df7
JS
3824 HDC hDC = (HDC) wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject());
3825 if (hDC != 0)
3826 {
3827 MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0);
3828 }
1e6feb95 3829#endif
63da7df7
JS
3830}
3831
1e6feb95 3832bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
a23fd0e1 3833{
42e69d6b
VZ
3834 // Prevents flicker when dragging
3835 if ( ::IsIconic(GetHwnd()) )
3836 return TRUE;
a23fd0e1 3837
85b43fbf
JS
3838#if 0
3839 if (GetParent() && GetParent()->GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
3840 {
3841 return FALSE;
3842 }
3843
3844 if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND)
3845 {
3846 if (wxUxThemeEngine::Get())
3847 {
3848 WXHTHEME hTheme = wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L"TAB");
3849 if (hTheme)
3850 {
3851 WXURECT rect;
3852 ::GetClientRect((HWND) GetHWND(), (RECT*) & rect);
3853 wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme, hdc, 10 /* TABP_BODY */, 0, &rect, &rect);
3854 wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme);
3855 return TRUE;
3856 }
3857 }
3858 }
3859#endif
577baeef 3860
7561aacd 3861 wxDCTemp dc(hdc);
c085e333 3862
1e6feb95
VZ
3863 dc.SetHDC(hdc);
3864 dc.SetWindow((wxWindow *)this);
564b2609 3865 dc.BeginDrawing();
c085e333 3866
2bda0e17 3867 wxEraseEvent event(m_windowId, &dc);
42e69d6b 3868 event.SetEventObject(this);
a23fd0e1 3869 bool rc = GetEventHandler()->ProcessEvent(event);
c085e333 3870
a23fd0e1 3871 dc.EndDrawing();
7561aacd
VZ
3872
3873 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
a23fd0e1 3874 dc.SelectOldObjects(hdc);
a23fd0e1
VZ
3875
3876 return rc;
2bda0e17
KB
3877}
3878
1e6feb95 3879void wxWindowMSW::OnEraseBackground(wxEraseEvent& event)
2bda0e17 3880{
2d0a075d 3881 RECT rect;
a23fd0e1 3882 ::GetClientRect(GetHwnd(), &rect);
2bda0e17 3883
42e69d6b
VZ
3884 COLORREF ref = PALETTERGB(m_backgroundColour.Red(),
3885 m_backgroundColour.Green(),
3886 m_backgroundColour.Blue());
ce3ed50d 3887 HBRUSH hBrush = ::CreateSolidBrush(ref);
42e69d6b 3888 if ( !hBrush )
f6bcfd97 3889 wxLogLastError(wxT("CreateSolidBrush"));
42e69d6b
VZ
3890
3891 HDC hdc = (HDC)event.GetDC()->GetHDC();
2bda0e17 3892
7f0586ef 3893#ifndef __WXWINCE__
42e69d6b 3894 int mode = ::SetMapMode(hdc, MM_TEXT);
7f0586ef 3895#endif
42e69d6b
VZ
3896
3897 ::FillRect(hdc, &rect, hBrush);
2d0a075d 3898 ::DeleteObject(hBrush);
7f0586ef
JS
3899
3900#ifndef __WXWINCE__
42e69d6b 3901 ::SetMapMode(hdc, mode);
7f0586ef 3902#endif
42e69d6b
VZ
3903}
3904
3905// ---------------------------------------------------------------------------
3906// moving and resizing
3907// ---------------------------------------------------------------------------
3908
1e6feb95 3909bool wxWindowMSW::HandleMinimize()
42e69d6b
VZ
3910{
3911 wxIconizeEvent event(m_windowId);
3912 event.SetEventObject(this);
2d0a075d 3913
42e69d6b 3914 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3915}
3916
1e6feb95 3917bool wxWindowMSW::HandleMaximize()
2bda0e17 3918{
42e69d6b
VZ
3919 wxMaximizeEvent event(m_windowId);
3920 event.SetEventObject(this);
c085e333 3921
42e69d6b
VZ
3922 return GetEventHandler()->ProcessEvent(event);
3923}
2bda0e17 3924
1e6feb95 3925bool wxWindowMSW::HandleMove(int x, int y)
42e69d6b
VZ
3926{
3927 wxMoveEvent event(wxPoint(x, y), m_windowId);
3928 event.SetEventObject(this);
3929
3930 return GetEventHandler()->ProcessEvent(event);
3931}
3932
5706de1c
JS
3933bool wxWindowMSW::HandleMoving(wxRect& rect)
3934{
3935 wxMoveEvent event(rect, m_windowId);
3936 event.SetEventObject(this);
577baeef 3937
5706de1c
JS
3938 bool rc = GetEventHandler()->ProcessEvent(event);
3939 if (rc)
3940 rect = event.GetRect();
3941 return rc;
3942}
3943
4e4a5fed
VZ
3944bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h),
3945 WXUINT WXUNUSED(flag))
42e69d6b 3946{
4e4a5fed
VZ
3947 // don't use w and h parameters as they specify the client size while
3948 // according to the docs EVT_SIZE handler is supposed to receive the total
3949 // size
3950 wxSizeEvent event(GetSize(), m_windowId);
42e69d6b
VZ
3951 event.SetEventObject(this);
3952
3953 return GetEventHandler()->ProcessEvent(event);
3954}
3955
5706de1c
JS
3956bool wxWindowMSW::HandleSizing(wxRect& rect)
3957{
3958 wxSizeEvent event(rect, m_windowId);
3959 event.SetEventObject(this);
577baeef 3960
5706de1c
JS
3961 bool rc = GetEventHandler()->ProcessEvent(event);
3962 if (rc)
3963 rect = event.GetRect();
3964 return rc;
3965}
3966
1e6feb95 3967bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo)
42e69d6b 3968{
7f0586ef
JS
3969#ifdef __WXWINCE__
3970 return FALSE;
3971#else
42e69d6b
VZ
3972 MINMAXINFO *info = (MINMAXINFO *)mmInfo;
3973
3974 bool rc = FALSE;
b2d5a7ee 3975
e7dda1ff
VS
3976 int minWidth = GetMinWidth(),
3977 minHeight = GetMinHeight(),
3978 maxWidth = GetMaxWidth(),
3979 maxHeight = GetMaxHeight();
42e69d6b 3980
e7dda1ff 3981 if ( minWidth != -1 )
2d0a075d 3982 {
e7dda1ff 3983 info->ptMinTrackSize.x = minWidth;
42e69d6b 3984 rc = TRUE;
2d0a075d 3985 }
2bda0e17 3986
e7dda1ff 3987 if ( minHeight != -1 )
42e69d6b 3988 {
e7dda1ff 3989 info->ptMinTrackSize.y = minHeight;
42e69d6b
VZ
3990 rc = TRUE;
3991 }
2bda0e17 3992
e7dda1ff 3993 if ( maxWidth != -1 )
42e69d6b 3994 {
e7dda1ff 3995 info->ptMaxTrackSize.x = maxWidth;
42e69d6b 3996 rc = TRUE;
2d0a075d 3997 }
2bda0e17 3998
e7dda1ff 3999 if ( maxHeight != -1 )
42e69d6b 4000 {
e7dda1ff 4001 info->ptMaxTrackSize.y = maxHeight;
42e69d6b
VZ
4002 rc = TRUE;
4003 }
2bda0e17 4004
42e69d6b 4005 return rc;
7f0586ef 4006#endif
42e69d6b 4007}
2d0a075d 4008
42e69d6b
VZ
4009// ---------------------------------------------------------------------------
4010// command messages
4011// ---------------------------------------------------------------------------
4012
1e6feb95 4013bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
42e69d6b 4014{
1e6feb95 4015#if wxUSE_MENUS_NATIVE
8c290175 4016 if ( !cmd && wxCurrentPopupMenu )
42e69d6b
VZ
4017 {
4018 wxMenu *popupMenu = wxCurrentPopupMenu;
4019 wxCurrentPopupMenu = NULL;
4020
4021 return popupMenu->MSWCommand(cmd, id);
4022 }
1e6feb95 4023#endif // wxUSE_MENUS_NATIVE
42e69d6b 4024
8c290175 4025 wxWindow *win = NULL;
71292fab
VZ
4026
4027 // first try to find it from HWND - this works even with the broken
4028 // programs using the same ids for different controls
4029 if ( control )
42e69d6b 4030 {
71292fab 4031 win = wxFindWinFromHandle(control);
b853f898 4032 }
2f4ef631 4033
71292fab
VZ
4034 // try the id
4035 if ( !win )
b853f898 4036 {
71292fab
VZ
4037 // must cast to a signed type before comparing with other ids!
4038 win = FindItem((signed short)id);
42e69d6b
VZ
4039 }
4040
4041 if ( win )
b94ae1ea 4042 {
42e69d6b 4043 return win->MSWCommand(cmd, id);
b94ae1ea
VZ
4044 }
4045
4046 // the messages sent from the in-place edit control used by the treectrl
4047 // for label editing have id == 0, but they should _not_ be treated as menu
4048 // messages (they are EN_XXX ones, in fact) so don't translate anything
4049 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
4050 if ( !control )
a84fc80b 4051 {
b94ae1ea
VZ
4052 // If no child window, it may be an accelerator, e.g. for a popup menu
4053 // command
a84fc80b
JS
4054
4055 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
4056 event.SetEventObject(this);
4057 event.SetId(id);
4058 event.SetInt(id);
b94ae1ea
VZ
4059
4060 return GetEventHandler()->ProcessEvent(event);
a84fc80b 4061 }
24ce4c18 4062#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
6fe19057
VZ
4063 else
4064 {
4065 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
4066 // notifications to its parent which we want to reflect back to
4067 // wxSpinCtrl
4068 wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control);
4069 if ( spin && spin->ProcessTextCommand(cmd, id) )
4070 return TRUE;
4071 }
4072#endif // wxUSE_SPINCTRL
42e69d6b
VZ
4073
4074 return FALSE;
2bda0e17
KB
4075}
4076
1e6feb95 4077bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam))
2bda0e17 4078{
7f0586ef 4079#ifndef __WXWINCE__
42e69d6b
VZ
4080 // 4 bits are reserved
4081 switch ( wParam & 0xFFFFFFF0 )
4082 {
4083 case SC_MAXIMIZE:
4084 return HandleMaximize();
2d0a075d 4085
42e69d6b
VZ
4086 case SC_MINIMIZE:
4087 return HandleMinimize();
2d0a075d 4088 }
7f0586ef 4089#endif
2bda0e17 4090
42e69d6b
VZ
4091 return FALSE;
4092}
4093
4094// ---------------------------------------------------------------------------
4095// mouse events
4096// ---------------------------------------------------------------------------
4097
1e6feb95
VZ
4098void wxWindowMSW::InitMouseEvent(wxMouseEvent& event,
4099 int x, int y,
4100 WXUINT flags)
42e69d6b 4101{
1e6feb95
VZ
4102 // our client coords are not quite the same as Windows ones
4103 wxPoint pt = GetClientAreaOrigin();
4104 event.m_x = x - pt.x;
4105 event.m_y = y - pt.y;
4106
4107 event.m_shiftDown = (flags & MK_SHIFT) != 0;
4108 event.m_controlDown = (flags & MK_CONTROL) != 0;
4109 event.m_leftDown = (flags & MK_LBUTTON) != 0;
4110 event.m_middleDown = (flags & MK_MBUTTON) != 0;
4111 event.m_rightDown = (flags & MK_RBUTTON) != 0;
1fdf858b
JS
4112 // event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0;
4113 // Returns different negative values on WinME and WinNT,
4114 // so simply test for negative value.
4115 event.m_altDown = ::GetKeyState(VK_MENU) < 0;
1e6feb95 4116
42e69d6b
VZ
4117 event.SetTimestamp(s_currentMsg.time);
4118 event.m_eventObject = this;
fb35f0c7 4119 event.SetId(GetId());
42e69d6b
VZ
4120
4121#if wxUSE_MOUSEEVENT_HACK
4122 m_lastMouseX = x;
4123 m_lastMouseY = y;
4124 m_lastMouseEvent = event.GetEventType();
4125#endif // wxUSE_MOUSEEVENT_HACK
2bda0e17
KB
4126}
4127
dfafa702
VZ
4128// Windows doesn't send the mouse events to the static controls (which are
4129// transparent in the sense that their WM_NCHITTEST handler returns
4130// HTTRANSPARENT) at all but we want all controls to receive the mouse events
4131// and so we manually check if we don't have a child window under mouse and if
4132// we do, send the event to it instead of the window Windows had sent WM_XXX
4133// to.
4134//
4135// Notice that this is not done for the mouse move events because this could
4136// (would?) be too slow, but only for clicks which means that the static texts
4137// still don't get move, enter nor leave events.
abcbaea7 4138static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) //TW:REQ:Univ
dfafa702
VZ
4139{
4140 wxCHECK_MSG( x && y, win, _T("NULL pointer in FindWindowForMouseEvent") );
4141
4142 // first try to find a non transparent child: this allows us to send events
4143 // to a static text which is inside a static box, for example
4144 POINT pt = { *x, *y };
4145 HWND hwnd = GetHwndOf(win),
4146 hwndUnderMouse;
4147
7f0586ef
JS
4148#ifdef __WXWINCE__
4149 hwndUnderMouse = ::ChildWindowFromPoint
4150 (
4151 hwnd,
4152 pt
4153 );
4154#else
dfafa702
VZ
4155 hwndUnderMouse = ::ChildWindowFromPointEx
4156 (
4157 hwnd,
4158 pt,
4159 CWP_SKIPINVISIBLE |
4160 CWP_SKIPDISABLED |
4161 CWP_SKIPTRANSPARENT
4162 );
7f0586ef 4163#endif
dfafa702
VZ
4164
4165 if ( !hwndUnderMouse || hwndUnderMouse == hwnd )
dfafa702
VZ
4166 {
4167 // now try any child window at all
4168 hwndUnderMouse = ::ChildWindowFromPoint(hwnd, pt);
4169 }
4170
4171 // check that we have a child window which is susceptible to receive mouse
4172 // events: for this it must be shown and enabled
4173 if ( hwndUnderMouse &&
4174 hwndUnderMouse != hwnd &&
4175 ::IsWindowVisible(hwndUnderMouse) &&
4176 ::IsWindowEnabled(hwndUnderMouse) )
4177 {
4178 wxWindow *winUnderMouse = wxFindWinFromHandle((WXHWND)hwndUnderMouse);
4179 if ( winUnderMouse )
4180 {
4181 // translate the mouse coords to the other window coords
4182 win->ClientToScreen(x, y);
4183 winUnderMouse->ScreenToClient(x, y);
4184
4185 win = winUnderMouse;
4186 }
4187 }
4188
4189 return win;
4190}
4191
1e6feb95 4192bool wxWindowMSW::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
2bda0e17 4193{
42e69d6b
VZ
4194 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
4195 // WM_MOUSELAST, so it's enough to substract WM_MOUSEMOVE == WM_MOUSEFIRST
4196 // from the message id and take the value in the table to get wxWin event
4197 // id
4198 static const wxEventType eventsMouse[] =
4199 {
4200 wxEVT_MOTION,
4201 wxEVT_LEFT_DOWN,
4202 wxEVT_LEFT_UP,
4203 wxEVT_LEFT_DCLICK,
4204 wxEVT_RIGHT_DOWN,
4205 wxEVT_RIGHT_UP,
4206 wxEVT_RIGHT_DCLICK,
4207 wxEVT_MIDDLE_DOWN,
4208 wxEVT_MIDDLE_UP,
4209 wxEVT_MIDDLE_DCLICK
4210 };
2bda0e17 4211
42e69d6b
VZ
4212 wxMouseEvent event(eventsMouse[msg - WM_MOUSEMOVE]);
4213 InitMouseEvent(event, x, y, flags);
4214
4215 return GetEventHandler()->ProcessEvent(event);
4216}
4217
1e6feb95 4218bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
42e69d6b
VZ
4219{
4220 if ( !m_mouseInWindow )
2bda0e17 4221 {
1e6feb95
VZ
4222 // it would be wrong to assume that just because we get a mouse move
4223 // event that the mouse is inside the window: although this is usually
4224 // true, it is not if we had captured the mouse, so we need to check
4225 // the mouse coordinates here
4226 if ( !HasCapture() || IsMouseInWindow() )
4227 {
4228 // Generate an ENTER event
4229 m_mouseInWindow = TRUE;
42e69d6b 4230
1e6feb95
VZ
4231 wxMouseEvent event(wxEVT_ENTER_WINDOW);
4232 InitMouseEvent(event, x, y, flags);
42e69d6b 4233
1e6feb95
VZ
4234 (void)GetEventHandler()->ProcessEvent(event);
4235 }
42e69d6b
VZ
4236 }
4237
4238#if wxUSE_MOUSEEVENT_HACK
4239 // Window gets a click down message followed by a mouse move message even
4240 // if position isn't changed! We want to discard the trailing move event
4241 // if x and y are the same.
4242 if ( (m_lastMouseEvent == wxEVT_RIGHT_DOWN ||
4243 m_lastMouseEvent == wxEVT_LEFT_DOWN ||
4244 m_lastMouseEvent == wxEVT_MIDDLE_DOWN) &&
06b32ebe 4245 (m_lastMouseX == x && m_lastMouseY == y) )
42e69d6b
VZ
4246 {
4247 m_lastMouseEvent = wxEVT_MOTION;
4248
4249 return FALSE;
4250 }
4251#endif // wxUSE_MOUSEEVENT_HACK
4252
4253 return HandleMouseEvent(WM_MOUSEMOVE, x, y, flags);
4254}
4255
d2c52078 4256
24ce4c18 4257bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
d2c52078
RD
4258{
4259#if wxUSE_MOUSEWHEEL
4260 wxMouseEvent event(wxEVT_MOUSEWHEEL);
4261 InitMouseEvent(event,
4262 GET_X_LPARAM(lParam),
4263 GET_Y_LPARAM(lParam),
4264 LOWORD(wParam));
d2c52078
RD
4265 event.m_wheelRotation = (short)HIWORD(wParam);
4266 event.m_wheelDelta = WHEEL_DELTA;
4267
0f7a546d
RD
4268 static int s_linesPerRotation = -1;
4269 if ( s_linesPerRotation == -1 )
4270 {
4271 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
4272 &s_linesPerRotation, 0))
4273 {
4274 // this is not supposed to happen
4275 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
4276
4277 // the default is 3, so use it if SystemParametersInfo() failed
4278 s_linesPerRotation = 3;
4279 }
4280 }
d2c52078 4281
0f7a546d 4282 event.m_linesPerAction = s_linesPerRotation;
d2c52078 4283 return GetEventHandler()->ProcessEvent(event);
0f7a546d 4284
d2c52078 4285#else
38caaa61
KB
4286 (void) wParam;
4287 (void) lParam;
4288
d2c52078
RD
4289 return FALSE;
4290#endif
4291}
4292
4293
42e69d6b
VZ
4294// ---------------------------------------------------------------------------
4295// keyboard handling
4296// ---------------------------------------------------------------------------
4297
c42404a5
VZ
4298// create the key event of the given type for the given key - used by
4299// HandleChar and HandleKeyDown/Up
1e6feb95 4300wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType,
b09bda68 4301 int id,
9c7df356
VZ
4302 WXLPARAM lParam,
4303 WXWPARAM wParam) const
c42404a5
VZ
4304{
4305 wxKeyEvent event(evType);
4306 event.SetId(GetId());
3f7bc32b
VZ
4307 event.m_shiftDown = wxIsShiftDown();
4308 event.m_controlDown = wxIsCtrlDown();
c42404a5
VZ
4309 event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN;
4310
4311 event.m_eventObject = (wxWindow *)this; // const_cast
4312 event.m_keyCode = id;
9c7df356
VZ
4313 event.m_rawCode = (wxUint32) wParam;
4314 event.m_rawFlags = (wxUint32) lParam;
c42404a5
VZ
4315 event.SetTimestamp(s_currentMsg.time);
4316
4317 // translate the position to client coords
4318 POINT pt;
4319 GetCursorPos(&pt);
4320 RECT rect;
4321 GetWindowRect(GetHwnd(),&rect);
4322 pt.x -= rect.left;
4323 pt.y -= rect.top;
4324
4325 event.m_x = pt.x;
4326 event.m_y = pt.y;
4327
4328 return event;
4329}
4330
42e69d6b
VZ
4331// isASCII is TRUE only when we're called from WM_CHAR handler and not from
4332// WM_KEYDOWN one
1e6feb95 4333bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
42e69d6b 4334{
c42404a5
VZ
4335 bool ctrlDown = FALSE;
4336
42e69d6b 4337 int id;
42e69d6b
VZ
4338 if ( isASCII )
4339 {
ad9f1aec
RD
4340 // If 1 -> 26, translate to either special keycode or just set
4341 // ctrlDown. IOW, Ctrl-C should result in keycode == 3 and
4342 // ControlDown() == TRUE.
42e69d6b
VZ
4343 id = wParam;
4344 if ( (id > 0) && (id < 27) )
2d0a075d 4345 {
42e69d6b
VZ
4346 switch (id)
4347 {
c42404a5 4348 case 13:
42e69d6b
VZ
4349 id = WXK_RETURN;
4350 break;
c42404a5
VZ
4351
4352 case 8:
42e69d6b
VZ
4353 id = WXK_BACK;
4354 break;
c42404a5
VZ
4355
4356 case 9:
42e69d6b
VZ
4357 id = WXK_TAB;
4358 break;
c42404a5
VZ
4359
4360 default:
4361 ctrlDown = TRUE;
ad9f1aec 4362 break;
42e69d6b 4363 }
2d0a075d 4364 }
2d0a075d 4365 }
9c7df356 4366 else // we're called from WM_KEYDOWN
c42404a5 4367 {
9c7df356
VZ
4368 id = wxCharCodeMSWToWX(wParam);
4369 if ( id == 0 )
c42404a5 4370 {
9c7df356
VZ
4371 // it's ASCII and will be processed here only when called from
4372 // WM_CHAR (i.e. when isASCII = TRUE), don't process it now
4373 return FALSE;
c42404a5 4374 }
9c7df356 4375 }
42e69d6b 4376
9c7df356 4377 wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam, wParam));
2b5f62a0
VZ
4378
4379 // the alphanumeric keys produced by pressing AltGr+something on European
4380 // keyboards have both Ctrl and Alt modifiers which may confuse the user
4381 // code as, normally, keys with Ctrl and/or Alt don't result in anything
4382 // alphanumeric, so pretend that there are no modifiers at all (the
4383 // KEY_DOWN event would still have the correct modifiers if they're really
4384 // needed)
4385 if ( event.m_controlDown && event.m_altDown &&
4386 (id >= 32 && id < 256) )
9c7df356 4387 {
2b5f62a0
VZ
4388 event.m_controlDown =
4389 event.m_altDown = FALSE;
2d0a075d 4390 }
c42404a5 4391
9c7df356 4392 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
4393}
4394
1e6feb95 4395bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
2bda0e17 4396{
c42404a5 4397 int id = wxCharCodeMSWToWX(wParam);
2bda0e17 4398
c42404a5
VZ
4399 if ( !id )
4400 {
4401 // normal ASCII char
42e69d6b
VZ
4402 id = wParam;
4403 }
4404
c42404a5 4405 if ( id != -1 ) // VZ: does this ever happen (FIXME)?
2bda0e17 4406 {
9c7df356 4407 wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
42e69d6b 4408 if ( GetEventHandler()->ProcessEvent(event) )
2d0a075d 4409 {
42e69d6b 4410 return TRUE;
2d0a075d 4411 }
42e69d6b 4412 }
c42404a5
VZ
4413
4414 return FALSE;
2bda0e17
KB
4415}
4416
1e6feb95 4417bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
2bda0e17 4418{
c42404a5 4419 int id = wxCharCodeMSWToWX(wParam);
2bda0e17 4420
c42404a5
VZ
4421 if ( !id )
4422 {
4423 // normal ASCII char
42e69d6b 4424 id = wParam;
2d0a075d 4425 }
2bda0e17 4426
c42404a5 4427 if ( id != -1 ) // VZ: does this ever happen (FIXME)?
42e69d6b 4428 {
9c7df356 4429 wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
42e69d6b
VZ
4430 if ( GetEventHandler()->ProcessEvent(event) )
4431 return TRUE;
42e69d6b 4432 }
c42404a5
VZ
4433
4434 return FALSE;
2bda0e17
KB
4435}
4436
b74cce40
VZ
4437int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam)
4438{
7f0586ef
JS
4439 // FIXME: implement GetMenuItemCount for WinCE, possibly
4440 // in terms of GetMenuItemInfo
4441#ifndef __WXWINCE__
b74cce40
VZ
4442 const HMENU hmenu = (HMENU)lParam;
4443
4444 MENUITEMINFO mii;
4445 wxZeroMemory(mii);
4446 mii.cbSize = sizeof(MENUITEMINFO);
4447 mii.fMask = MIIM_TYPE | MIIM_DATA;
4448
4449 // find if we have this letter in any owner drawn item
4450 const int count = ::GetMenuItemCount(hmenu);
4451 for ( int i = 0; i < count; i++ )
4452 {
4453 if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) )
4454 {
4455 if ( mii.fType == MFT_OWNERDRAW )
4456 {
4457 // dwItemData member of the MENUITEMINFO is a
4458 // pointer to the associated wxMenuItem -- see the
4459 // menu creation code
4460 wxMenuItem *item = (wxMenuItem*)mii.dwItemData;
4461
4462 const wxChar *p = wxStrchr(item->GetText(), _T('&'));
4463 while ( p++ )
4464 {
4465 if ( *p == _T('&') )
4466 {
4467 // this is not the accel char, find the real one
4468 p = wxStrchr(p + 1, _T('&'));
4469 }
4470 else // got the accel char
4471 {
4472 // FIXME-UNICODE: this comparison doesn't risk to work
4473 // for non ASCII accelerator characters I'm afraid, but
4474 // what can we do?
4475 if ( wxToupper(*p) == chAccel )
4476 {
4477 return i;
4478 }
4479 else
4480 {
4481 // this one doesn't match
4482 break;
4483 }
4484 }
4485 }
4486 }
4487 }
e39af974 4488 else // failed to get the menu text?
b74cce40
VZ
4489 {
4490 // it's not fatal, so don't show error, but still log
4491 // it
4492 wxLogLastError(_T("GetMenuItemInfo"));
4493 }
4494 }
7f0586ef 4495#endif
b74cce40
VZ
4496 return wxNOT_FOUND;
4497}
4498
42e69d6b
VZ
4499// ---------------------------------------------------------------------------
4500// joystick
4501// ---------------------------------------------------------------------------
4502
1e6feb95 4503bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags)
2bda0e17 4504{
8cb172b4 4505#ifdef JOY_BUTTON1
42e69d6b
VZ
4506 int change = 0;
4507 if ( flags & JOY_BUTTON1CHG )
4508 change = wxJOY_BUTTON1;
4509 if ( flags & JOY_BUTTON2CHG )
4510 change = wxJOY_BUTTON2;
4511 if ( flags & JOY_BUTTON3CHG )
4512 change = wxJOY_BUTTON3;
4513 if ( flags & JOY_BUTTON4CHG )
4514 change = wxJOY_BUTTON4;
2bda0e17 4515
42e69d6b
VZ
4516 int buttons = 0;
4517 if ( flags & JOY_BUTTON1 )
4518 buttons |= wxJOY_BUTTON1;
4519 if ( flags & JOY_BUTTON2 )
4520 buttons |= wxJOY_BUTTON2;
4521 if ( flags & JOY_BUTTON3 )
4522 buttons |= wxJOY_BUTTON3;
4523 if ( flags & JOY_BUTTON4 )
4524 buttons |= wxJOY_BUTTON4;
c085e333 4525
42e69d6b
VZ
4526 // the event ids aren't consecutive so we can't use table based lookup
4527 int joystick;
4528 wxEventType eventType;
4529 switch ( msg )
4530 {
4531 case MM_JOY1MOVE:
4532 joystick = 1;
4533 eventType = wxEVT_JOY_MOVE;
4534 break;
2bda0e17 4535
42e69d6b
VZ
4536 case MM_JOY2MOVE:
4537 joystick = 2;
4538 eventType = wxEVT_JOY_MOVE;
4539 break;
2bda0e17 4540
42e69d6b
VZ
4541 case MM_JOY1ZMOVE:
4542 joystick = 1;
4543 eventType = wxEVT_JOY_ZMOVE;
4544 break;
2bda0e17 4545
42e69d6b
VZ
4546 case MM_JOY2ZMOVE:
4547 joystick = 2;
4548 eventType = wxEVT_JOY_ZMOVE;
4549 break;
2bda0e17 4550
42e69d6b
VZ
4551 case MM_JOY1BUTTONDOWN:
4552 joystick = 1;
4553 eventType = wxEVT_JOY_BUTTON_DOWN;
4554 break;
2bda0e17 4555
42e69d6b
VZ
4556 case MM_JOY2BUTTONDOWN:
4557 joystick = 2;
4558 eventType = wxEVT_JOY_BUTTON_DOWN;
4559 break;
2bda0e17 4560
42e69d6b
VZ
4561 case MM_JOY1BUTTONUP:
4562 joystick = 1;
4563 eventType = wxEVT_JOY_BUTTON_UP;
4564 break;
4565
4566 case MM_JOY2BUTTONUP:
4567 joystick = 2;
4568 eventType = wxEVT_JOY_BUTTON_UP;
4569 break;
4570
4571 default:
223d09f6 4572 wxFAIL_MSG(wxT("no such joystick event"));
2d0a075d 4573
42e69d6b 4574 return FALSE;
2d0a075d 4575 }
2bda0e17 4576
42e69d6b
VZ
4577 wxJoystickEvent event(eventType, buttons, joystick, change);
4578 event.SetPosition(wxPoint(x, y));
4579 event.SetEventObject(this);
c085e333 4580
42e69d6b 4581 return GetEventHandler()->ProcessEvent(event);
8cb172b4
JS
4582#else
4583 return FALSE;
4584#endif
2bda0e17
KB
4585}
4586
42e69d6b
VZ
4587// ---------------------------------------------------------------------------
4588// scrolling
4589// ---------------------------------------------------------------------------
4590
1e6feb95 4591bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
f4f734c1 4592 WXWORD pos, WXHWND control)
2bda0e17 4593{
42e69d6b 4594 if ( control )
cc2b7472 4595 {
42e69d6b
VZ
4596 wxWindow *child = wxFindWinFromHandle(control);
4597 if ( child )
4598 return child->MSWOnScroll(orientation, wParam, pos, control);
cc2b7472 4599 }
2bda0e17 4600
9145664b 4601 wxScrollWinEvent event;
42e69d6b
VZ
4602 event.SetPosition(pos);
4603 event.SetOrientation(orientation);
4604 event.m_eventObject = this;
cc2b7472 4605
42e69d6b
VZ
4606 switch ( wParam )
4607 {
4608 case SB_TOP:
9145664b 4609 event.m_eventType = wxEVT_SCROLLWIN_TOP;
42e69d6b 4610 break;
cc2b7472 4611
42e69d6b 4612 case SB_BOTTOM:
9145664b 4613 event.m_eventType = wxEVT_SCROLLWIN_BOTTOM;
42e69d6b 4614 break;
cc2b7472 4615
42e69d6b 4616 case SB_LINEUP:
9145664b 4617 event.m_eventType = wxEVT_SCROLLWIN_LINEUP;
42e69d6b 4618 break;
2bda0e17 4619
42e69d6b 4620 case SB_LINEDOWN:
9145664b 4621 event.m_eventType = wxEVT_SCROLLWIN_LINEDOWN;
42e69d6b 4622 break;
a02eb1d2 4623
42e69d6b 4624 case SB_PAGEUP:
9145664b 4625 event.m_eventType = wxEVT_SCROLLWIN_PAGEUP;
42e69d6b 4626 break;
2bda0e17 4627
42e69d6b 4628 case SB_PAGEDOWN:
9145664b 4629 event.m_eventType = wxEVT_SCROLLWIN_PAGEDOWN;
42e69d6b 4630 break;
2bda0e17 4631
42e69d6b 4632 case SB_THUMBPOSITION:
feda3011 4633 case SB_THUMBTRACK:
f6bcfd97
BP
4634 // under Win32, the scrollbar range and position are 32 bit integers,
4635 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
4636 // explicitly query the scrollbar for the correct position (this must
4637 // be done only for these two SB_ events as they are the only one
4638 // carrying the scrollbar position)
4639 {
0cf5de11 4640 WinStruct<SCROLLINFO> scrollInfo;
f6bcfd97
BP
4641 scrollInfo.fMask = SIF_TRACKPOS;
4642
4643 if ( !::GetScrollInfo(GetHwnd(),
4644 orientation == wxHORIZONTAL ? SB_HORZ
4645 : SB_VERT,
4646 &scrollInfo) )
4647 {
4648 wxLogLastError(_T("GetScrollInfo"));
4649 }
4650
4651 event.SetPosition(scrollInfo.nTrackPos);
4652 }
f6bcfd97
BP
4653
4654 event.m_eventType = wParam == SB_THUMBPOSITION
4655 ? wxEVT_SCROLLWIN_THUMBRELEASE
4656 : wxEVT_SCROLLWIN_THUMBTRACK;
42e69d6b 4657 break;
c085e333 4658
42e69d6b
VZ
4659 default:
4660 return FALSE;
564b2609 4661 }
2bda0e17 4662
42e69d6b 4663 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
4664}
4665
42e69d6b
VZ
4666// ===========================================================================
4667// global functions
4668// ===========================================================================
4669
f68586e5 4670void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font)
2bda0e17 4671{
42e69d6b
VZ
4672 TEXTMETRIC tm;
4673 HDC dc = ::GetDC((HWND) wnd);
4674 HFONT fnt =0;
4675 HFONT was = 0;
4676 if ( the_font )
2d0a075d 4677 {
42e69d6b
VZ
4678 // the_font->UseResource();
4679 // the_font->RealizeResource();
f68586e5 4680 fnt = (HFONT)((wxFont *)the_font)->GetResourceHandle(); // const_cast
42e69d6b
VZ
4681 if ( fnt )
4682 was = (HFONT) SelectObject(dc,fnt);
2d0a075d 4683 }
42e69d6b
VZ
4684 GetTextMetrics(dc, &tm);
4685 if ( the_font && fnt && was )
2d0a075d 4686 {
42e69d6b 4687 SelectObject(dc,was);
2d0a075d 4688 }
42e69d6b 4689 ReleaseDC((HWND)wnd, dc);
0655ad29
VZ
4690
4691 if ( x )
4692 *x = tm.tmAveCharWidth;
4693 if ( y )
4694 *y = tm.tmHeight + tm.tmExternalLeading;
2bda0e17 4695
42e69d6b
VZ
4696 // if ( the_font )
4697 // the_font->ReleaseResource();
4698}
c085e333 4699
42e69d6b
VZ
4700// Returns 0 if was a normal ASCII value, not a special key. This indicates that
4701// the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4702int wxCharCodeMSWToWX(int keySym)
4703{
f6bcfd97 4704 int id;
42e69d6b
VZ
4705 switch (keySym)
4706 {
f6bcfd97
BP
4707 case VK_CANCEL: id = WXK_CANCEL; break;
4708 case VK_BACK: id = WXK_BACK; break;
4709 case VK_TAB: id = WXK_TAB; break;
4710 case VK_CLEAR: id = WXK_CLEAR; break;
4711 case VK_RETURN: id = WXK_RETURN; break;
4712 case VK_SHIFT: id = WXK_SHIFT; break;
4713 case VK_CONTROL: id = WXK_CONTROL; break;
4714 case VK_MENU : id = WXK_MENU; break;
4715 case VK_PAUSE: id = WXK_PAUSE; break;
9c7df356 4716 case VK_CAPITAL: id = WXK_CAPITAL; break;
f6bcfd97
BP
4717 case VK_SPACE: id = WXK_SPACE; break;
4718 case VK_ESCAPE: id = WXK_ESCAPE; break;
4719 case VK_PRIOR: id = WXK_PRIOR; break;
4720 case VK_NEXT : id = WXK_NEXT; break;
4721 case VK_END: id = WXK_END; break;
4722 case VK_HOME : id = WXK_HOME; break;
4723 case VK_LEFT : id = WXK_LEFT; break;
4724 case VK_UP: id = WXK_UP; break;
4725 case VK_RIGHT: id = WXK_RIGHT; break;
4726 case VK_DOWN : id = WXK_DOWN; break;
4727 case VK_SELECT: id = WXK_SELECT; break;
4728 case VK_PRINT: id = WXK_PRINT; break;
4729 case VK_EXECUTE: id = WXK_EXECUTE; break;
4730 case VK_INSERT: id = WXK_INSERT; break;
4731 case VK_DELETE: id = WXK_DELETE; break;
4732 case VK_HELP : id = WXK_HELP; break;
4733 case VK_NUMPAD0: id = WXK_NUMPAD0; break;
4734 case VK_NUMPAD1: id = WXK_NUMPAD1; break;
4735 case VK_NUMPAD2: id = WXK_NUMPAD2; break;
4736 case VK_NUMPAD3: id = WXK_NUMPAD3; break;
4737 case VK_NUMPAD4: id = WXK_NUMPAD4; break;
4738 case VK_NUMPAD5: id = WXK_NUMPAD5; break;
4739 case VK_NUMPAD6: id = WXK_NUMPAD6; break;
4740 case VK_NUMPAD7: id = WXK_NUMPAD7; break;
4741 case VK_NUMPAD8: id = WXK_NUMPAD8; break;
4742 case VK_NUMPAD9: id = WXK_NUMPAD9; break;
32a87ae7 4743 case VK_MULTIPLY: id = WXK_NUMPAD_MULTIPLY; break;
32a87ae7 4744 case VK_ADD: id = WXK_NUMPAD_ADD; break;
32a87ae7 4745 case VK_SUBTRACT: id = WXK_NUMPAD_SUBTRACT; break;
32a87ae7
VZ
4746 case VK_DECIMAL: id = WXK_NUMPAD_DECIMAL; break;
4747 case VK_DIVIDE: id = WXK_NUMPAD_DIVIDE; break;
f6bcfd97
BP
4748 case VK_F1: id = WXK_F1; break;
4749 case VK_F2: id = WXK_F2; break;
4750 case VK_F3: id = WXK_F3; break;
4751 case VK_F4: id = WXK_F4; break;
4752 case VK_F5: id = WXK_F5; break;
4753 case VK_F6: id = WXK_F6; break;
4754 case VK_F7: id = WXK_F7; break;
4755 case VK_F8: id = WXK_F8; break;
4756 case VK_F9: id = WXK_F9; break;
4757 case VK_F10: id = WXK_F10; break;
4758 case VK_F11: id = WXK_F11; break;
4759 case VK_F12: id = WXK_F12; break;
4760 case VK_F13: id = WXK_F13; break;
4761 case VK_F14: id = WXK_F14; break;
4762 case VK_F15: id = WXK_F15; break;
4763 case VK_F16: id = WXK_F16; break;
4764 case VK_F17: id = WXK_F17; break;
4765 case VK_F18: id = WXK_F18; break;
4766 case VK_F19: id = WXK_F19; break;
4767 case VK_F20: id = WXK_F20; break;
4768 case VK_F21: id = WXK_F21; break;
4769 case VK_F22: id = WXK_F22; break;
4770 case VK_F23: id = WXK_F23; break;
4771 case VK_F24: id = WXK_F24; break;
4772 case VK_NUMLOCK: id = WXK_NUMLOCK; break;
4773 case VK_SCROLL: id = WXK_SCROLL; break;
9c7df356
VZ
4774
4775 case VK_OEM_1: id = ';'; break;
4776 case VK_OEM_PLUS: id = '+'; break;
4777 case VK_OEM_COMMA: id = ','; break;
4778 case VK_OEM_MINUS: id = '-'; break;
4779 case VK_OEM_PERIOD: id = '.'; break;
4780 case VK_OEM_2: id = '/'; break;
4781 case VK_OEM_3: id = '~'; break;
4782 case VK_OEM_4: id = '['; break;
4783 case VK_OEM_5: id = '\\'; break;
4784 case VK_OEM_6: id = ']'; break;
4785 case VK_OEM_7: id = '\''; break;
4786
702c4208
VZ
4787#ifdef VK_APPS
4788 case VK_LWIN: id = WXK_WINDOWS_LEFT; break;
4789 case VK_RWIN: id = WXK_WINDOWS_RIGHT; break;
4790 case VK_APPS: id = WXK_WINDOWS_MENU; break;
4791#endif // VK_APPS defined
4792
f6bcfd97
BP
4793 default:
4794 id = 0;
42e69d6b 4795 }
f6bcfd97 4796
42e69d6b 4797 return id;
2bda0e17
KB
4798}
4799
42e69d6b 4800int wxCharCodeWXToMSW(int id, bool *isVirtual)
2bda0e17 4801{
42e69d6b
VZ
4802 *isVirtual = TRUE;
4803 int keySym = 0;
4804 switch (id)
2bda0e17 4805 {
42e69d6b
VZ
4806 case WXK_CANCEL: keySym = VK_CANCEL; break;
4807 case WXK_CLEAR: keySym = VK_CLEAR; break;
4808 case WXK_SHIFT: keySym = VK_SHIFT; break;
4809 case WXK_CONTROL: keySym = VK_CONTROL; break;
4810 case WXK_MENU : keySym = VK_MENU; break;
4811 case WXK_PAUSE: keySym = VK_PAUSE; break;
4812 case WXK_PRIOR: keySym = VK_PRIOR; break;
4813 case WXK_NEXT : keySym = VK_NEXT; break;
4814 case WXK_END: keySym = VK_END; break;
4815 case WXK_HOME : keySym = VK_HOME; break;
4816 case WXK_LEFT : keySym = VK_LEFT; break;
4817 case WXK_UP: keySym = VK_UP; break;
4818 case WXK_RIGHT: keySym = VK_RIGHT; break;
4819 case WXK_DOWN : keySym = VK_DOWN; break;
4820 case WXK_SELECT: keySym = VK_SELECT; break;
4821 case WXK_PRINT: keySym = VK_PRINT; break;
4822 case WXK_EXECUTE: keySym = VK_EXECUTE; break;
4823 case WXK_INSERT: keySym = VK_INSERT; break;
4824 case WXK_DELETE: keySym = VK_DELETE; break;
4825 case WXK_HELP : keySym = VK_HELP; break;
4826 case WXK_NUMPAD0: keySym = VK_NUMPAD0; break;
4827 case WXK_NUMPAD1: keySym = VK_NUMPAD1; break;
4828 case WXK_NUMPAD2: keySym = VK_NUMPAD2; break;
4829 case WXK_NUMPAD3: keySym = VK_NUMPAD3; break;
4830 case WXK_NUMPAD4: keySym = VK_NUMPAD4; break;
4831 case WXK_NUMPAD5: keySym = VK_NUMPAD5; break;
4832 case WXK_NUMPAD6: keySym = VK_NUMPAD6; break;
4833 case WXK_NUMPAD7: keySym = VK_NUMPAD7; break;
4834 case WXK_NUMPAD8: keySym = VK_NUMPAD8; break;
4835 case WXK_NUMPAD9: keySym = VK_NUMPAD9; break;
32a87ae7
VZ
4836 case WXK_NUMPAD_MULTIPLY: keySym = VK_MULTIPLY; break;
4837 case WXK_NUMPAD_ADD: keySym = VK_ADD; break;
4838 case WXK_NUMPAD_SUBTRACT: keySym = VK_SUBTRACT; break;
4839 case WXK_NUMPAD_DECIMAL: keySym = VK_DECIMAL; break;
4840 case WXK_NUMPAD_DIVIDE: keySym = VK_DIVIDE; break;
42e69d6b
VZ
4841 case WXK_F1: keySym = VK_F1; break;
4842 case WXK_F2: keySym = VK_F2; break;
4843 case WXK_F3: keySym = VK_F3; break;
4844 case WXK_F4: keySym = VK_F4; break;
4845 case WXK_F5: keySym = VK_F5; break;
4846 case WXK_F6: keySym = VK_F6; break;
4847 case WXK_F7: keySym = VK_F7; break;
4848 case WXK_F8: keySym = VK_F8; break;
4849 case WXK_F9: keySym = VK_F9; break;
4850 case WXK_F10: keySym = VK_F10; break;
4851 case WXK_F11: keySym = VK_F11; break;
4852 case WXK_F12: keySym = VK_F12; break;
4853 case WXK_F13: keySym = VK_F13; break;
4854 case WXK_F14: keySym = VK_F14; break;
4855 case WXK_F15: keySym = VK_F15; break;
4856 case WXK_F16: keySym = VK_F16; break;
4857 case WXK_F17: keySym = VK_F17; break;
4858 case WXK_F18: keySym = VK_F18; break;
4859 case WXK_F19: keySym = VK_F19; break;
4860 case WXK_F20: keySym = VK_F20; break;
4861 case WXK_F21: keySym = VK_F21; break;
4862 case WXK_F22: keySym = VK_F22; break;
4863 case WXK_F23: keySym = VK_F23; break;
4864 case WXK_F24: keySym = VK_F24; break;
4865 case WXK_NUMLOCK: keySym = VK_NUMLOCK; break;
4866 case WXK_SCROLL: keySym = VK_SCROLL; break;
4867 default:
4868 {
4869 *isVirtual = FALSE;
4870 keySym = id;
4871 break;
4872 }
2bda0e17 4873 }
42e69d6b 4874 return keySym;
2bda0e17
KB
4875}
4876
42e69d6b 4877wxWindow *wxGetActiveWindow()
2bda0e17 4878{
42e69d6b
VZ
4879 HWND hWnd = GetActiveWindow();
4880 if ( hWnd != 0 )
2d0a075d 4881 {
42e69d6b 4882 return wxFindWinFromHandle((WXHWND) hWnd);
2d0a075d 4883 }
42e69d6b 4884 return NULL;
2bda0e17
KB
4885}
4886
8614c467
VZ
4887extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
4888{
4889 HWND hwnd = (HWND)hWnd;
4890
4891 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
4892 // by code in msw/radiobox.cpp), for all the others we just search up the
4893 // window hierarchy
4894 wxWindow *win = (wxWindow *)NULL;
4895 if ( hwnd )
4896 {
4897 win = wxFindWinFromHandle((WXHWND)hwnd);
4898 if ( !win )
4899 {
a2242341 4900#if wxUSE_RADIOBOX
8614c467
VZ
4901 // native radiobuttons return DLGC_RADIOBUTTON here and for any
4902 // wxWindow class which overrides WM_GETDLGCODE processing to
4903 // do it as well, win would be already non NULL
a2242341 4904 if ( ::SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_RADIOBUTTON )
8614c467
VZ
4905 {
4906 win = (wxWindow *)::GetWindowLong(hwnd, GWL_USERDATA);
4907 }
a2242341
VZ
4908 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
4909#endif // wxUSE_RADIOBOX
4910
4911 // spin control text buddy window should be mapped to spin ctrl
4912 // itself so try it too
24ce4c18 4913#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
a2242341
VZ
4914 if ( !win )
4915 {
4916 win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
4917 }
4918#endif // wxUSE_SPINCTRL
8614c467 4919 }
8614c467
VZ
4920 }
4921
4922 while ( hwnd && !win )
4923 {
761989ff
VZ
4924 // this is a really ugly hack needed to avoid mistakenly returning the
4925 // parent frame wxWindow for the find/replace modeless dialog HWND -
4926 // this, in turn, is needed to call IsDialogMessage() from
4927 // wxApp::ProcessMessage() as for this we must return NULL from here
4928 //
4929 // FIXME: this is clearly not the best way to do it but I think we'll
4930 // need to change HWND <-> wxWindow code more heavily than I can
4931 // do it now to fix it
c67d6888 4932#ifndef __WXMICROWIN__
761989ff
VZ
4933 if ( ::GetWindow(hwnd, GW_OWNER) )
4934 {
4935 // it's a dialog box, don't go upwards
4936 break;
4937 }
c67d6888 4938#endif
761989ff 4939
8614c467 4940 hwnd = ::GetParent(hwnd);
761989ff 4941 win = wxFindWinFromHandle((WXHWND)hwnd);
8614c467
VZ
4942 }
4943
4944 return win;
4945}
4946
7f0586ef 4947#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
04ef50df 4948
42e69d6b
VZ
4949// Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
4950// in active frames and dialogs, regardless of where the focus is.
4951static HHOOK wxTheKeyboardHook = 0;
4952static FARPROC wxTheKeyboardHookProc = 0;
4953int APIENTRY _EXPORT
4954wxKeyboardHook(int nCode, WORD wParam, DWORD lParam);
2bda0e17 4955
42e69d6b 4956void wxSetKeyboardHook(bool doIt)
2bda0e17 4957{
42e69d6b 4958 if ( doIt )
2d0a075d 4959 {
42e69d6b
VZ
4960 wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
4961 wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
c7527e3f 4962
8614c467 4963 GetCurrentThreadId()
42e69d6b 4964 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
8614c467 4965 );
2d0a075d 4966 }
2d0a075d 4967 else
2d0a075d 4968 {
42e69d6b 4969 UnhookWindowsHookEx(wxTheKeyboardHook);
2d0a075d 4970 }
2bda0e17
KB
4971}
4972
42e69d6b
VZ
4973int APIENTRY _EXPORT
4974wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
2bda0e17 4975{
42e69d6b
VZ
4976 DWORD hiWord = HIWORD(lParam);
4977 if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) )
43d811ea 4978 {
32de7d24
VZ
4979 int id = wxCharCodeMSWToWX(wParam);
4980 if ( id != 0 )
43d811ea 4981 {
42e69d6b
VZ
4982 wxKeyEvent event(wxEVT_CHAR_HOOK);
4983 if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN )
4984 event.m_altDown = TRUE;
c085e333 4985
42e69d6b
VZ
4986 event.m_eventObject = NULL;
4987 event.m_keyCode = id;
3f7bc32b
VZ
4988 event.m_shiftDown = wxIsShiftDown();
4989 event.m_controlDown = wxIsCtrlDown();
42e69d6b 4990 event.SetTimestamp(s_currentMsg.time);
c085e333 4991
42e69d6b 4992 wxWindow *win = wxGetActiveWindow();
32de7d24 4993 wxEvtHandler *handler;
42e69d6b
VZ
4994 if ( win )
4995 {
32de7d24
VZ
4996 handler = win->GetEventHandler();
4997 event.SetId(win->GetId());
42e69d6b
VZ
4998 }
4999 else
5000 {
32de7d24
VZ
5001 handler = wxTheApp;
5002 event.SetId(-1);
5003 }
5004
5005 if ( handler && handler->ProcessEvent(event) )
5006 {
5007 // processed
5008 return 1;
42e69d6b 5009 }
43d811ea
JS
5010 }
5011 }
32de7d24 5012
42e69d6b 5013 return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam);
4fabb575 5014}
cd4453e5
VZ
5015
5016#endif // !__WXMICROWIN__
4fabb575 5017
b2aef89b 5018#ifdef __WXDEBUG__
f449ef69 5019const char *wxGetMessageName(int message)
47cbd6da 5020{
42e69d6b
VZ
5021 switch ( message )
5022 {
5023 case 0x0000: return "WM_NULL";
5024 case 0x0001: return "WM_CREATE";
5025 case 0x0002: return "WM_DESTROY";
5026 case 0x0003: return "WM_MOVE";
5027 case 0x0005: return "WM_SIZE";
5028 case 0x0006: return "WM_ACTIVATE";
5029 case 0x0007: return "WM_SETFOCUS";
5030 case 0x0008: return "WM_KILLFOCUS";
5031 case 0x000A: return "WM_ENABLE";
5032 case 0x000B: return "WM_SETREDRAW";
9b64e798
VZ
5033 case 0x000C: return "WM_SETTEXT";
5034 case 0x000D: return "WM_GETTEXT";
42e69d6b 5035 case 0x000E: return "WM_GETTEXTLENGTH";
9b64e798 5036 case 0x000F: return "WM_PAINT";
42e69d6b
VZ
5037 case 0x0010: return "WM_CLOSE";
5038 case 0x0011: return "WM_QUERYENDSESSION";
9b64e798 5039 case 0x0012: return "WM_QUIT";
42e69d6b
VZ
5040 case 0x0013: return "WM_QUERYOPEN";
5041 case 0x0014: return "WM_ERASEBKGND";
5042 case 0x0015: return "WM_SYSCOLORCHANGE";
5043 case 0x0016: return "WM_ENDSESSION";
5044 case 0x0017: return "WM_SYSTEMERROR";
5045 case 0x0018: return "WM_SHOWWINDOW";
5046 case 0x0019: return "WM_CTLCOLOR";
5047 case 0x001A: return "WM_WININICHANGE";
5048 case 0x001B: return "WM_DEVMODECHANGE";
5049 case 0x001C: return "WM_ACTIVATEAPP";
5050 case 0x001D: return "WM_FONTCHANGE";
5051 case 0x001E: return "WM_TIMECHANGE";
5052 case 0x001F: return "WM_CANCELMODE";
5053 case 0x0020: return "WM_SETCURSOR";
5054 case 0x0021: return "WM_MOUSEACTIVATE";
5055 case 0x0022: return "WM_CHILDACTIVATE";
5056 case 0x0023: return "WM_QUEUESYNC";
5057 case 0x0024: return "WM_GETMINMAXINFO";
5058 case 0x0026: return "WM_PAINTICON";
5059 case 0x0027: return "WM_ICONERASEBKGND";
5060 case 0x0028: return "WM_NEXTDLGCTL";
5061 case 0x002A: return "WM_SPOOLERSTATUS";
5062 case 0x002B: return "WM_DRAWITEM";
5063 case 0x002C: return "WM_MEASUREITEM";
5064 case 0x002D: return "WM_DELETEITEM";
5065 case 0x002E: return "WM_VKEYTOITEM";
5066 case 0x002F: return "WM_CHARTOITEM";
9b64e798
VZ
5067 case 0x0030: return "WM_SETFONT";
5068 case 0x0031: return "WM_GETFONT";
42e69d6b
VZ
5069 case 0x0037: return "WM_QUERYDRAGICON";
5070 case 0x0039: return "WM_COMPAREITEM";
5071 case 0x0041: return "WM_COMPACTING";
5072 case 0x0044: return "WM_COMMNOTIFY";
5073 case 0x0046: return "WM_WINDOWPOSCHANGING";
5074 case 0x0047: return "WM_WINDOWPOSCHANGED";
5075 case 0x0048: return "WM_POWER";
c085e333 5076
42e69d6b
VZ
5077 case 0x004A: return "WM_COPYDATA";
5078 case 0x004B: return "WM_CANCELJOURNAL";
5079 case 0x004E: return "WM_NOTIFY";
9b64e798 5080 case 0x0050: return "WM_INPUTLANGCHANGEREQUEST";
42e69d6b
VZ
5081 case 0x0051: return "WM_INPUTLANGCHANGE";
5082 case 0x0052: return "WM_TCARD";
5083 case 0x0053: return "WM_HELP";
5084 case 0x0054: return "WM_USERCHANGED";
9b64e798 5085 case 0x0055: return "WM_NOTIFYFORMAT";
42e69d6b
VZ
5086 case 0x007B: return "WM_CONTEXTMENU";
5087 case 0x007C: return "WM_STYLECHANGING";
5088 case 0x007D: return "WM_STYLECHANGED";
5089 case 0x007E: return "WM_DISPLAYCHANGE";
5090 case 0x007F: return "WM_GETICON";
5091 case 0x0080: return "WM_SETICON";
c085e333 5092
42e69d6b
VZ
5093 case 0x0081: return "WM_NCCREATE";
5094 case 0x0082: return "WM_NCDESTROY";
5095 case 0x0083: return "WM_NCCALCSIZE";
9b64e798
VZ
5096 case 0x0084: return "WM_NCHITTEST";
5097 case 0x0085: return "WM_NCPAINT";
42e69d6b
VZ
5098 case 0x0086: return "WM_NCACTIVATE";
5099 case 0x0087: return "WM_GETDLGCODE";
5100 case 0x00A0: return "WM_NCMOUSEMOVE";
5101 case 0x00A1: return "WM_NCLBUTTONDOWN";
5102 case 0x00A2: return "WM_NCLBUTTONUP";
5103 case 0x00A3: return "WM_NCLBUTTONDBLCLK";
5104 case 0x00A4: return "WM_NCRBUTTONDOWN";
5105 case 0x00A5: return "WM_NCRBUTTONUP";
5106 case 0x00A6: return "WM_NCRBUTTONDBLCLK";
5107 case 0x00A7: return "WM_NCMBUTTONDOWN";
5108 case 0x00A8: return "WM_NCMBUTTONUP";
5109 case 0x00A9: return "WM_NCMBUTTONDBLCLK";
5110 case 0x0100: return "WM_KEYDOWN";
5111 case 0x0101: return "WM_KEYUP";
5112 case 0x0102: return "WM_CHAR";
5113 case 0x0103: return "WM_DEADCHAR";
5114 case 0x0104: return "WM_SYSKEYDOWN";
5115 case 0x0105: return "WM_SYSKEYUP";
5116 case 0x0106: return "WM_SYSCHAR";
5117 case 0x0107: return "WM_SYSDEADCHAR";
9b64e798 5118 case 0x0108: return "WM_KEYLAST";
c085e333 5119
42e69d6b
VZ
5120 case 0x010D: return "WM_IME_STARTCOMPOSITION";
5121 case 0x010E: return "WM_IME_ENDCOMPOSITION";
5122 case 0x010F: return "WM_IME_COMPOSITION";
c085e333 5123
42e69d6b
VZ
5124 case 0x0110: return "WM_INITDIALOG";
5125 case 0x0111: return "WM_COMMAND";
5126 case 0x0112: return "WM_SYSCOMMAND";
5127 case 0x0113: return "WM_TIMER";
5128 case 0x0114: return "WM_HSCROLL";
5129 case 0x0115: return "WM_VSCROLL";
5130 case 0x0116: return "WM_INITMENU";
5131 case 0x0117: return "WM_INITMENUPOPUP";
9b64e798 5132 case 0x011F: return "WM_MENUSELECT";
42e69d6b
VZ
5133 case 0x0120: return "WM_MENUCHAR";
5134 case 0x0121: return "WM_ENTERIDLE";
5135 case 0x0200: return "WM_MOUSEMOVE";
5136 case 0x0201: return "WM_LBUTTONDOWN";
5137 case 0x0202: return "WM_LBUTTONUP";
5138 case 0x0203: return "WM_LBUTTONDBLCLK";
5139 case 0x0204: return "WM_RBUTTONDOWN";
5140 case 0x0205: return "WM_RBUTTONUP";
5141 case 0x0206: return "WM_RBUTTONDBLCLK";
5142 case 0x0207: return "WM_MBUTTONDOWN";
5143 case 0x0208: return "WM_MBUTTONUP";
5144 case 0x0209: return "WM_MBUTTONDBLCLK";
d2c52078 5145 case 0x020A: return "WM_MOUSEWHEEL";
42e69d6b
VZ
5146 case 0x0210: return "WM_PARENTNOTIFY";
5147 case 0x0211: return "WM_ENTERMENULOOP";
5148 case 0x0212: return "WM_EXITMENULOOP";
c085e333 5149
42e69d6b
VZ
5150 case 0x0213: return "WM_NEXTMENU";
5151 case 0x0214: return "WM_SIZING";
5152 case 0x0215: return "WM_CAPTURECHANGED";
5153 case 0x0216: return "WM_MOVING";
9b64e798 5154 case 0x0218: return "WM_POWERBROADCAST";
42e69d6b 5155 case 0x0219: return "WM_DEVICECHANGE";
c085e333 5156
42e69d6b
VZ
5157 case 0x0220: return "WM_MDICREATE";
5158 case 0x0221: return "WM_MDIDESTROY";
5159 case 0x0222: return "WM_MDIACTIVATE";
5160 case 0x0223: return "WM_MDIRESTORE";
9b64e798 5161 case 0x0224: return "WM_MDINEXT";
42e69d6b
VZ
5162 case 0x0225: return "WM_MDIMAXIMIZE";
5163 case 0x0226: return "WM_MDITILE";
5164 case 0x0227: return "WM_MDICASCADE";
5165 case 0x0228: return "WM_MDIICONARRANGE";
5166 case 0x0229: return "WM_MDIGETACTIVE";
5167 case 0x0230: return "WM_MDISETMENU";
5168 case 0x0233: return "WM_DROPFILES";
c085e333 5169
9b64e798 5170 case 0x0281: return "WM_IME_SETCONTEXT";
42e69d6b
VZ
5171 case 0x0282: return "WM_IME_NOTIFY";
5172 case 0x0283: return "WM_IME_CONTROL";
5173 case 0x0284: return "WM_IME_COMPOSITIONFULL";
9b64e798 5174 case 0x0285: return "WM_IME_SELECT";
42e69d6b
VZ
5175 case 0x0286: return "WM_IME_CHAR";
5176 case 0x0290: return "WM_IME_KEYDOWN";
5177 case 0x0291: return "WM_IME_KEYUP";
c085e333 5178
9b64e798 5179 case 0x0300: return "WM_CUT";
42e69d6b
VZ
5180 case 0x0301: return "WM_COPY";
5181 case 0x0302: return "WM_PASTE";
5182 case 0x0303: return "WM_CLEAR";
5183 case 0x0304: return "WM_UNDO";
9b64e798 5184 case 0x0305: return "WM_RENDERFORMAT";
42e69d6b
VZ
5185 case 0x0306: return "WM_RENDERALLFORMATS";
5186 case 0x0307: return "WM_DESTROYCLIPBOARD";
5187 case 0x0308: return "WM_DRAWCLIPBOARD";
5188 case 0x0309: return "WM_PAINTCLIPBOARD";
5189 case 0x030A: return "WM_VSCROLLCLIPBOARD";
5190 case 0x030B: return "WM_SIZECLIPBOARD";
5191 case 0x030C: return "WM_ASKCBFORMATNAME";
5192 case 0x030D: return "WM_CHANGECBCHAIN";
5193 case 0x030E: return "WM_HSCROLLCLIPBOARD";
5194 case 0x030F: return "WM_QUERYNEWPALETTE";
5195 case 0x0310: return "WM_PALETTEISCHANGING";
5196 case 0x0311: return "WM_PALETTECHANGED";
5048c832
JS
5197#if wxUSE_HOTKEY
5198 case 0x0312: return "WM_HOTKEY";
5199#endif
c085e333 5200
2d0a075d
JS
5201 // common controls messages - although they're not strictly speaking
5202 // standard, it's nice to decode them nevertheless
a02eb1d2 5203
2d0a075d 5204 // listview
42e69d6b
VZ
5205 case 0x1000 + 0: return "LVM_GETBKCOLOR";
5206 case 0x1000 + 1: return "LVM_SETBKCOLOR";
9b64e798
VZ
5207 case 0x1000 + 2: return "LVM_GETIMAGELIST";
5208 case 0x1000 + 3: return "LVM_SETIMAGELIST";
5209 case 0x1000 + 4: return "LVM_GETITEMCOUNT";
42e69d6b
VZ
5210 case 0x1000 + 5: return "LVM_GETITEMA";
5211 case 0x1000 + 75: return "LVM_GETITEMW";
5212 case 0x1000 + 6: return "LVM_SETITEMA";
5213 case 0x1000 + 76: return "LVM_SETITEMW";
5214 case 0x1000 + 7: return "LVM_INSERTITEMA";
5215 case 0x1000 + 77: return "LVM_INSERTITEMW";
5216 case 0x1000 + 8: return "LVM_DELETEITEM";
5217 case 0x1000 + 9: return "LVM_DELETEALLITEMS";
5218 case 0x1000 + 10: return "LVM_GETCALLBACKMASK";
5219 case 0x1000 + 11: return "LVM_SETCALLBACKMASK";
5220 case 0x1000 + 12: return "LVM_GETNEXTITEM";
5221 case 0x1000 + 13: return "LVM_FINDITEMA";
5222 case 0x1000 + 83: return "LVM_FINDITEMW";
9b64e798 5223 case 0x1000 + 14: return "LVM_GETITEMRECT";
42e69d6b
VZ
5224 case 0x1000 + 15: return "LVM_SETITEMPOSITION";
5225 case 0x1000 + 16: return "LVM_GETITEMPOSITION";
5226 case 0x1000 + 17: return "LVM_GETSTRINGWIDTHA";
5227 case 0x1000 + 87: return "LVM_GETSTRINGWIDTHW";
9b64e798 5228 case 0x1000 + 18: return "LVM_HITTEST";
42e69d6b
VZ
5229 case 0x1000 + 19: return "LVM_ENSUREVISIBLE";
5230 case 0x1000 + 20: return "LVM_SCROLL";
5231 case 0x1000 + 21: return "LVM_REDRAWITEMS";
5232 case 0x1000 + 22: return "LVM_ARRANGE";
5233 case 0x1000 + 23: return "LVM_EDITLABELA";
5234 case 0x1000 + 118: return "LVM_EDITLABELW";
5235 case 0x1000 + 24: return "LVM_GETEDITCONTROL";
5236 case 0x1000 + 25: return "LVM_GETCOLUMNA";
5237 case 0x1000 + 95: return "LVM_GETCOLUMNW";
5238 case 0x1000 + 26: return "LVM_SETCOLUMNA";
5239 case 0x1000 + 96: return "LVM_SETCOLUMNW";
5240 case 0x1000 + 27: return "LVM_INSERTCOLUMNA";
5241 case 0x1000 + 97: return "LVM_INSERTCOLUMNW";
5242 case 0x1000 + 28: return "LVM_DELETECOLUMN";
5243 case 0x1000 + 29: return "LVM_GETCOLUMNWIDTH";
5244 case 0x1000 + 30: return "LVM_SETCOLUMNWIDTH";
5245 case 0x1000 + 31: return "LVM_GETHEADER";
5246 case 0x1000 + 33: return "LVM_CREATEDRAGIMAGE";
9b64e798 5247 case 0x1000 + 34: return "LVM_GETVIEWRECT";
42e69d6b
VZ
5248 case 0x1000 + 35: return "LVM_GETTEXTCOLOR";
5249 case 0x1000 + 36: return "LVM_SETTEXTCOLOR";
5250 case 0x1000 + 37: return "LVM_GETTEXTBKCOLOR";
5251 case 0x1000 + 38: return "LVM_SETTEXTBKCOLOR";
5252 case 0x1000 + 39: return "LVM_GETTOPINDEX";
5253 case 0x1000 + 40: return "LVM_GETCOUNTPERPAGE";
5254 case 0x1000 + 41: return "LVM_GETORIGIN";
5255 case 0x1000 + 42: return "LVM_UPDATE";
5256 case 0x1000 + 43: return "LVM_SETITEMSTATE";
5257 case 0x1000 + 44: return "LVM_GETITEMSTATE";
5258 case 0x1000 + 45: return "LVM_GETITEMTEXTA";
5259 case 0x1000 + 115: return "LVM_GETITEMTEXTW";
5260 case 0x1000 + 46: return "LVM_SETITEMTEXTA";
5261 case 0x1000 + 116: return "LVM_SETITEMTEXTW";
9b64e798 5262 case 0x1000 + 47: return "LVM_SETITEMCOUNT";
42e69d6b
VZ
5263 case 0x1000 + 48: return "LVM_SORTITEMS";
5264 case 0x1000 + 49: return "LVM_SETITEMPOSITION32";
9b64e798 5265 case 0x1000 + 50: return "LVM_GETSELECTEDCOUNT";
42e69d6b
VZ
5266 case 0x1000 + 51: return "LVM_GETITEMSPACING";
5267 case 0x1000 + 52: return "LVM_GETISEARCHSTRINGA";
5268 case 0x1000 + 117: return "LVM_GETISEARCHSTRINGW";
5269 case 0x1000 + 53: return "LVM_SETICONSPACING";
5270 case 0x1000 + 54: return "LVM_SETEXTENDEDLISTVIEWSTYLE";
5271 case 0x1000 + 55: return "LVM_GETEXTENDEDLISTVIEWSTYLE";
9b64e798
VZ
5272 case 0x1000 + 56: return "LVM_GETSUBITEMRECT";
5273 case 0x1000 + 57: return "LVM_SUBITEMHITTEST";
42e69d6b
VZ
5274 case 0x1000 + 58: return "LVM_SETCOLUMNORDERARRAY";
5275 case 0x1000 + 59: return "LVM_GETCOLUMNORDERARRAY";
5276 case 0x1000 + 60: return "LVM_SETHOTITEM";
5277 case 0x1000 + 61: return "LVM_GETHOTITEM";
5278 case 0x1000 + 62: return "LVM_SETHOTCURSOR";
5279 case 0x1000 + 63: return "LVM_GETHOTCURSOR";
9b64e798 5280 case 0x1000 + 64: return "LVM_APPROXIMATEVIEWRECT";
42e69d6b 5281 case 0x1000 + 65: return "LVM_SETWORKAREA";
c085e333 5282
2d0a075d 5283 // tree view
42e69d6b
VZ
5284 case 0x1100 + 0: return "TVM_INSERTITEMA";
5285 case 0x1100 + 50: return "TVM_INSERTITEMW";
5286 case 0x1100 + 1: return "TVM_DELETEITEM";
5287 case 0x1100 + 2: return "TVM_EXPAND";
9b64e798
VZ
5288 case 0x1100 + 4: return "TVM_GETITEMRECT";
5289 case 0x1100 + 5: return "TVM_GETCOUNT";
5290 case 0x1100 + 6: return "TVM_GETINDENT";
5291 case 0x1100 + 7: return "TVM_SETINDENT";
5292 case 0x1100 + 8: return "TVM_GETIMAGELIST";
5293 case 0x1100 + 9: return "TVM_SETIMAGELIST";
42e69d6b
VZ
5294 case 0x1100 + 10: return "TVM_GETNEXTITEM";
5295 case 0x1100 + 11: return "TVM_SELECTITEM";
5296 case 0x1100 + 12: return "TVM_GETITEMA";
5297 case 0x1100 + 62: return "TVM_GETITEMW";
5298 case 0x1100 + 13: return "TVM_SETITEMA";
5299 case 0x1100 + 63: return "TVM_SETITEMW";
5300 case 0x1100 + 14: return "TVM_EDITLABELA";
5301 case 0x1100 + 65: return "TVM_EDITLABELW";
5302 case 0x1100 + 15: return "TVM_GETEDITCONTROL";
9b64e798
VZ
5303 case 0x1100 + 16: return "TVM_GETVISIBLECOUNT";
5304 case 0x1100 + 17: return "TVM_HITTEST";
42e69d6b
VZ
5305 case 0x1100 + 18: return "TVM_CREATEDRAGIMAGE";
5306 case 0x1100 + 19: return "TVM_SORTCHILDREN";
5307 case 0x1100 + 20: return "TVM_ENSUREVISIBLE";
5308 case 0x1100 + 21: return "TVM_SORTCHILDRENCB";
5309 case 0x1100 + 22: return "TVM_ENDEDITLABELNOW";
5310 case 0x1100 + 23: return "TVM_GETISEARCHSTRINGA";
5311 case 0x1100 + 64: return "TVM_GETISEARCHSTRINGW";
5312 case 0x1100 + 24: return "TVM_SETTOOLTIPS";
5313 case 0x1100 + 25: return "TVM_GETTOOLTIPS";
c085e333 5314
2d0a075d 5315 // header
9b64e798 5316 case 0x1200 + 0: return "HDM_GETITEMCOUNT";
42e69d6b
VZ
5317 case 0x1200 + 1: return "HDM_INSERTITEMA";
5318 case 0x1200 + 10: return "HDM_INSERTITEMW";
5319 case 0x1200 + 2: return "HDM_DELETEITEM";
5320 case 0x1200 + 3: return "HDM_GETITEMA";
5321 case 0x1200 + 11: return "HDM_GETITEMW";
5322 case 0x1200 + 4: return "HDM_SETITEMA";
5323 case 0x1200 + 12: return "HDM_SETITEMW";
9b64e798
VZ
5324 case 0x1200 + 5: return "HDM_LAYOUT";
5325 case 0x1200 + 6: return "HDM_HITTEST";
5326 case 0x1200 + 7: return "HDM_GETITEMRECT";
5327 case 0x1200 + 8: return "HDM_SETIMAGELIST";
5328 case 0x1200 + 9: return "HDM_GETIMAGELIST";
42e69d6b
VZ
5329 case 0x1200 + 15: return "HDM_ORDERTOINDEX";
5330 case 0x1200 + 16: return "HDM_CREATEDRAGIMAGE";
5331 case 0x1200 + 17: return "HDM_GETORDERARRAY";
5332 case 0x1200 + 18: return "HDM_SETORDERARRAY";
5333 case 0x1200 + 19: return "HDM_SETHOTDIVIDER";
c085e333 5334
2d0a075d 5335 // tab control
9b64e798
VZ
5336 case 0x1300 + 2: return "TCM_GETIMAGELIST";
5337 case 0x1300 + 3: return "TCM_SETIMAGELIST";
5338 case 0x1300 + 4: return "TCM_GETITEMCOUNT";
42e69d6b
VZ
5339 case 0x1300 + 5: return "TCM_GETITEMA";
5340 case 0x1300 + 60: return "TCM_GETITEMW";
5341 case 0x1300 + 6: return "TCM_SETITEMA";
5342 case 0x1300 + 61: return "TCM_SETITEMW";
5343 case 0x1300 + 7: return "TCM_INSERTITEMA";
5344 case 0x1300 + 62: return "TCM_INSERTITEMW";
5345 case 0x1300 + 8: return "TCM_DELETEITEM";
5346 case 0x1300 + 9: return "TCM_DELETEALLITEMS";
9b64e798 5347 case 0x1300 + 10: return "TCM_GETITEMRECT";
42e69d6b
VZ
5348 case 0x1300 + 11: return "TCM_GETCURSEL";
5349 case 0x1300 + 12: return "TCM_SETCURSEL";
9b64e798 5350 case 0x1300 + 13: return "TCM_HITTEST";
42e69d6b 5351 case 0x1300 + 14: return "TCM_SETITEMEXTRA";
9b64e798 5352 case 0x1300 + 40: return "TCM_ADJUSTRECT";
42e69d6b
VZ
5353 case 0x1300 + 41: return "TCM_SETITEMSIZE";
5354 case 0x1300 + 42: return "TCM_REMOVEIMAGE";
5355 case 0x1300 + 43: return "TCM_SETPADDING";
9b64e798 5356 case 0x1300 + 44: return "TCM_GETROWCOUNT";
42e69d6b
VZ
5357 case 0x1300 + 45: return "TCM_GETTOOLTIPS";
5358 case 0x1300 + 46: return "TCM_SETTOOLTIPS";
5359 case 0x1300 + 47: return "TCM_GETCURFOCUS";
5360 case 0x1300 + 48: return "TCM_SETCURFOCUS";
5361 case 0x1300 + 49: return "TCM_SETMINTABWIDTH";
5362 case 0x1300 + 50: return "TCM_DESELECTALL";
c085e333 5363
2d0a075d 5364 // toolbar
42e69d6b
VZ
5365 case WM_USER+1: return "TB_ENABLEBUTTON";
5366 case WM_USER+2: return "TB_CHECKBUTTON";
5367 case WM_USER+3: return "TB_PRESSBUTTON";
5368 case WM_USER+4: return "TB_HIDEBUTTON";
5369 case WM_USER+5: return "TB_INDETERMINATE";
5370 case WM_USER+9: return "TB_ISBUTTONENABLED";
5371 case WM_USER+10: return "TB_ISBUTTONCHECKED";
5372 case WM_USER+11: return "TB_ISBUTTONPRESSED";
5373 case WM_USER+12: return "TB_ISBUTTONHIDDEN";
5374 case WM_USER+13: return "TB_ISBUTTONINDETERMINATE";
5375 case WM_USER+17: return "TB_SETSTATE";
5376 case WM_USER+18: return "TB_GETSTATE";
5377 case WM_USER+19: return "TB_ADDBITMAP";
5378 case WM_USER+20: return "TB_ADDBUTTONS";
5379 case WM_USER+21: return "TB_INSERTBUTTON";
5380 case WM_USER+22: return "TB_DELETEBUTTON";
5381 case WM_USER+23: return "TB_GETBUTTON";
9b64e798 5382 case WM_USER+24: return "TB_BUTTONCOUNT";
42e69d6b
VZ
5383 case WM_USER+25: return "TB_COMMANDTOINDEX";
5384 case WM_USER+26: return "TB_SAVERESTOREA";
5385 case WM_USER+76: return "TB_SAVERESTOREW";
5386 case WM_USER+27: return "TB_CUSTOMIZE";
5387 case WM_USER+28: return "TB_ADDSTRINGA";
5388 case WM_USER+77: return "TB_ADDSTRINGW";
9b64e798 5389 case WM_USER+29: return "TB_GETITEMRECT";
42e69d6b
VZ
5390 case WM_USER+30: return "TB_BUTTONSTRUCTSIZE";
5391 case WM_USER+31: return "TB_SETBUTTONSIZE";
5392 case WM_USER+32: return "TB_SETBITMAPSIZE";
5393 case WM_USER+33: return "TB_AUTOSIZE";
5394 case WM_USER+35: return "TB_GETTOOLTIPS";
5395 case WM_USER+36: return "TB_SETTOOLTIPS";
9b64e798 5396 case WM_USER+37: return "TB_SETPARENT";
42e69d6b
VZ
5397 case WM_USER+39: return "TB_SETROWS";
5398 case WM_USER+40: return "TB_GETROWS";
5399 case WM_USER+42: return "TB_SETCMDID";
5400 case WM_USER+43: return "TB_CHANGEBITMAP";
5401 case WM_USER+44: return "TB_GETBITMAP";
5402 case WM_USER+45: return "TB_GETBUTTONTEXTA";
5403 case WM_USER+75: return "TB_GETBUTTONTEXTW";
5404 case WM_USER+46: return "TB_REPLACEBITMAP";
9b64e798
VZ
5405 case WM_USER+47: return "TB_SETINDENT";
5406 case WM_USER+48: return "TB_SETIMAGELIST";
5407 case WM_USER+49: return "TB_GETIMAGELIST";
42e69d6b 5408 case WM_USER+50: return "TB_LOADIMAGES";
9b64e798
VZ
5409 case WM_USER+51: return "TB_GETRECT";
5410 case WM_USER+52: return "TB_SETHOTIMAGELIST";
5411 case WM_USER+53: return "TB_GETHOTIMAGELIST";
5412 case WM_USER+54: return "TB_SETDISABLEDIMAGELIST";
5413 case WM_USER+55: return "TB_GETDISABLEDIMAGELIST";
42e69d6b
VZ
5414 case WM_USER+56: return "TB_SETSTYLE";
5415 case WM_USER+57: return "TB_GETSTYLE";
5416 case WM_USER+58: return "TB_GETBUTTONSIZE";
5417 case WM_USER+59: return "TB_SETBUTTONWIDTH";
5418 case WM_USER+60: return "TB_SETMAXTEXTROWS";
5419 case WM_USER+61: return "TB_GETTEXTROWS";
5420 case WM_USER+41: return "TB_GETBITMAPFLAGS";
c085e333 5421
42e69d6b
VZ
5422 default:
5423 static char s_szBuf[128];
5424 sprintf(s_szBuf, "<unknown message = %d>", message);
5425 return s_szBuf;
5426 }
47cbd6da 5427}
ea57084d 5428#endif //__WXDEBUG__
4aff28fc 5429
1e6feb95
VZ
5430static void TranslateKbdEventToMouse(wxWindowMSW *win,
5431 int *x, int *y, WPARAM *flags)
4aff28fc
VZ
5432{
5433 // construct the key mask
5434 WPARAM& fwKeys = *flags;
5435
5436 fwKeys = MK_RBUTTON;
3f7bc32b 5437 if ( wxIsCtrlDown() )
4aff28fc 5438 fwKeys |= MK_CONTROL;
3f7bc32b 5439 if ( wxIsShiftDown() )
4aff28fc
VZ
5440 fwKeys |= MK_SHIFT;
5441
5442 // simulate right mouse button click
5443 DWORD dwPos = ::GetMessagePos();
5444 *x = GET_X_LPARAM(dwPos);
5445 *y = GET_Y_LPARAM(dwPos);
5446
5447 win->ScreenToClient(x, y);
5448}
f6bcfd97 5449
1e6feb95 5450static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
f6bcfd97
BP
5451{
5452 // prepare the DC
5453 TEXTMETRIC tm;
5454 HWND hwnd = GetHwndOf(win);
5455 HDC hdc = ::GetDC(hwnd);
5456
5457#if !wxDIALOG_UNIT_COMPATIBILITY
5458 // and select the current font into it
5459 HFONT hfont = GetHfontOf(win->GetFont());
5460 if ( hfont )
5461 {
5462 hfont = (HFONT)::SelectObject(hdc, hfont);
5463 }
5464#endif
5465
5466 // finally retrieve the text metrics from it
5467 GetTextMetrics(hdc, &tm);
5468
5469#if !wxDIALOG_UNIT_COMPATIBILITY
5470 // and clean up
5471 if ( hfont )
5472 {
5473 (void)::SelectObject(hdc, hfont);
5474 }
5475#endif
5476
5477 ::ReleaseDC(hwnd, hdc);
5478
5479 return tm;
5480}
3723b7b1
JS
5481
5482// Find the wxWindow at the current mouse position, returning the mouse
5483// position.
2b5f62a0 5484wxWindow* wxFindWindowAtPointer(wxPoint& pt)
3723b7b1 5485{
2b5f62a0
VZ
5486 pt = wxGetMousePosition();
5487 return wxFindWindowAtPoint(pt);
57591e0e
JS
5488}
5489
5490wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
5491{
5492 POINT pt2;
5493 pt2.x = pt.x;
5494 pt2.y = pt.y;
5495 HWND hWndHit = ::WindowFromPoint(pt2);
3723b7b1
JS
5496
5497 wxWindow* win = wxFindWinFromHandle((WXHWND) hWndHit) ;
5498 HWND hWnd = hWndHit;
5499
5500 // Try to find a window with a wxWindow associated with it
5501 while (!win && (hWnd != 0))
5502 {
5503 hWnd = ::GetParent(hWnd);
5504 win = wxFindWinFromHandle((WXHWND) hWnd) ;
5505 }
5506 return win;
5507}
5508
5509// Get the current mouse position.
5510wxPoint wxGetMousePosition()
5511{
1772ead0
JS
5512 POINT pt;
5513 GetCursorPos( & pt );
5cd16c0c 5514
1772ead0 5515 return wxPoint(pt.x, pt.y);
3723b7b1
JS
5516}
5517
5048c832 5518#if wxUSE_HOTKEY
540b6b09
VZ
5519
5520bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
5048c832
JS
5521{
5522 UINT win_modifiers=0;
540b6b09
VZ
5523 if ( modifiers & wxMOD_ALT )
5524 win_modifiers |= MOD_ALT;
5525 if ( modifiers & wxMOD_SHIFT )
5526 win_modifiers |= MOD_SHIFT;
5527 if ( modifiers & wxMOD_CONTROL )
5528 win_modifiers |= MOD_CONTROL;
5529 if ( modifiers & wxMOD_WIN )
5530 win_modifiers |= MOD_WIN;
5531
5532 if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) )
5533 {
5534 wxLogLastError(_T("RegisterHotKey"));
5048c832 5535
540b6b09
VZ
5536 return FALSE;
5537 }
5538
5539 return TRUE;
5048c832
JS
5540}
5541
5542bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
5543{
540b6b09
VZ
5544 if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) )
5545 {
5546 wxLogLastError(_T("UnregisterHotKey"));
5547
5548 return FALSE;
5549 }
5550
5551 return TRUE;
5048c832
JS
5552}
5553
5554bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
5555{
540b6b09
VZ
5556 int hotkeyId = wParam;
5557 int virtualKey = HIWORD(lParam);
5558 int win_modifiers = LOWORD(lParam);
5559
5048c832
JS
5560 wxKeyEvent event(CreateKeyEvent(wxEVT_HOTKEY, virtualKey, wParam, lParam));
5561 event.SetId(hotkeyId);
5562 event.m_shiftDown = (win_modifiers & MOD_SHIFT) != 0;
5563 event.m_controlDown = (win_modifiers & MOD_CONTROL) != 0;
5564 event.m_altDown = (win_modifiers & MOD_ALT) != 0;
5565 event.m_metaDown = (win_modifiers & MOD_WIN) != 0;
540b6b09
VZ
5566
5567 return GetEventHandler()->ProcessEvent(event);
5048c832 5568}
540b6b09
VZ
5569
5570#endif // wxUSE_HOTKEY
5048c832 5571