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