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