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