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