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