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