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