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