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