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