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