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