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