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