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