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