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