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