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