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