]> git.saurik.com Git - wxWidgets.git/blame - src/msw/window.cpp
don't dereferencep ossibly NULL pointers in DoScreenToClient/ClientToScreen()
[wxWidgets.git] / src / msw / window.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
faa49bfd
WS
2// Name: src/msw/window.cpp
3// Purpose: wxWindowMSW
2bda0e17 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 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
a23fd0e1
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
09914df7 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
e4db172a
WS
27#include "wx/window.h"
28
2bda0e17 29#ifndef WX_PRECOMP
9ed0d735 30 #include "wx/msw/wrapwin.h"
57bd4c60
WS
31 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
32 #include "wx/msw/missing.h"
0c589ad0 33 #include "wx/accel.h"
3a19e16d
VZ
34 #include "wx/menu.h"
35 #include "wx/dc.h"
36 #include "wx/dcclient.h"
8e92ccef 37 #include "wx/dcmemory.h"
3a19e16d
VZ
38 #include "wx/utils.h"
39 #include "wx/app.h"
3a19e16d
VZ
40 #include "wx/layout.h"
41 #include "wx/dialog.h"
42 #include "wx/frame.h"
43 #include "wx/listbox.h"
44 #include "wx/button.h"
3a19e16d 45 #include "wx/msgdlg.h"
1f3943e0 46 #include "wx/settings.h"
8d753488 47 #include "wx/statbox.h"
1e2aa2f8 48 #include "wx/sizer.h"
88a7a4e1 49 #include "wx/intl.h"
e4db172a 50 #include "wx/log.h"
fec9cc08 51 #include "wx/textctrl.h"
25466131 52 #include "wx/menuitem.h"
02761f6c 53 #include "wx/module.h"
2bda0e17
KB
54#endif
55
61fef19b 56#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
09914df7 57 #include "wx/ownerdrw.h"
2bda0e17
KB
58#endif
59
a3dc1da9 60#include "wx/evtloop.h"
355debca 61#include "wx/power.h"
c6430ed0 62#include "wx/sysopt.h"
d79df32c 63
9e2896e5
VZ
64#if wxUSE_DRAG_AND_DROP
65 #include "wx/dnd.h"
2bda0e17
KB
66#endif
67
ed5317e5
JS
68#if wxUSE_ACCESSIBILITY
69 #include "wx/access.h"
bef8d481 70 #include <ole2.h>
ed5317e5
JS
71 #include <oleacc.h>
72 #ifndef WM_GETOBJECT
73 #define WM_GETOBJECT 0x003D
74 #endif
75 #ifndef OBJID_CLIENT
76 #define OBJID_CLIENT 0xFFFFFFFC
77 #endif
78#endif
79
0c589ad0
BM
80#include "wx/msw/private.h"
81
750b78ba 82#if wxUSE_TOOLTIPS
42e69d6b 83 #include "wx/tooltip.h"
750b78ba
JS
84#endif
85
789295bf
VZ
86#if wxUSE_CARET
87 #include "wx/caret.h"
88#endif // wxUSE_CARET
89
6fe19057
VZ
90#if wxUSE_SPINCTRL
91 #include "wx/spinctrl.h"
92#endif // wxUSE_SPINCTRL
93
d9317fd4 94#include "wx/notebook.h"
5c6c3176 95#include "wx/listctrl.h"
aafb9978 96#include "wx/dynlib.h"
2a47d3c1 97
2bda0e17
KB
98#include <string.h>
99
d61c1a6f 100#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
3a19e16d
VZ
101 #include <shellapi.h>
102 #include <mmsystem.h>
2bda0e17
KB
103#endif
104
105#ifdef __WIN32__
3a19e16d 106 #include <windowsx.h>
2bda0e17
KB
107#endif
108
dcfd4ac4 109#if !defined __WXWINCE__ && !defined NEED_PBT_H
dbc74bcc
WS
110 #include <pbt.h>
111#endif
2bda0e17 112
7f0586ef 113#if defined(__WXWINCE__)
4e5c6c33 114 #include "wx/msw/wince/missing.h"
7d4f65e3
JS
115#ifdef __POCKETPC__
116 #include <windows.h>
117 #include <shellapi.h>
118 #include <ole2.h>
119 #include <aygshell.h>
120#endif
7f0586ef
JS
121#endif
122
aafb9978 123#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS
4e5c6c33
VZ
124 #define HAVE_TRACKMOUSEEVENT
125#endif // everything needed for TrackMouseEvent()
126
7d86a2d4
VZ
127// if this is set to 1, we use deferred window sizing to reduce flicker when
128// resizing complicated window hierarchies, but this can in theory result in
129// different behaviour than the old code so we keep the possibility to use it
130// by setting this to 0 (in the future this should be removed completely)
f2197644
JS
131#ifdef __WXWINCE__
132#define USE_DEFERRED_SIZING 0
133#else
8e44f3ca 134#define USE_DEFERRED_SIZING 1
f2197644 135#endif
8e44f3ca 136
c358ea41
VZ
137// set this to 1 to filter out duplicate mouse events, e.g. mouse move events
138// when mouse position didnd't change
139#ifdef __WXWINCE__
140 #define wxUSE_MOUSEEVENT_HACK 0
141#else
142 #define wxUSE_MOUSEEVENT_HACK 1
143#endif
144
a23fd0e1 145// ---------------------------------------------------------------------------
42e69d6b 146// global variables
a23fd0e1 147// ---------------------------------------------------------------------------
47cbd6da 148
1e6feb95 149#if wxUSE_MENUS_NATIVE
2bda0e17 150wxMenu *wxCurrentPopupMenu = NULL;
1e6feb95
VZ
151#endif // wxUSE_MENUS_NATIVE
152
46fa338b
RR
153#ifdef __WXWINCE__
154extern wxChar *wxCanvasClassName;
155#else
2ffa221c 156extern const wxChar *wxCanvasClassName;
46fa338b 157#endif
42e69d6b 158
90c1530a
VZ
159// true if we had already created the std colour map, used by
160// wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT)
08158721 161static bool gs_hasStdCmap = false;
90c1530a 162
c358ea41
VZ
163// last mouse event information we need to filter out the duplicates
164#if wxUSE_MOUSEEVENT_HACK
2b053ae9 165static struct MouseEventInfoDummy
c358ea41
VZ
166{
167 // mouse position (in screen coordinates)
168 wxPoint pos;
169
170 // last mouse event type
171 wxEventType type;
172} gs_lastMouseEvent;
173#endif // wxUSE_MOUSEEVENT_HACK
174
42e69d6b
VZ
175// ---------------------------------------------------------------------------
176// private functions
177// ---------------------------------------------------------------------------
178
179// the window proc for all our windows
3135f4a7 180LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
42e69d6b 181 WPARAM wParam, LPARAM lParam);
577baeef 182
42e69d6b
VZ
183
184#ifdef __WXDEBUG__
4a712ba3 185 const wxChar *wxGetMessageName(int message);
42e69d6b 186#endif //__WXDEBUG__
2bda0e17 187
1e6feb95 188void wxRemoveHandleAssociation(wxWindowMSW *win);
cc972ac6 189extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win);
2bda0e17
KB
190wxWindow *wxFindWinFromHandle(WXHWND hWnd);
191
f6bcfd97 192// get the text metrics for the current font
1e6feb95
VZ
193static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
194
42b1fb63 195#ifdef __WXWINCE__
dfafa702 196// find the window for the mouse event at the specified position
42b1fb63
VZ
197static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y);
198#endif // __WXWINCE__
dfafa702 199
c48926e1 200// wrapper around BringWindowToTop() API
44d5b352 201static inline void wxBringWindowToTop(HWND hwnd)
c48926e1
VZ
202{
203#ifdef __WXMICROWIN__
204 // It seems that MicroWindows brings the _parent_ of the window to the top,
205 // which can be the wrong one.
206
207 // activate (set focus to) specified window
208 ::SetFocus(hwnd);
313901f3 209#endif
c48926e1
VZ
210
211 // raise top level parent to top of z order
313901f3 212 if (!::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE))
c48926e1 213 {
313901f3 214 wxLogLastError(_T("SetWindowPos"));
c48926e1 215 }
c48926e1 216}
f6bcfd97 217
e0c5c96f
VZ
218#ifndef __WXWINCE__
219
ee471817
VZ
220// ensure that all our parent windows have WS_EX_CONTROLPARENT style
221static void EnsureParentHasControlParentStyle(wxWindow *parent)
222{
223 /*
224 If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
225 parent as well as otherwise several Win32 functions using
226 GetNextDlgTabItem() to iterate over all controls such as
227 IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
228 all of them iterate over all the controls starting from the currently
229 focused one and stop iterating when they get back to the focus but
230 unless all parents have WS_EX_CONTROLPARENT bit set, they would never
231 get back to the initial (focused) window: as we do have this style,
232 GetNextDlgTabItem() will leave this window and continue in its parent,
233 but if the parent doesn't have it, it wouldn't recurse inside it later
90e572f1 234 on and so wouldn't have a chance of getting back to this window either.
ee471817 235 */
ee471817
VZ
236 while ( parent && !parent->IsTopLevel() )
237 {
238 LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
239 if ( !(exStyle & WS_EX_CONTROLPARENT) )
240 {
241 // force the parent to have this style
242 ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
243 exStyle | WS_EX_CONTROLPARENT);
244 }
245
246 parent = parent->GetParent();
247 }
ee471817
VZ
248}
249
e0c5c96f
VZ
250#endif // !__WXWINCE__
251
f2325516
JS
252#ifdef __WXWINCE__
253// On Windows CE, GetCursorPos can return an error, so use this function
254// instead
255bool GetCursorPosWinCE(POINT* pt)
256{
7d30268c
JS
257 if (!GetCursorPos(pt))
258 {
259 DWORD pos = GetMessagePos();
260 pt->x = LOWORD(pos);
261 pt->y = HIWORD(pos);
262 }
f2325516
JS
263 return true;
264}
265#endif
266
a23fd0e1
VZ
267// ---------------------------------------------------------------------------
268// event tables
269// ---------------------------------------------------------------------------
270
1e6feb95
VZ
271// in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
272// method
273#ifdef __WXUNIVERSAL__
274 IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW, wxWindowBase)
275#else // __WXMSW__
51596bcb 276#if wxUSE_EXTENDED_RTTI
6a89f9ee 277
f3291a82
SC
278// windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls
279// must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as
280// windows with negative ids never can be recreated anyway
281
282bool wxWindowStreamingCallback( const wxObject *object, wxWriter * , wxPersister * , wxxVariantArray & )
283{
284 const wxWindow * win = dynamic_cast<const wxWindow*>(object) ;
285 if ( win && win->GetId() < 0 )
286 return false ;
287 return true ;
288}
289
290IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow, wxWindowBase,"wx/window.h", wxWindowStreamingCallback)
51596bcb 291
6a89f9ee
SC
292// make wxWindowList known before the property is used
293
321239b6 294wxCOLLECTION_TYPE_INFO( wxWindow* , wxWindowList ) ;
6a89f9ee
SC
295
296template<> void wxCollectionToVariantArray( wxWindowList const &theList, wxxVariantArray &value)
297{
0c6b0084 298 wxListCollectionToVariantArray<wxWindowList::compatibility_iterator>( theList , value ) ;
6a89f9ee
SC
299}
300
bc9fb572
JS
301WX_DEFINE_FLAGS( wxWindowStyle )
302
321239b6 303wxBEGIN_FLAGS( wxWindowStyle )
bc9fb572
JS
304 // new style border flags, we put them first to
305 // use them for streaming out
5c6c3176 306
321239b6
SC
307 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
308 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
309 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
310 wxFLAGS_MEMBER(wxBORDER_RAISED)
311 wxFLAGS_MEMBER(wxBORDER_STATIC)
312 wxFLAGS_MEMBER(wxBORDER_NONE)
35bbb0c6 313
bc9fb572 314 // old style border flags
321239b6
SC
315 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
316 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
317 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
318 wxFLAGS_MEMBER(wxRAISED_BORDER)
319 wxFLAGS_MEMBER(wxSTATIC_BORDER)
cb0afb26 320 wxFLAGS_MEMBER(wxBORDER)
bc9fb572
JS
321
322 // standard window styles
321239b6
SC
323 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
324 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
325 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
326 wxFLAGS_MEMBER(wxWANTS_CHARS)
cb0afb26 327 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
321239b6
SC
328 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
329 wxFLAGS_MEMBER(wxVSCROLL)
330 wxFLAGS_MEMBER(wxHSCROLL)
331
332wxEND_FLAGS( wxWindowStyle )
333
334wxBEGIN_PROPERTIES_TABLE(wxWindow)
3a3c8603
DS
335 wxEVENT_PROPERTY( Close , wxEVT_CLOSE_WINDOW , wxCloseEvent)
336 wxEVENT_PROPERTY( Create , wxEVT_CREATE , wxWindowCreateEvent )
337 wxEVENT_PROPERTY( Destroy , wxEVT_DESTROY , wxWindowDestroyEvent )
51741307
SC
338 // Always constructor Properties first
339
af498247 340 wxREADONLY_PROPERTY( Parent,wxWindow*, GetParent, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
fb7e28db 341 wxPROPERTY( Id,wxWindowID, SetId, GetId, -1 /*wxID_ANY*/ , 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
abb74e0f
WS
342 wxPROPERTY( Position,wxPoint, SetPosition , GetPosition, wxDefaultPosition , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos
343 wxPROPERTY( Size,wxSize, SetSize, GetSize, wxDefaultSize , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size
af498247 344 wxPROPERTY( WindowStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
51741307
SC
345
346 // Then all relations of the object graph
347
321239b6 348 wxREADONLY_PROPERTY_COLLECTION( Children , wxWindowList , wxWindowBase* , GetWindowChildren , wxPROP_OBJECT_GRAPH /*flags*/ , wxT("Helpstring") , wxT("group"))
51741307
SC
349
350 // and finally all other properties
351
3a3c8603
DS
352 wxPROPERTY( ExtraStyle , long , SetExtraStyle , GetExtraStyle , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle
353 wxPROPERTY( BackgroundColour , wxColour , SetBackgroundColour , GetBackgroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg
354 wxPROPERTY( ForegroundColour , wxColour , SetForegroundColour , GetForegroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg
355 wxPROPERTY( Enabled , bool , Enable , IsEnabled , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
356 wxPROPERTY( Shown , bool , Show , IsShown , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
51741307
SC
357#if 0
358 // possible property candidates (not in xrc) or not valid in all subclasses
8b5d5223 359 wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxEmptyString )
3a3c8603 360 wxPROPERTY( Font , wxFont , SetFont , GetWindowFont , )
8b5d5223 361 wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxEmptyString )
3a3c8603
DS
362 // MaxHeight, Width , MinHeight , Width
363 // TODO switch label to control and title to toplevels
6a89f9ee 364
3a3c8603
DS
365 wxPROPERTY( ThemeEnabled , bool , SetThemeEnabled , GetThemeEnabled , )
366 //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , )
367 // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , )
368 wxPROPERTY( AutoLayout , bool , SetAutoLayout , GetAutoLayout , )
6a89f9ee
SC
369
370
371
51741307 372#endif
321239b6 373wxEND_PROPERTIES_TABLE()
51596bcb 374
321239b6
SC
375wxBEGIN_HANDLERS_TABLE(wxWindow)
376wxEND_HANDLERS_TABLE()
51596bcb 377
321239b6 378wxCONSTRUCTOR_DUMMY(wxWindow)
6a89f9ee 379
51596bcb 380#else
1e6feb95 381 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
51596bcb 382#endif
1e6feb95
VZ
383#endif // __WXUNIVERSAL__/__WXMSW__
384
385BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase)
1e6feb95 386 EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged)
8681b094 387 EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground)
79099b80 388#ifdef __WXWINCE__
1e6feb95 389 EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog)
79099b80 390#endif
2bda0e17
KB
391END_EVENT_TABLE()
392
a23fd0e1
VZ
393// ===========================================================================
394// implementation
395// ===========================================================================
396
42e69d6b
VZ
397// ---------------------------------------------------------------------------
398// wxWindow utility functions
399// ---------------------------------------------------------------------------
400
2bda0e17 401// Find an item given the MS Windows id
1e6feb95 402wxWindow *wxWindowMSW::FindItem(long id) const
2bda0e17 403{
1e6feb95 404#if wxUSE_CONTROLS
f7637829 405 wxControl *item = wxDynamicCastThis(wxControl);
f048e32f
VZ
406 if ( item )
407 {
90e572f1 408 // is it us or one of our "internal" children?
1e6feb95
VZ
409 if ( item->GetId() == id
410#ifndef __WXUNIVERSAL__
411 || (item->GetSubcontrols().Index(id) != wxNOT_FOUND)
412#endif // __WXUNIVERSAL__
413 )
f048e32f
VZ
414 {
415 return item;
416 }
417 }
1e6feb95 418#endif // wxUSE_CONTROLS
f048e32f 419
222ed1d6 420 wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
2d0a075d
JS
421 while (current)
422 {
42e69d6b 423 wxWindow *childWin = current->GetData();
2bda0e17 424
42e69d6b 425 wxWindow *wnd = childWin->FindItem(id);
cc2b7472 426 if ( wnd )
42e69d6b 427 return wnd;
2bda0e17 428
42e69d6b 429 current = current->GetNext();
2bda0e17 430 }
42e69d6b 431
2d0a075d 432 return NULL;
2bda0e17
KB
433}
434
435// Find an item given the MS Windows handle
1e6feb95 436wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const
2bda0e17 437{
222ed1d6 438 wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
2d0a075d 439 while (current)
2bda0e17 440 {
42e69d6b
VZ
441 wxWindow *parent = current->GetData();
442
2d0a075d 443 // Do a recursive search.
42e69d6b 444 wxWindow *wnd = parent->FindItemByHWND(hWnd);
cc2b7472 445 if ( wnd )
42e69d6b 446 return wnd;
2d0a075d 447
1e6feb95
VZ
448 if ( !controlOnly
449#if wxUSE_CONTROLS
450 || parent->IsKindOf(CLASSINFO(wxControl))
451#endif // wxUSE_CONTROLS
452 )
2d0a075d 453 {
42e69d6b
VZ
454 wxWindow *item = current->GetData();
455 if ( item->GetHWND() == hWnd )
2d0a075d
JS
456 return item;
457 else
458 {
459 if ( item->ContainsHWND(hWnd) )
460 return item;
461 }
462 }
42e69d6b
VZ
463
464 current = current->GetNext();
2bda0e17 465 }
2d0a075d 466 return NULL;
2bda0e17
KB
467}
468
469// Default command handler
1e6feb95 470bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id))
2bda0e17 471{
08158721 472 return false;
2bda0e17
KB
473}
474
fd3f686c
VZ
475// ----------------------------------------------------------------------------
476// constructors and such
477// ----------------------------------------------------------------------------
478
1e6feb95 479void wxWindowMSW::Init()
2bda0e17 480{
cc2b7472 481 // MSW specific
08158721 482 m_isBeingDeleted = false;
5a403e3f 483 m_oldWndProc = NULL;
08158721
DS
484 m_mouseInWindow = false;
485 m_lastKeydownProcessed = false;
2bda0e17 486
a1037371 487 m_frozenness = 0;
d7cbabe0 488
319fefa9 489 m_hWnd = 0;
220f77b0 490 m_hDWP = 0;
319fefa9 491
2d0a075d
JS
492 m_xThumbSize = 0;
493 m_yThumbSize = 0;
2bda0e17 494
67644c1d
RD
495 m_pendingPosition = wxDefaultPosition;
496 m_pendingSize = wxDefaultSize;
7d4f65e3
JS
497
498#ifdef __POCKETPC__
499 m_contextMenuEnabled = false;
500#endif
fd3f686c
VZ
501}
502
2bda0e17 503// Destructor
1e6feb95 504wxWindowMSW::~wxWindowMSW()
2bda0e17 505{
08158721 506 m_isBeingDeleted = true;
2bda0e17 507
2e9f62da 508#ifndef __WXUNIVERSAL__
4a41c655 509 // VS: make sure there's no wxFrame with last focus set to us:
2e9f62da 510 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
4a41c655 511 {
085ad686 512 wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
4a41c655
VS
513 if ( frame )
514 {
c5053639 515 if ( frame->GetLastFocus() == this )
2e9f62da 516 {
085ad686 517 frame->SetLastFocus(NULL);
2e9f62da 518 }
4552892f
VZ
519
520 // apparently sometimes we can end up with our grand parent
521 // pointing to us as well: this is surely a bug in focus handling
522 // code but it's not clear where it happens so for now just try to
523 // fix it here by not breaking out of the loop
524 //break;
4a41c655
VS
525 }
526 }
2e9f62da 527#endif // __WXUNIVERSAL__
2bda0e17 528
cc0c7cd8 529 // VS: destroy children first and _then_ detach *this from its parent.
90e572f1 530 // If we did it the other way around, children wouldn't be able
cc0c7cd8
VS
531 // find their parent frame (see above).
532 DestroyChildren();
533
cc2b7472 534 if ( m_hWnd )
42e69d6b 535 {
98440bc3
VZ
536 // VZ: test temp removed to understand what really happens here
537 //if (::IsWindow(GetHwnd()))
df61c009
JS
538 {
539 if ( !::DestroyWindow(GetHwnd()) )
f6bcfd97 540 wxLogLastError(wxT("DestroyWindow"));
df61c009 541 }
2bda0e17 542
c50f1fb9
VZ
543 // remove hWnd <-> wxWindow association
544 wxRemoveHandleAssociation(this);
545 }
d7cbabe0 546
2bda0e17
KB
547}
548
fd3f686c 549// real construction (Init() must have been called before!)
1e6feb95
VZ
550bool wxWindowMSW::Create(wxWindow *parent,
551 wxWindowID id,
552 const wxPoint& pos,
553 const wxSize& size,
554 long style,
555 const wxString& name)
2d0a075d 556{
08158721 557 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
2bda0e17 558
8d99be5f 559 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
08158721 560 return false;
42e69d6b 561
fd3f686c 562 parent->AddChild(this);
2bda0e17 563
b2d5a7ee 564 WXDWORD exstyle;
e49d97e6 565 DWORD msflags = MSWGetCreateWindowFlags(&exstyle);
1e6feb95
VZ
566
567#ifdef __WXUNIVERSAL__
d1fe917b 568 // no borders, we draw them ourselves
76c79ff4
VZ
569 exstyle &= ~(WS_EX_DLGMODALFRAME |
570 WS_EX_STATICEDGE |
571 WS_EX_CLIENTEDGE |
572 WS_EX_WINDOWEDGE);
d1fe917b 573 msflags &= ~WS_BORDER;
b2d5a7ee 574#endif // wxUniversal
1e6feb95 575
ff792344 576 if ( IsShown() )
e49d97e6
VZ
577 {
578 msflags |= WS_VISIBLE;
579 }
1e6feb95 580
45956e37
VZ
581 if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
582 return false;
583
584 InheritAttributes();
585
586 return true;
2bda0e17
KB
587}
588
42e69d6b
VZ
589// ---------------------------------------------------------------------------
590// basic operations
591// ---------------------------------------------------------------------------
592
1e6feb95 593void wxWindowMSW::SetFocus()
2bda0e17 594{
a23fd0e1 595 HWND hWnd = GetHwnd();
1e6feb95
VZ
596 wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
597
7f0586ef 598#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95 599 ::SetLastError(0);
8cb172b4 600#endif
d0a3d109 601
1e6feb95
VZ
602 if ( !::SetFocus(hWnd) )
603 {
5262eb0a 604#if defined(__WXDEBUG__) && !defined(__WXMICROWIN__)
1e6feb95
VZ
605 // was there really an error?
606 DWORD dwRes = ::GetLastError();
607 if ( dwRes )
608 {
5262eb0a
VZ
609 HWND hwndFocus = ::GetFocus();
610 if ( hwndFocus != hWnd )
611 {
612 wxLogApiError(_T("SetFocus"), dwRes);
613 }
1e6feb95 614 }
5262eb0a 615#endif // Debug
1e6feb95 616 }
2bda0e17
KB
617}
618
ddf9d04f
VZ
619void wxWindowMSW::SetFocusFromKbd()
620{
ddf9d04f
VZ
621 // when the focus is given to the control with DLGC_HASSETSEL style from
622 // keyboard its contents should be entirely selected: this is what
623 // ::IsDialogMessage() does and so we should do it as well to provide the
624 // same LNF as the native programs
625 if ( ::SendMessage(GetHwnd(), WM_GETDLGCODE, 0, 0) & DLGC_HASSETSEL )
626 {
627 ::SendMessage(GetHwnd(), EM_SETSEL, 0, -1);
628 }
1b1ca07a
VZ
629
630 // do this after (maybe) setting the selection as like this when
631 // wxEVT_SET_FOCUS handler is called, the selection would have been already
632 // set correctly -- this may be important
633 wxWindowBase::SetFocusFromKbd();
ddf9d04f
VZ
634}
635
42e69d6b 636// Get the window with the focus
0fe02759 637wxWindow *wxWindowBase::DoFindFocus()
42e69d6b
VZ
638{
639 HWND hWnd = ::GetFocus();
640 if ( hWnd )
641 {
a2242341 642 return wxGetWindowFromHWND((WXHWND)hWnd);
42e69d6b
VZ
643 }
644
645 return NULL;
646}
647
47a8a4d5 648void wxWindowMSW::DoEnable( bool enable )
2bda0e17 649{
a23fd0e1 650 HWND hWnd = GetHwnd();
cc2b7472 651 if ( hWnd )
2d0a075d 652 ::EnableWindow(hWnd, (BOOL)enable);
2bda0e17
KB
653}
654
1e6feb95 655bool wxWindowMSW::Show(bool show)
42e69d6b
VZ
656{
657 if ( !wxWindowBase::Show(show) )
08158721 658 return false;
42e69d6b
VZ
659
660 HWND hWnd = GetHwnd();
42e69d6b 661
a068160f
VZ
662 // we could be called before the underlying window is created (this is
663 // actually useful to prevent it from being initially shown), e.g.
664 //
665 // wxFoo *foo = new wxFoo;
666 // foo->Hide();
667 // foo->Create(parent, ...);
668 //
669 // should work without errors
670 if ( hWnd )
42e69d6b 671 {
a068160f 672 ::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
42e69d6b
VZ
673 }
674
08158721 675 return true;
42e69d6b
VZ
676}
677
678// Raise the window to the top of the Z order
1e6feb95 679void wxWindowMSW::Raise()
42e69d6b 680{
c48926e1 681 wxBringWindowToTop(GetHwnd());
42e69d6b
VZ
682}
683
684// Lower the window to the bottom of the Z order
1e6feb95 685void wxWindowMSW::Lower()
42e69d6b
VZ
686{
687 ::SetWindowPos(GetHwnd(), HWND_BOTTOM, 0, 0, 0, 0,
688 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
689}
690
94633ad9 691void wxWindowMSW::DoCaptureMouse()
2bda0e17 692{
a23fd0e1 693 HWND hWnd = GetHwnd();
1e6feb95 694 if ( hWnd )
2d0a075d 695 {
1e6feb95 696 ::SetCapture(hWnd);
2d0a075d 697 }
2bda0e17
KB
698}
699
94633ad9 700void wxWindowMSW::DoReleaseMouse()
2bda0e17 701{
1e6feb95 702 if ( !::ReleaseCapture() )
2d0a075d 703 {
1e6feb95 704 wxLogLastError(_T("ReleaseCapture"));
2d0a075d 705 }
2bda0e17
KB
706}
707
1e6feb95
VZ
708/* static */ wxWindow *wxWindowBase::GetCapture()
709{
710 HWND hwnd = ::GetCapture();
711 return hwnd ? wxFindWinFromHandle((WXHWND)hwnd) : (wxWindow *)NULL;
712}
713
714bool wxWindowMSW::SetFont(const wxFont& font)
2bda0e17 715{
42e69d6b
VZ
716 if ( !wxWindowBase::SetFont(font) )
717 {
718 // nothing to do
08158721 719 return false;
2d0a075d 720 }
195896c7 721
42e69d6b
VZ
722 HWND hWnd = GetHwnd();
723 if ( hWnd != 0 )
724 {
725 WXHANDLE hFont = m_font.GetResourceHandle();
2bda0e17 726
223d09f6 727 wxASSERT_MSG( hFont, wxT("should have valid font") );
3a19e16d 728
c50f1fb9 729 ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
42e69d6b 730 }
2bda0e17 731
08158721 732 return true;
42e69d6b 733}
1e6feb95 734bool wxWindowMSW::SetCursor(const wxCursor& cursor)
2bda0e17 735{
42e69d6b
VZ
736 if ( !wxWindowBase::SetCursor(cursor) )
737 {
738 // no change
08158721 739 return false;
42e69d6b
VZ
740 }
741
8e75dca8
VZ
742 // don't "overwrite" busy cursor
743 if ( m_cursor.Ok() && !wxIsBusy() )
8a9c2246 744 {
a8b2285e
VZ
745 // normally we should change the cursor only if it's over this window
746 // but we should do it always if we capture the mouse currently
747 bool set = HasCapture();
748 if ( !set )
749 {
750 HWND hWnd = GetHwnd();
751
752 POINT point;
753#ifdef __WXWINCE__
754 ::GetCursorPosWinCE(&point);
755#else
756 ::GetCursorPos(&point);
757#endif
758
759 RECT rect = wxGetWindowRect(hWnd);
760
761 set = ::PtInRect(&rect, point) != 0;
762 }
763
764 if ( set )
765 {
766 ::SetCursor(GetHcursorOf(m_cursor));
767 }
768 //else: will be set later when the mouse enters this window
8a9c2246 769 }
3a19e16d 770
08158721 771 return true;
3a19e16d
VZ
772}
773
d7e0024b 774void wxWindowMSW::WarpPointer(int x, int y)
2bda0e17 775{
1e6feb95 776 ClientToScreen(&x, &y);
42e69d6b 777
1e6feb95
VZ
778 if ( !::SetCursorPos(x, y) )
779 {
780 wxLogLastError(_T("SetCursorPos"));
781 }
2bda0e17
KB
782}
783
1ca78aa1 784void wxWindowMSW::MSWUpdateUIState(int action, int state)
d7e0024b 785{
1ca78aa1 786 // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good
d7e0024b
VZ
787 // to use it on older systems -- and could possibly do some harm
788 static int s_needToUpdate = -1;
789 if ( s_needToUpdate == -1 )
790 {
791 int verMaj, verMin;
406d283a 792 s_needToUpdate = wxGetOsVersion(&verMaj, &verMin) == wxOS_WINDOWS_NT &&
d7e0024b
VZ
793 verMaj >= 5;
794 }
795
796 if ( s_needToUpdate )
797 {
1ca78aa1
JS
798 // we send WM_CHANGEUISTATE so if nothing needs changing then the system
799 // won't send WM_UPDATEUISTATE
800 ::SendMessage(GetHwnd(), WM_CHANGEUISTATE, MAKEWPARAM(action, state), 0);
d7e0024b
VZ
801 }
802}
803
42e69d6b
VZ
804// ---------------------------------------------------------------------------
805// scrolling stuff
806// ---------------------------------------------------------------------------
2d0a075d 807
9cd6d737
VZ
808inline int GetScrollPosition(HWND hWnd, int wOrient)
809{
810#ifdef __WXMICROWIN__
811 return ::GetScrollPosWX(hWnd, wOrient);
812#else
f676b387 813 WinStruct<SCROLLINFO> scrollInfo;
4676948b 814 scrollInfo.cbSize = sizeof(SCROLLINFO);
7f0586ef 815 scrollInfo.fMask = SIF_POS;
e795e8b5 816 ::GetScrollInfo(hWnd, wOrient, &scrollInfo );
a71d815b 817
7f0586ef 818 return scrollInfo.nPos;
e795e8b5 819
9cd6d737
VZ
820#endif
821}
822
1e6feb95 823int wxWindowMSW::GetScrollPos(int orient) const
2bda0e17 824{
42e69d6b 825 HWND hWnd = GetHwnd();
9cd6d737
VZ
826 wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") );
827
0cf5de11 828 return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT);
42e69d6b 829}
2bda0e17 830
42e69d6b
VZ
831// This now returns the whole range, not just the number
832// of positions that we can scroll.
1e6feb95 833int wxWindowMSW::GetScrollRange(int orient) const
42e69d6b 834{
7f0586ef 835 int maxPos;
a23fd0e1 836 HWND hWnd = GetHwnd();
0cf5de11 837 if ( !hWnd )
42e69d6b 838 return 0;
7f0586ef 839#if 0
0cf5de11
VZ
840 ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
841 &minPos, &maxPos);
7f0586ef 842#endif
f676b387 843 WinStruct<SCROLLINFO> scrollInfo;
7f0586ef
JS
844 scrollInfo.fMask = SIF_RANGE;
845 if ( !::GetScrollInfo(hWnd,
f676b387
RD
846 orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
847 &scrollInfo) )
7f0586ef 848 {
f676b387
RD
849 // Most of the time this is not really an error, since the return
850 // value can also be zero when there is no scrollbar yet.
851 // wxLogLastError(_T("GetScrollInfo"));
7f0586ef
JS
852 }
853 maxPos = scrollInfo.nMax;
0cf5de11
VZ
854
855 // undo "range - 1" done in SetScrollbar()
856 return maxPos + 1;
cc2b7472 857}
2bda0e17 858
1e6feb95 859int wxWindowMSW::GetScrollThumb(int orient) const
2bda0e17 860{
0cf5de11 861 return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize;
2bda0e17
KB
862}
863
1e6feb95 864void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
2bda0e17 865{
5f3286d1
VZ
866 HWND hWnd = GetHwnd();
867 wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") );
72fd19a1 868
0cf5de11 869 WinStruct<SCROLLINFO> info;
42e69d6b
VZ
870 info.nPage = 0;
871 info.nMin = 0;
872 info.nPos = pos;
873 info.fMask = SIF_POS;
a647d42a
VZ
874 if ( HasFlag(wxALWAYS_SHOW_SB) )
875 {
876 // disable scrollbar instead of removing it then
877 info.fMask |= SIF_DISABLENOSCROLL;
878 }
2d0a075d 879
0cf5de11
VZ
880 ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
881 &info, refresh);
2bda0e17
KB
882}
883
42e69d6b 884// New function that will replace some of the above.
0cf5de11
VZ
885void wxWindowMSW::SetScrollbar(int orient,
886 int pos,
887 int pageSize,
888 int range,
889 bool refresh)
890{
891 WinStruct<SCROLLINFO> info;
892 info.nPage = pageSize;
893 info.nMin = 0; // range is nMax - nMin + 1
894 info.nMax = range - 1; // as both nMax and nMax are inclusive
42e69d6b
VZ
895 info.nPos = pos;
896 info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
a647d42a
VZ
897 if ( HasFlag(wxALWAYS_SHOW_SB) )
898 {
899 // disable scrollbar instead of removing it then
900 info.fMask |= SIF_DISABLENOSCROLL;
901 }
2bda0e17 902
42e69d6b
VZ
903 HWND hWnd = GetHwnd();
904 if ( hWnd )
81d66cf3 905 {
55a667b6
JS
906 // We have to set the variables here to make them valid in events
907 // triggered by ::SetScrollInfo()
908 *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize;
521bf4ff 909
0cf5de11
VZ
910 ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT,
911 &info, refresh);
81d66cf3
JS
912 }
913}
914
1e6feb95 915void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect)
2bda0e17 916{
574c939e
KB
917 RECT rect;
918 RECT *pr;
1e6feb95 919 if ( prect )
2d0a075d 920 {
1e6feb95
VZ
921 rect.left = prect->x;
922 rect.top = prect->y;
923 rect.right = prect->x + prect->width;
924 rect.bottom = prect->y + prect->height;
f797e53d
VZ
925 pr = &rect;
926 }
927 else
928 {
929 pr = NULL;
304b8bc1 930
2d0a075d 931 }
2bda0e17 932
7f0586ef
JS
933#ifdef __WXWINCE__
934 // FIXME: is this the exact equivalent of the line below?
304b8bc1 935 ::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
7f0586ef 936#else
f797e53d 937 ::ScrollWindow(GetHwnd(), dx, dy, pr, pr);
7f0586ef 938#endif
2bda0e17
KB
939}
940
9cd6d737 941static bool ScrollVertically(HWND hwnd, int kind, int count)
b9b3393e 942{
9cd6d737
VZ
943 int posStart = GetScrollPosition(hwnd, SB_VERT);
944
945 int pos = posStart;
c0cdd6cc
VZ
946 for ( int n = 0; n < count; n++ )
947 {
948 ::SendMessage(hwnd, WM_VSCROLL, kind, 0);
9cd6d737
VZ
949
950 int posNew = GetScrollPosition(hwnd, SB_VERT);
951 if ( posNew == pos )
952 {
953 // don't bother to continue, we're already at top/bottom
954 break;
955 }
956
957 pos = posNew;
c0cdd6cc 958 }
9cd6d737
VZ
959
960 return pos != posStart;
b9b3393e
VZ
961}
962
9cd6d737 963bool wxWindowMSW::ScrollLines(int lines)
b9b3393e
VZ
964{
965 bool down = lines > 0;
966
9cd6d737
VZ
967 return ScrollVertically(GetHwnd(),
968 down ? SB_LINEDOWN : SB_LINEUP,
969 down ? lines : -lines);
b9b3393e
VZ
970}
971
9cd6d737 972bool wxWindowMSW::ScrollPages(int pages)
b9b3393e
VZ
973{
974 bool down = pages > 0;
975
9cd6d737
VZ
976 return ScrollVertically(GetHwnd(),
977 down ? SB_PAGEDOWN : SB_PAGEUP,
978 down ? pages : -pages);
b9b3393e
VZ
979}
980
978af864
VZ
981// ----------------------------------------------------------------------------
982// RTL support
983// ----------------------------------------------------------------------------
984
985void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
986{
08a58133
WS
987#ifdef __WXWINCE__
988 wxUnusedVar(dir);
989#else
978af864
VZ
990 const HWND hwnd = GetHwnd();
991 wxCHECK_RET( hwnd, _T("layout direction must be set after window creation") );
992
993 LONG styleOld = ::GetWindowLong(hwnd, GWL_EXSTYLE);
994
995 LONG styleNew = styleOld;
996 switch ( dir )
997 {
998 case wxLayout_LeftToRight:
999 styleNew &= ~WS_EX_LAYOUTRTL;
1000 break;
1001
1002 case wxLayout_RightToLeft:
1003 styleNew |= WS_EX_LAYOUTRTL;
1004 break;
1005
1006 default:
1007 wxFAIL_MSG(_T("unsupported layout direction"));
1008 break;
1009 }
1010
1011 if ( styleNew != styleOld )
1012 {
1013 ::SetWindowLong(hwnd, GWL_EXSTYLE, styleNew);
1014 }
08a58133 1015#endif
978af864
VZ
1016}
1017
1018wxLayoutDirection wxWindowMSW::GetLayoutDirection() const
1019{
08a58133
WS
1020#ifdef __WXWINCE__
1021 return wxLayout_Default;
1022#else
978af864
VZ
1023 const HWND hwnd = GetHwnd();
1024 wxCHECK_MSG( hwnd, wxLayout_Default, _T("invalid window") );
1025
1026 return ::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL
1027 ? wxLayout_RightToLeft
1028 : wxLayout_LeftToRight;
08a58133 1029#endif
978af864
VZ
1030}
1031
1032wxCoord
1033wxWindowMSW::AdjustForLayoutDirection(wxCoord x,
1034 wxCoord WXUNUSED(width),
1035 wxCoord WXUNUSED(widthTotal)) const
1036{
1037 // Win32 mirrors the coordinates of RTL windows automatically, so don't
1038 // redo it ourselves
1039 return x;
1040}
1041
42e69d6b
VZ
1042// ---------------------------------------------------------------------------
1043// subclassing
1044// ---------------------------------------------------------------------------
1045
1e6feb95 1046void wxWindowMSW::SubclassWin(WXHWND hWnd)
2bda0e17 1047{
223d09f6 1048 wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") );
2bda0e17 1049
c50f1fb9 1050 HWND hwnd = (HWND)hWnd;
223d09f6 1051 wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") );
c50f1fb9
VZ
1052
1053 wxAssociateWinWithHandle(hwnd, this);
2bda0e17 1054
975b6bcf 1055 m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd);
b2d5a7ee 1056
b225f659
VZ
1057 // we don't need to subclass the window of our own class (in the Windows
1058 // sense of the word)
3a3c8603 1059 if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
b225f659 1060 {
975b6bcf 1061 wxSetWindowProc(hwnd, wxWndProc);
b225f659
VZ
1062 }
1063 else
1064 {
90e572f1 1065 // don't bother restoring it either: this also makes it easy to
08158721 1066 // implement IsOfStandardClass() method which returns true for the
77ffb593 1067 // standard controls and false for the wxWidgets own windows as it can
5a403e3f 1068 // simply check m_oldWndProc
b225f659
VZ
1069 m_oldWndProc = NULL;
1070 }
e7c652bc
VZ
1071
1072 // we're officially created now, send the event
1073 wxWindowCreateEvent event((wxWindow *)this);
1074 (void)GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
1075}
1076
1e6feb95 1077void wxWindowMSW::UnsubclassWin()
2bda0e17 1078{
42e69d6b 1079 wxRemoveHandleAssociation(this);
2bda0e17 1080
42e69d6b 1081 // Restore old Window proc
c50f1fb9
VZ
1082 HWND hwnd = GetHwnd();
1083 if ( hwnd )
42e69d6b 1084 {
ed4780ea 1085 SetHWND(0);
c50f1fb9 1086
223d09f6 1087 wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
c50f1fb9 1088
b225f659 1089 if ( m_oldWndProc )
42e69d6b 1090 {
eb5e4d9a 1091 if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) )
b225f659 1092 {
975b6bcf 1093 wxSetWindowProc(hwnd, (WNDPROC)m_oldWndProc);
b225f659
VZ
1094 }
1095
1096 m_oldWndProc = NULL;
42e69d6b 1097 }
42e69d6b 1098 }
2bda0e17
KB
1099}
1100
a4d1972d 1101void wxWindowMSW::AssociateHandle(WXWidget handle)
ed4780ea
VZ
1102{
1103 if ( m_hWnd )
1104 {
1105 if ( !::DestroyWindow(GetHwnd()) )
1106 wxLogLastError(wxT("DestroyWindow"));
1107 }
a4d1972d 1108
ed4780ea
VZ
1109 WXHWND wxhwnd = (WXHWND)handle;
1110
1111 SetHWND(wxhwnd);
1112 SubclassWin(wxhwnd);
1113}
1114
1115void wxWindowMSW::DissociateHandle()
a4d1972d 1116{
ed4780ea 1117 // this also calls SetHWND(0) for us
a4d1972d 1118 UnsubclassWin();
ed4780ea
VZ
1119}
1120
1121
0c0d1521 1122bool wxCheckWindowWndProc(WXHWND hWnd,
11f104e5 1123 WXFARPROC WXUNUSED(wndProc))
eb5e4d9a 1124{
f57f984c
RD
1125// TODO: This list of window class names should be factored out so they can be
1126// managed in one place and then accessed from here and other places, such as
1127// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
521bf4ff
WS
1128
1129#ifdef __WXWINCE__
3a3c8603
DS
1130 extern wxChar *wxCanvasClassName;
1131 extern wxChar *wxCanvasClassNameNR;
f57f984c
RD
1132#else
1133 extern const wxChar *wxCanvasClassName;
1134 extern const wxChar *wxCanvasClassNameNR;
1135#endif
3a3c8603
DS
1136 extern const wxChar *wxMDIFrameClassName;
1137 extern const wxChar *wxMDIFrameClassNameNoRedraw;
1138 extern const wxChar *wxMDIChildFrameClassName;
1139 extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
1140 wxString str(wxGetWindowClass(hWnd));
1141 if (str == wxCanvasClassName ||
1142 str == wxCanvasClassNameNR ||
26c2a266
JG
1143#if wxUSE_GLCANVAS
1144 str == _T("wxGLCanvasClass") ||
1145 str == _T("wxGLCanvasClassNR") ||
1146#endif // wxUSE_GLCANVAS
3a3c8603
DS
1147 str == wxMDIFrameClassName ||
1148 str == wxMDIFrameClassNameNoRedraw ||
1149 str == wxMDIChildFrameClassName ||
1150 str == wxMDIChildFrameClassNameNoRedraw ||
1151 str == _T("wxTLWHiddenParent"))
1152 return true; // Effectively means don't subclass
f57f984c 1153 else
08158721 1154 return false;
eb5e4d9a
VS
1155}
1156
b2d5a7ee
VZ
1157// ----------------------------------------------------------------------------
1158// Style handling
1159// ----------------------------------------------------------------------------
1160
1161void wxWindowMSW::SetWindowStyleFlag(long flags)
1162{
1163 long flagsOld = GetWindowStyleFlag();
1164 if ( flags == flagsOld )
1165 return;
1166
1167 // update the internal variable
1168 wxWindowBase::SetWindowStyleFlag(flags);
1169
7bd6bf45
VZ
1170 // and the real window flags
1171 MSWUpdateStyle(flagsOld, GetExtraStyle());
1172}
1173
1174void wxWindowMSW::SetExtraStyle(long exflags)
1175{
1176 long exflagsOld = GetExtraStyle();
1177 if ( exflags == exflagsOld )
1178 return;
1179
1180 // update the internal variable
1181 wxWindowBase::SetExtraStyle(exflags);
1182
1183 // and the real window flags
1184 MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld);
1185}
1186
1187void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld)
1188{
5b2f31eb
VZ
1189 // now update the Windows style as well if needed - and if the window had
1190 // been already created
1191 if ( !GetHwnd() )
1192 return;
1193
9ce75461
VZ
1194 // we may need to call SetWindowPos() when we change some styles
1195 bool callSWP = false;
1196
7bd6bf45
VZ
1197 WXDWORD exstyle;
1198 long style = MSWGetStyle(GetWindowStyleFlag(), &exstyle);
1199
1200 // this is quite a horrible hack but we need it because MSWGetStyle()
1201 // doesn't take exflags as parameter but uses GetExtraStyle() internally
1202 // and so we have to modify the window exflags temporarily to get the
1203 // correct exstyleOld
1204 long exflagsNew = GetExtraStyle();
1205 wxWindowBase::SetExtraStyle(exflagsOld);
1206
1207 WXDWORD exstyleOld;
1208 long styleOld = MSWGetStyle(flagsOld, &exstyleOld);
1209
1210 wxWindowBase::SetExtraStyle(exflagsNew);
1211
b2d5a7ee
VZ
1212
1213 if ( style != styleOld )
1214 {
1215 // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1216 // this function so instead of simply setting the style to the new
1217 // value we clear the bits which were set in styleOld but are set in
1218 // the new one and set the ones which were not set before
1219 long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE);
1220 styleReal &= ~styleOld;
1221 styleReal |= style;
1222
1223 ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
9ce75461 1224
7bd6bf45
VZ
1225 // we need to call SetWindowPos() if any of the styles affecting the
1226 // frame appearance have changed
9ce75461
VZ
1227 callSWP = ((styleOld ^ style ) & (WS_BORDER |
1228 WS_THICKFRAME |
1229 WS_CAPTION |
1230 WS_DLGFRAME |
1231 WS_MAXIMIZEBOX |
1232 WS_MINIMIZEBOX |
1233 WS_SYSMENU) ) != 0;
b2d5a7ee
VZ
1234 }
1235
1236 // and the extended style
9ce75461
VZ
1237 long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
1238
b2d5a7ee
VZ
1239 if ( exstyle != exstyleOld )
1240 {
b2d5a7ee
VZ
1241 exstyleReal &= ~exstyleOld;
1242 exstyleReal |= exstyle;
1243
1244 ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
1245
9ce75461
VZ
1246 // ex style changes don't take effect without calling SetWindowPos
1247 callSWP = true;
1248 }
1249
1250 if ( callSWP )
1251 {
85d8df29 1252 // we must call SetWindowPos() to flush the cached extended style and
b2d5a7ee
VZ
1253 // also to make the change to wxSTAY_ON_TOP style take effect: just
1254 // setting the style simply doesn't work
1255 if ( !::SetWindowPos(GetHwnd(),
1256 exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
1257 : HWND_NOTOPMOST,
1258 0, 0, 0, 0,
9ce75461 1259 SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED) )
b2d5a7ee
VZ
1260 {
1261 wxLogLastError(_T("SetWindowPos"));
1262 }
1263 }
1264}
1265
1266WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
1267{
77ffb593 1268 // translate common wxWidgets styles to Windows ones
af495479
VZ
1269
1270 // most of windows are child ones, those which are not (such as
1271 // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle()
1272 WXDWORD style = WS_CHILD;
b2d5a7ee 1273
9b6ae450
VZ
1274 // using this flag results in very significant reduction in flicker,
1275 // especially with controls inside the static boxes (as the interior of the
90e572f1 1276 // box is not redrawn twice), but sometimes results in redraw problems, so
c7e1d004
VZ
1277 // optionally allow the old code to continue to use it provided a special
1278 // system option is turned on
1279 if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
1280 || (flags & wxCLIP_CHILDREN) )
c6430ed0 1281 style |= WS_CLIPCHILDREN;
9b6ae450
VZ
1282
1283 // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
1284 // don't support overlapping windows and it only makes sense for them and,
1285 // presumably, gives the system some extra work (to manage more clipping
1286 // regions), so avoid it alltogether
b2d5a7ee 1287
b2d5a7ee 1288
f9007c32
JS
1289 if ( flags & wxVSCROLL )
1290 style |= WS_VSCROLL;
1291
1292 if ( flags & wxHSCROLL )
1293 style |= WS_HSCROLL;
1294
65bc172c 1295 const wxBorder border = GetBorder(flags);
577baeef 1296
65bc172c
VZ
1297 // WS_BORDER is only required for wxBORDER_SIMPLE
1298 if ( border == wxBORDER_SIMPLE )
b2d5a7ee 1299 style |= WS_BORDER;
577baeef 1300
b2d5a7ee
VZ
1301 // now deal with ext style if the caller wants it
1302 if ( exstyle )
1303 {
1304 *exstyle = 0;
1305
7f0586ef 1306#ifndef __WXWINCE__
b2d5a7ee
VZ
1307 if ( flags & wxTRANSPARENT_WINDOW )
1308 *exstyle |= WS_EX_TRANSPARENT;
7f0586ef 1309#endif
b2d5a7ee 1310
fe3d9123 1311 switch ( border )
b2d5a7ee
VZ
1312 {
1313 default:
65bc172c 1314 case wxBORDER_DEFAULT:
b2d5a7ee
VZ
1315 wxFAIL_MSG( _T("unknown border style") );
1316 // fall through
1317
1318 case wxBORDER_NONE:
1319 case wxBORDER_SIMPLE:
1320 break;
1321
1322 case wxBORDER_STATIC:
1323 *exstyle |= WS_EX_STATICEDGE;
1324 break;
1325
1326 case wxBORDER_RAISED:
7699361c 1327 *exstyle |= WS_EX_DLGMODALFRAME;
b2d5a7ee
VZ
1328 break;
1329
b2d5a7ee
VZ
1330 case wxBORDER_SUNKEN:
1331 *exstyle |= WS_EX_CLIENTEDGE;
fe3d9123 1332 style &= ~WS_BORDER;
b2d5a7ee
VZ
1333 break;
1334
1335 case wxBORDER_DOUBLE:
1336 *exstyle |= WS_EX_DLGMODALFRAME;
1337 break;
1338 }
d515c32d 1339
09168de7 1340 // wxUniv doesn't use Windows dialog navigation functions at all
7f0586ef 1341#if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
5b9c12e1 1342 // to make the dialog navigation work with the nested panels we must
09168de7
VZ
1343 // use this style (top level windows such as dialogs don't need it)
1344 if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
d515c32d
VZ
1345 {
1346 *exstyle |= WS_EX_CONTROLPARENT;
1347 }
09168de7 1348#endif // __WXUNIVERSAL__
b2d5a7ee
VZ
1349 }
1350
1351 return style;
1352}
eb5e4d9a 1353
42e69d6b 1354// Setup background and foreground colours correctly
1e6feb95 1355void wxWindowMSW::SetupColours()
42e69d6b
VZ
1356{
1357 if ( GetParent() )
1358 SetBackgroundColour(GetParent()->GetBackgroundColour());
1359}
a23fd0e1 1360
1e6feb95
VZ
1361bool wxWindowMSW::IsMouseInWindow() const
1362{
1363 // get the mouse position
1364 POINT pt;
f2325516
JS
1365#ifdef __WXWINCE__
1366 ::GetCursorPosWinCE(&pt);
1367#else
1e6feb95 1368 ::GetCursorPos(&pt);
f2325516 1369#endif
1e6feb95
VZ
1370
1371 // find the window which currently has the cursor and go up the window
1372 // chain until we find this window - or exhaust it
1373 HWND hwnd = ::WindowFromPoint(pt);
1374 while ( hwnd && (hwnd != GetHwnd()) )
1375 hwnd = ::GetParent(hwnd);
1376
1377 return hwnd != NULL;
1378}
1379
e39af974 1380void wxWindowMSW::OnInternalIdle()
42e69d6b 1381{
4e5c6c33 1382#ifndef HAVE_TRACKMOUSEEVENT
42e69d6b
VZ
1383 // Check if we need to send a LEAVE event
1384 if ( m_mouseInWindow )
2d0a075d 1385 {
ee74faf9
VZ
1386 // note that we should generate the leave event whether the window has
1387 // or doesn't have mouse capture
1388 if ( !IsMouseInWindow() )
42e69d6b 1389 {
51e4e266 1390 GenerateMouseLeave();
42e69d6b
VZ
1391 }
1392 }
4e5c6c33 1393#endif // !HAVE_TRACKMOUSEEVENT
c085e333 1394
e39af974
JS
1395 if (wxUpdateUIEvent::CanUpdate(this))
1396 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
42e69d6b 1397}
568cb543 1398
42e69d6b 1399// Set this window to be the child of 'parent'.
1e6feb95 1400bool wxWindowMSW::Reparent(wxWindowBase *parent)
42e69d6b
VZ
1401{
1402 if ( !wxWindowBase::Reparent(parent) )
08158721 1403 return false;
c085e333 1404
42e69d6b
VZ
1405 HWND hWndChild = GetHwnd();
1406 HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
a23fd0e1 1407
42e69d6b 1408 ::SetParent(hWndChild, hWndParent);
a23fd0e1 1409
ee471817
VZ
1410#ifndef __WXWINCE__
1411 if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
1412 {
1413 EnsureParentHasControlParentStyle(GetParent());
1414 }
1415#endif // !__WXWINCE__
1416
08158721 1417 return true;
42e69d6b 1418}
a23fd0e1 1419
a0e449ff
VZ
1420static inline void SendSetRedraw(HWND hwnd, bool on)
1421{
c67d6888 1422#ifndef __WXMICROWIN__
a0e449ff 1423 ::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)on, 0);
c67d6888 1424#endif
a0e449ff
VZ
1425}
1426
1427void wxWindowMSW::Freeze()
1428{
a1037371
VZ
1429 if ( !m_frozenness++ )
1430 {
dc993cbf
VZ
1431 if ( IsShown() )
1432 SendSetRedraw(GetHwnd(), false);
a1037371 1433 }
a0e449ff
VZ
1434}
1435
1436void wxWindowMSW::Thaw()
1437{
a1037371 1438 wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
c0cdd6cc 1439
8d7eaf91 1440 if ( --m_frozenness == 0 )
a1037371 1441 {
dc993cbf
VZ
1442 if ( IsShown() )
1443 {
1444 SendSetRedraw(GetHwnd(), true);
a1037371 1445
dc993cbf
VZ
1446 // we need to refresh everything or otherwise the invalidated area
1447 // is not going to be repainted
1448 Refresh();
1449 }
a1037371 1450 }
a0e449ff
VZ
1451}
1452
1e6feb95 1453void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
42e69d6b
VZ
1454{
1455 HWND hWnd = GetHwnd();
1456 if ( hWnd )
1457 {
d181e053
VZ
1458 RECT mswRect;
1459 const RECT *pRect;
42e69d6b
VZ
1460 if ( rect )
1461 {
42e69d6b
VZ
1462 mswRect.left = rect->x;
1463 mswRect.top = rect->y;
1464 mswRect.right = rect->x + rect->width;
1465 mswRect.bottom = rect->y + rect->height;
a23fd0e1 1466
d181e053 1467 pRect = &mswRect;
42e69d6b
VZ
1468 }
1469 else
d181e053
VZ
1470 {
1471 pRect = NULL;
1472 }
1473
82e3664e 1474 // RedrawWindow not available on SmartPhone or eVC++ 3
41527143 1475#if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
d181e053
VZ
1476 UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
1477 if ( eraseBack )
1478 flags |= RDW_ERASE;
1479
1480 ::RedrawWindow(hWnd, pRect, NULL, flags);
480e9098 1481#else
16d652a5 1482 ::InvalidateRect(hWnd, pRect, eraseBack);
480e9098 1483#endif
42e69d6b
VZ
1484 }
1485}
a23fd0e1 1486
1e6feb95
VZ
1487void wxWindowMSW::Update()
1488{
1489 if ( !::UpdateWindow(GetHwnd()) )
1490 {
1491 wxLogLastError(_T("UpdateWindow"));
1492 }
2b5f62a0 1493
7f0586ef 1494#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95
VZ
1495 // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
1496 // handler needs to be really drawn right now
1497 (void)::GdiFlush();
1498#endif // __WIN32__
1499}
1500
42e69d6b
VZ
1501// ---------------------------------------------------------------------------
1502// drag and drop
1503// ---------------------------------------------------------------------------
a23fd0e1 1504
3febc967
VZ
1505#if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__)
1506
1507#if wxUSE_STATBOX
1508
006b8dff
JG
1509// we need to lower the sibling static boxes so controls contained within can be
1510// a drop target
3febc967 1511static void AdjustStaticBoxZOrder(wxWindow *parent)
006b8dff 1512{
deb0d191
JG
1513 // no sibling static boxes if we have no parent (ie TLW)
1514 if ( !parent )
1515 return;
1516
006b8dff
JG
1517 for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
1518 node;
1519 node = node->GetNext() )
1520 {
1521 wxStaticBox *statbox = wxDynamicCast(node->GetData(), wxStaticBox);
1522 if ( statbox )
1523 {
1524 ::SetWindowPos(GetHwndOf(statbox), HWND_BOTTOM, 0, 0, 0, 0,
1525 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1526 }
1527 }
1528}
a23fd0e1 1529
3febc967
VZ
1530#else // !wxUSE_STATBOX
1531
1532static inline void AdjustStaticBoxZOrder(wxWindow * WXUNUSED(parent))
1533{
1534}
1535
1536#endif // wxUSE_STATBOX/!wxUSE_STATBOX
1537
1538#endif // drag and drop is used
1539
4ce1efe1 1540#if wxUSE_DRAG_AND_DROP
1e6feb95 1541void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
42e69d6b
VZ
1542{
1543 if ( m_dropTarget != 0 ) {
1544 m_dropTarget->Revoke(m_hWnd);
1545 delete m_dropTarget;
1546 }
a23fd0e1 1547
42e69d6b
VZ
1548 m_dropTarget = pDropTarget;
1549 if ( m_dropTarget != 0 )
006b8dff
JG
1550 {
1551 AdjustStaticBoxZOrder(GetParent());
42e69d6b 1552 m_dropTarget->Register(m_hWnd);
006b8dff 1553 }
42e69d6b 1554}
42e69d6b 1555#endif // wxUSE_DRAG_AND_DROP
2a47d3c1 1556
90e572f1 1557// old-style file manager drag&drop support: we retain the old-style
42e69d6b 1558// DragAcceptFiles in parallel with SetDropTarget.
0c0d1521 1559void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept))
42e69d6b 1560{
0c0d1521 1561#ifndef __WXWINCE__
42e69d6b
VZ
1562 HWND hWnd = GetHwnd();
1563 if ( hWnd )
006b8dff
JG
1564 {
1565 AdjustStaticBoxZOrder(GetParent());
42e69d6b 1566 ::DragAcceptFiles(hWnd, (BOOL)accept);
006b8dff 1567 }
7f0586ef 1568#endif
42e69d6b 1569}
a23fd0e1 1570
42e69d6b
VZ
1571// ----------------------------------------------------------------------------
1572// tooltips
1573// ----------------------------------------------------------------------------
dbda9e86 1574
42e69d6b 1575#if wxUSE_TOOLTIPS
2d0a075d 1576
1e6feb95 1577void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
42e69d6b
VZ
1578{
1579 wxWindowBase::DoSetToolTip(tooltip);
839b865d 1580
42e69d6b 1581 if ( m_tooltip )
d4e5272b 1582 m_tooltip->SetWindow((wxWindow *)this);
42e69d6b 1583}
9a05fd8d 1584
42e69d6b 1585#endif // wxUSE_TOOLTIPS
9a05fd8d 1586
42e69d6b
VZ
1587// ---------------------------------------------------------------------------
1588// moving and resizing
1589// ---------------------------------------------------------------------------
839b865d 1590
f7040b5f
VZ
1591bool wxWindowMSW::IsSizeDeferred() const
1592{
1593#if USE_DEFERRED_SIZING
1594 if ( m_pendingPosition != wxDefaultPosition ||
1595 m_pendingSize != wxDefaultSize )
1596 return true;
1597#endif // USE_DEFERRED_SIZING
1598
1599 return false;
1600}
1601
42e69d6b 1602// Get total size
1e6feb95 1603void wxWindowMSW::DoGetSize(int *x, int *y) const
42e69d6b 1604{
0d6fdb3c 1605#if USE_DEFERRED_SIZING
11cfa8ef
VZ
1606 // if SetSize() had been called at wx level but not realized at Windows
1607 // level yet (i.e. EndDeferWindowPos() not called), we still should return
1608 // the new and not the old position to the other wx code
1609 if ( m_pendingSize != wxDefaultSize )
1610 {
1611 if ( x )
1612 *x = m_pendingSize.x;
1613 if ( y )
1614 *y = m_pendingSize.y;
1615 }
1616 else // use current size
0d6fdb3c 1617#endif // USE_DEFERRED_SIZING
11cfa8ef
VZ
1618 {
1619 RECT rect = wxGetWindowRect(GetHwnd());
82c9f85c 1620
11cfa8ef
VZ
1621 if ( x )
1622 *x = rect.right - rect.left;
1623 if ( y )
1624 *y = rect.bottom - rect.top;
1625 }
42e69d6b
VZ
1626}
1627
82c9f85c
VZ
1628// Get size *available for subwindows* i.e. excluding menu bar etc.
1629void wxWindowMSW::DoGetClientSize(int *x, int *y) const
42e69d6b 1630{
f2197644 1631#if USE_DEFERRED_SIZING
0d6fdb3c 1632 if ( m_pendingSize != wxDefaultSize )
0d7f75df 1633 {
0d6fdb3c 1634 // we need to calculate the client size corresponding to pending size
dc497201
JG
1635 RECT rect;
1636 rect.left = m_pendingPosition.x;
1637 rect.top = m_pendingPosition.y;
1638 rect.right = rect.left + m_pendingSize.x;
1639 rect.bottom = rect.top + m_pendingSize.y;
1640
1641 ::SendMessage(GetHwnd(), WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
1642
1643 if ( x )
1644 *x = rect.right - rect.left;
1645 if ( y )
1646 *y = rect.bottom - rect.top;
0d7f75df 1647 }
0d6fdb3c
VZ
1648 else
1649#endif // USE_DEFERRED_SIZING
1650 {
1651 RECT rect = wxGetClientRect(GetHwnd());
1652
1653 if ( x )
1654 *x = rect.right;
1655 if ( y )
1656 *y = rect.bottom;
1657 }
82c9f85c
VZ
1658}
1659
1660void wxWindowMSW::DoGetPosition(int *x, int *y) const
1661{
a7e0e432
VZ
1662 wxWindow * const parent = GetParent();
1663
1664 wxPoint pos;
11cfa8ef
VZ
1665 if ( m_pendingPosition != wxDefaultPosition )
1666 {
a7e0e432 1667 pos = m_pendingPosition;
11cfa8ef
VZ
1668 }
1669 else // use current position
1670 {
1671 RECT rect = wxGetWindowRect(GetHwnd());
42e69d6b 1672
11cfa8ef
VZ
1673 POINT point;
1674 point.x = rect.left;
1675 point.y = rect.top;
42e69d6b 1676
11cfa8ef
VZ
1677 // we do the adjustments with respect to the parent only for the "real"
1678 // children, not for the dialogs/frames
1679 if ( !IsTopLevel() )
92049cd4 1680 {
e5b5af91
VZ
1681 if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
1682 {
967acfb5 1683 // In RTL mode, we want the logical left x-coordinate,
e5b5af91
VZ
1684 // which would be the physical right x-coordinate.
1685 point.x = rect.right;
1686 }
1687
11cfa8ef
VZ
1688 // Since we now have the absolute screen coords, if there's a
1689 // parent we must subtract its top left corner
11cfa8ef
VZ
1690 if ( parent )
1691 {
a7e0e432 1692 ::ScreenToClient(GetHwndOf(parent), &point);
11cfa8ef 1693 }
89e3037c 1694 }
42e69d6b 1695
a7e0e432
VZ
1696 pos.x = point.x;
1697 pos.y = point.y;
1698 }
1699
1700 // we also must adjust by the client area offset: a control which is just
1701 // under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx
1702 if ( parent && !IsTopLevel() )
1703 {
1704 const wxPoint pt(parent->GetClientAreaOrigin());
1705 pos.x -= pt.x;
1706 pos.y -= pt.y;
11cfa8ef 1707 }
a7e0e432
VZ
1708
1709 if ( x )
1710 *x = pos.x;
1711 if ( y )
1712 *y = pos.y;
42e69d6b 1713}
54bdd8b0 1714
1e6feb95 1715void wxWindowMSW::DoScreenToClient(int *x, int *y) const
42e69d6b
VZ
1716{
1717 POINT pt;
1718 if ( x )
1719 pt.x = *x;
1720 if ( y )
1721 pt.y = *y;
54bdd8b0 1722
82c9f85c 1723 ::ScreenToClient(GetHwnd(), &pt);
a23fd0e1 1724
42e69d6b
VZ
1725 if ( x )
1726 *x = pt.x;
1727 if ( y )
1728 *y = pt.y;
1729}
a23fd0e1 1730
1e6feb95 1731void wxWindowMSW::DoClientToScreen(int *x, int *y) const
42e69d6b
VZ
1732{
1733 POINT pt;
1734 if ( x )
1735 pt.x = *x;
1736 if ( y )
1737 pt.y = *y;
54bdd8b0 1738
82c9f85c 1739 ::ClientToScreen(GetHwnd(), &pt);
a23fd0e1 1740
42e69d6b
VZ
1741 if ( x )
1742 *x = pt.x;
1743 if ( y )
1744 *y = pt.y;
1745}
a23fd0e1 1746
86e30911 1747bool
7d86a2d4
VZ
1748wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
1749{
1750#if USE_DEFERRED_SIZING
1751 // if our parent had prepared a defer window handle for us, use it (unless
1752 // we are a top level window)
1753 wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
1754
1755 HDWP hdwp = parent ? (HDWP)parent->m_hDWP : NULL;
1756 if ( hdwp )
1757 {
1758 hdwp = ::DeferWindowPos(hdwp, (HWND)hwnd, NULL, x, y, width, height,
dd28827a 1759 SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
7d86a2d4
VZ
1760 if ( !hdwp )
1761 {
1762 wxLogLastError(_T("DeferWindowPos"));
1763 }
1764 }
1765
1766 if ( parent )
1767 {
1768 // hdwp must be updated as it may have been changed
1769 parent->m_hDWP = (WXHANDLE)hdwp;
1770 }
1771
86e30911
VZ
1772 if ( hdwp )
1773 {
1774 // did deferred move, remember new coordinates of the window as they're
1775 // different from what Windows would return for it
1776 return true;
1777 }
1778
7d86a2d4 1779 // otherwise (or if deferring failed) move the window in place immediately
7d86a2d4 1780#endif // USE_DEFERRED_SIZING
86e30911 1781 if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) )
7d86a2d4 1782 {
86e30911 1783 wxLogLastError(wxT("MoveWindow"));
7d86a2d4 1784 }
86e30911
VZ
1785
1786 // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move,
1787 // ignored otherwise
1788 return false;
7d86a2d4
VZ
1789}
1790
1e6feb95 1791void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
b782f2e0 1792{
62e1ba75
JS
1793 // TODO: is this consistent with other platforms?
1794 // Still, negative width or height shouldn't be allowed
1795 if (width < 0)
1796 width = 0;
1797 if (height < 0)
1798 height = 0;
9b6ae450 1799
86e30911
VZ
1800 if ( DoMoveSibling(m_hWnd, x, y, width, height) )
1801 {
1802#if USE_DEFERRED_SIZING
1803 m_pendingPosition = wxPoint(x, y);
1804 m_pendingSize = wxSize(width, height);
1805#endif // USE_DEFERRED_SIZING
1806 }
b782f2e0
VZ
1807}
1808
4438caf4
VZ
1809// set the size of the window: if the dimensions are positive, just use them,
1810// but if any of them is equal to -1, it means that we must find the value for
1811// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1812// which case -1 is a valid value for x and y)
1813//
1814// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1815// the width/height to best suit our contents, otherwise we reuse the current
1816// width/height
1e6feb95 1817void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
42e69d6b 1818{
4438caf4 1819 // get the current size and position...
42e69d6b 1820 int currentX, currentY;
da78f3b1
RD
1821 int currentW, currentH;
1822
42e69d6b 1823 GetPosition(&currentX, &currentY);
42e69d6b 1824 GetSize(&currentW, &currentH);
a23fd0e1 1825
952f2aaa
VZ
1826 // ... and don't do anything (avoiding flicker) if it's already ok unless
1827 // we're forced to resize the window
4438caf4 1828 if ( x == currentX && y == currentY &&
952f2aaa
VZ
1829 width == currentW && height == currentH &&
1830 !(sizeFlags & wxSIZE_FORCE) )
4438caf4 1831 {
42e69d6b 1832 return;
4438caf4 1833 }
a23fd0e1 1834
422d0ff0 1835 if ( x == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
4438caf4 1836 x = currentX;
422d0ff0 1837 if ( y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
4438caf4 1838 y = currentY;
a23fd0e1 1839
4438caf4 1840 AdjustForParentClientOrigin(x, y, sizeFlags);
a23fd0e1 1841
abb74e0f 1842 wxSize size = wxDefaultSize;
422d0ff0 1843 if ( width == wxDefaultCoord )
4438caf4 1844 {
9e2896e5 1845 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
4438caf4
VZ
1846 {
1847 size = DoGetBestSize();
1848 width = size.x;
1849 }
1850 else
1851 {
1852 // just take the current one
1853 width = currentW;
1854 }
1855 }
1856
422d0ff0 1857 if ( height == wxDefaultCoord )
4438caf4 1858 {
9e2896e5 1859 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
4438caf4 1860 {
422d0ff0 1861 if ( size.x == wxDefaultCoord )
4438caf4 1862 {
b782f2e0 1863 size = DoGetBestSize();
4438caf4
VZ
1864 }
1865 //else: already called DoGetBestSize() above
a23fd0e1 1866
4438caf4
VZ
1867 height = size.y;
1868 }
1869 else
1870 {
1871 // just take the current one
1872 height = currentH;
1873 }
1874 }
1875
b782f2e0 1876 DoMoveWindow(x, y, width, height);
4438caf4
VZ
1877}
1878
1e6feb95 1879void wxWindowMSW::DoSetClientSize(int width, int height)
42e69d6b 1880{
90e572f1 1881 // setting the client size is less obvious than it could have been
d4597e13 1882 // because in the result of changing the total size the window scrollbar
c72b1ad7
VZ
1883 // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect()
1884 // doesn't take neither into account) and so the client size will not be
1885 // correct as the difference between the total and client size changes --
1886 // so we keep changing it until we get it right
d4597e13 1887 //
d6a97306
VZ
1888 // normally this loop shouldn't take more than 3 iterations (usually 1 but
1889 // if scrollbars [dis]appear as the result of the first call, then 2 and it
1890 // may become 3 if the window had 0 size originally and so we didn't
1891 // calculate the scrollbar correction correctly during the first iteration)
1892 // but just to be on the safe side we check for it instead of making it an
d4597e13 1893 // "infinite" loop (i.e. leaving break inside as the only way to get out)
d6a97306 1894 for ( int i = 0; i < 4; i++ )
d4597e13
VZ
1895 {
1896 RECT rectClient;
1897 ::GetClientRect(GetHwnd(), &rectClient);
2bda0e17 1898
b0268daf 1899 // if the size is already ok, stop here (NB: rectClient.left = top = 0)
422d0ff0
WS
1900 if ( (rectClient.right == width || width == wxDefaultCoord) &&
1901 (rectClient.bottom == height || height == wxDefaultCoord) )
d4597e13
VZ
1902 {
1903 break;
1904 }
a23fd0e1 1905
d4597e13
VZ
1906 // Find the difference between the entire window (title bar and all)
1907 // and the client area; add this to the new client size to move the
1908 // window
1909 RECT rectWin;
1910 ::GetWindowRect(GetHwnd(), &rectWin);
1911
b0268daf
VZ
1912 const int widthWin = rectWin.right - rectWin.left,
1913 heightWin = rectWin.bottom - rectWin.top;
387a3b02 1914
d4597e13
VZ
1915 // MoveWindow positions the child windows relative to the parent, so
1916 // adjust if necessary
1917 if ( !IsTopLevel() )
1918 {
1919 wxWindow *parent = GetParent();
1920 if ( parent )
1921 {
b0268daf 1922 ::ScreenToClient(GetHwndOf(parent), (POINT *)&rectWin);
d4597e13
VZ
1923 }
1924 }
a23fd0e1 1925
b0268daf 1926 // don't call DoMoveWindow() because we want to move window immediately
c72b1ad7
VZ
1927 // and not defer it here as otherwise the value returned by
1928 // GetClient/WindowRect() wouldn't change as the window wouldn't be
1929 // really resized
b0268daf
VZ
1930 if ( !::MoveWindow(GetHwnd(),
1931 rectWin.left,
1932 rectWin.top,
1933 width + widthWin - rectClient.right,
1934 height + heightWin - rectClient.bottom,
1935 TRUE) )
1936 {
1937 wxLogLastError(_T("MoveWindow"));
1938 }
d4597e13 1939 }
42e69d6b 1940}
a23fd0e1 1941
42e69d6b
VZ
1942// ---------------------------------------------------------------------------
1943// text metrics
1944// ---------------------------------------------------------------------------
a23fd0e1 1945
1e6feb95 1946int wxWindowMSW::GetCharHeight() const
42e69d6b 1947{
f6bcfd97 1948 return wxGetTextMetrics(this).tmHeight;
42e69d6b 1949}
3eddf563 1950
1e6feb95 1951int wxWindowMSW::GetCharWidth() const
42e69d6b 1952{
f6bcfd97
BP
1953 // +1 is needed because Windows apparently adds it when calculating the
1954 // dialog units size in pixels
1955#if wxDIALOG_UNIT_COMPATIBILITY
1e6feb95 1956 return wxGetTextMetrics(this).tmAveCharWidth;
f6bcfd97
BP
1957#else
1958 return wxGetTextMetrics(this).tmAveCharWidth + 1;
1959#endif
42e69d6b 1960}
f4621a09 1961
1e6feb95 1962void wxWindowMSW::GetTextExtent(const wxString& string,
34636400 1963 int *x, int *y,
42e69d6b
VZ
1964 int *descent, int *externalLeading,
1965 const wxFont *theFont) const
1966{
64869ab7
VZ
1967 wxASSERT_MSG( !theFont || theFont->Ok(),
1968 _T("invalid font in GetTextExtent()") );
634903fd 1969
2d17baae
VS
1970 wxFont fontToUse;
1971 if (theFont)
1972 fontToUse = *theFont;
1973 else
1974 fontToUse = GetFont();
634903fd 1975
64869ab7
VZ
1976 WindowHDC hdc(GetHwnd());
1977 SelectInHDC selectFont(hdc, GetHfontOf(fontToUse));
341c92a8 1978
42e69d6b
VZ
1979 SIZE sizeRect;
1980 TEXTMETRIC tm;
767b35a5 1981 ::GetTextExtentPoint32(hdc, string, string.length(), &sizeRect);
64869ab7 1982 GetTextMetrics(hdc, &tm);
42e69d6b 1983
0655ad29
VZ
1984 if ( x )
1985 *x = sizeRect.cx;
1986 if ( y )
1987 *y = sizeRect.cy;
1988 if ( descent )
1989 *descent = tm.tmDescent;
1990 if ( externalLeading )
1991 *externalLeading = tm.tmExternalLeading;
2bda0e17
KB
1992}
1993
c50f1fb9
VZ
1994// ---------------------------------------------------------------------------
1995// popup menu
1996// ---------------------------------------------------------------------------
1997
2e9f62da
VZ
1998#if wxUSE_MENUS_NATIVE
1999
ed45e263
VZ
2000// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
2001// immediately, without waiting for the next event loop iteration
2002//
2003// NB: this function should probably be made public later as it can almost
2004// surely replace wxYield() elsewhere as well
2005static void wxYieldForCommandsOnly()
2006{
2007 // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
2008 // want to process it here)
2009 MSG msg;
1bf77ee5 2010 while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE) )
ed45e263 2011 {
dd7ebf8b 2012 if ( msg.message == WM_QUIT )
1bf77ee5
VZ
2013 {
2014 // if we retrieved a WM_QUIT, insert back into the message queue.
2015 ::PostQuitMessage(0);
2016 break;
2017 }
7de59551 2018
1bf77ee5
VZ
2019 // luckily (as we don't have access to wxEventLoopImpl method from here
2020 // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it
2021 // immediately
2022 ::TranslateMessage(&msg);
2023 ::DispatchMessage(&msg);
2024 }
ed45e263
VZ
2025}
2026
1e6feb95 2027bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y)
c50f1fb9
VZ
2028{
2029 menu->SetInvokingWindow(this);
2030 menu->UpdateUI();
2031
27d2dbbc 2032 if ( x == wxDefaultCoord && y == wxDefaultCoord )
971562cb
VS
2033 {
2034 wxPoint mouse = ScreenToClient(wxGetMousePosition());
2035 x = mouse.x; y = mouse.y;
2036 }
2037
c50f1fb9
VZ
2038 HWND hWnd = GetHwnd();
2039 HMENU hMenu = GetHmenuOf(menu);
2040 POINT point;
2041 point.x = x;
2042 point.y = y;
2043 ::ClientToScreen(hWnd, &point);
2044 wxCurrentPopupMenu = menu;
5cb598ae 2045#if defined(__WXWINCE__)
b40bf35c
VZ
2046 static const UINT flags = 0;
2047#else // !__WXWINCE__
2048 UINT flags = TPM_RIGHTBUTTON;
2049 // NT4 doesn't support TPM_RECURSE and simply doesn't show the menu at all
2050 // when it's use, I'm not sure about Win95/98 but prefer to err on the safe
2051 // side and not to use it there neither -- modify the test if it does work
2052 // on these systems
2053 if ( wxGetWinVersion() >= wxWinVersion_5 )
2054 {
2055 // using TPM_RECURSE allows us to show a popup menu while another menu
2056 // is opened which can be useful and is supported by the other
2057 // platforms, so allow it under Windows too
2058 flags |= TPM_RECURSE;
2059 }
2060#endif // __WXWINCE__/!__WXWINCE__
2061
7f0586ef 2062 ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL);
ed45e263 2063
90e572f1 2064 // we need to do it right now as otherwise the events are never going to be
ed45e263
VZ
2065 // sent to wxCurrentPopupMenu from HandleCommand()
2066 //
2067 // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
2068 // help and we'd still need wxYieldForCommandsOnly() as the menu may be
2069 // destroyed as soon as we return (it can be a local variable in the caller
2070 // for example) and so we do need to process the event immediately
2071 wxYieldForCommandsOnly();
2072
c50f1fb9
VZ
2073 wxCurrentPopupMenu = NULL;
2074
2075 menu->SetInvokingWindow(NULL);
2076
08158721 2077 return true;
c50f1fb9
VZ
2078}
2079
1e6feb95
VZ
2080#endif // wxUSE_MENUS_NATIVE
2081
42e69d6b
VZ
2082// ===========================================================================
2083// pre/post message processing
2084// ===========================================================================
2bda0e17 2085
c140b7e7 2086WXLRESULT wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
42e69d6b
VZ
2087{
2088 if ( m_oldWndProc )
2089 return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
2090 else
2091 return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
2092}
2bda0e17 2093
1e6feb95 2094bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
42e69d6b 2095{
1e6feb95
VZ
2096 // wxUniversal implements tab traversal itself
2097#ifndef __WXUNIVERSAL__
42e69d6b 2098 if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) )
2d0a075d 2099 {
42e69d6b
VZ
2100 // intercept dialog navigation keys
2101 MSG *msg = (MSG *)pMsg;
d9317fd4
VZ
2102
2103 // here we try to do all the job which ::IsDialogMessage() usually does
2104 // internally
573a1586 2105 if ( msg->message == WM_KEYDOWN )
42e69d6b 2106 {
3f7bc32b
VZ
2107 bool bCtrlDown = wxIsCtrlDown();
2108 bool bShiftDown = wxIsShiftDown();
a23fd0e1 2109
42e69d6b
VZ
2110 // WM_GETDLGCODE: ask the control if it wants the key for itself,
2111 // don't process it if it's the case (except for Ctrl-Tab/Enter
2112 // combinations which are always processed)
977f50f3
VZ
2113 LONG lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0);
2114
2115 // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the
2116 // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically,
2117 // it, of course, implies them
2118 if ( lDlgCode & DLGC_WANTALLKEYS )
42e69d6b 2119 {
977f50f3 2120 lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS;
42e69d6b 2121 }
a23fd0e1 2122
08158721 2123 bool bForward = true,
298ca00c
VZ
2124 bWindowChange = false,
2125 bFromTab = false;
a23fd0e1 2126
573a1586 2127 // should we process this message specially?
08158721 2128 bool bProcess = true;
9145664b 2129 switch ( msg->wParam )
42e69d6b
VZ
2130 {
2131 case VK_TAB:
7cc44669
VZ
2132 if ( (lDlgCode & DLGC_WANTTAB) && !bCtrlDown )
2133 {
2134 // let the control have the TAB
08158721 2135 bProcess = false;
42e69d6b 2136 }
7cc44669
VZ
2137 else // use it for navigation
2138 {
42e69d6b
VZ
2139 // Ctrl-Tab cycles thru notebook pages
2140 bWindowChange = bCtrlDown;
319fefa9 2141 bForward = !bShiftDown;
298ca00c 2142 bFromTab = true;
42e69d6b
VZ
2143 }
2144 break;
a23fd0e1 2145
42e69d6b
VZ
2146 case VK_UP:
2147 case VK_LEFT:
2148 if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
08158721 2149 bProcess = false;
42e69d6b 2150 else
08158721 2151 bForward = false;
42e69d6b 2152 break;
a02eb1d2 2153
42e69d6b
VZ
2154 case VK_DOWN:
2155 case VK_RIGHT:
2156 if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown )
08158721 2157 bProcess = false;
42e69d6b 2158 break;
2bda0e17 2159
efe5e221
VZ
2160 case VK_PRIOR:
2161 bForward = false;
2162 // fall through
2163
2164 case VK_NEXT:
2165 // we treat PageUp/Dn as arrows because chances are that
2166 // a control which needs arrows also needs them for
2167 // navigation (e.g. wxTextCtrl, wxListCtrl, ...)
ada5f90d 2168 if ( (lDlgCode & DLGC_WANTARROWS) && !bCtrlDown )
efe5e221 2169 bProcess = false;
ada5f90d 2170 else // OTOH Ctrl-PageUp/Dn works as [Shift-]Ctrl-Tab
efe5e221
VZ
2171 bWindowChange = true;
2172 break;
2173
42e69d6b
VZ
2174 case VK_RETURN:
2175 {
edccf428 2176 if ( (lDlgCode & DLGC_WANTMESSAGE) && !bCtrlDown )
42e69d6b
VZ
2177 {
2178 // control wants to process Enter itself, don't
90c6edd7 2179 // call IsDialogMessage() which would consume it
08158721 2180 return false;
42e69d6b 2181 }
3147bb58 2182
90c6edd7 2183#if wxUSE_BUTTON
3147bb58 2184 // currently active button should get enter press even
90c6edd7
VZ
2185 // if there is a default button elsewhere so check if
2186 // this window is a button first
2187 wxWindow *btn = NULL;
3147bb58 2188 if ( lDlgCode & DLGC_DEFPUSHBUTTON )
319fefa9 2189 {
3e79ed96
VZ
2190 // let IsDialogMessage() handle this for all
2191 // buttons except the owner-drawn ones which it
2192 // just seems to ignore
2193 long style = ::GetWindowLong(msg->hwnd, GWL_STYLE);
2194 if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
2195 {
2196 // emulate the button click
90c6edd7 2197 btn = wxFindWinFromHandle((WXHWND)msg->hwnd);
3e79ed96
VZ
2198 }
2199
08158721 2200 bProcess = false;
319fefa9 2201 }
90c6edd7 2202 else // not a button itself, do we have default button?
c50f1fb9 2203 {
90c6edd7
VZ
2204 wxTopLevelWindow *
2205 tlw = wxDynamicCast(wxGetTopLevelParent(this),
2206 wxTopLevelWindow);
6c20e8f8 2207 if ( tlw )
c50f1fb9 2208 {
90c6edd7
VZ
2209 btn = wxDynamicCast(tlw->GetDefaultItem(),
2210 wxButton);
c50f1fb9 2211 }
90c6edd7
VZ
2212 }
2213
2214 if ( btn && btn->IsEnabled() )
2215 {
2216 btn->MSWCommand(BN_CLICKED, 0 /* unused */);
2217 return true;
2218 }
2219
1e6feb95 2220#endif // wxUSE_BUTTON
90c6edd7 2221
7b504551 2222#ifdef __WXWINCE__
90c6edd7
VZ
2223 // map Enter presses into button presses on PDAs
2224 wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN);
2225 event.SetEventObject(this);
2226 if ( GetEventHandler()->ProcessEvent(event) )
2227 return true;
2228#endif // __WXWINCE__
42e69d6b
VZ
2229 }
2230 break;
2bda0e17 2231
42e69d6b 2232 default:
08158721 2233 bProcess = false;
42e69d6b 2234 }
2bda0e17 2235
42e69d6b
VZ
2236 if ( bProcess )
2237 {
2238 wxNavigationKeyEvent event;
2239 event.SetDirection(bForward);
2240 event.SetWindowChange(bWindowChange);
298ca00c 2241 event.SetFromTab(bFromTab);
42e69d6b 2242 event.SetEventObject(this);
3572173c 2243
42e69d6b 2244 if ( GetEventHandler()->ProcessEvent(event) )
57c0af52 2245 {
d7e0024b
VZ
2246 // as we don't call IsDialogMessage(), which would take of
2247 // this by default, we need to manually send this message
1ca78aa1
JS
2248 // so that controls can change their UI state if needed
2249 MSWUpdateUIState(UIS_CLEAR, UISF_HIDEFOCUS);
d7e0024b 2250
08158721 2251 return true;
57c0af52 2252 }
42e69d6b
VZ
2253 }
2254 }
a23fd0e1 2255
98ebf919 2256 if ( ::IsDialogMessage(GetHwnd(), msg) )
f6bcfd97 2257 {
98ebf919
VZ
2258 // IsDialogMessage() did something...
2259 return true;
f6bcfd97 2260 }
42e69d6b 2261 }
1e6feb95 2262#endif // __WXUNIVERSAL__
a23fd0e1 2263
42e69d6b
VZ
2264#if wxUSE_TOOLTIPS
2265 if ( m_tooltip )
387a3b02 2266 {
42e69d6b
VZ
2267 // relay mouse move events to the tooltip control
2268 MSG *msg = (MSG *)pMsg;
2269 if ( msg->message == WM_MOUSEMOVE )
259a4264 2270 wxToolTip::RelayEvent(pMsg);
387a3b02 2271 }
42e69d6b 2272#endif // wxUSE_TOOLTIPS
a23fd0e1 2273
08158721 2274 return false;
387a3b02
JS
2275}
2276
1e6feb95 2277bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg)
387a3b02 2278{
1e6feb95 2279#if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
c50f1fb9 2280 return m_acceleratorTable.Translate(this, pMsg);
1e6feb95 2281#else
574c939e 2282 (void) pMsg;
08158721 2283 return false;
1e6feb95 2284#endif // wxUSE_ACCEL
387a3b02
JS
2285}
2286
98ebf919 2287bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* msg)
a37d422a 2288{
98ebf919
VZ
2289 // all tests below have to deal with various bugs/misfeatures of
2290 // IsDialogMessage(): we have to prevent it from being called from our
2291 // MSWProcessMessage() in some situations
2292
2293 // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the
2294 // message even when there is no cancel button and when the message is
2295 // needed by the control itself: in particular, it prevents the tree in
2296 // place edit control from being closed with Escape in a dialog
2297 if ( msg->message == WM_KEYDOWN && msg->wParam == VK_ESCAPE )
2298 {
2299 return false;
2300 }
2301
2302 // ::IsDialogMessage() is broken and may sometimes hang the application by
2303 // going into an infinite loop when it tries to find the control to give
2304 // focus to when Alt-<key> is pressed, so we try to detect [some of] the
2305 // situations when this may happen and not call it then
2306 if ( msg->message != WM_SYSCHAR )
2307 return true;
2308
2309 // assume we can call it by default
2310 bool canSafelyCallIsDlgMsg = true;
2311
2312 HWND hwndFocus = ::GetFocus();
2313
2314 // if the currently focused window itself has WS_EX_CONTROLPARENT style,
2315 // ::IsDialogMessage() will also enter an infinite loop, because it will
2316 // recursively check the child windows but not the window itself and so if
2317 // none of the children accepts focus it loops forever (as it only stops
2318 // when it gets back to the window it started from)
2319 //
2320 // while it is very unusual that a window with WS_EX_CONTROLPARENT
2321 // style has the focus, it can happen. One such possibility is if
2322 // all windows are either toplevel, wxDialog, wxPanel or static
2323 // controls and no window can actually accept keyboard input.
2324#if !defined(__WXWINCE__)
2325 if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
2326 {
2327 // pessimistic by default
2328 canSafelyCallIsDlgMsg = false;
2329 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2330 node;
2331 node = node->GetNext() )
2332 {
2333 wxWindow * const win = node->GetData();
ad02525d 2334 if ( win->CanAcceptFocus() &&
98ebf919
VZ
2335 !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) &
2336 WS_EX_CONTROLPARENT) )
2337 {
2338 // it shouldn't hang...
2339 canSafelyCallIsDlgMsg = true;
2340
2341 break;
2342 }
2343 }
2344 }
2345#endif // !__WXWINCE__
2346
2347 if ( canSafelyCallIsDlgMsg )
2348 {
2349 // ::IsDialogMessage() can enter in an infinite loop when the
2350 // currently focused window is disabled or hidden and its
2351 // parent has WS_EX_CONTROLPARENT style, so don't call it in
2352 // this case
2353 while ( hwndFocus )
2354 {
2355 if ( !::IsWindowEnabled(hwndFocus) ||
2356 !::IsWindowVisible(hwndFocus) )
2357 {
2358 // it would enter an infinite loop if we do this!
2359 canSafelyCallIsDlgMsg = false;
2360
2361 break;
2362 }
2363
2364 if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) )
2365 {
2366 // it's a top level window, don't go further -- e.g. even
2367 // if the parent of a dialog is disabled, this doesn't
2368 // break navigation inside the dialog
2369 break;
2370 }
2371
2372 hwndFocus = ::GetParent(hwndFocus);
2373 }
2374 }
2375
2376 return canSafelyCallIsDlgMsg;
a37d422a
VZ
2377}
2378
42e69d6b 2379// ---------------------------------------------------------------------------
e39af974 2380// message params unpackers
42e69d6b 2381// ---------------------------------------------------------------------------
2bda0e17 2382
1e6feb95 2383void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b
VZ
2384 WORD *id, WXHWND *hwnd, WORD *cmd)
2385{
2386 *id = LOWORD(wParam);
2387 *hwnd = (WXHWND)lParam;
2388 *cmd = HIWORD(wParam);
2bda0e17
KB
2389}
2390
1e6feb95 2391void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2392 WXWORD *state, WXWORD *minimized, WXHWND *hwnd)
2bda0e17 2393{
42e69d6b
VZ
2394 *state = LOWORD(wParam);
2395 *minimized = HIWORD(wParam);
2396 *hwnd = (WXHWND)lParam;
2bda0e17
KB
2397}
2398
1e6feb95 2399void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2400 WXWORD *code, WXWORD *pos, WXHWND *hwnd)
2bda0e17 2401{
42e69d6b
VZ
2402 *code = LOWORD(wParam);
2403 *pos = HIWORD(wParam);
2404 *hwnd = (WXHWND)lParam;
2405}
a23fd0e1 2406
1e6feb95 2407void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam,
01c500af 2408 WXHDC *hdc, WXHWND *hwnd)
42e69d6b 2409{
42e69d6b
VZ
2410 *hwnd = (WXHWND)lParam;
2411 *hdc = (WXHDC)wParam;
2bda0e17
KB
2412}
2413
1e6feb95 2414void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam,
42e69d6b 2415 WXWORD *item, WXWORD *flags, WXHMENU *hmenu)
2bda0e17 2416{
42e69d6b
VZ
2417 *item = (WXWORD)wParam;
2418 *flags = HIWORD(wParam);
2419 *hmenu = (WXHMENU)lParam;
2420}
c085e333 2421
42e69d6b 2422// ---------------------------------------------------------------------------
77ffb593 2423// Main wxWidgets window proc and the window proc for wxWindow
42e69d6b 2424// ---------------------------------------------------------------------------
2bda0e17 2425
42e69d6b
VZ
2426// Hook for new window just as it's being created, when the window isn't yet
2427// associated with the handle
b225f659
VZ
2428static wxWindowMSW *gs_winBeingCreated = NULL;
2429
2430// implementation of wxWindowCreationHook class: it just sets gs_winBeingCreated to the
2431// window being created and insures that it's always unset back later
2432wxWindowCreationHook::wxWindowCreationHook(wxWindowMSW *winBeingCreated)
2433{
2434 gs_winBeingCreated = winBeingCreated;
2435}
2436
2437wxWindowCreationHook::~wxWindowCreationHook()
2438{
2439 gs_winBeingCreated = NULL;
2440}
42e69d6b
VZ
2441
2442// Main window proc
3135f4a7 2443LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2bda0e17 2444{
42e69d6b
VZ
2445 // trace all messages - useful for the debugging
2446#ifdef __WXDEBUG__
13e4c4d9
VZ
2447 wxLogTrace(wxTraceMessages,
2448 wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"),
2449 wxGetMessageName(message), (long)hWnd, (long)wParam, lParam);
42e69d6b 2450#endif // __WXDEBUG__
2bda0e17 2451
1e6feb95 2452 wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd);
c085e333 2453
42e69d6b 2454 // when we get the first message for the HWND we just created, we associate
b225f659
VZ
2455 // it with wxWindow stored in gs_winBeingCreated
2456 if ( !wnd && gs_winBeingCreated )
2d0a075d 2457 {
b225f659
VZ
2458 wxAssociateWinWithHandle(hWnd, gs_winBeingCreated);
2459 wnd = gs_winBeingCreated;
2460 gs_winBeingCreated = NULL;
42e69d6b 2461 wnd->SetHWND((WXHWND)hWnd);
2d0a075d 2462 }
2bda0e17 2463
42e69d6b 2464 LRESULT rc;
a23fd0e1 2465
a3dc1da9 2466 if ( wnd && wxEventLoop::AllowProcessing(wnd) )
b225f659 2467 rc = wnd->MSWWindowProc(message, wParam, lParam);
a23fd0e1 2468 else
b225f659 2469 rc = ::DefWindowProc(hWnd, message, wParam, lParam);
2bda0e17 2470
42e69d6b 2471 return rc;
f7bd2698
JS
2472}
2473
c140b7e7 2474WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
f7bd2698 2475{
42e69d6b 2476 // did we process the message?
08158721 2477 bool processed = false;
f7bd2698 2478
42e69d6b
VZ
2479 // the return value
2480 union
2bda0e17 2481 {
42e69d6b 2482 bool allow;
c140b7e7 2483 WXLRESULT result;
42e69d6b
VZ
2484 WXHBRUSH hBrush;
2485 } rc;
2bda0e17 2486
42e69d6b
VZ
2487 // for most messages we should return 0 when we do process the message
2488 rc.result = 0;
2bda0e17 2489
42e69d6b 2490 switch ( message )
39136494 2491 {
42e69d6b
VZ
2492 case WM_CREATE:
2493 {
2494 bool mayCreate;
2495 processed = HandleCreate((WXLPCREATESTRUCT)lParam, &mayCreate);
2496 if ( processed )
2497 {
2498 // return 0 to allow window creation
2499 rc.result = mayCreate ? 0 : -1;
2500 }
2501 }
2502 break;
47cbd6da 2503
42e69d6b 2504 case WM_DESTROY:
08158721 2505 // never set processed to true and *always* pass WM_DESTROY to
ad4297f3
VZ
2506 // DefWindowProc() as Windows may do some internal cleanup when
2507 // processing it and failing to pass the message along may cause
2508 // memory and resource leaks!
2509 (void)HandleDestroy();
42e69d6b
VZ
2510 break;
2511
9b6ae450
VZ
2512 case WM_SIZE:
2513 processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam);
9b6ae450
VZ
2514 break;
2515
42e69d6b 2516 case WM_MOVE:
132cb640 2517 processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
42e69d6b 2518 break;
47cbd6da 2519
7f0586ef 2520#if !defined(__WXWINCE__)
5706de1c 2521 case WM_MOVING:
540b6b09
VZ
2522 {
2523 LPRECT pRect = (LPRECT)lParam;
2524 wxRect rc;
2525 rc.SetLeft(pRect->left);
2526 rc.SetTop(pRect->top);
2527 rc.SetRight(pRect->right);
2528 rc.SetBottom(pRect->bottom);
2529 processed = HandleMoving(rc);
2530 if (processed) {
2531 pRect->left = rc.GetLeft();
2532 pRect->top = rc.GetTop();
2533 pRect->right = rc.GetRight();
2534 pRect->bottom = rc.GetBottom();
2535 }
2536 }
5706de1c
JS
2537 break;
2538
5706de1c
JS
2539 case WM_SIZING:
2540 {
2541 LPRECT pRect = (LPRECT)lParam;
2542 wxRect rc;
2543 rc.SetLeft(pRect->left);
2544 rc.SetTop(pRect->top);
2545 rc.SetRight(pRect->right);
2546 rc.SetBottom(pRect->bottom);
2547 processed = HandleSizing(rc);
2548 if (processed) {
2549 pRect->left = rc.GetLeft();
2550 pRect->top = rc.GetTop();
2551 pRect->right = rc.GetRight();
2552 pRect->bottom = rc.GetBottom();
2553 }
2554 }
2555 break;
9b6ae450 2556#endif // !__WXWINCE__
5706de1c 2557
7f0586ef 2558#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
1e6feb95 2559 case WM_ACTIVATEAPP:
afafd942 2560 // This implicitly sends a wxEVT_ACTIVATE_APP event
1e6feb95 2561 wxTheApp->SetActive(wParam != 0, FindFocus());
42e69d6b 2562 break;
8a46f9b1 2563#endif
47cbd6da 2564
42e69d6b 2565 case WM_ACTIVATE:
341c92a8 2566 {
42e69d6b
VZ
2567 WXWORD state, minimized;
2568 WXHWND hwnd;
2569 UnpackActivate(wParam, lParam, &state, &minimized, &hwnd);
2570
2571 processed = HandleActivate(state, minimized != 0, (WXHWND)hwnd);
341c92a8 2572 }
42e69d6b 2573 break;
341c92a8 2574
42e69d6b
VZ
2575 case WM_SETFOCUS:
2576 processed = HandleSetFocus((WXHWND)(HWND)wParam);
2577 break;
47cbd6da 2578
42e69d6b
VZ
2579 case WM_KILLFOCUS:
2580 processed = HandleKillFocus((WXHWND)(HWND)wParam);
2581 break;
47cbd6da 2582
c3732409 2583 case WM_PRINTCLIENT:
1a784dfc 2584 processed = HandlePrintClient((WXHDC)wParam);
07c19327
VZ
2585 break;
2586
c3732409
VZ
2587 case WM_PAINT:
2588 if ( wParam )
5c6c3176 2589 {
5c6c3176 2590 wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
07c19327 2591
5c6c3176
RD
2592 processed = HandlePaint();
2593 }
c3732409
VZ
2594 else // no DC given
2595 {
2596 processed = HandlePaint();
2597 }
5c6c3176
RD
2598 break;
2599
42e69d6b 2600 case WM_CLOSE:
9fd9e47a
JS
2601#ifdef __WXUNIVERSAL__
2602 // Universal uses its own wxFrame/wxDialog, so we don't receive
2603 // close events unless we have this.
2604 Close();
c3732409
VZ
2605#endif // __WXUNIVERSAL__
2606
42e69d6b
VZ
2607 // don't let the DefWindowProc() destroy our window - we'll do it
2608 // ourselves in ~wxWindow
08158721 2609 processed = true;
42e69d6b
VZ
2610 rc.result = TRUE;
2611 break;
47cbd6da 2612
42e69d6b
VZ
2613 case WM_SHOWWINDOW:
2614 processed = HandleShow(wParam != 0, (int)lParam);
2615 break;
3a19e16d 2616
42e69d6b 2617 case WM_MOUSEMOVE:
132cb640
VZ
2618 processed = HandleMouseMove(GET_X_LPARAM(lParam),
2619 GET_Y_LPARAM(lParam),
2620 wParam);
2621 break;
0d0512bd 2622
4e5c6c33 2623#ifdef HAVE_TRACKMOUSEEVENT
e5297b7f 2624 case WM_MOUSELEAVE:
aafb9978
VZ
2625 // filter out excess WM_MOUSELEAVE events sent after PopupMenu()
2626 // (on XP at least)
4e5c6c33 2627 if ( m_mouseInWindow )
e5297b7f 2628 {
4e5c6c33 2629 GenerateMouseLeave();
e5297b7f 2630 }
4e5c6c33
VZ
2631
2632 // always pass processed back as false, this allows the window
2633 // manager to process the message too. This is needed to
2634 // ensure windows XP themes work properly as the mouse moves
2635 // over widgets like buttons. So don't set processed to true here.
51e4e266 2636 break;
4e5c6c33 2637#endif // HAVE_TRACKMOUSEEVENT
35bbb0c6 2638
d2c52078
RD
2639#if wxUSE_MOUSEWHEEL
2640 case WM_MOUSEWHEEL:
2641 processed = HandleMouseWheel(wParam, lParam);
2642 break;
2643#endif
2644
42e69d6b
VZ
2645 case WM_LBUTTONDOWN:
2646 case WM_LBUTTONUP:
2647 case WM_LBUTTONDBLCLK:
2648 case WM_RBUTTONDOWN:
2649 case WM_RBUTTONUP:
2650 case WM_RBUTTONDBLCLK:
2651 case WM_MBUTTONDOWN:
2652 case WM_MBUTTONUP:
2653 case WM_MBUTTONDBLCLK:
dfafa702 2654 {
98363307 2655#ifdef __WXMICROWIN__
cd4453e5
VZ
2656 // MicroWindows seems to ignore the fact that a window is
2657 // disabled. So catch mouse events and throw them away if
2658 // necessary.
d0a3d109 2659 wxWindowMSW* win = this;
dfafa702 2660 for ( ;; )
d0a3d109
VZ
2661 {
2662 if (!win->IsEnabled())
2663 {
08158721 2664 processed = true;
d0a3d109
VZ
2665 break;
2666 }
dfafa702 2667
d0a3d109 2668 win = win->GetParent();
dfafa702 2669 if ( !win || win->IsTopLevel() )
d0a3d109
VZ
2670 break;
2671 }
dfafa702 2672
03e0b2b1
VZ
2673 if ( processed )
2674 break;
2675
dfafa702 2676#endif // __WXMICROWIN__
03e0b2b1
VZ
2677 int x = GET_X_LPARAM(lParam),
2678 y = GET_Y_LPARAM(lParam);
dfafa702 2679
42b1fb63 2680#ifdef __WXWINCE__
03e0b2b1 2681 // redirect the event to a static control if necessary by
42b1fb63
VZ
2682 // finding one under mouse because under CE the static controls
2683 // don't generate mouse events (even with SS_NOTIFY)
03e0b2b1
VZ
2684 wxWindowMSW *win;
2685 if ( GetCapture() == this )
2686 {
2687 // but don't do it if the mouse is captured by this window
2688 // because then it should really get this event itself
2689 win = this;
d0a3d109 2690 }
03e0b2b1
VZ
2691 else
2692 {
2693 win = FindWindowForMouseEvent(this, &x, &y);
2b5f62a0
VZ
2694
2695 // this should never happen
2696 wxCHECK_MSG( win, 0,
2697 _T("FindWindowForMouseEvent() returned NULL") );
9f011847 2698 }
7d4f65e3
JS
2699#ifdef __POCKETPC__
2700 if (IsContextMenuEnabled() && message == WM_LBUTTONDOWN)
2701 {
2702 SHRGINFO shrgi = {0};
faa94f3e 2703
7d4f65e3
JS
2704 shrgi.cbSize = sizeof(SHRGINFO);
2705 shrgi.hwndClient = (HWND) GetHWND();
2706 shrgi.ptDown.x = x;
2707 shrgi.ptDown.y = y;
faa94f3e 2708
7d4f65e3
JS
2709 shrgi.dwFlags = SHRG_RETURNCMD;
2710 // shrgi.dwFlags = SHRG_NOTIFYPARENT;
faa94f3e 2711
7d4f65e3
JS
2712 if (GN_CONTEXTMENU == ::SHRecognizeGesture(&shrgi))
2713 {
2714 wxPoint pt(x, y);
2715 pt = ClientToScreen(pt);
faa94f3e 2716
7d4f65e3 2717 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
faa94f3e 2718
7d4f65e3
JS
2719 evtCtx.SetEventObject(this);
2720 if (GetEventHandler()->ProcessEvent(evtCtx))
f350d4b2 2721 {
7d4f65e3 2722 processed = true;
f350d4b2
JS
2723 return true;
2724 }
7d4f65e3
JS
2725 }
2726 }
2727#endif
2728
42b1fb63
VZ
2729#else // !__WXWINCE__
2730 wxWindowMSW *win = this;
2731#endif // __WXWINCE__/!__WXWINCE__
9f011847
VZ
2732
2733 processed = win->HandleMouseEvent(message, x, y, wParam);
2b5f62a0 2734
9f011847
VZ
2735 // if the app didn't eat the event, handle it in the default
2736 // way, that is by giving this window the focus
2737 if ( !processed )
2738 {
2b5f62a0
VZ
2739 // for the standard classes their WndProc sets the focus to
2740 // them anyhow and doing it from here results in some weird
9f011847 2741 // problems, so don't do it for them (unnecessary anyhow)
2b5f62a0
VZ
2742 if ( !win->IsOfStandardClass() )
2743 {
ad02525d 2744 if ( message == WM_LBUTTONDOWN && win->CanAcceptFocus() )
2b5f62a0
VZ
2745 win->SetFocus();
2746 }
03e0b2b1 2747 }
98363307 2748 }
dfafa702 2749 break;
d0a3d109 2750
cd4453e5 2751#ifdef MM_JOY1MOVE
42e69d6b
VZ
2752 case MM_JOY1MOVE:
2753 case MM_JOY2MOVE:
2754 case MM_JOY1ZMOVE:
2755 case MM_JOY2ZMOVE:
2756 case MM_JOY1BUTTONDOWN:
2757 case MM_JOY2BUTTONDOWN:
2758 case MM_JOY1BUTTONUP:
2759 case MM_JOY2BUTTONUP:
132cb640
VZ
2760 processed = HandleJoystickEvent(message,
2761 GET_X_LPARAM(lParam),
2762 GET_Y_LPARAM(lParam),
2763 wParam);
42e69d6b 2764 break;
cd4453e5 2765#endif // __WXMICROWIN__
47cbd6da 2766
42e69d6b
VZ
2767 case WM_COMMAND:
2768 {
2769 WORD id, cmd;
2770 WXHWND hwnd;
2771 UnpackCommand(wParam, lParam, &id, &hwnd, &cmd);
47cbd6da 2772
42e69d6b
VZ
2773 processed = HandleCommand(id, cmd, hwnd);
2774 }
2775 break;
7d532b0c 2776
42e69d6b
VZ
2777 case WM_NOTIFY:
2778 processed = HandleNotify((int)wParam, lParam, &rc.result);
2779 break;
2bda0e17 2780
27005f3a
VZ
2781 // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU,
2782 // otherwise DefWindowProc() does it perfectly fine for us, but MSLU
2783 // apparently doesn't always behave properly and needs some help
2784#if wxUSE_UNICODE_MSLU && defined(NF_QUERY)
2785 case WM_NOTIFYFORMAT:
2786 if ( lParam == NF_QUERY )
2787 {
2788 processed = true;
2789 rc.result = NFR_UNICODE;
2790 }
2791 break;
2792#endif // wxUSE_UNICODE_MSLU
2793
08158721 2794 // for these messages we must return true if process the message
cd4453e5 2795#ifdef WM_DRAWITEM
42e69d6b
VZ
2796 case WM_DRAWITEM:
2797 case WM_MEASUREITEM:
2798 {
2799 int idCtrl = (UINT)wParam;
2800 if ( message == WM_DRAWITEM )
2801 {
2802 processed = MSWOnDrawItem(idCtrl,
2803 (WXDRAWITEMSTRUCT *)lParam);
2804 }
2805 else
2806 {
2807 processed = MSWOnMeasureItem(idCtrl,
2808 (WXMEASUREITEMSTRUCT *)lParam);
2809 }
57a7b7c1 2810
42e69d6b
VZ
2811 if ( processed )
2812 rc.result = TRUE;
2813 }
2814 break;
cd4453e5
VZ
2815#endif // defined(WM_DRAWITEM)
2816
9bf84618 2817 case WM_GETDLGCODE:
ff7282e1 2818 if ( !IsOfStandardClass() || HasFlag(wxWANTS_CHARS) )
9bf84618 2819 {
5a403e3f
VZ
2820 // we always want to get the char events
2821 rc.result = DLGC_WANTCHARS;
2822
ff7282e1 2823 if ( HasFlag(wxWANTS_CHARS) )
5a403e3f
VZ
2824 {
2825 // in fact, we want everything
2826 rc.result |= DLGC_WANTARROWS |
2827 DLGC_WANTTAB |
2828 DLGC_WANTALLKEYS;
2829 }
2830
08158721 2831 processed = true;
9bf84618 2832 }
101f488c 2833 //else: get the dlg code from the DefWindowProc()
9bf84618
VZ
2834 break;
2835
4004f41e 2836 case WM_SYSKEYDOWN:
42e69d6b 2837 case WM_KEYDOWN:
9c7df356
VZ
2838 // If this has been processed by an event handler, return 0 now
2839 // (we've handled it).
2840 m_lastKeydownProcessed = HandleKeyDown((WORD) wParam, lParam);
2841 if ( m_lastKeydownProcessed )
2d0a075d 2842 {
08158721 2843 processed = true;
2d0a075d 2844 }
81d66cf3 2845
2b5f62a0 2846 if ( !processed )
42e69d6b 2847 {
2b5f62a0
VZ
2848 switch ( wParam )
2849 {
90e572f1 2850 // we consider these messages "not interesting" to OnChar, so
2b5f62a0
VZ
2851 // just don't do anything more with them
2852 case VK_SHIFT:
2853 case VK_CONTROL:
2854 case VK_MENU:
2855 case VK_CAPITAL:
2856 case VK_NUMLOCK:
2857 case VK_SCROLL:
08158721 2858 processed = true;
2b5f62a0 2859 break;
2bda0e17 2860
2b5f62a0
VZ
2861 // avoid duplicate messages to OnChar for these ASCII keys:
2862 // they will be translated by TranslateMessage() and received
2863 // in WM_CHAR
2864 case VK_ESCAPE:
2865 case VK_SPACE:
2866 case VK_RETURN:
2867 case VK_BACK:
2868 case VK_TAB:
2869 case VK_ADD:
2870 case VK_SUBTRACT:
2871 case VK_MULTIPLY:
2872 case VK_DIVIDE:
3f2174bb
VZ
2873 case VK_NUMPAD0:
2874 case VK_NUMPAD1:
2875 case VK_NUMPAD2:
2876 case VK_NUMPAD3:
2877 case VK_NUMPAD4:
2878 case VK_NUMPAD5:
2879 case VK_NUMPAD6:
2880 case VK_NUMPAD7:
2881 case VK_NUMPAD8:
2882 case VK_NUMPAD9:
2b5f62a0
VZ
2883 case VK_OEM_1:
2884 case VK_OEM_2:
2885 case VK_OEM_3:
2886 case VK_OEM_4:
2887 case VK_OEM_5:
2888 case VK_OEM_6:
2889 case VK_OEM_7:
2890 case VK_OEM_PLUS:
2891 case VK_OEM_COMMA:
2892 case VK_OEM_MINUS:
2893 case VK_OEM_PERIOD:
08158721 2894 // but set processed to false, not true to still pass them
2b5f62a0
VZ
2895 // to the control's default window proc - otherwise
2896 // built-in keyboard handling won't work
08158721 2897 processed = false;
2b5f62a0 2898 break;
2bda0e17 2899
42e69d6b 2900#ifdef VK_APPS
2b5f62a0
VZ
2901 // special case of VK_APPS: treat it the same as right mouse
2902 // click because both usually pop up a context menu
2903 case VK_APPS:
ae177b45 2904 processed = HandleMouseEvent(WM_RBUTTONDOWN, -1, -1, 0);
2b5f62a0 2905 break;
42e69d6b 2906#endif // VK_APPS
2bda0e17 2907
2b5f62a0
VZ
2908 default:
2909 // do generate a CHAR event
2910 processed = HandleChar((WORD)wParam, lParam);
2911 }
42e69d6b 2912 }
2b5f62a0 2913 if (message == WM_SYSKEYDOWN) // Let Windows still handle the SYSKEYs
08158721 2914 processed = false;
42e69d6b 2915 break;
2bda0e17 2916
4004f41e 2917 case WM_SYSKEYUP:
42e69d6b 2918 case WM_KEYUP:
4aff28fc
VZ
2919#ifdef VK_APPS
2920 // special case of VK_APPS: treat it the same as right mouse button
2921 if ( wParam == VK_APPS )
2922 {
ae177b45 2923 processed = HandleMouseEvent(WM_RBUTTONUP, -1, -1, 0);
4aff28fc
VZ
2924 }
2925 else
2926#endif // VK_APPS
2927 {
2928 processed = HandleKeyUp((WORD) wParam, lParam);
2929 }
42e69d6b 2930 break;
debe6624 2931
170cbe33 2932 case WM_SYSCHAR:
42e69d6b 2933 case WM_CHAR: // Always an ASCII character
d9f14e16
RD
2934 if ( m_lastKeydownProcessed )
2935 {
2936 // The key was handled in the EVT_KEY_DOWN and handling
2937 // a key in an EVT_KEY_DOWN handler is meant, by
2938 // design, to prevent EVT_CHARs from happening
08158721
DS
2939 m_lastKeydownProcessed = false;
2940 processed = true;
d9f14e16
RD
2941 }
2942 else
7de5bdf4 2943 {
08158721 2944 processed = HandleChar((WORD)wParam, lParam, true);
7de5bdf4 2945 }
42e69d6b 2946 break;
2bda0e17 2947
5048c832
JS
2948#if wxUSE_HOTKEY
2949 case WM_HOTKEY:
2950 processed = HandleHotKey((WORD)wParam, lParam);
2951 break;
540b6b09 2952#endif // wxUSE_HOTKEY
5048c832 2953
42e69d6b
VZ
2954 case WM_HSCROLL:
2955 case WM_VSCROLL:
a23fd0e1 2956 {
42e69d6b
VZ
2957 WXWORD code, pos;
2958 WXHWND hwnd;
2959 UnpackScroll(wParam, lParam, &code, &pos, &hwnd);
2bda0e17 2960
42e69d6b
VZ
2961 processed = MSWOnScroll(message == WM_HSCROLL ? wxHORIZONTAL
2962 : wxVERTICAL,
2963 code, pos, hwnd);
a23fd0e1 2964 }
42e69d6b 2965 break;
a23fd0e1 2966
42e69d6b 2967 // CTLCOLOR messages are sent by children to query the parent for their
01c500af 2968 // colors
04ef50df 2969#ifndef __WXMICROWIN__
42e69d6b
VZ
2970 case WM_CTLCOLORMSGBOX:
2971 case WM_CTLCOLOREDIT:
2972 case WM_CTLCOLORLISTBOX:
2973 case WM_CTLCOLORBTN:
2974 case WM_CTLCOLORDLG:
2975 case WM_CTLCOLORSCROLLBAR:
2976 case WM_CTLCOLORSTATIC:
a23fd0e1 2977 {
42e69d6b
VZ
2978 WXHDC hdc;
2979 WXHWND hwnd;
01c500af 2980 UnpackCtlColor(wParam, lParam, &hdc, &hwnd);
42e69d6b 2981
48fa6bd3 2982 processed = HandleCtlColor(&rc.hBrush, (WXHDC)hdc, (WXHWND)hwnd);
a23fd0e1 2983 }
42e69d6b 2984 break;
cd4453e5 2985#endif // !__WXMICROWIN__
debe6624 2986
42e69d6b 2987 case WM_SYSCOLORCHANGE:
90c1530a 2988 // the return value for this message is ignored
42e69d6b
VZ
2989 processed = HandleSysColorChange();
2990 break;
2bda0e17 2991
7f0586ef 2992#if !defined(__WXWINCE__)
574c939e
KB
2993 case WM_DISPLAYCHANGE:
2994 processed = HandleDisplayChange();
2995 break;
7f0586ef 2996#endif
574c939e 2997
42e69d6b
VZ
2998 case WM_PALETTECHANGED:
2999 processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
3000 break;
2bda0e17 3001
a5e84126
JS
3002 case WM_CAPTURECHANGED:
3003 processed = HandleCaptureChanged((WXHWND) (HWND) lParam);
3004 break;
3005
3c96418b
JG
3006 case WM_SETTINGCHANGE:
3007 processed = HandleSettingChange(wParam, lParam);
3008 break;
3009
42e69d6b
VZ
3010 case WM_QUERYNEWPALETTE:
3011 processed = HandleQueryNewPalette();
3012 break;
2bda0e17 3013
42e69d6b
VZ
3014 case WM_ERASEBKGND:
3015 processed = HandleEraseBkgnd((WXHDC)(HDC)wParam);
3016 if ( processed )
3017 {
3018 // we processed the message, i.e. erased the background
3019 rc.result = TRUE;
3020 }
3021 break;
debe6624 3022
7f0586ef 3023#if !defined(__WXWINCE__)
42e69d6b
VZ
3024 case WM_DROPFILES:
3025 processed = HandleDropFiles(wParam);
3026 break;
7f0586ef 3027#endif
2bda0e17 3028
42e69d6b
VZ
3029 case WM_INITDIALOG:
3030 processed = HandleInitDialog((WXHWND)(HWND)wParam);
a23fd0e1 3031
42e69d6b
VZ
3032 if ( processed )
3033 {
3034 // we never set focus from here
3035 rc.result = FALSE;
3036 }
3037 break;
a23fd0e1 3038
7f0586ef 3039#if !defined(__WXWINCE__)
42e69d6b
VZ
3040 case WM_QUERYENDSESSION:
3041 processed = HandleQueryEndSession(lParam, &rc.allow);
3042 break;
2bda0e17 3043
42e69d6b
VZ
3044 case WM_ENDSESSION:
3045 processed = HandleEndSession(wParam != 0, lParam);
3046 break;
2bda0e17 3047
42e69d6b 3048 case WM_GETMINMAXINFO:
25889d3c 3049 processed = HandleGetMinMaxInfo((MINMAXINFO*)lParam);
42e69d6b 3050 break;
7f0586ef 3051#endif
debe6624 3052
42e69d6b
VZ
3053 case WM_SETCURSOR:
3054 processed = HandleSetCursor((WXHWND)(HWND)wParam,
3055 LOWORD(lParam), // hit test
3056 HIWORD(lParam)); // mouse msg
3057
3058 if ( processed )
3059 {
3060 // returning TRUE stops the DefWindowProc() from further
3061 // processing this message - exactly what we need because we've
3062 // just set the cursor.
3063 rc.result = TRUE;
3064 }
3065 break;
4cdc2c13 3066
ed5317e5
JS
3067#if wxUSE_ACCESSIBILITY
3068 case WM_GETOBJECT:
3069 {
3070 //WPARAM dwFlags = (WPARAM) (DWORD) wParam;
3071 LPARAM dwObjId = (LPARAM) (DWORD) lParam;
3072
66b9ec3d 3073 if (dwObjId == (LPARAM)OBJID_CLIENT && GetOrCreateAccessible())
ed5317e5
JS
3074 {
3075 return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible());
3076 }
3077 break;
3078 }
3079#endif
3080
e39af974 3081#if defined(WM_HELP)
b96340e6 3082 case WM_HELP:
b96340e6 3083 {
a9c11b71
VZ
3084 // by default, WM_HELP is propagated by DefWindowProc() upwards
3085 // to the window parent but as we do it ourselves already
3086 // (wxHelpEvent is derived from wxCommandEvent), we don't want
3087 // to get the other events if we process this message at all
3088 processed = true;
3089
3090 // WM_HELP doesn't use lParam under CE
7f0586ef 3091#ifndef __WXWINCE__
4cdc2c13 3092 HELPINFO* info = (HELPINFO*) lParam;
a9c11b71 3093 if ( info->iContextType == HELPINFO_WINDOW )
b96340e6 3094 {
a9c11b71
VZ
3095#endif // !__WXWINCE__
3096 wxHelpEvent helpEvent
3097 (
3098 wxEVT_HELP,
3099 GetId(),
7f0586ef 3100#ifdef __WXWINCE__
2d4ec362 3101 wxGetMousePosition() // what else?
7f0586ef 3102#else
a9c11b71 3103 wxPoint(info->MousePos.x, info->MousePos.y)
7f0586ef 3104#endif
a9c11b71 3105 );
b96340e6 3106
a9c11b71
VZ
3107 helpEvent.SetEventObject(this);
3108 GetEventHandler()->ProcessEvent(helpEvent);
7f0586ef 3109#ifndef __WXWINCE__
b96340e6 3110 }
a9c11b71 3111 else if ( info->iContextType == HELPINFO_MENUITEM )
4cdc2c13
VZ
3112 {
3113 wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
3114 helpEvent.SetEventObject(this);
a9c11b71 3115 GetEventHandler()->ProcessEvent(helpEvent);
69231000 3116
4cdc2c13 3117 }
a9c11b71
VZ
3118 else // unknown help event?
3119 {
3120 processed = false;
3121 }
3122#endif // !__WXWINCE__
b96340e6 3123 }
b96340e6 3124 break;
a9c11b71 3125#endif // WM_HELP
4cdc2c13 3126
7f0586ef 3127#if !defined(__WXWINCE__)
69231000 3128 case WM_CONTEXTMENU:
4cdc2c13
VZ
3129 {
3130 // we don't convert from screen to client coordinates as
3131 // the event may be handled by a parent window
3132 wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
3133
3134 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
2d1715aa
VZ
3135
3136 // we could have got an event from our child, reflect it back
3137 // to it if this is the case
d85c53a5 3138 wxWindowMSW *win = NULL;
c140b7e7 3139 if ( (WXHWND)wParam != m_hWnd )
2d1715aa
VZ
3140 {
3141 win = FindItemByHWND((WXHWND)wParam);
3142 }
3143
3144 if ( !win )
3145 win = this;
3146
3147 evtCtx.SetEventObject(win);
3148 processed = win->GetEventHandler()->ProcessEvent(evtCtx);
4cdc2c13 3149 }
69231000 3150 break;
7f0586ef 3151#endif
b74cce40
VZ
3152
3153 case WM_MENUCHAR:
3154 // we're only interested in our own menus, not MF_SYSMENU
3155 if ( HIWORD(wParam) == MF_POPUP )
3156 {
3157 // handle menu chars for ownerdrawn menu items
3158 int i = HandleMenuChar(toupper(LOWORD(wParam)), lParam);
3159 if ( i != wxNOT_FOUND )
3160 {
3161 rc.result = MAKELRESULT(i, MNC_EXECUTE);
08158721 3162 processed = true;
b74cce40
VZ
3163 }
3164 }
3165 break;
355debca 3166
dbc74bcc 3167#ifndef __WXWINCE__
355debca
VZ
3168 case WM_POWERBROADCAST:
3169 {
3170 bool vetoed;
3171 processed = HandlePower(wParam, lParam, &vetoed);
3172 rc.result = processed && vetoed ? BROADCAST_QUERY_DENY : TRUE;
3173 }
3174 break;
dbc74bcc 3175#endif // __WXWINCE__
a23fd0e1 3176 }
2d0a075d 3177
42e69d6b 3178 if ( !processed )
2d0a075d 3179 {
42e69d6b 3180#ifdef __WXDEBUG__
223d09f6 3181 wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
42e69d6b
VZ
3182 wxGetMessageName(message));
3183#endif // __WXDEBUG__
3184 rc.result = MSWDefWindowProc(message, wParam, lParam);
a23fd0e1 3185 }
2bda0e17 3186
42e69d6b 3187 return rc.result;
2bda0e17
KB
3188}
3189
b225f659
VZ
3190// ----------------------------------------------------------------------------
3191// wxWindow <-> HWND map
3192// ----------------------------------------------------------------------------
2bda0e17 3193
1bffa913 3194wxWinHashTable *wxWinHandleHash = NULL;
b225f659 3195
42e69d6b 3196wxWindow *wxFindWinFromHandle(WXHWND hWnd)
4ce81a75 3197{
40ad3426 3198 return (wxWindow*)wxWinHandleHash->Get((long)hWnd);
42e69d6b 3199}
4ce81a75 3200
1e6feb95 3201void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win)
42e69d6b
VZ
3202{
3203 // adding NULL hWnd is (first) surely a result of an error and
3204 // (secondly) breaks menu command processing
3205 wxCHECK_RET( hWnd != (HWND)NULL,
223d09f6 3206 wxT("attempt to add a NULL hWnd to window list ignored") );
4ce81a75 3207
c7527e3f 3208 wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd);
b225f659 3209#ifdef __WXDEBUG__
c7527e3f
JS
3210 if ( oldWin && (oldWin != win) )
3211 {
b225f659 3212 wxLogDebug(wxT("HWND %X already associated with another window (%s)"),
9b601c24 3213 (int) hWnd, win->GetClassInfo()->GetClassName());
c7527e3f 3214 }
b225f659
VZ
3215 else
3216#endif // __WXDEBUG__
3217 if (!oldWin)
c7527e3f 3218 {
d2d14464 3219 wxWinHandleHash->Put((long)hWnd, (wxWindow *)win);
c7527e3f 3220 }
42e69d6b 3221}
4ce81a75 3222
1e6feb95 3223void wxRemoveHandleAssociation(wxWindowMSW *win)
42e69d6b 3224{
1bffa913 3225 wxWinHandleHash->Delete((long)win->GetHWND());
4ce81a75
JS
3226}
3227
b225f659
VZ
3228// ----------------------------------------------------------------------------
3229// various MSW speciic class dependent functions
3230// ----------------------------------------------------------------------------
3231
42e69d6b
VZ
3232// Default destroyer - override if you destroy it in some other way
3233// (e.g. with MDI child windows)
1e6feb95 3234void wxWindowMSW::MSWDestroyWindow()
4ce81a75 3235{
42e69d6b 3236}
4ce81a75 3237
b225f659
VZ
3238bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos,
3239 const wxSize& size,
3240 int& x, int& y,
3241 int& w, int& h) const
2bda0e17 3242{
9cb57df4 3243 // yes, those are just some arbitrary hardcoded numbers
2a77c8c4 3244 static const int DEFAULT_Y = 200;
2a77c8c4 3245
08158721 3246 bool nonDefault = false;
c085e333 3247
422d0ff0 3248 if ( pos.x == wxDefaultCoord )
b225f659 3249 {
9cb57df4
VZ
3250 // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we
3251 // can just as well set it to CW_USEDEFAULT as well
b225f659
VZ
3252 x =
3253 y = CW_USEDEFAULT;
3254 }
3255 else
a23fd0e1 3256 {
2a77c8c4
VZ
3257 // OTOH, if x is not set to CW_USEDEFAULT, y shouldn't be set to it
3258 // neither because it is not handled as a special value by Windows then
3259 // and so we have to choose some default value for it
b225f659 3260 x = pos.x;
422d0ff0 3261 y = pos.y == wxDefaultCoord ? DEFAULT_Y : pos.y;
c085e333 3262
08158721 3263 nonDefault = true;
42e69d6b 3264 }
2bda0e17 3265
b889a3a2
VZ
3266 /*
3267 NB: there used to be some code here which set the initial size of the
3268 window to the client size of the parent if no explicit size was
77ffb593 3269 specified. This was wrong because wxWidgets programs often assume
b889a3a2
VZ
3270 that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke
3271 it. To see why, you should understand that Windows sends WM_SIZE from
3272 inside ::CreateWindow() anyhow. However, ::CreateWindow() is called
3273 from some base class ctor and so this WM_SIZE is not processed in the
3274 real class' OnSize() (because it's not fully constructed yet and the
3275 event goes to some base class OnSize() instead). So the WM_SIZE we
3276 rely on is the one sent when the parent frame resizes its children
3277 but here is the problem: if the child already has just the right
77ffb593 3278 size, nothing will happen as both wxWidgets and Windows check for
b889a3a2
VZ
3279 this and ignore any attempts to change the window size to the size it
3280 already has - so no WM_SIZE would be sent.
3281 */
b225f659 3282
35bbb0c6 3283
426936d1
RD
3284 // we don't use CW_USEDEFAULT here for several reasons:
3285 //
3286 // 1. it results in huge frames on modern screens (1000*800 is not
3287 // uncommon on my 1280*1024 screen) which is way too big for a half
77ffb593 3288 // empty frame of most of wxWidgets samples for example)
426936d1
RD
3289 //
3290 // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which
3291 // the default is for whatever reason 8*8 which breaks client <->
3292 // window size calculations (it would be nice if it didn't, but it
3293 // does and the simplest way to fix it seemed to change the broken
3294 // default size anyhow)
3295 //
3296 // 3. there is just no advantage in doing it: with x and y it is
3297 // possible that [future versions of] Windows position the new top
3298 // level window in some smart way which we can't do, but we can
3299 // guess a reasonably good size for a new window just as well
3300 // ourselves
960b193e 3301
3a3c8603
DS
3302 // However, on PocketPC devices, we must use the default
3303 // size if possible.
960b193e 3304#ifdef _WIN32_WCE
422d0ff0 3305 if (size.x == wxDefaultCoord)
3a3c8603
DS
3306 w = CW_USEDEFAULT;
3307 else
3308 w = size.x;
422d0ff0 3309 if (size.y == wxDefaultCoord)
3a3c8603
DS
3310 h = CW_USEDEFAULT;
3311 else
3312 h = size.y;
960b193e 3313#else
422d0ff0 3314 if ( size.x == wxDefaultCoord || size.y == wxDefaultCoord)
426936d1 3315 {
08158721 3316 nonDefault = true;
8614c467 3317 }
426936d1
RD
3318 w = WidthDefault(size.x);
3319 h = HeightDefault(size.y);
960b193e 3320#endif
8614c467 3321
4e9d23cd
VZ
3322 AdjustForParentClientOrigin(x, y);
3323
b225f659
VZ
3324 return nonDefault;
3325}
3326
9dfef5ac
VZ
3327WXHWND wxWindowMSW::MSWGetParent() const
3328{
d285d708 3329 return m_parent ? m_parent->GetHWND() : WXHWND(NULL);
9dfef5ac
VZ
3330}
3331
b225f659
VZ
3332bool wxWindowMSW::MSWCreate(const wxChar *wclass,
3333 const wxChar *title,
3334 const wxPoint& pos,
3335 const wxSize& size,
3336 WXDWORD style,
3337 WXDWORD extendedStyle)
3338{
3339 // choose the position/size for the new window
3340 int x, y, w, h;
3341 (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
3342
b225f659
VZ
3343 // controlId is menu handle for the top level windows, so set it to 0
3344 // unless we're creating a child window
f586fde3 3345 int controlId = style & WS_CHILD ? GetId() : 0;
2bda0e17 3346
b225f659
VZ
3347 // for each class "Foo" we have we also have "FooNR" ("no repaint") class
3348 // which is the same but without CS_[HV]REDRAW class styles so using it
3349 // ensures that the window is not fully repainted on each resize
3350 wxString className(wclass);
e441e1f4 3351 if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
b225f659
VZ
3352 {
3353 className += wxT("NR");
a23fd0e1 3354 }
c085e333 3355
b225f659
VZ
3356 // do create the window
3357 wxWindowCreationHook hook(this);
b3daa5a3 3358
5e67eb97
VZ
3359 m_hWnd = (WXHWND)::CreateWindowEx
3360 (
3361 extendedStyle,
3362 className,
c9f78968 3363 title ? title : (const wxChar*)m_windowName.c_str(),
5e67eb97
VZ
3364 style,
3365 x, y, w, h,
3366 (HWND)MSWGetParent(),
3367 (HMENU)controlId,
3368 wxGetInstance(),
3369 NULL // no extra data
3370 );
b225f659
VZ
3371
3372 if ( !m_hWnd )
c7527e3f 3373 {
5e67eb97 3374 wxLogSysError(_("Can't create window of class %s"), className.c_str());
b225f659 3375
08158721 3376 return false;
c7527e3f 3377 }
b3daa5a3 3378
b225f659 3379 SubclassWin(m_hWnd);
c085e333 3380
08158721 3381 return true;
2bda0e17
KB
3382}
3383
42e69d6b
VZ
3384// ===========================================================================
3385// MSW message handlers
3386// ===========================================================================
3387
3388// ---------------------------------------------------------------------------
3389// WM_NOTIFY
3390// ---------------------------------------------------------------------------
3391
1e6feb95 3392bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
2bda0e17 3393{
04ef50df 3394#ifndef __WXMICROWIN__
42e69d6b
VZ
3395 LPNMHDR hdr = (LPNMHDR)lParam;
3396 HWND hWnd = hdr->hwndFrom;
3397 wxWindow *win = wxFindWinFromHandle((WXHWND)hWnd);
3398
2b15b970 3399 // if the control is one of our windows, let it handle the message itself
42e69d6b 3400 if ( win )
564b2609 3401 {
42e69d6b 3402 return win->MSWOnNotify(idCtrl, lParam, result);
564b2609 3403 }
2bda0e17 3404
2b15b970
VZ
3405 // VZ: why did we do it? normally this is unnecessary and, besides, it
3406 // breaks the message processing for the toolbars because the tooltip
3407 // notifications were being forwarded to the toolbar child controls
3408 // (if it had any) before being passed to the toolbar itself, so in my
3409 // example the tooltip for the combobox was always shown instead of the
3410 // correct button tooltips
3411#if 0
42e69d6b 3412 // try all our children
222ed1d6 3413 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
42e69d6b 3414 while ( node )
564b2609 3415 {
42e69d6b
VZ
3416 wxWindow *child = node->GetData();
3417 if ( child->MSWOnNotify(idCtrl, lParam, result) )
3418 {
08158721 3419 return true;
42e69d6b 3420 }
2d0a075d 3421
42e69d6b
VZ
3422 node = node->GetNext();
3423 }
2b15b970 3424#endif // 0
2d0a075d 3425
2b15b970 3426 // by default, handle it ourselves
42e69d6b 3427 return MSWOnNotify(idCtrl, lParam, result);
cd4453e5 3428#else // __WXMICROWIN__
08158721 3429 return false;
04ef50df 3430#endif
42e69d6b 3431}
2d0a075d 3432
bd9cd534
VZ
3433#if wxUSE_TOOLTIPS
3434
3435bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
3436 WXLPARAM lParam,
3437 const wxString& ttip)
3438{
3439 // I don't know why it happens, but the versions of comctl32.dll starting
3440 // from 4.70 sometimes send TTN_NEEDTEXTW even to ANSI programs (normally,
3441 // this message is supposed to be sent to Unicode programs only) -- hence
3442 // we need to handle it as well, otherwise no tooltips will be shown in
3443 // this case
7f0586ef 3444#ifndef __WXWINCE__
118208ac
VZ
3445 if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW)
3446 || ttip.empty() )
bd9cd534
VZ
3447 {
3448 // not a tooltip message or no tooltip to show anyhow
08158721 3449 return false;
bd9cd534 3450 }
7f0586ef 3451#endif
bd9cd534
VZ
3452
3453 LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
3454
118208ac
VZ
3455 // We don't want to use the szText buffer because it has a limit of 80
3456 // bytes and this is not enough, especially for Unicode build where it
3457 // limits the tooltip string length to only 40 characters
3458 //
3459 // The best would be, of course, to not impose any length limitations at
3460 // all but then the buffer would have to be dynamic and someone would have
3461 // to free it and we don't have the tooltip owner object here any more, so
3462 // for now use our own static buffer with a higher fixed max length.
3463 //
3464 // Note that using a static buffer should not be a problem as only a single
3465 // tooltip can be shown at the same time anyhow.
2b5f62a0 3466#if !wxUSE_UNICODE
118208ac 3467 if ( code == (WXUINT) TTN_NEEDTEXTW )
bd9cd534 3468 {
118208ac
VZ
3469 // We need to convert tooltip from multi byte to Unicode on the fly.
3470 static wchar_t buf[513];
25c46fda 3471
118208ac
VZ
3472 // Truncate tooltip length if needed as otherwise we might not have
3473 // enough space for it in the buffer and MultiByteToWideChar() would
3474 // return an error
fec9cc08 3475 size_t tipLength = wxMin(ttip.length(), WXSIZEOF(buf) - 1);
7afebc8c
JS
3476
3477 // Convert to WideChar without adding the NULL character. The NULL
25c46fda 3478 // character is added afterwards (this is more efficient).
118208ac
VZ
3479 int len = ::MultiByteToWideChar
3480 (
3481 CP_ACP,
3482 0, // no flags
3483 ttip,
3484 tipLength,
3485 buf,
3486 WXSIZEOF(buf) - 1
3487 );
3488
3489 if ( !len )
3490 {
3491 wxLogLastError(_T("MultiByteToWideChar()"));
3492 }
7afebc8c 3493
118208ac
VZ
3494 buf[len] = L'\0';
3495 ttText->lpszText = (LPSTR) buf;
3496 }
3497 else // TTN_NEEDTEXTA
3498#endif // !wxUSE_UNICODE
3499 {
3500 // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or
3501 // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
3502 // to copy the string we have into the buffer
3503 static wxChar buf[513];
3504 wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1);
3505 buf[WXSIZEOF(buf) - 1] = _T('\0');
3506 ttText->lpszText = buf;
bd9cd534
VZ
3507 }
3508
08158721 3509 return true;
bd9cd534
VZ
3510}
3511
3512#endif // wxUSE_TOOLTIPS
3513
1e6feb95 3514bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl),
bd9cd534
VZ
3515 WXLPARAM lParam,
3516 WXLPARAM* WXUNUSED(result))
42e69d6b
VZ
3517{
3518#if wxUSE_TOOLTIPS
bd9cd534 3519 if ( m_tooltip )
42e69d6b 3520 {
bd9cd534
VZ
3521 NMHDR* hdr = (NMHDR *)lParam;
3522 if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip()))
3523 {
3524 // processed
08158721 3525 return true;
bd9cd534 3526 }
42e69d6b 3527 }
f5dd1cf1
WS
3528#else
3529 wxUnusedVar(lParam);
42e69d6b
VZ
3530#endif // wxUSE_TOOLTIPS
3531
08158721 3532 return false;
42e69d6b 3533}
2b15b970 3534
42e69d6b
VZ
3535// ---------------------------------------------------------------------------
3536// end session messages
3537// ---------------------------------------------------------------------------
2d0a075d 3538
1e6feb95 3539bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
42e69d6b 3540{
040e5f77 3541#ifdef ENDSESSION_LOGOFF
abb74e0f 3542 wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY);
42e69d6b 3543 event.SetEventObject(wxTheApp);
08158721 3544 event.SetCanVeto(true);
a17e237f 3545 event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF);
2d0a075d 3546
42e69d6b
VZ
3547 bool rc = wxTheApp->ProcessEvent(event);
3548
3549 if ( rc )
3550 {
3551 // we may end only if the app didn't veto session closing (double
3552 // negation...)
3553 *mayEnd = !event.GetVeto();
2d0a075d
JS
3554 }
3555
42e69d6b 3556 return rc;
7f0586ef 3557#else
040e5f77
VZ
3558 wxUnusedVar(logOff);
3559 wxUnusedVar(mayEnd);
08158721 3560 return false;
7f0586ef 3561#endif
2bda0e17
KB
3562}
3563
1e6feb95 3564bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
2bda0e17 3565{
040e5f77 3566#ifdef ENDSESSION_LOGOFF
42e69d6b
VZ
3567 // do nothing if the session isn't ending
3568 if ( !endSession )
08158721 3569 return false;
a23fd0e1 3570
519dc37f
VZ
3571 // only send once
3572 if ( (this != wxTheApp->GetTopWindow()) )
08158721 3573 return false;
519dc37f 3574
abb74e0f 3575 wxCloseEvent event(wxEVT_END_SESSION, wxID_ANY);
42e69d6b 3576 event.SetEventObject(wxTheApp);
08158721 3577 event.SetCanVeto(false);
a17e237f 3578 event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
519dc37f
VZ
3579
3580 return wxTheApp->ProcessEvent(event);
7f0586ef 3581#else
040e5f77
VZ
3582 wxUnusedVar(endSession);
3583 wxUnusedVar(logOff);
08158721 3584 return false;
7f0586ef 3585#endif
2bda0e17
KB
3586}
3587
42e69d6b
VZ
3588// ---------------------------------------------------------------------------
3589// window creation/destruction
3590// ---------------------------------------------------------------------------
3591
0c0d1521
WS
3592bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED_IN_WINCE(cs),
3593 bool *mayCreate)
61179e28 3594{
ee471817
VZ
3595 // VZ: why is this commented out for WinCE? If it doesn't support
3596 // WS_EX_CONTROLPARENT at all it should be somehow handled globally,
3597 // not with multiple #ifdef's!
7f0586ef 3598#ifndef __WXWINCE__
61179e28 3599 if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
ee471817
VZ
3600 EnsureParentHasControlParentStyle(GetParent());
3601#endif // !__WXWINCE__
61179e28 3602
08158721 3603 *mayCreate = true;
42e69d6b 3604
08158721 3605 return true;
2bda0e17
KB
3606}
3607
1e6feb95 3608bool wxWindowMSW::HandleDestroy()
2bda0e17 3609{
7de59551 3610 SendDestroyEvent();
42e69d6b
VZ
3611
3612 // delete our drop target if we've got one
3613#if wxUSE_DRAG_AND_DROP
3614 if ( m_dropTarget != NULL )
2d0a075d 3615 {
42e69d6b
VZ
3616 m_dropTarget->Revoke(m_hWnd);
3617
3618 delete m_dropTarget;
3619 m_dropTarget = NULL;
2d0a075d 3620 }
42e69d6b 3621#endif // wxUSE_DRAG_AND_DROP
2bda0e17 3622
42e69d6b 3623 // WM_DESTROY handled
08158721 3624 return true;
2bda0e17
KB
3625}
3626
42e69d6b
VZ
3627// ---------------------------------------------------------------------------
3628// activation/focus
3629// ---------------------------------------------------------------------------
3630
1e6feb95 3631bool wxWindowMSW::HandleActivate(int state,
42e69d6b
VZ
3632 bool WXUNUSED(minimized),
3633 WXHWND WXUNUSED(activate))
2bda0e17 3634{
42e69d6b
VZ
3635 wxActivateEvent event(wxEVT_ACTIVATE,
3636 (state == WA_ACTIVE) || (state == WA_CLICKACTIVE),
3637 m_windowId);
3638 event.SetEventObject(this);
3639
3640 return GetEventHandler()->ProcessEvent(event);
3641}
3642
1e6feb95 3643bool wxWindowMSW::HandleSetFocus(WXHWND hwnd)
42e69d6b 3644{
c7aee865
RD
3645 // Strangly enough, some controls get set focus events when they are being
3646 // deleted, even if they already had focus before.
3647 if ( m_isBeingDeleted )
3648 {
3649 return false;
3650 }
35bbb0c6 3651
456bc6d9
VZ
3652 // notify the parent keeping track of focus for the kbd navigation
3653 // purposes that we got it
e72aa7f5 3654 wxChildFocusEvent eventFocus((wxWindow *)this);
456bc6d9
VZ
3655 (void)GetEventHandler()->ProcessEvent(eventFocus);
3656
789295bf 3657#if wxUSE_CARET
42e69d6b 3658 // Deal with caret
789295bf 3659 if ( m_caret )
2d0a075d 3660 {
789295bf 3661 m_caret->OnSetFocus();
2bda0e17 3662 }
789295bf 3663#endif // wxUSE_CARET
42e69d6b 3664
ab93a576
RD
3665#if wxUSE_TEXTCTRL
3666 // If it's a wxTextCtrl don't send the event as it will be done
456bc6d9
VZ
3667 // after the control gets to process it from EN_FOCUS handler
3668 if ( wxDynamicCastThis(wxTextCtrl) )
ab93a576 3669 {
08158721 3670 return false;
ab93a576 3671 }
456bc6d9 3672#endif // wxUSE_TEXTCTRL
ab93a576 3673
42e69d6b
VZ
3674 wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
3675 event.SetEventObject(this);
3676
1e6feb95
VZ
3677 // wxFindWinFromHandle() may return NULL, it is ok
3678 event.SetWindow(wxFindWinFromHandle(hwnd));
3679
42e69d6b 3680 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3681}
3682
1e6feb95 3683bool wxWindowMSW::HandleKillFocus(WXHWND hwnd)
2bda0e17 3684{
789295bf 3685#if wxUSE_CARET
42e69d6b 3686 // Deal with caret
789295bf 3687 if ( m_caret )
2d0a075d 3688 {
789295bf 3689 m_caret->OnKillFocus();
2bda0e17 3690 }
789295bf 3691#endif // wxUSE_CARET
42e69d6b 3692
ab93a576
RD
3693#if wxUSE_TEXTCTRL
3694 // If it's a wxTextCtrl don't send the event as it will be done
3695 // after the control gets to process it.
3696 wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl);
3697 if ( ctrl )
3698 {
08158721 3699 return false;
ab93a576
RD
3700 }
3701#endif
3702
2913e597
RD
3703 // Don't send the event when in the process of being deleted. This can
3704 // only cause problems if the event handler tries to access the object.
3705 if ( m_isBeingDeleted )
3706 {
08158721 3707 return false;
2913e597
RD
3708 }
3709
42e69d6b
VZ
3710 wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
3711 event.SetEventObject(this);
3712
1e6feb95
VZ
3713 // wxFindWinFromHandle() may return NULL, it is ok
3714 event.SetWindow(wxFindWinFromHandle(hwnd));
3715
42e69d6b 3716 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3717}
3718
faa49bfd
WS
3719// ---------------------------------------------------------------------------
3720// labels
3721// ---------------------------------------------------------------------------
3722
3723void wxWindowMSW::SetLabel( const wxString& label)
3724{
3725 SetWindowText(GetHwnd(), label.c_str());
3726}
3727
3728wxString wxWindowMSW::GetLabel() const
3729{
3730 return wxGetWindowText(GetHWND());
3731}
3732
42e69d6b
VZ
3733// ---------------------------------------------------------------------------
3734// miscellaneous
3735// ---------------------------------------------------------------------------
3736
1e6feb95 3737bool wxWindowMSW::HandleShow(bool show, int WXUNUSED(status))
2bda0e17 3738{
42e69d6b 3739 wxShowEvent event(GetId(), show);
687706f5 3740 event.SetEventObject(this);
42e69d6b
VZ
3741
3742 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3743}
3744
1e6feb95 3745bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus))
2bda0e17 3746{
42e69d6b 3747 wxInitDialogEvent event(GetId());
687706f5 3748 event.SetEventObject(this);
42e69d6b
VZ
3749
3750 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
3751}
3752
1e6feb95 3753bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
2bda0e17 3754{
7f0586ef 3755#if defined (__WXMICROWIN__) || defined(__WXWINCE__)
35bbb0c6 3756 wxUnusedVar(wParam);
08158721 3757 return false;
4ce1efe1 3758#else // __WXMICROWIN__
42e69d6b 3759 HDROP hFilesInfo = (HDROP) wParam;
42e69d6b
VZ
3760
3761 // Get the total number of files dropped
c3c39620 3762 UINT gwFilesDropped = ::DragQueryFile
f6bcfd97
BP
3763 (
3764 (HDROP)hFilesInfo,
3765 (UINT)-1,
3766 (LPTSTR)0,
3767 (UINT)0
3768 );
42e69d6b
VZ
3769
3770 wxString *files = new wxString[gwFilesDropped];
c3c39620 3771 for ( UINT wIndex = 0; wIndex < gwFilesDropped; wIndex++ )
2d0a075d 3772 {
c3c39620
VZ
3773 // first get the needed buffer length (+1 for terminating NUL)
3774 size_t len = ::DragQueryFile(hFilesInfo, wIndex, NULL, 0) + 1;
3775
3776 // and now get the file name
3777 ::DragQueryFile(hFilesInfo, wIndex,
de564874 3778 wxStringBuffer(files[wIndex], len), len);
2d0a075d 3779 }
42e69d6b 3780 DragFinish (hFilesInfo);
2bda0e17 3781
42e69d6b 3782 wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
687706f5 3783 event.SetEventObject(this);
c3c39620
VZ
3784
3785 POINT dropPoint;
3786 DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint);
b3dc8a3e
VZ
3787 event.m_pos.x = dropPoint.x;
3788 event.m_pos.y = dropPoint.y;
42e69d6b 3789
c3c39620 3790 return GetEventHandler()->ProcessEvent(event);
04ef50df 3791#endif
2bda0e17
KB
3792}
3793
cc972ac6 3794
1e6feb95
VZ
3795bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
3796 short nHitTest,
3797 int WXUNUSED(mouseMsg))
2bda0e17 3798{
04ef50df 3799#ifndef __WXMICROWIN__
bfbd6dc1 3800 // the logic is as follows:
43b5058d
VZ
3801 // -1. don't set cursor for non client area, including but not limited to
3802 // the title bar, scrollbars, &c
3803 // 0. allow the user to override default behaviour by using EVT_SET_CURSOR
bfbd6dc1
VZ
3804 // 1. if we have the cursor set it unless wxIsBusy()
3805 // 2. if we're a top level window, set some cursor anyhow
3806 // 3. if wxIsBusy(), set the busy cursor, otherwise the global one
42e69d6b 3807
43b5058d
VZ
3808 if ( nHitTest != HTCLIENT )
3809 {
08158721 3810 return false;
43b5058d
VZ
3811 }
3812
bfbd6dc1 3813 HCURSOR hcursor = 0;
43b5058d
VZ
3814
3815 // first ask the user code - it may wish to set the cursor in some very
3816 // specific way (for example, depending on the current position)
3817 POINT pt;
f2325516 3818#ifdef __WXWINCE__
7d30268c 3819 if ( !::GetCursorPosWinCE(&pt))
f2325516 3820#else
43b5058d 3821 if ( !::GetCursorPos(&pt) )
3fca879c 3822#endif
43b5058d 3823 {
f6bcfd97 3824 wxLogLastError(wxT("GetCursorPos"));
43b5058d
VZ
3825 }
3826
3827 int x = pt.x,
3828 y = pt.y;
3829 ScreenToClient(&x, &y);
3830 wxSetCursorEvent event(x, y);
3831
3832 bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event);
3833 if ( processedEvtSetCursor && event.HasCursor() )
bfbd6dc1 3834 {
43b5058d 3835 hcursor = GetHcursorOf(event.GetCursor());
bfbd6dc1 3836 }
42e69d6b 3837
43b5058d 3838 if ( !hcursor )
bfbd6dc1 3839 {
43b5058d
VZ
3840 bool isBusy = wxIsBusy();
3841
3842 // the test for processedEvtSetCursor is here to prevent using m_cursor
3843 // if the user code caught EVT_SET_CURSOR() and returned nothing from
3844 // it - this is a way to say that our cursor shouldn't be used for this
3845 // point
3846 if ( !processedEvtSetCursor && m_cursor.Ok() )
bfbd6dc1 3847 {
43b5058d 3848 hcursor = GetHcursorOf(m_cursor);
bfbd6dc1 3849 }
43b5058d
VZ
3850
3851 if ( !GetParent() )
bfbd6dc1 3852 {
43b5058d 3853 if ( isBusy )
42e69d6b 3854 {
43b5058d
VZ
3855 hcursor = wxGetCurrentBusyCursor();
3856 }
3857 else if ( !hcursor )
3858 {
3859 const wxCursor *cursor = wxGetGlobalCursor();
3860 if ( cursor && cursor->Ok() )
3861 {
3862 hcursor = GetHcursorOf(*cursor);
3863 }
42e69d6b
VZ
3864 }
3865 }
3866 }
3867
bfbd6dc1
VZ
3868 if ( hcursor )
3869 {
2b5f62a0
VZ
3870// wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor);
3871
bfbd6dc1
VZ
3872 ::SetCursor(hcursor);
3873
3874 // cursor set, stop here
08158721 3875 return true;
bfbd6dc1 3876 }
cd4453e5
VZ
3877#endif // __WXMICROWIN__
3878
3ca6a5f0 3879 // pass up the window chain
08158721 3880 return false;
2bda0e17
KB
3881}
3882
dbc74bcc 3883bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
355debca 3884 WXLPARAM WXUNUSED(lParam),
dbc74bcc 3885 bool *WXUNUSED_IN_WINCE(vetoed))
355debca 3886{
dbc74bcc
WS
3887#ifdef __WXWINCE__
3888 // FIXME
3889 return false;
3890#else
355debca
VZ
3891 wxEventType evtType;
3892 switch ( wParam )
3893 {
3894 case PBT_APMQUERYSUSPEND:
3895 evtType = wxEVT_POWER_SUSPENDING;
3896 break;
3897
3898 case PBT_APMQUERYSUSPENDFAILED:
3899 evtType = wxEVT_POWER_SUSPEND_CANCEL;
3900 break;
3901
3902 case PBT_APMSUSPEND:
3903 evtType = wxEVT_POWER_SUSPENDED;
3904 break;
3905
3906 case PBT_APMRESUMESUSPEND:
d4cd85a0
VZ
3907#ifdef PBT_APMRESUMEAUTOMATIC
3908 case PBT_APMRESUMEAUTOMATIC:
3909#endif
355debca
VZ
3910 evtType = wxEVT_POWER_RESUME;
3911 break;
3912
3913 default:
3914 wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam);
3915 // fall through
3916
3917 // these messages are currently not mapped to wx events
3918 case PBT_APMQUERYSTANDBY:
3919 case PBT_APMQUERYSTANDBYFAILED:
3920 case PBT_APMSTANDBY:
3921 case PBT_APMRESUMESTANDBY:
3922 case PBT_APMBATTERYLOW:
3923 case PBT_APMPOWERSTATUSCHANGE:
3924 case PBT_APMOEMEVENT:
355debca
VZ
3925 case PBT_APMRESUMECRITICAL:
3926 evtType = wxEVT_NULL;
3927 break;
3928 }
3929
3930 // don't handle unknown messages
3931 if ( evtType == wxEVT_NULL )
3932 return false;
3933
3934 // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events?
3935
3936 wxPowerEvent event(evtType);
3937 if ( !GetEventHandler()->ProcessEvent(event) )
3938 return false;
3939
3940 *vetoed = event.IsVetoed();
3941
3942 return true;
dbc74bcc 3943#endif
355debca
VZ
3944}
3945
2e992e06
VZ
3946bool wxWindowMSW::IsDoubleBuffered() const
3947{
967acfb5 3948 for ( const wxWindowMSW *wnd = this;
c719013f
VZ
3949 wnd && !wnd->IsTopLevel(); wnd =
3950 wnd->GetParent() )
2e992e06 3951 {
c719013f 3952 if ( ::GetWindowLong(GetHwndOf(wnd), GWL_EXSTYLE) & WS_EX_COMPOSITED )
2e992e06 3953 return true;
2e992e06
VZ
3954 }
3955
3956 return false;
3957}
3958
42e69d6b
VZ
3959// ---------------------------------------------------------------------------
3960// owner drawn stuff
3961// ---------------------------------------------------------------------------
3962
61fef19b
VZ
3963#if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \
3964 (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__))
3965 #define WXUNUSED_UNLESS_ODRAWN(param) param
3966#else
3967 #define WXUNUSED_UNLESS_ODRAWN(param)
3968#endif
3969
3970bool
3971wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id),
3972 WXDRAWITEMSTRUCT * WXUNUSED_UNLESS_ODRAWN(itemStruct))
2bda0e17 3973{
4286a5b5 3974#if wxUSE_OWNER_DRAWN
1e6feb95
VZ
3975
3976#if wxUSE_MENUS_NATIVE
42e69d6b 3977 // is it a menu item?
6f806543
VZ
3978 DRAWITEMSTRUCT *pDrawStruct = (DRAWITEMSTRUCT *)itemStruct;
3979 if ( id == 0 && pDrawStruct->CtlType == ODT_MENU )
42e69d6b 3980 {
42e69d6b 3981 wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
03cef643 3982
2d29bf54
JS
3983 // see comment before the same test in MSWOnMeasureItem() below
3984 if ( !pMenuItem )
3985 return false;
3986
3987 wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
42f25dcf 3988 false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
42e69d6b 3989
7561aacd
VZ
3990 // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
3991 // the DC from being released
3992 wxDCTemp dc((WXHDC)pDrawStruct->hDC);
42e69d6b
VZ
3993 wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top,
3994 pDrawStruct->rcItem.right - pDrawStruct->rcItem.left,
3995 pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top);
3996
3997 return pMenuItem->OnDrawItem
7561aacd
VZ
3998 (
3999 dc,
4000 rect,
4001 (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
4002 (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
4003 );
42e69d6b 4004 }
1e6feb95 4005#endif // wxUSE_MENUS_NATIVE
42e69d6b 4006
c8e4fa8b
JS
4007#endif // USE_OWNER_DRAWN
4008
6a89f9ee 4009#if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)
c8e4fa8b 4010
c8e4fa8b 4011#if wxUSE_OWNER_DRAWN
1384636d 4012 wxControl *item = wxDynamicCast(FindItem(id), wxControl);
567be187 4013#else // !wxUSE_OWNER_DRAWN
1384636d
VS
4014 // we may still have owner-drawn buttons internally because we have to make
4015 // them owner-drawn to support colour change
35bbb0c6 4016 wxControl *item =
095b80e2
WS
4017# if wxUSE_BUTTON
4018 wxDynamicCast(FindItem(id), wxButton)
4019# else
4020 NULL
4021# endif
4022 ;
cd0b1709 4023#endif // USE_OWNER_DRAWN
567be187
VZ
4024
4025 if ( item )
4026 {
4027 return item->MSWOnDraw(itemStruct);
4028 }
4286a5b5 4029
c8e4fa8b
JS
4030#endif // wxUSE_CONTROLS
4031
08158721 4032 return false;
2bda0e17
KB
4033}
4034
61fef19b 4035bool
d1d276f2 4036wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
2bda0e17 4037{
61fef19b 4038#if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
42e69d6b 4039 // is it a menu item?
6f806543
VZ
4040 MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct;
4041 if ( id == 0 && pMeasureStruct->CtlType == ODT_MENU )
2d0a075d 4042 {
42e69d6b
VZ
4043 wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
4044
b6afa1a3
VZ
4045 // according to Carsten Fuchs the pointer may be NULL under XP if an
4046 // MDI child frame is initially maximized, see this for more info:
4047 // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745
4048 //
4049 // so silently ignore it instead of asserting
4050 if ( !pMenuItem )
4051 return false;
4052
4053 wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
42f25dcf 4054 false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
42e69d6b 4055
975b6bcf
VZ
4056 size_t w, h;
4057 bool rc = pMenuItem->OnMeasureItem(&w, &h);
4058
4059 pMeasureStruct->itemWidth = w;
4060 pMeasureStruct->itemHeight = h;
4061
4062 return rc;
2d0a075d 4063 }
42e69d6b 4064
567be187
VZ
4065 wxControl *item = wxDynamicCast(FindItem(id), wxControl);
4066 if ( item )
42e69d6b 4067 {
567be187 4068 return item->MSWOnMeasure(itemStruct);
42e69d6b 4069 }
d1d276f2
WS
4070#else
4071 wxUnusedVar(id);
4072 wxUnusedVar(itemStruct);
4073#endif // wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE
567be187 4074
08158721 4075 return false;
2bda0e17
KB
4076}
4077
42e69d6b
VZ
4078// ---------------------------------------------------------------------------
4079// colours and palettes
4080// ---------------------------------------------------------------------------
2bda0e17 4081
1e6feb95 4082bool wxWindowMSW::HandleSysColorChange()
2bda0e17 4083{
42e69d6b
VZ
4084 wxSysColourChangedEvent event;
4085 event.SetEventObject(this);
4086
23895080
VZ
4087 (void)GetEventHandler()->ProcessEvent(event);
4088
4089 // always let the system carry on the default processing to allow the
4090 // native controls to react to the colours update
08158721 4091 return false;
42e69d6b
VZ
4092}
4093
574c939e
KB
4094bool wxWindowMSW::HandleDisplayChange()
4095{
4096 wxDisplayChangedEvent event;
4097 event.SetEventObject(this);
4098
4099 return GetEventHandler()->ProcessEvent(event);
4100}
4101
04ef50df 4102#ifndef __WXMICROWIN__
42e69d6b 4103
1a784dfc 4104bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC hDC, WXHWND hWnd)
01c500af 4105{
3d74a760 4106#if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
43bfb798 4107 wxUnusedVar(hDC);
3d74a760
WS
4108 wxUnusedVar(hWnd);
4109#else
2bae4332 4110 wxControl *item = wxDynamicCast(FindItemByHWND(hWnd, true), wxControl);
c3732409 4111
01c500af 4112 if ( item )
1a784dfc 4113 *brush = item->MSWControlColor(hDC, hWnd);
2d0a075d 4114 else
1e6feb95 4115#endif // wxUSE_CONTROLS
01c500af 4116 *brush = NULL;
42e69d6b 4117
01c500af 4118 return *brush != NULL;
2bda0e17
KB
4119}
4120
01c500af
VZ
4121#endif // __WXMICROWIN__
4122
1e6feb95 4123bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
42e69d6b 4124{
574c939e 4125#if wxUSE_PALETTE
b95edd47
VZ
4126 // same as below except we don't respond to our own messages
4127 if ( hWndPalChange != GetHWND() )
4128 {
574c939e 4129 // check to see if we our our parents have a custom palette
fa21d338 4130 wxWindowMSW *win = this;
b95edd47
VZ
4131 while ( win && !win->HasCustomPalette() )
4132 {
4133 win = win->GetParent();
4134 }
4135
4136 if ( win && win->HasCustomPalette() )
4137 {
4138 // realize the palette to see whether redrawing is needed
4139 HDC hdc = ::GetDC((HWND) hWndPalChange);
4140 win->m_palette.SetHPALETTE((WXHPALETTE)
4141 ::SelectPalette(hdc, GetHpaletteOf(win->m_palette), FALSE));
574c939e
KB
4142
4143 int result = ::RealizePalette(hdc);
b95edd47
VZ
4144
4145 // restore the palette (before releasing the DC)
4146 win->m_palette.SetHPALETTE((WXHPALETTE)
4147 ::SelectPalette(hdc, GetHpaletteOf(win->m_palette), FALSE));
4148 ::RealizePalette(hdc);
4149 ::ReleaseDC((HWND) hWndPalChange, hdc);
4150
4151 // now check for the need to redraw
574c939e 4152 if (result > 0)
08158721 4153 ::InvalidateRect((HWND) hWndPalChange, NULL, TRUE);
574c939e 4154 }
b95edd47
VZ
4155
4156 }
4157#endif // wxUSE_PALETTE
574c939e 4158
42e69d6b
VZ
4159 wxPaletteChangedEvent event(GetId());
4160 event.SetEventObject(this);
4161 event.SetChangedWindow(wxFindWinFromHandle(hWndPalChange));
2d0a075d 4162
42e69d6b
VZ
4163 return GetEventHandler()->ProcessEvent(event);
4164}
4165
a5e84126
JS
4166bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
4167{
63e819f2
VS
4168 // notify windows on the capture stack about lost capture
4169 // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
72f8c792 4170 wxWindowBase::NotifyCaptureLost();
a5e84126 4171
72f8c792 4172 wxWindow *win = wxFindWinFromHandle(hWndGainedCapture);
63e819f2
VS
4173 wxMouseCaptureChangedEvent event(GetId(), win);
4174 event.SetEventObject(this);
a5e84126
JS
4175 return GetEventHandler()->ProcessEvent(event);
4176}
4177
3c96418b
JG
4178bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam, WXLPARAM lParam)
4179{
4180 // despite MSDN saying "(This message cannot be sent directly to a window.)"
4181 // we need to send this to child windows (it is only sent to top-level
4182 // windows) so {list,tree}ctrls can adjust their font size if necessary
4183 // this is exactly how explorer does it to enable the font size changes
4184
4185 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
4186 while ( node )
4187 {
4188 // top-level windows already get this message from the system
4189 wxWindow *win = node->GetData();
4190 if ( !win->IsTopLevel() )
4191 {
4192 ::SendMessage(GetHwndOf(win), WM_SETTINGCHANGE, wParam, lParam);
4193 }
4194
4195 node = node->GetNext();
4196 }
4197
3c96418b
JG
4198 // let the system handle it
4199 return false;
4200}
4201
1e6feb95 4202bool wxWindowMSW::HandleQueryNewPalette()
42e69d6b 4203{
574c939e
KB
4204
4205#if wxUSE_PALETTE
4206 // check to see if we our our parents have a custom palette
fa21d338 4207 wxWindowMSW *win = this;
574c939e
KB
4208 while (!win->HasCustomPalette() && win->GetParent()) win = win->GetParent();
4209 if (win->HasCustomPalette()) {
4210 /* realize the palette to see whether redrawing is needed */
3a3c8603 4211 HDC hdc = ::GetDC((HWND) GetHWND());
574c939e 4212 win->m_palette.SetHPALETTE( (WXHPALETTE)
b95edd47 4213 ::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), FALSE) );
574c939e
KB
4214
4215 int result = ::RealizePalette(hdc);
4216 /* restore the palette (before releasing the DC) */
4217 win->m_palette.SetHPALETTE( (WXHPALETTE)
b95edd47 4218 ::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), TRUE) );
574c939e
KB
4219 ::RealizePalette(hdc);
4220 ::ReleaseDC((HWND) GetHWND(), hdc);
4221 /* now check for the need to redraw */
4222 if (result > 0)
4223 ::InvalidateRect((HWND) GetHWND(), NULL, TRUE);
4224 }
b95edd47 4225#endif // wxUSE_PALETTE
574c939e 4226
42e69d6b
VZ
4227 wxQueryNewPaletteEvent event(GetId());
4228 event.SetEventObject(this);
4229
4230 return GetEventHandler()->ProcessEvent(event) && event.GetPaletteRealized();
4231}
4232
4233// Responds to colour changes: passes event on to children.
574c939e 4234void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
42e69d6b 4235{
90c1530a
VZ
4236 // the top level window also reset the standard colour map as it might have
4237 // changed (there is no need to do it for the non top level windows as we
4238 // only have to do it once)
4239 if ( IsTopLevel() )
4240 {
4241 // FIXME-MT
08158721 4242 gs_hasStdCmap = false;
90c1530a 4243 }
222ed1d6 4244 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
42e69d6b
VZ
4245 while ( node )
4246 {
23895080
VZ
4247 // Only propagate to non-top-level windows because Windows already
4248 // sends this event to all top-level ones
4249 wxWindow *win = node->GetData();
4250 if ( !win->IsTopLevel() )
42e69d6b 4251 {
23895080
VZ
4252 // we need to send the real WM_SYSCOLORCHANGE and not just trigger
4253 // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
4254 // the standard controls
4255 ::SendMessage(GetHwndOf(win), WM_SYSCOLORCHANGE, 0, 0);
564b2609 4256 }
42e69d6b 4257
23895080
VZ
4258 node = node->GetNext();
4259 }
2bda0e17
KB
4260}
4261
90c1530a
VZ
4262extern wxCOLORMAP *wxGetStdColourMap()
4263{
4264 static COLORREF s_stdColours[wxSTD_COL_MAX];
4265 static wxCOLORMAP s_cmap[wxSTD_COL_MAX];
4266
4267 if ( !gs_hasStdCmap )
4268 {
08158721 4269 static bool s_coloursInit = false;
90c1530a
VZ
4270
4271 if ( !s_coloursInit )
4272 {
4273 // When a bitmap is loaded, the RGB values can change (apparently
4274 // because Windows adjusts them to care for the old programs always
4275 // using 0xc0c0c0 while the transparent colour for the new Windows
4276 // versions is different). But we do this adjustment ourselves so
4277 // we want to avoid Windows' "help" and for this we need to have a
4278 // reference bitmap which can tell us what the RGB values change
4279 // to.
e5dbcb50 4280 wxLogNull logNo; // suppress error if we couldn't load the bitmap
90c1530a
VZ
4281 wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
4282 if ( stdColourBitmap.Ok() )
4283 {
4284 // the pixels in the bitmap must correspond to wxSTD_COL_XXX!
4285 wxASSERT_MSG( stdColourBitmap.GetWidth() == wxSTD_COL_MAX,
4286 _T("forgot to update wxBITMAP_STD_COLOURS!") );
4287
4288 wxMemoryDC memDC;
4289 memDC.SelectObject(stdColourBitmap);
4290
4291 wxColour colour;
4292 for ( size_t i = 0; i < WXSIZEOF(s_stdColours); i++ )
4293 {
4294 memDC.GetPixel(i, 0, &colour);
4295 s_stdColours[i] = wxColourToRGB(colour);
4296 }
4297 }
4298 else // wxBITMAP_STD_COLOURS couldn't be loaded
4299 {
4300 s_stdColours[0] = RGB(000,000,000); // black
4301 s_stdColours[1] = RGB(128,128,128); // dark grey
4302 s_stdColours[2] = RGB(192,192,192); // light grey
4303 s_stdColours[3] = RGB(255,255,255); // white
4304 //s_stdColours[4] = RGB(000,000,255); // blue
4305 //s_stdColours[5] = RGB(255,000,255); // magenta
4306 }
4307
08158721 4308 s_coloursInit = true;
90c1530a
VZ
4309 }
4310
08158721 4311 gs_hasStdCmap = true;
90c1530a
VZ
4312
4313 // create the colour map
4314#define INIT_CMAP_ENTRY(col) \
4315 s_cmap[wxSTD_COL_##col].from = s_stdColours[wxSTD_COL_##col]; \
4316 s_cmap[wxSTD_COL_##col].to = ::GetSysColor(COLOR_##col)
4317
4318 INIT_CMAP_ENTRY(BTNTEXT);
4319 INIT_CMAP_ENTRY(BTNSHADOW);
4320 INIT_CMAP_ENTRY(BTNFACE);
4321 INIT_CMAP_ENTRY(BTNHIGHLIGHT);
4322
4323#undef INIT_CMAP_ENTRY
4324 }
4325
4326 return s_cmap;
4327}
4328
42e69d6b
VZ
4329// ---------------------------------------------------------------------------
4330// painting
4331// ---------------------------------------------------------------------------
4332
1e6feb95 4333bool wxWindowMSW::HandlePaint()
2bda0e17 4334{
42e69d6b
VZ
4335 HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
4336 if ( !hRegion )
f6bcfd97 4337 wxLogLastError(wxT("CreateRectRgn"));
42e69d6b 4338 if ( ::GetUpdateRgn(GetHwnd(), hRegion, FALSE) == ERROR )
f6bcfd97 4339 wxLogLastError(wxT("GetUpdateRgn"));
c085e333 4340
42e69d6b 4341 m_updateRegion = wxRegion((WXHRGN) hRegion);
c085e333 4342
42e69d6b
VZ
4343 wxPaintEvent event(m_windowId);
4344 event.SetEventObject(this);
2bda0e17 4345
1e6feb95
VZ
4346 bool processed = GetEventHandler()->ProcessEvent(event);
4347
4348 // note that we must generate NC event after the normal one as otherwise
4349 // BeginPaint() will happily overwrite our decorations with the background
4350 // colour
4351 wxNcPaintEvent eventNc(m_windowId);
4352 eventNc.SetEventObject(this);
4353 GetEventHandler()->ProcessEvent(eventNc);
4354
4355 return processed;
2bda0e17
KB
4356}
4357
63da7df7 4358// Can be called from an application's OnPaint handler
1e6feb95 4359void wxWindowMSW::OnPaint(wxPaintEvent& event)
63da7df7 4360{
1e6feb95
VZ
4361#ifdef __WXUNIVERSAL__
4362 event.Skip();
4363#else
63da7df7
JS
4364 HDC hDC = (HDC) wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject());
4365 if (hDC != 0)
4366 {
4367 MSWDefWindowProc(WM_PAINT, (WPARAM) hDC, 0);
4368 }
1e6feb95 4369#endif
63da7df7
JS
4370}
4371
1e6feb95 4372bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
a23fd0e1 4373{
e0e6ac8a 4374 wxDCTemp dc(hdc, GetClientSize());
c085e333 4375
1e6feb95
VZ
4376 dc.SetHDC(hdc);
4377 dc.SetWindow((wxWindow *)this);
c085e333 4378
2bda0e17 4379 wxEraseEvent event(m_windowId, &dc);
42e69d6b 4380 event.SetEventObject(this);
a23fd0e1 4381 bool rc = GetEventHandler()->ProcessEvent(event);
c085e333 4382
7561aacd 4383 // must be called manually as ~wxDC doesn't do anything for wxDCTemp
a23fd0e1 4384 dc.SelectOldObjects(hdc);
a23fd0e1
VZ
4385
4386 return rc;
2bda0e17
KB
4387}
4388
8681b094
VZ
4389void wxWindowMSW::OnEraseBackground(wxEraseEvent& event)
4390{
52c3e064
VZ
4391 // standard non top level controls (i.e. except the dialogs) always erase
4392 // their background themselves in HandleCtlColor() or have some control-
4393 // specific ways to set the colours (common controls)
4394 if ( IsOfStandardClass() && !IsTopLevel() )
b8335252 4395 {
c5bd3c62
VZ
4396 event.Skip();
4397 return;
4398 }
b8335252 4399
c5bd3c62
VZ
4400 if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM )
4401 {
4402 // don't skip the event here, custom background means that the app
4403 // is drawing it itself in its OnPaint(), so don't draw it at all
4404 // now to avoid flicker
4405 return;
4406 }
8681b094 4407
8681b094 4408
c5bd3c62 4409 // do default background painting
c3732409 4410 if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
c5bd3c62
VZ
4411 {
4412 // let the system paint the background
4413 event.Skip();
4414 }
4415}
4416
c3732409 4417bool wxWindowMSW::DoEraseBackground(WXHDC hDC)
c581abbc 4418{
c3732409
VZ
4419 HBRUSH hbr = (HBRUSH)MSWGetBgBrush(hDC);
4420 if ( !hbr )
c581abbc
VZ
4421 return false;
4422
c3732409 4423 wxFillRect(GetHwnd(), (HDC)hDC, hbr);
c581abbc
VZ
4424
4425 return true;
4426}
4427
c3732409 4428WXHBRUSH
2bae4332 4429wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), WXHWND hWnd)
c5bd3c62 4430{
accbb1e7
VZ
4431 if ( m_hasBgCol )
4432 {
8d075f8d
VZ
4433 // our background colour applies to:
4434 // 1. this window itself, always
4435 // 2. all children unless the colour is "not inheritable"
c3732409
VZ
4436 // 3. even if it is not inheritable, our immediate transparent
4437 // children should still inherit it -- but not any transparent
4438 // children because it would look wrong if a child of non
4439 // transparent child would show our bg colour when the child itself
4440 // does not
2bae4332
VZ
4441 wxWindow *win = wxFindWinFromHandle(hWnd);
4442 if ( win == this ||
c3732409 4443 m_inheritBgCol ||
2bae4332
VZ
4444 (win && win->HasTransparentBackground() &&
4445 win->GetParent() == this) )
accbb1e7 4446 {
c3732409
VZ
4447 // draw children with the same colour as the parent
4448 wxBrush *
4449 brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour());
4450
4451 return (WXHBRUSH)GetHbrushOf(*brush);
accbb1e7
VZ
4452 }
4453 }
4454
c3732409 4455 return 0;
c5bd3c62 4456}
8681b094 4457
2bae4332 4458WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, WXHWND hWndToPaint)
bdd1a35d 4459{
2bae4332
VZ
4460 if ( !hWndToPaint )
4461 hWndToPaint = GetHWND();
bdd1a35d 4462
c3732409 4463 for ( wxWindowMSW *win = this; win; win = win->GetParent() )
c5bd3c62 4464 {
2bae4332 4465 WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, hWndToPaint);
c5bd3c62
VZ
4466 if ( hBrush )
4467 return hBrush;
24cb4019 4468
c3732409
VZ
4469 // background is not inherited beyond top level windows
4470 if ( win->IsTopLevel() )
24cb4019 4471 break;
01c500af 4472 }
c5bd3c62
VZ
4473
4474 return 0;
8681b094
VZ
4475}
4476
b728a212 4477bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
1a784dfc 4478{
b728a212
JG
4479 // we receive this message when DrawThemeParentBackground() is
4480 // called from def window proc of several controls under XP and we
4481 // must draw properly themed background here
4482 //
4483 // note that naively I'd expect filling the client rect with the
4484 // brush returned by MSWGetBgBrush() work -- but for some reason it
4485 // doesn't and we have to call parents MSWPrintChild() which is
4486 // supposed to call DrawThemeBackground() with appropriate params
4487 //
4488 // also note that in this case lParam == PRF_CLIENT but we're
4489 // clearly expected to paint the background and nothing else!
4490
4491 if ( IsTopLevel() || InheritsBackgroundColour() )
4492 return false;
4493
4494 // sometimes we don't want the parent to handle it at all, instead
4495 // return whatever value this window wants
4496 if ( !MSWShouldPropagatePrintChild() )
4497 return MSWPrintChild(hDC, (wxWindow *)this);
4498
4499 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
4500 {
4501 if ( win->MSWPrintChild(hDC, (wxWindow *)this) )
4502 return true;
4503
4504 if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
4505 break;
4506 }
4507
1a784dfc
VZ
4508 return false;
4509}
4510
42e69d6b
VZ
4511// ---------------------------------------------------------------------------
4512// moving and resizing
4513// ---------------------------------------------------------------------------
4514
1e6feb95 4515bool wxWindowMSW::HandleMinimize()
42e69d6b
VZ
4516{
4517 wxIconizeEvent event(m_windowId);
4518 event.SetEventObject(this);
2d0a075d 4519
42e69d6b 4520 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
4521}
4522
1e6feb95 4523bool wxWindowMSW::HandleMaximize()
2bda0e17 4524{
42e69d6b
VZ
4525 wxMaximizeEvent event(m_windowId);
4526 event.SetEventObject(this);
c085e333 4527
42e69d6b
VZ
4528 return GetEventHandler()->ProcessEvent(event);
4529}
2bda0e17 4530
1e6feb95 4531bool wxWindowMSW::HandleMove(int x, int y)
42e69d6b 4532{
907173e5
WS
4533 wxPoint point(x,y);
4534 wxMoveEvent event(point, m_windowId);
42e69d6b
VZ
4535 event.SetEventObject(this);
4536
4537 return GetEventHandler()->ProcessEvent(event);
4538}
4539
5706de1c
JS
4540bool wxWindowMSW::HandleMoving(wxRect& rect)
4541{
4542 wxMoveEvent event(rect, m_windowId);
4543 event.SetEventObject(this);
577baeef 4544
5706de1c
JS
4545 bool rc = GetEventHandler()->ProcessEvent(event);
4546 if (rc)
4547 rect = event.GetRect();
4548 return rc;
4549}
4550
4bc0f25e 4551bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
42e69d6b 4552{
c3723477
JS
4553#if USE_DEFERRED_SIZING
4554 // when we resize this window, its children are probably going to be
4555 // repositioned as well, prepare to use DeferWindowPos() for them
4556 int numChildren = 0;
4557 for ( HWND child = ::GetWindow(GetHwndOf(this), GW_CHILD);
4558 child;
4559 child = ::GetWindow(child, GW_HWNDNEXT) )
4560 {
4561 numChildren ++;
4562 }
4563
3fca879c 4564 // Protect against valid m_hDWP being overwritten
c3723477
JS
4565 bool useDefer = false;
4566
3f48c8e2
VZ
4567 if ( numChildren > 1 )
4568 {
c3723477 4569 if (!m_hDWP)
3fca879c 4570 {
c3723477
JS
4571 m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
4572 if ( !m_hDWP )
4573 {
4574 wxLogLastError(_T("BeginDeferWindowPos"));
4575 }
4576 if (m_hDWP)
4577 useDefer = true;
3f48c8e2
VZ
4578 }
4579 }
f7040b5f 4580#endif // USE_DEFERRED_SIZING
42e69d6b 4581
3f48c8e2
VZ
4582 // update this window size
4583 bool processed = false;
4bc0f25e
VZ
4584 switch ( wParam )
4585 {
4586 default:
4587 wxFAIL_MSG( _T("unexpected WM_SIZE parameter") );
4588 // fall through nevertheless
4589
4590 case SIZE_MAXHIDE:
4591 case SIZE_MAXSHOW:
4592 // we're not interested in these messages at all
4593 break;
4594
4595 case SIZE_MINIMIZED:
4596 processed = HandleMinimize();
4597 break;
4598
4599 case SIZE_MAXIMIZED:
a4d1972d 4600 /* processed = */ HandleMaximize();
4bc0f25e
VZ
4601 // fall through to send a normal size event as well
4602
4603 case SIZE_RESTORED:
4604 // don't use w and h parameters as they specify the client size
4605 // while according to the docs EVT_SIZE handler is supposed to
4606 // receive the total size
4607 wxSizeEvent event(GetSize(), m_windowId);
4608 event.SetEventObject(this);
4609
4610 processed = GetEventHandler()->ProcessEvent(event);
4611 }
4612
c3723477 4613#if USE_DEFERRED_SIZING
3f48c8e2 4614 // and finally change the positions of all child windows at once
c3723477 4615 if ( useDefer && m_hDWP )
3f48c8e2
VZ
4616 {
4617 // reset m_hDWP to NULL so that child windows don't try to use our
4618 // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
4619 // happen anyhow normally but who knows what weird flow of control we
4620 // may have depending on what the users EVT_SIZE handler does...)
4621 HDWP hDWP = (HDWP)m_hDWP;
4622 m_hDWP = NULL;
3fca879c 4623
3f48c8e2
VZ
4624 // do put all child controls in place at once
4625 if ( !::EndDeferWindowPos(hDWP) )
4626 {
4627 wxLogLastError(_T("EndDeferWindowPos"));
4628 }
c3723477 4629
da78f3b1 4630 // Reset our children's pending pos/size values.
c3723477
JS
4631 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
4632 node;
4633 node = node->GetNext() )
4634 {
82e3664e 4635 wxWindowMSW *child = node->GetData();
67644c1d
RD
4636 child->m_pendingPosition = wxDefaultPosition;
4637 child->m_pendingSize = wxDefaultSize;
c3723477 4638 }
3f48c8e2 4639 }
7d86a2d4 4640#endif // USE_DEFERRED_SIZING
3f48c8e2 4641
4bc0f25e 4642 return processed;
42e69d6b
VZ
4643}
4644
5706de1c
JS
4645bool wxWindowMSW::HandleSizing(wxRect& rect)
4646{
4647 wxSizeEvent event(rect, m_windowId);
4648 event.SetEventObject(this);
577baeef 4649
5706de1c
JS
4650 bool rc = GetEventHandler()->ProcessEvent(event);
4651 if (rc)
4652 rect = event.GetRect();
4653 return rc;
4654}
4655
0c0d1521 4656bool wxWindowMSW::HandleGetMinMaxInfo(void *WXUNUSED_IN_WINCE(mmInfo))
42e69d6b 4657{
7f0586ef 4658#ifdef __WXWINCE__
08158721 4659 return false;
7f0586ef 4660#else
42e69d6b
VZ
4661 MINMAXINFO *info = (MINMAXINFO *)mmInfo;
4662
08158721 4663 bool rc = false;
b2d5a7ee 4664
e7dda1ff
VS
4665 int minWidth = GetMinWidth(),
4666 minHeight = GetMinHeight(),
4667 maxWidth = GetMaxWidth(),
4668 maxHeight = GetMaxHeight();
42e69d6b 4669
422d0ff0 4670 if ( minWidth != wxDefaultCoord )
2d0a075d 4671 {
e7dda1ff 4672 info->ptMinTrackSize.x = minWidth;
08158721 4673 rc = true;
2d0a075d 4674 }
2bda0e17 4675
422d0ff0 4676 if ( minHeight != wxDefaultCoord )
42e69d6b 4677 {
e7dda1ff 4678 info->ptMinTrackSize.y = minHeight;
08158721 4679 rc = true;
42e69d6b 4680 }
2bda0e17 4681
422d0ff0 4682 if ( maxWidth != wxDefaultCoord )
42e69d6b 4683 {
e7dda1ff 4684 info->ptMaxTrackSize.x = maxWidth;
08158721 4685 rc = true;
2d0a075d 4686 }
2bda0e17 4687
422d0ff0 4688 if ( maxHeight != wxDefaultCoord )
42e69d6b 4689 {
e7dda1ff 4690 info->ptMaxTrackSize.y = maxHeight;
08158721 4691 rc = true;
42e69d6b 4692 }
2bda0e17 4693
42e69d6b 4694 return rc;
7f0586ef 4695#endif
42e69d6b 4696}
2d0a075d 4697
42e69d6b
VZ
4698// ---------------------------------------------------------------------------
4699// command messages
4700// ---------------------------------------------------------------------------
4701
1e6feb95 4702bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
42e69d6b 4703{
1e6feb95 4704#if wxUSE_MENUS_NATIVE
8c290175 4705 if ( !cmd && wxCurrentPopupMenu )
42e69d6b
VZ
4706 {
4707 wxMenu *popupMenu = wxCurrentPopupMenu;
4708 wxCurrentPopupMenu = NULL;
4709
4710 return popupMenu->MSWCommand(cmd, id);
4711 }
1e6feb95 4712#endif // wxUSE_MENUS_NATIVE
42e69d6b 4713
8c290175 4714 wxWindow *win = NULL;
71292fab
VZ
4715
4716 // first try to find it from HWND - this works even with the broken
4717 // programs using the same ids for different controls
4718 if ( control )
42e69d6b 4719 {
71292fab 4720 win = wxFindWinFromHandle(control);
b853f898 4721 }
2f4ef631 4722
71292fab
VZ
4723 // try the id
4724 if ( !win )
b853f898 4725 {
71292fab
VZ
4726 // must cast to a signed type before comparing with other ids!
4727 win = FindItem((signed short)id);
42e69d6b
VZ
4728 }
4729
4730 if ( win )
b94ae1ea 4731 {
42e69d6b 4732 return win->MSWCommand(cmd, id);
b94ae1ea
VZ
4733 }
4734
4735 // the messages sent from the in-place edit control used by the treectrl
4736 // for label editing have id == 0, but they should _not_ be treated as menu
4737 // messages (they are EN_XXX ones, in fact) so don't translate anything
4738 // coming from a control to wxEVT_COMMAND_MENU_SELECTED
4739 if ( !control )
a84fc80b 4740 {
b94ae1ea
VZ
4741 // If no child window, it may be an accelerator, e.g. for a popup menu
4742 // command
a84fc80b
JS
4743
4744 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
4745 event.SetEventObject(this);
4746 event.SetId(id);
4747 event.SetInt(id);
b94ae1ea
VZ
4748
4749 return GetEventHandler()->ProcessEvent(event);
a84fc80b 4750 }
6fe19057
VZ
4751 else
4752 {
01d2bf4d 4753#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
6fe19057
VZ
4754 // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
4755 // notifications to its parent which we want to reflect back to
4756 // wxSpinCtrl
4757 wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control);
4758 if ( spin && spin->ProcessTextCommand(cmd, id) )
08158721 4759 return true;
6fe19057 4760#endif // wxUSE_SPINCTRL
42e69d6b 4761
01d2bf4d
WS
4762#if wxUSE_CHOICE && defined(__SMARTPHONE__)
4763 // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND
4764 // notifications to its parent which we want to reflect back to
4765 // wxChoice
4766 wxChoice *choice = wxChoice::GetChoiceForListBox(control);
4767 if ( choice && choice->MSWCommand(cmd, id) )
4768 return true;
4769#endif
4770 }
4771
08158721 4772 return false;
2bda0e17
KB
4773}
4774
42e69d6b
VZ
4775// ---------------------------------------------------------------------------
4776// mouse events
4777// ---------------------------------------------------------------------------
4778
1e6feb95
VZ
4779void wxWindowMSW::InitMouseEvent(wxMouseEvent& event,
4780 int x, int y,
4781 WXUINT flags)
42e69d6b 4782{
1e6feb95
VZ
4783 // our client coords are not quite the same as Windows ones
4784 wxPoint pt = GetClientAreaOrigin();
4785 event.m_x = x - pt.x;
4786 event.m_y = y - pt.y;
4787
4788 event.m_shiftDown = (flags & MK_SHIFT) != 0;
4789 event.m_controlDown = (flags & MK_CONTROL) != 0;
4790 event.m_leftDown = (flags & MK_LBUTTON) != 0;
4791 event.m_middleDown = (flags & MK_MBUTTON) != 0;
4792 event.m_rightDown = (flags & MK_RBUTTON) != 0;
1fdf858b 4793 event.m_altDown = ::GetKeyState(VK_MENU) < 0;
1e6feb95 4794
f0b1ccde 4795#ifndef __WXWINCE__
1bf77ee5 4796 event.SetTimestamp(::GetMessageTime());
f0b1ccde
JS
4797#endif
4798
687706f5 4799 event.SetEventObject(this);
fb35f0c7 4800 event.SetId(GetId());
42e69d6b
VZ
4801
4802#if wxUSE_MOUSEEVENT_HACK
c358ea41
VZ
4803 gs_lastMouseEvent.pos = ClientToScreen(wxPoint(x, y));
4804 gs_lastMouseEvent.type = event.GetEventType();
42e69d6b 4805#endif // wxUSE_MOUSEEVENT_HACK
2bda0e17
KB
4806}
4807
42b1fb63 4808#ifdef __WXWINCE__
dfafa702
VZ
4809// Windows doesn't send the mouse events to the static controls (which are
4810// transparent in the sense that their WM_NCHITTEST handler returns
4811// HTTRANSPARENT) at all but we want all controls to receive the mouse events
4812// and so we manually check if we don't have a child window under mouse and if
4813// we do, send the event to it instead of the window Windows had sent WM_XXX
4814// to.
4815//
4816// Notice that this is not done for the mouse move events because this could
4817// (would?) be too slow, but only for clicks which means that the static texts
4818// still don't get move, enter nor leave events.
42b1fb63 4819static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y)
dfafa702
VZ
4820{
4821 wxCHECK_MSG( x && y, win, _T("NULL pointer in FindWindowForMouseEvent") );
4822
4823 // first try to find a non transparent child: this allows us to send events
4824 // to a static text which is inside a static box, for example
4825 POINT pt = { *x, *y };
4826 HWND hwnd = GetHwndOf(win),
4827 hwndUnderMouse;
4828
7f0586ef
JS
4829#ifdef __WXWINCE__
4830 hwndUnderMouse = ::ChildWindowFromPoint
4831 (
4832 hwnd,
4833 pt
4834 );
4835#else
dfafa702
VZ
4836 hwndUnderMouse = ::ChildWindowFromPointEx
4837 (
4838 hwnd,
4839 pt,
4840 CWP_SKIPINVISIBLE |
4841 CWP_SKIPDISABLED |
4842 CWP_SKIPTRANSPARENT
4843 );
7f0586ef 4844#endif
dfafa702
VZ
4845
4846 if ( !hwndUnderMouse || hwndUnderMouse == hwnd )
dfafa702
VZ
4847 {
4848 // now try any child window at all
4849 hwndUnderMouse = ::ChildWindowFromPoint(hwnd, pt);
4850 }
4851
4852 // check that we have a child window which is susceptible to receive mouse
4853 // events: for this it must be shown and enabled
4854 if ( hwndUnderMouse &&
4855 hwndUnderMouse != hwnd &&
4856 ::IsWindowVisible(hwndUnderMouse) &&
4857 ::IsWindowEnabled(hwndUnderMouse) )
4858 {
4859 wxWindow *winUnderMouse = wxFindWinFromHandle((WXHWND)hwndUnderMouse);
4860 if ( winUnderMouse )
4861 {
4862 // translate the mouse coords to the other window coords
4863 win->ClientToScreen(x, y);
4864 winUnderMouse->ScreenToClient(x, y);
4865
4866 win = winUnderMouse;
4867 }
4868 }
4869
4870 return win;
4871}
42b1fb63 4872#endif // __WXWINCE__
dfafa702 4873
1e6feb95 4874bool wxWindowMSW::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
2bda0e17 4875{
42e69d6b 4876 // the mouse events take consecutive IDs from WM_MOUSEFIRST to
34621cc5 4877 // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST
42e69d6b
VZ
4878 // from the message id and take the value in the table to get wxWin event
4879 // id
4880 static const wxEventType eventsMouse[] =
4881 {
4882 wxEVT_MOTION,
4883 wxEVT_LEFT_DOWN,
4884 wxEVT_LEFT_UP,
4885 wxEVT_LEFT_DCLICK,
4886 wxEVT_RIGHT_DOWN,
4887 wxEVT_RIGHT_UP,
4888 wxEVT_RIGHT_DCLICK,
4889 wxEVT_MIDDLE_DOWN,
4890 wxEVT_MIDDLE_UP,
4891 wxEVT_MIDDLE_DCLICK
4892 };
2bda0e17 4893
42e69d6b
VZ
4894 wxMouseEvent event(eventsMouse[msg - WM_MOUSEMOVE]);
4895 InitMouseEvent(event, x, y, flags);
4896
4897 return GetEventHandler()->ProcessEvent(event);
4898}
4899
1e6feb95 4900bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
42e69d6b
VZ
4901{
4902 if ( !m_mouseInWindow )
2bda0e17 4903 {
1e6feb95
VZ
4904 // it would be wrong to assume that just because we get a mouse move
4905 // event that the mouse is inside the window: although this is usually
4906 // true, it is not if we had captured the mouse, so we need to check
4907 // the mouse coordinates here
4908 if ( !HasCapture() || IsMouseInWindow() )
4909 {
4910 // Generate an ENTER event
08158721 4911 m_mouseInWindow = true;
e5297b7f 4912
4e5c6c33 4913#ifdef HAVE_TRACKMOUSEEVENT
aafb9978
VZ
4914 typedef BOOL (WINAPI *_TrackMouseEvent_t)(LPTRACKMOUSEEVENT);
4915#ifdef __WXWINCE__
4916 static const _TrackMouseEvent_t
4917 s_pfn_TrackMouseEvent = _TrackMouseEvent;
4918#else // !__WXWINCE__
4919 static _TrackMouseEvent_t s_pfn_TrackMouseEvent;
4920 static bool s_initDone = false;
4921 if ( !s_initDone )
4922 {
4923 wxLogNull noLog;
4924
4925 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
4926 if ( dllComCtl32.IsLoaded() )
4927 {
4928 s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
4929 dllComCtl32.GetSymbol(_T("_TrackMouseEvent"));
4930 }
4931
4932 s_initDone = true;
4e5c6c33 4933
aafb9978
VZ
4934 // notice that it's ok to unload comctl32.dll here as it won't
4935 // be really unloaded, being still in use because we link to it
4936 // statically too
4937 }
4938
4939 if ( s_pfn_TrackMouseEvent )
4940#endif // __WXWINCE__/!__WXWINCE__
4941 {
4942 WinStruct<TRACKMOUSEEVENT> trackinfo;
4e5c6c33 4943
aafb9978
VZ
4944 trackinfo.dwFlags = TME_LEAVE;
4945 trackinfo.hwndTrack = GetHwnd();
4946
4947 (*s_pfn_TrackMouseEvent)(&trackinfo);
4948 }
4e5c6c33
VZ
4949#endif // HAVE_TRACKMOUSEEVENT
4950
1e6feb95
VZ
4951 wxMouseEvent event(wxEVT_ENTER_WINDOW);
4952 InitMouseEvent(event, x, y, flags);
42e69d6b 4953
1e6feb95
VZ
4954 (void)GetEventHandler()->ProcessEvent(event);
4955 }
42e69d6b 4956 }
cff58b52 4957#ifdef HAVE_TRACKMOUSEEVENT
aafb9978 4958 else // mouse not in window
cff58b52
KH
4959 {
4960 // Check if we need to send a LEAVE event
4961 // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so
4962 // send it here if we are using native mouse leave tracking
4963 if ( HasCapture() && !IsMouseInWindow() )
4964 {
4965 GenerateMouseLeave();
4966 }
4967 }
1ca78aa1 4968#endif // HAVE_TRACKMOUSEEVENT
42e69d6b
VZ
4969
4970#if wxUSE_MOUSEEVENT_HACK
c358ea41
VZ
4971 // Windows often generates mouse events even if mouse position hasn't
4972 // changed (http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/66576)
4973 //
4974 // Filter this out as it can result in unexpected behaviour compared to
4975 // other platforms
4976 if ( gs_lastMouseEvent.type == wxEVT_RIGHT_DOWN ||
4977 gs_lastMouseEvent.type == wxEVT_LEFT_DOWN ||
4978 gs_lastMouseEvent.type == wxEVT_MIDDLE_DOWN ||
4979 gs_lastMouseEvent.type == wxEVT_MOTION )
4980 {
4981 if ( ClientToScreen(wxPoint(x, y)) == gs_lastMouseEvent.pos )
4982 {
4983 gs_lastMouseEvent.type = wxEVT_MOTION;
42e69d6b 4984
c358ea41
VZ
4985 return false;
4986 }
42e69d6b
VZ
4987 }
4988#endif // wxUSE_MOUSEEVENT_HACK
4989
4990 return HandleMouseEvent(WM_MOUSEMOVE, x, y, flags);
4991}
4992
d2c52078 4993
24ce4c18 4994bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
d2c52078
RD
4995{
4996#if wxUSE_MOUSEWHEEL
3c297348
VZ
4997 // notice that WM_MOUSEWHEEL position is in screen coords (as it's
4998 // forwarded up to the parent by DefWindowProc()) and not in the client
4999 // ones as all the other messages, translate them to the client coords for
5000 // consistency
5001 const wxPoint
5002 pt = ScreenToClient(wxPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
d2c52078 5003 wxMouseEvent event(wxEVT_MOUSEWHEEL);
3c297348 5004 InitMouseEvent(event, pt.x, pt.y, LOWORD(wParam));
d2c52078
RD
5005 event.m_wheelRotation = (short)HIWORD(wParam);
5006 event.m_wheelDelta = WHEEL_DELTA;
5007
0f7a546d
RD
5008 static int s_linesPerRotation = -1;
5009 if ( s_linesPerRotation == -1 )
5010 {
5011 if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
5012 &s_linesPerRotation, 0))
5013 {
5014 // this is not supposed to happen
5015 wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
5016
5017 // the default is 3, so use it if SystemParametersInfo() failed
5018 s_linesPerRotation = 3;
5019 }
5020 }
d2c52078 5021
0f7a546d 5022 event.m_linesPerAction = s_linesPerRotation;
d2c52078 5023 return GetEventHandler()->ProcessEvent(event);
0f7a546d 5024
51e4e266
VZ
5025#else // !wxUSE_MOUSEWHEEL
5026 wxUnusedVar(wParam);
5027 wxUnusedVar(lParam);
38caaa61 5028
08158721 5029 return false;
51e4e266 5030#endif // wxUSE_MOUSEWHEEL/!wxUSE_MOUSEWHEEL
d2c52078
RD
5031}
5032
51e4e266
VZ
5033void wxWindowMSW::GenerateMouseLeave()
5034{
5035 m_mouseInWindow = false;
5036
5037 int state = 0;
5038 if ( wxIsShiftDown() )
5039 state |= MK_SHIFT;
5040 if ( wxIsCtrlDown() )
5041 state |= MK_CONTROL;
5042
5043 // Only the high-order bit should be tested
5044 if ( GetKeyState( VK_LBUTTON ) & (1<<15) )
5045 state |= MK_LBUTTON;
5046 if ( GetKeyState( VK_MBUTTON ) & (1<<15) )
5047 state |= MK_MBUTTON;
5048 if ( GetKeyState( VK_RBUTTON ) & (1<<15) )
5049 state |= MK_RBUTTON;
5050
5051 POINT pt;
f2325516
JS
5052#ifdef __WXWINCE__
5053 if ( !::GetCursorPosWinCE(&pt) )
5054#else
51e4e266 5055 if ( !::GetCursorPos(&pt) )
f2325516 5056#endif
51e4e266
VZ
5057 {
5058 wxLogLastError(_T("GetCursorPos"));
5059 }
5060
5061 // we need to have client coordinates here for symmetry with
5062 // wxEVT_ENTER_WINDOW
5063 RECT rect = wxGetWindowRect(GetHwnd());
5064 pt.x -= rect.left;
5065 pt.y -= rect.top;
5066
5067 wxMouseEvent event(wxEVT_LEAVE_WINDOW);
5068 InitMouseEvent(event, pt.x, pt.y, state);
5069
5070 (void)GetEventHandler()->ProcessEvent(event);
5071}
d2c52078 5072
42e69d6b
VZ
5073// ---------------------------------------------------------------------------
5074// keyboard handling
5075// ---------------------------------------------------------------------------
5076
c42404a5
VZ
5077// create the key event of the given type for the given key - used by
5078// HandleChar and HandleKeyDown/Up
1e6feb95 5079wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType,
b09bda68 5080 int id,
9c7df356
VZ
5081 WXLPARAM lParam,
5082 WXWPARAM wParam) const
c42404a5
VZ
5083{
5084 wxKeyEvent event(evType);
5085 event.SetId(GetId());
3f7bc32b
VZ
5086 event.m_shiftDown = wxIsShiftDown();
5087 event.m_controlDown = wxIsCtrlDown();
c42404a5
VZ
5088 event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN;
5089
687706f5 5090 event.SetEventObject((wxWindow *)this); // const_cast
c42404a5 5091 event.m_keyCode = id;
0d9b2c16 5092#if wxUSE_UNICODE
32b13913 5093 event.m_uniChar = (wxChar) wParam;
0d9b2c16 5094#endif
9c7df356
VZ
5095 event.m_rawCode = (wxUint32) wParam;
5096 event.m_rawFlags = (wxUint32) lParam;
f0b1ccde 5097#ifndef __WXWINCE__
1bf77ee5 5098 event.SetTimestamp(::GetMessageTime());
f0b1ccde 5099#endif
c42404a5
VZ
5100
5101 // translate the position to client coords
5102 POINT pt;
f2325516
JS
5103#ifdef __WXWINCE__
5104 GetCursorPosWinCE(&pt);
5105#else
c42404a5 5106 GetCursorPos(&pt);
f2325516 5107#endif
c42404a5
VZ
5108 RECT rect;
5109 GetWindowRect(GetHwnd(),&rect);
5110 pt.x -= rect.left;
5111 pt.y -= rect.top;
5112
5113 event.m_x = pt.x;
5114 event.m_y = pt.y;
5115
5116 return event;
5117}
5118
08158721 5119// isASCII is true only when we're called from WM_CHAR handler and not from
42e69d6b 5120// WM_KEYDOWN one
1e6feb95 5121bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII)
42e69d6b
VZ
5122{
5123 int id;
42e69d6b
VZ
5124 if ( isASCII )
5125 {
42e69d6b 5126 id = wParam;
2d0a075d 5127 }
9c7df356 5128 else // we're called from WM_KEYDOWN
c42404a5 5129 {
6121a198
VZ
5130 // don't pass lParam to wxCharCodeMSWToWX() here because we don't want
5131 // to get numpad key codes: CHAR events should use the logical keys
5132 // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events
5133 id = wxCharCodeMSWToWX(wParam);
9c7df356 5134 if ( id == 0 )
c42404a5 5135 {
9c7df356 5136 // it's ASCII and will be processed here only when called from
08158721
DS
5137 // WM_CHAR (i.e. when isASCII = true), don't process it now
5138 return false;
c42404a5 5139 }
9c7df356 5140 }
42e69d6b 5141
9c7df356 5142 wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam, wParam));
2b5f62a0
VZ
5143
5144 // the alphanumeric keys produced by pressing AltGr+something on European
5145 // keyboards have both Ctrl and Alt modifiers which may confuse the user
5146 // code as, normally, keys with Ctrl and/or Alt don't result in anything
5147 // alphanumeric, so pretend that there are no modifiers at all (the
5148 // KEY_DOWN event would still have the correct modifiers if they're really
5149 // needed)
5150 if ( event.m_controlDown && event.m_altDown &&
5151 (id >= 32 && id < 256) )
9c7df356 5152 {
2b5f62a0 5153 event.m_controlDown =
08158721 5154 event.m_altDown = false;
2d0a075d 5155 }
c42404a5 5156
9c7df356 5157 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
5158}
5159
1e6feb95 5160bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
2bda0e17 5161{
ff792344 5162 int id = wxCharCodeMSWToWX(wParam, lParam);
2bda0e17 5163
c42404a5
VZ
5164 if ( !id )
5165 {
5166 // normal ASCII char
42e69d6b
VZ
5167 id = wParam;
5168 }
5169
b60978b2
VZ
5170 wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam));
5171 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
5172}
5173
1e6feb95 5174bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
2bda0e17 5175{
ff792344 5176 int id = wxCharCodeMSWToWX(wParam, lParam);
2bda0e17 5177
c42404a5
VZ
5178 if ( !id )
5179 {
5180 // normal ASCII char
42e69d6b 5181 id = wParam;
2d0a075d 5182 }
2bda0e17 5183
b60978b2
VZ
5184 wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam));
5185 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
5186}
5187
0c0d1521
WS
5188int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
5189 WXLPARAM WXUNUSED_IN_WINCE(lParam))
b74cce40 5190{
7f0586ef
JS
5191 // FIXME: implement GetMenuItemCount for WinCE, possibly
5192 // in terms of GetMenuItemInfo
5193#ifndef __WXWINCE__
b74cce40
VZ
5194 const HMENU hmenu = (HMENU)lParam;
5195
5196 MENUITEMINFO mii;
5197 wxZeroMemory(mii);
5198 mii.cbSize = sizeof(MENUITEMINFO);
c70ffbdb
VZ
5199
5200 // we could use MIIM_FTYPE here as we only need to know if the item is
5201 // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but
5202 // MIIM_FTYPE is not supported under Win95
b74cce40
VZ
5203 mii.fMask = MIIM_TYPE | MIIM_DATA;
5204
5205 // find if we have this letter in any owner drawn item
5206 const int count = ::GetMenuItemCount(hmenu);
5207 for ( int i = 0; i < count; i++ )
5208 {
c70ffbdb
VZ
5209 // previous loop iteration could modify it, reset it back before
5210 // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData
5211 mii.cch = 0;
5212
b74cce40
VZ
5213 if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) )
5214 {
5215 if ( mii.fType == MFT_OWNERDRAW )
5216 {
5217 // dwItemData member of the MENUITEMINFO is a
5218 // pointer to the associated wxMenuItem -- see the
5219 // menu creation code
5220 wxMenuItem *item = (wxMenuItem*)mii.dwItemData;
5221
5222 const wxChar *p = wxStrchr(item->GetText(), _T('&'));
5223 while ( p++ )
5224 {
5225 if ( *p == _T('&') )
5226 {
5227 // this is not the accel char, find the real one
5228 p = wxStrchr(p + 1, _T('&'));
5229 }
5230 else // got the accel char
5231 {
5232 // FIXME-UNICODE: this comparison doesn't risk to work
5233 // for non ASCII accelerator characters I'm afraid, but
5234 // what can we do?
907173e5 5235 if ( (wchar_t)wxToupper(*p) == (wchar_t)chAccel )
b74cce40
VZ
5236 {
5237 return i;
5238 }
5239 else
5240 {
5241 // this one doesn't match
5242 break;
5243 }
5244 }
5245 }
5246 }
5247 }
e39af974 5248 else // failed to get the menu text?
b74cce40 5249 {
c70ffbdb 5250 // it's not fatal, so don't show error, but still log it
b74cce40
VZ
5251 wxLogLastError(_T("GetMenuItemInfo"));
5252 }
5253 }
7f0586ef 5254#endif
b74cce40
VZ
5255 return wxNOT_FOUND;
5256}
5257
78c91815
VZ
5258bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg )
5259{
5260 const wxEventType type = ( nMsg == WM_CUT ) ? wxEVT_COMMAND_TEXT_CUT :
5261 ( nMsg == WM_COPY ) ? wxEVT_COMMAND_TEXT_COPY :
5262 /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE;
5263 wxClipboardTextEvent evt(type, GetId());
5264
5265 evt.SetEventObject(this);
5266
5267 return GetEventHandler()->ProcessEvent(evt);
5268}
5269
42e69d6b
VZ
5270// ---------------------------------------------------------------------------
5271// joystick
5272// ---------------------------------------------------------------------------
5273
1e6feb95 5274bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags)
2bda0e17 5275{
8cb172b4 5276#ifdef JOY_BUTTON1
42e69d6b
VZ
5277 int change = 0;
5278 if ( flags & JOY_BUTTON1CHG )
5279 change = wxJOY_BUTTON1;
5280 if ( flags & JOY_BUTTON2CHG )
5281 change = wxJOY_BUTTON2;
5282 if ( flags & JOY_BUTTON3CHG )
5283 change = wxJOY_BUTTON3;
5284 if ( flags & JOY_BUTTON4CHG )
5285 change = wxJOY_BUTTON4;
2bda0e17 5286
42e69d6b
VZ
5287 int buttons = 0;
5288 if ( flags & JOY_BUTTON1 )
5289 buttons |= wxJOY_BUTTON1;
5290 if ( flags & JOY_BUTTON2 )
5291 buttons |= wxJOY_BUTTON2;
5292 if ( flags & JOY_BUTTON3 )
5293 buttons |= wxJOY_BUTTON3;
5294 if ( flags & JOY_BUTTON4 )
5295 buttons |= wxJOY_BUTTON4;
c085e333 5296
42e69d6b
VZ
5297 // the event ids aren't consecutive so we can't use table based lookup
5298 int joystick;
5299 wxEventType eventType;
5300 switch ( msg )
5301 {
5302 case MM_JOY1MOVE:
5303 joystick = 1;
5304 eventType = wxEVT_JOY_MOVE;
5305 break;
2bda0e17 5306
42e69d6b
VZ
5307 case MM_JOY2MOVE:
5308 joystick = 2;
5309 eventType = wxEVT_JOY_MOVE;
5310 break;
2bda0e17 5311
42e69d6b
VZ
5312 case MM_JOY1ZMOVE:
5313 joystick = 1;
5314 eventType = wxEVT_JOY_ZMOVE;
5315 break;
2bda0e17 5316
42e69d6b
VZ
5317 case MM_JOY2ZMOVE:
5318 joystick = 2;
5319 eventType = wxEVT_JOY_ZMOVE;
5320 break;
2bda0e17 5321
42e69d6b
VZ
5322 case MM_JOY1BUTTONDOWN:
5323 joystick = 1;
5324 eventType = wxEVT_JOY_BUTTON_DOWN;
5325 break;
2bda0e17 5326
42e69d6b
VZ
5327 case MM_JOY2BUTTONDOWN:
5328 joystick = 2;
5329 eventType = wxEVT_JOY_BUTTON_DOWN;
5330 break;
2bda0e17 5331
42e69d6b
VZ
5332 case MM_JOY1BUTTONUP:
5333 joystick = 1;
5334 eventType = wxEVT_JOY_BUTTON_UP;
5335 break;
5336
5337 case MM_JOY2BUTTONUP:
5338 joystick = 2;
5339 eventType = wxEVT_JOY_BUTTON_UP;
5340 break;
5341
5342 default:
223d09f6 5343 wxFAIL_MSG(wxT("no such joystick event"));
2d0a075d 5344
08158721 5345 return false;
2d0a075d 5346 }
2bda0e17 5347
42e69d6b
VZ
5348 wxJoystickEvent event(eventType, buttons, joystick, change);
5349 event.SetPosition(wxPoint(x, y));
5350 event.SetEventObject(this);
c085e333 5351
42e69d6b 5352 return GetEventHandler()->ProcessEvent(event);
8cb172b4 5353#else
991420e6
WS
5354 wxUnusedVar(msg);
5355 wxUnusedVar(x);
5356 wxUnusedVar(y);
5357 wxUnusedVar(flags);
08158721 5358 return false;
8cb172b4 5359#endif
2bda0e17
KB
5360}
5361
42e69d6b
VZ
5362// ---------------------------------------------------------------------------
5363// scrolling
5364// ---------------------------------------------------------------------------
5365
1e6feb95 5366bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam,
f4f734c1 5367 WXWORD pos, WXHWND control)
35bbb0c6 5368{
a0d924c6 5369 if ( control && control != m_hWnd ) // Prevent infinite recursion
cc2b7472 5370 {
42e69d6b
VZ
5371 wxWindow *child = wxFindWinFromHandle(control);
5372 if ( child )
5373 return child->MSWOnScroll(orientation, wParam, pos, control);
cc2b7472 5374 }
2bda0e17 5375
9145664b 5376 wxScrollWinEvent event;
42e69d6b
VZ
5377 event.SetPosition(pos);
5378 event.SetOrientation(orientation);
687706f5 5379 event.SetEventObject(this);
cc2b7472 5380
42e69d6b
VZ
5381 switch ( wParam )
5382 {
5383 case SB_TOP:
687706f5 5384 event.SetEventType(wxEVT_SCROLLWIN_TOP);
42e69d6b 5385 break;
cc2b7472 5386
42e69d6b 5387 case SB_BOTTOM:
687706f5 5388 event.SetEventType(wxEVT_SCROLLWIN_BOTTOM);
42e69d6b 5389 break;
cc2b7472 5390
42e69d6b 5391 case SB_LINEUP:
687706f5 5392 event.SetEventType(wxEVT_SCROLLWIN_LINEUP);
42e69d6b 5393 break;
2bda0e17 5394
42e69d6b 5395 case SB_LINEDOWN:
687706f5 5396 event.SetEventType(wxEVT_SCROLLWIN_LINEDOWN);
42e69d6b 5397 break;
a02eb1d2 5398
42e69d6b 5399 case SB_PAGEUP:
687706f5 5400 event.SetEventType(wxEVT_SCROLLWIN_PAGEUP);
42e69d6b 5401 break;
2bda0e17 5402
42e69d6b 5403 case SB_PAGEDOWN:
687706f5 5404 event.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN);
42e69d6b 5405 break;
2bda0e17 5406
42e69d6b 5407 case SB_THUMBPOSITION:
feda3011 5408 case SB_THUMBTRACK:
f6bcfd97
BP
5409 // under Win32, the scrollbar range and position are 32 bit integers,
5410 // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must
5411 // explicitly query the scrollbar for the correct position (this must
5412 // be done only for these two SB_ events as they are the only one
5413 // carrying the scrollbar position)
5414 {
0cf5de11 5415 WinStruct<SCROLLINFO> scrollInfo;
f6bcfd97
BP
5416 scrollInfo.fMask = SIF_TRACKPOS;
5417
5418 if ( !::GetScrollInfo(GetHwnd(),
5419 orientation == wxHORIZONTAL ? SB_HORZ
5420 : SB_VERT,
5421 &scrollInfo) )
5422 {
3103e8a9 5423 // Not necessarily an error, if there are no scrollbars yet.
f676b387 5424 // wxLogLastError(_T("GetScrollInfo"));
f6bcfd97
BP
5425 }
5426
5427 event.SetPosition(scrollInfo.nTrackPos);
5428 }
f6bcfd97 5429
687706f5 5430 event.SetEventType( wParam == SB_THUMBPOSITION
f6bcfd97 5431 ? wxEVT_SCROLLWIN_THUMBRELEASE
687706f5 5432 : wxEVT_SCROLLWIN_THUMBTRACK );
42e69d6b 5433 break;
c085e333 5434
42e69d6b 5435 default:
08158721 5436 return false;
564b2609 5437 }
2bda0e17 5438
42e69d6b 5439 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
5440}
5441
42e69d6b
VZ
5442// ===========================================================================
5443// global functions
5444// ===========================================================================
5445
7a5e53ab 5446void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont& the_font)
2bda0e17 5447{
42e69d6b
VZ
5448 TEXTMETRIC tm;
5449 HDC dc = ::GetDC((HWND) wnd);
42e69d6b 5450 HFONT was = 0;
35bbb0c6 5451
7a5e53ab
VS
5452 // the_font.UseResource();
5453 // the_font.RealizeResource();
c57c2993 5454 HFONT fnt = (HFONT)the_font.GetResourceHandle(); // const_cast
7a5e53ab
VS
5455 if ( fnt )
5456 was = (HFONT) SelectObject(dc,fnt);
35bbb0c6 5457
42e69d6b 5458 GetTextMetrics(dc, &tm);
7a5e53ab 5459 if ( fnt && was )
2d0a075d 5460 {
42e69d6b 5461 SelectObject(dc,was);
2d0a075d 5462 }
42e69d6b 5463 ReleaseDC((HWND)wnd, dc);
0655ad29
VZ
5464
5465 if ( x )
5466 *x = tm.tmAveCharWidth;
5467 if ( y )
5468 *y = tm.tmHeight + tm.tmExternalLeading;
2bda0e17 5469
7a5e53ab 5470 // the_font.ReleaseResource();
42e69d6b 5471}
c085e333 5472
5004c3ad
JG
5473// use the "extended" bit (24) of lParam to distinguish extended keys
5474// from normal keys as the same key is sent
ed5bc8f1
VZ
5475static inline
5476int ChooseNormalOrExtended(int lParam, int keyNormal, int keyExtended)
5004c3ad 5477{
ed5bc8f1
VZ
5478 // except that if lParam is 0, it means we don't have real lParam from
5479 // WM_KEYDOWN but are just translating just a VK constant (e.g. done from
5480 // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a
5481 // non-numpad (hence extended) key as this is a more common case
5482 return !lParam || (lParam & (1 << 24)) ? keyExtended : keyNormal;
5004c3ad
JG
5483}
5484
d5c21b02
VZ
5485// this array contains the Windows virtual key codes which map one to one to
5486// WXK_xxx constants and is used in wxCharCodeMSWToWX/WXToMSW() below
5487//
5488// note that keys having a normal and numpad version (e.g. WXK_HOME and
5489// WXK_NUMPAD_HOME) are not included in this table as the mapping is not 1-to-1
5490static const struct wxKeyMapping
5491{
5492 int vk;
5493 wxKeyCode wxk;
5494} gs_specialKeys[] =
5495{
5496 { VK_CANCEL, WXK_CANCEL },
5497 { VK_BACK, WXK_BACK },
5498 { VK_TAB, WXK_TAB },
5499 { VK_CLEAR, WXK_CLEAR },
5500 { VK_SHIFT, WXK_SHIFT },
5501 { VK_CONTROL, WXK_CONTROL },
5502 { VK_MENU , WXK_ALT },
5503 { VK_PAUSE, WXK_PAUSE },
5504 { VK_CAPITAL, WXK_CAPITAL },
5505 { VK_SPACE, WXK_SPACE },
5506 { VK_ESCAPE, WXK_ESCAPE },
5507 { VK_SELECT, WXK_SELECT },
5508 { VK_PRINT, WXK_PRINT },
5509 { VK_EXECUTE, WXK_EXECUTE },
e59c2b2d
VZ
5510 { VK_SNAPSHOT, WXK_SNAPSHOT },
5511 { VK_HELP, WXK_HELP },
d5c21b02
VZ
5512
5513 { VK_NUMPAD0, WXK_NUMPAD0 },
5514 { VK_NUMPAD1, WXK_NUMPAD1 },
5515 { VK_NUMPAD2, WXK_NUMPAD2 },
5516 { VK_NUMPAD3, WXK_NUMPAD3 },
5517 { VK_NUMPAD4, WXK_NUMPAD4 },
5518 { VK_NUMPAD5, WXK_NUMPAD5 },
5519 { VK_NUMPAD6, WXK_NUMPAD6 },
5520 { VK_NUMPAD7, WXK_NUMPAD7 },
5521 { VK_NUMPAD8, WXK_NUMPAD8 },
5522 { VK_NUMPAD9, WXK_NUMPAD9 },
5523 { VK_MULTIPLY, WXK_NUMPAD_MULTIPLY },
5524 { VK_ADD, WXK_NUMPAD_ADD },
5525 { VK_SUBTRACT, WXK_NUMPAD_SUBTRACT },
5526 { VK_DECIMAL, WXK_NUMPAD_DECIMAL },
5527 { VK_DIVIDE, WXK_NUMPAD_DIVIDE },
5528
5529 { VK_F1, WXK_F1 },
5530 { VK_F2, WXK_F2 },
5531 { VK_F3, WXK_F3 },
5532 { VK_F4, WXK_F4 },
5533 { VK_F5, WXK_F5 },
5534 { VK_F6, WXK_F6 },
5535 { VK_F7, WXK_F7 },
5536 { VK_F8, WXK_F8 },
5537 { VK_F9, WXK_F9 },
5538 { VK_F10, WXK_F10 },
5539 { VK_F11, WXK_F11 },
5540 { VK_F12, WXK_F12 },
5541 { VK_F13, WXK_F13 },
5542 { VK_F14, WXK_F14 },
5543 { VK_F15, WXK_F15 },
5544 { VK_F16, WXK_F16 },
5545 { VK_F17, WXK_F17 },
5546 { VK_F18, WXK_F18 },
5547 { VK_F19, WXK_F19 },
5548 { VK_F20, WXK_F20 },
5549 { VK_F21, WXK_F21 },
5550 { VK_F22, WXK_F22 },
5551 { VK_F23, WXK_F23 },
5552 { VK_F24, WXK_F24 },
5553
5554 { VK_NUMLOCK, WXK_NUMLOCK },
5555 { VK_SCROLL, WXK_SCROLL },
5556
5557#ifdef VK_APPS
5558 { VK_LWIN, WXK_WINDOWS_LEFT },
5559 { VK_RWIN, WXK_WINDOWS_RIGHT },
5560 { VK_APPS, WXK_WINDOWS_MENU },
5561#endif // VK_APPS defined
5562};
5563
42e69d6b
VZ
5564// Returns 0 if was a normal ASCII value, not a special key. This indicates that
5565// the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
d5c21b02 5566int wxCharCodeMSWToWX(int vk, WXLPARAM lParam)
42e69d6b 5567{
d5c21b02
VZ
5568 // check the table first
5569 for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ )
5570 {
5571 if ( gs_specialKeys[n].vk == vk )
5572 return gs_specialKeys[n].wxk;
5573 }
9c7df356 5574
d5c21b02
VZ
5575 // keys requiring special handling
5576 int wxk;
5577 switch ( vk )
5578 {
e77c5d96
VZ
5579 // the mapping for these keys may be incorrect on non-US keyboards so
5580 // maybe we shouldn't map them to ASCII values at all
d5c21b02
VZ
5581 case VK_OEM_1: wxk = ';'; break;
5582 case VK_OEM_PLUS: wxk = '+'; break;
5583 case VK_OEM_COMMA: wxk = ','; break;
5584 case VK_OEM_MINUS: wxk = '-'; break;
5585 case VK_OEM_PERIOD: wxk = '.'; break;
5586 case VK_OEM_2: wxk = '/'; break;
5587 case VK_OEM_3: wxk = '~'; break;
5588 case VK_OEM_4: wxk = '['; break;
5589 case VK_OEM_5: wxk = '\\'; break;
5590 case VK_OEM_6: wxk = ']'; break;
5591 case VK_OEM_7: wxk = '\''; break;
702c4208 5592
5004c3ad 5593 // handle extended keys
413553cc 5594 case VK_PRIOR:
d5c21b02 5595 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEUP, WXK_PAGEUP);
413553cc 5596 break;
d5c21b02 5597
413553cc 5598 case VK_NEXT:
d5c21b02 5599 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEDOWN, WXK_PAGEDOWN);
413553cc 5600 break;
d5c21b02 5601
413553cc 5602 case VK_END:
d5c21b02 5603 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_END, WXK_END);
413553cc 5604 break;
d5c21b02 5605
413553cc 5606 case VK_HOME:
d5c21b02 5607 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_HOME, WXK_HOME);
413553cc 5608 break;
d5c21b02 5609
413553cc 5610 case VK_LEFT:
d5c21b02 5611 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_LEFT, WXK_LEFT);
413553cc 5612 break;
d5c21b02 5613
413553cc 5614 case VK_UP:
d5c21b02 5615 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_UP, WXK_UP);
413553cc 5616 break;
d5c21b02 5617
413553cc 5618 case VK_RIGHT:
d5c21b02 5619 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_RIGHT, WXK_RIGHT);
413553cc 5620 break;
d5c21b02 5621
413553cc 5622 case VK_DOWN:
d5c21b02 5623 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DOWN, WXK_DOWN);
413553cc 5624 break;
d5c21b02 5625
413553cc 5626 case VK_INSERT:
d5c21b02 5627 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_INSERT, WXK_INSERT);
413553cc 5628 break;
d5c21b02 5629
413553cc 5630 case VK_DELETE:
d5c21b02 5631 wxk = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE);
413553cc 5632 break;
d5c21b02 5633
ff792344 5634 case VK_RETURN:
ed5bc8f1
VZ
5635 // don't use ChooseNormalOrExtended() here as the keys are reversed
5636 // here: numpad enter is the extended one
d5c21b02 5637 wxk = lParam && (lParam & (1 << 24)) ? WXK_NUMPAD_ENTER : WXK_RETURN;
ff792344
VZ
5638 break;
5639
f6bcfd97 5640 default:
d5c21b02
VZ
5641 wxk = 0;
5642 }
5643
5644 return wxk;
5645}
5646
5647WXWORD wxCharCodeWXToMSW(int wxk, bool *isVirtual)
5648{
5649 if ( isVirtual )
5650 *isVirtual = true;
5651
5652 // check the table first
5653 for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ )
5654 {
5655 if ( gs_specialKeys[n].wxk == wxk )
5656 return gs_specialKeys[n].vk;
5657 }
5658
5659 // and then check for special keys not included in the table
5660 WXWORD vk;
5661 switch ( wxk )
5662 {
71403278
VZ
5663 case WXK_PAGEUP:
5664 case WXK_NUMPAD_PAGEUP:
5665 vk = VK_PRIOR;
5666 break;
5667
5668 case WXK_PAGEDOWN:
5669 case WXK_NUMPAD_PAGEDOWN:
5670 vk = VK_NEXT;
5671 break;
5672
5673 case WXK_END:
5674 case WXK_NUMPAD_END:
5675 vk = VK_END;
5676 break;
5677
5678 case WXK_HOME:
5679 case WXK_NUMPAD_HOME:
5680 vk = VK_HOME;
5681 break;
5682
5683 case WXK_LEFT:
5684 case WXK_NUMPAD_LEFT:
5685 vk = VK_LEFT;
5686 break;
5687
5688 case WXK_UP:
5689 case WXK_NUMPAD_UP:
5690 vk = VK_UP;
5691 break;
5692
5693 case WXK_RIGHT:
5694 case WXK_NUMPAD_RIGHT:
5695 vk = VK_RIGHT;
5696 break;
5697
5698 case WXK_DOWN:
5699 case WXK_NUMPAD_DOWN:
5700 vk = VK_DOWN;
5701 break;
5702
5703 case WXK_INSERT:
5704 case WXK_NUMPAD_INSERT:
5705 vk = VK_INSERT;
5706 break;
5707
5708 case WXK_DELETE:
5709 case WXK_NUMPAD_DELETE:
5710 vk = VK_DELETE;
5711 break;
d5c21b02
VZ
5712
5713 default:
5714 if ( isVirtual )
5715 *isVirtual = false;
5716 vk = (WXWORD)wxk;
42e69d6b 5717 break;
2bda0e17 5718 }
d5c21b02
VZ
5719
5720 return vk;
5721}
5722
b8f434e7
JS
5723#ifndef SM_SWAPBUTTON
5724 #define SM_SWAPBUTTON 23
5725#endif
5726
d5c21b02
VZ
5727// small helper for wxGetKeyState() and wxGetMouseState()
5728static inline bool wxIsKeyDown(WXWORD vk)
5729{
b8f434e7
JS
5730 switch (vk)
5731 {
5732 case VK_LBUTTON:
f4322df6 5733 if (GetSystemMetrics(SM_SWAPBUTTON)) vk = VK_RBUTTON;
b8f434e7
JS
5734 break;
5735 case VK_RBUTTON:
5736 if (GetSystemMetrics(SM_SWAPBUTTON)) vk = VK_LBUTTON;
5737 break;
5738 }
d5c21b02
VZ
5739 // the low order bit indicates whether the key was pressed since the last
5740 // call and the high order one indicates whether it is down right now and
5741 // we only want that one
b8f434e7 5742 return (GetAsyncKeyState(vk) & (1<<15)) != 0;
2bda0e17
KB
5743}
5744
1751226c 5745bool wxGetKeyState(wxKeyCode key)
6ed892f3 5746{
d5c21b02
VZ
5747 // although this does work under Windows, it is not supported under other
5748 // platforms so don't allow it, you must use wxGetMouseState() instead
5749 wxASSERT_MSG( key != VK_LBUTTON &&
5750 key != VK_RBUTTON &&
5751 key != VK_MBUTTON,
5752 wxT("can't use wxGetKeyState() for mouse buttons") );
6ed892f3 5753
d5c21b02 5754 const WXWORD vk = wxCharCodeWXToMSW(key);
44353523 5755
d5c21b02
VZ
5756 // if the requested key is a LED key, return true if the led is pressed
5757 if ( key == WXK_NUMLOCK || key == WXK_CAPITAL || key == WXK_SCROLL )
fdec2c05 5758 {
d5c21b02
VZ
5759 // low order bit means LED is highlighted and high order one means the
5760 // key is down; for compatibility with the other ports return true if
5761 // either one is set
b8f434e7 5762 return GetKeyState(vk) != 0;
35bbb0c6 5763
fdec2c05 5764 }
d5c21b02 5765 else // normal key
84c51ddf 5766 {
d5c21b02 5767 return wxIsKeyDown(vk);
84c51ddf 5768 }
6ed892f3
RN
5769}
5770
7dd40b6f
RD
5771
5772wxMouseState wxGetMouseState()
5773{
5774 wxMouseState ms;
5775 POINT pt;
5776 GetCursorPos( &pt );
5777
5778 ms.SetX(pt.x);
5779 ms.SetY(pt.y);
d5c21b02
VZ
5780 ms.SetLeftDown(wxIsKeyDown(VK_LBUTTON));
5781 ms.SetMiddleDown(wxIsKeyDown(VK_MBUTTON));
5782 ms.SetRightDown(wxIsKeyDown(VK_RBUTTON));
dd28827a 5783
d5c21b02
VZ
5784 ms.SetControlDown(wxIsKeyDown(VK_CONTROL));
5785 ms.SetShiftDown(wxIsKeyDown(VK_SHIFT));
5786 ms.SetAltDown(wxIsKeyDown(VK_MENU));
7dd40b6f 5787// ms.SetMetaDown();
dd28827a 5788
7dd40b6f
RD
5789 return ms;
5790}
5791
5792
42e69d6b 5793wxWindow *wxGetActiveWindow()
2bda0e17 5794{
42e69d6b
VZ
5795 HWND hWnd = GetActiveWindow();
5796 if ( hWnd != 0 )
2d0a075d 5797 {
42e69d6b 5798 return wxFindWinFromHandle((WXHWND) hWnd);
2d0a075d 5799 }
42e69d6b 5800 return NULL;
2bda0e17
KB
5801}
5802
8614c467
VZ
5803extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
5804{
5805 HWND hwnd = (HWND)hWnd;
5806
5807 // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
5808 // by code in msw/radiobox.cpp), for all the others we just search up the
5809 // window hierarchy
5810 wxWindow *win = (wxWindow *)NULL;
5811 if ( hwnd )
5812 {
5813 win = wxFindWinFromHandle((WXHWND)hwnd);
5814 if ( !win )
5815 {
a2242341 5816#if wxUSE_RADIOBOX
8614c467
VZ
5817 // native radiobuttons return DLGC_RADIOBUTTON here and for any
5818 // wxWindow class which overrides WM_GETDLGCODE processing to
5819 // do it as well, win would be already non NULL
a2242341 5820 if ( ::SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_RADIOBUTTON )
8614c467 5821 {
975b6bcf 5822 win = (wxWindow *)wxGetWindowUserData(hwnd);
8614c467 5823 }
a2242341
VZ
5824 //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
5825#endif // wxUSE_RADIOBOX
5826
5827 // spin control text buddy window should be mapped to spin ctrl
5828 // itself so try it too
24ce4c18 5829#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
a2242341
VZ
5830 if ( !win )
5831 {
5832 win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
5833 }
5834#endif // wxUSE_SPINCTRL
8614c467 5835 }
8614c467
VZ
5836 }
5837
5838 while ( hwnd && !win )
5839 {
761989ff
VZ
5840 // this is a really ugly hack needed to avoid mistakenly returning the
5841 // parent frame wxWindow for the find/replace modeless dialog HWND -
5842 // this, in turn, is needed to call IsDialogMessage() from
5843 // wxApp::ProcessMessage() as for this we must return NULL from here
5844 //
5845 // FIXME: this is clearly not the best way to do it but I think we'll
5846 // need to change HWND <-> wxWindow code more heavily than I can
5847 // do it now to fix it
c67d6888 5848#ifndef __WXMICROWIN__
761989ff
VZ
5849 if ( ::GetWindow(hwnd, GW_OWNER) )
5850 {
5851 // it's a dialog box, don't go upwards
5852 break;
5853 }
c67d6888 5854#endif
761989ff 5855
8614c467 5856 hwnd = ::GetParent(hwnd);
761989ff 5857 win = wxFindWinFromHandle((WXHWND)hwnd);
8614c467
VZ
5858 }
5859
5860 return win;
5861}
5862
7f0586ef 5863#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
04ef50df 5864
42e69d6b
VZ
5865// Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
5866// in active frames and dialogs, regardless of where the focus is.
5867static HHOOK wxTheKeyboardHook = 0;
5868static FARPROC wxTheKeyboardHookProc = 0;
5869int APIENTRY _EXPORT
5870wxKeyboardHook(int nCode, WORD wParam, DWORD lParam);
2bda0e17 5871
42e69d6b 5872void wxSetKeyboardHook(bool doIt)
2bda0e17 5873{
42e69d6b 5874 if ( doIt )
2d0a075d 5875 {
42e69d6b
VZ
5876 wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
5877 wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
c7527e3f 5878
8614c467 5879 GetCurrentThreadId()
42e69d6b 5880 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
8614c467 5881 );
2d0a075d 5882 }
2d0a075d 5883 else
2d0a075d 5884 {
42e69d6b 5885 UnhookWindowsHookEx(wxTheKeyboardHook);
2d0a075d 5886 }
2bda0e17
KB
5887}
5888
42e69d6b
VZ
5889int APIENTRY _EXPORT
5890wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
2bda0e17 5891{
42e69d6b
VZ
5892 DWORD hiWord = HIWORD(lParam);
5893 if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) )
43d811ea 5894 {
ff792344 5895 int id = wxCharCodeMSWToWX(wParam, lParam);
32de7d24 5896 if ( id != 0 )
43d811ea 5897 {
42e69d6b
VZ
5898 wxKeyEvent event(wxEVT_CHAR_HOOK);
5899 if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN )
08158721 5900 event.m_altDown = true;
c085e333 5901
687706f5 5902 event.SetEventObject(NULL);
42e69d6b 5903 event.m_keyCode = id;
3f7bc32b
VZ
5904 event.m_shiftDown = wxIsShiftDown();
5905 event.m_controlDown = wxIsCtrlDown();
f0b1ccde 5906#ifndef __WXWINCE__
1bf77ee5 5907 event.SetTimestamp(::GetMessageTime());
f0b1ccde 5908#endif
42e69d6b 5909 wxWindow *win = wxGetActiveWindow();
32de7d24 5910 wxEvtHandler *handler;
42e69d6b
VZ
5911 if ( win )
5912 {
32de7d24
VZ
5913 handler = win->GetEventHandler();
5914 event.SetId(win->GetId());
42e69d6b
VZ
5915 }
5916 else
5917 {
32de7d24 5918 handler = wxTheApp;
abb74e0f 5919 event.SetId(wxID_ANY);
32de7d24
VZ
5920 }
5921
5922 if ( handler && handler->ProcessEvent(event) )
5923 {
5924 // processed
5925 return 1;
42e69d6b 5926 }
43d811ea
JS
5927 }
5928 }
32de7d24 5929
42e69d6b 5930 return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam);
4fabb575 5931}
cd4453e5
VZ
5932
5933#endif // !__WXMICROWIN__
4fabb575 5934
b2aef89b 5935#ifdef __WXDEBUG__
4a712ba3 5936const wxChar *wxGetMessageName(int message)
47cbd6da 5937{
42e69d6b
VZ
5938 switch ( message )
5939 {
4a712ba3
VZ
5940 case 0x0000: return wxT("WM_NULL");
5941 case 0x0001: return wxT("WM_CREATE");
5942 case 0x0002: return wxT("WM_DESTROY");
5943 case 0x0003: return wxT("WM_MOVE");
5944 case 0x0005: return wxT("WM_SIZE");
5945 case 0x0006: return wxT("WM_ACTIVATE");
5946 case 0x0007: return wxT("WM_SETFOCUS");
5947 case 0x0008: return wxT("WM_KILLFOCUS");
5948 case 0x000A: return wxT("WM_ENABLE");
5949 case 0x000B: return wxT("WM_SETREDRAW");
5950 case 0x000C: return wxT("WM_SETTEXT");
5951 case 0x000D: return wxT("WM_GETTEXT");
5952 case 0x000E: return wxT("WM_GETTEXTLENGTH");
5953 case 0x000F: return wxT("WM_PAINT");
5954 case 0x0010: return wxT("WM_CLOSE");
5955 case 0x0011: return wxT("WM_QUERYENDSESSION");
5956 case 0x0012: return wxT("WM_QUIT");
5957 case 0x0013: return wxT("WM_QUERYOPEN");
5958 case 0x0014: return wxT("WM_ERASEBKGND");
5959 case 0x0015: return wxT("WM_SYSCOLORCHANGE");
5960 case 0x0016: return wxT("WM_ENDSESSION");
5961 case 0x0017: return wxT("WM_SYSTEMERROR");
5962 case 0x0018: return wxT("WM_SHOWWINDOW");
5963 case 0x0019: return wxT("WM_CTLCOLOR");
5964 case 0x001A: return wxT("WM_WININICHANGE");
5965 case 0x001B: return wxT("WM_DEVMODECHANGE");
5966 case 0x001C: return wxT("WM_ACTIVATEAPP");
5967 case 0x001D: return wxT("WM_FONTCHANGE");
5968 case 0x001E: return wxT("WM_TIMECHANGE");
5969 case 0x001F: return wxT("WM_CANCELMODE");
5970 case 0x0020: return wxT("WM_SETCURSOR");
5971 case 0x0021: return wxT("WM_MOUSEACTIVATE");
5972 case 0x0022: return wxT("WM_CHILDACTIVATE");
5973 case 0x0023: return wxT("WM_QUEUESYNC");
5974 case 0x0024: return wxT("WM_GETMINMAXINFO");
5975 case 0x0026: return wxT("WM_PAINTICON");
5976 case 0x0027: return wxT("WM_ICONERASEBKGND");
5977 case 0x0028: return wxT("WM_NEXTDLGCTL");
5978 case 0x002A: return wxT("WM_SPOOLERSTATUS");
5979 case 0x002B: return wxT("WM_DRAWITEM");
5980 case 0x002C: return wxT("WM_MEASUREITEM");
5981 case 0x002D: return wxT("WM_DELETEITEM");
5982 case 0x002E: return wxT("WM_VKEYTOITEM");
5983 case 0x002F: return wxT("WM_CHARTOITEM");
5984 case 0x0030: return wxT("WM_SETFONT");
5985 case 0x0031: return wxT("WM_GETFONT");
5986 case 0x0037: return wxT("WM_QUERYDRAGICON");
5987 case 0x0039: return wxT("WM_COMPAREITEM");
5988 case 0x0041: return wxT("WM_COMPACTING");
5989 case 0x0044: return wxT("WM_COMMNOTIFY");
5990 case 0x0046: return wxT("WM_WINDOWPOSCHANGING");
5991 case 0x0047: return wxT("WM_WINDOWPOSCHANGED");
5992 case 0x0048: return wxT("WM_POWER");
5993
5994 case 0x004A: return wxT("WM_COPYDATA");
5995 case 0x004B: return wxT("WM_CANCELJOURNAL");
5996 case 0x004E: return wxT("WM_NOTIFY");
5997 case 0x0050: return wxT("WM_INPUTLANGCHANGEREQUEST");
5998 case 0x0051: return wxT("WM_INPUTLANGCHANGE");
5999 case 0x0052: return wxT("WM_TCARD");
6000 case 0x0053: return wxT("WM_HELP");
6001 case 0x0054: return wxT("WM_USERCHANGED");
6002 case 0x0055: return wxT("WM_NOTIFYFORMAT");
6003 case 0x007B: return wxT("WM_CONTEXTMENU");
6004 case 0x007C: return wxT("WM_STYLECHANGING");
6005 case 0x007D: return wxT("WM_STYLECHANGED");
6006 case 0x007E: return wxT("WM_DISPLAYCHANGE");
6007 case 0x007F: return wxT("WM_GETICON");
6008 case 0x0080: return wxT("WM_SETICON");
6009
6010 case 0x0081: return wxT("WM_NCCREATE");
6011 case 0x0082: return wxT("WM_NCDESTROY");
6012 case 0x0083: return wxT("WM_NCCALCSIZE");
6013 case 0x0084: return wxT("WM_NCHITTEST");
6014 case 0x0085: return wxT("WM_NCPAINT");
6015 case 0x0086: return wxT("WM_NCACTIVATE");
6016 case 0x0087: return wxT("WM_GETDLGCODE");
6017 case 0x00A0: return wxT("WM_NCMOUSEMOVE");
6018 case 0x00A1: return wxT("WM_NCLBUTTONDOWN");
6019 case 0x00A2: return wxT("WM_NCLBUTTONUP");
6020 case 0x00A3: return wxT("WM_NCLBUTTONDBLCLK");
6021 case 0x00A4: return wxT("WM_NCRBUTTONDOWN");
6022 case 0x00A5: return wxT("WM_NCRBUTTONUP");
6023 case 0x00A6: return wxT("WM_NCRBUTTONDBLCLK");
6024 case 0x00A7: return wxT("WM_NCMBUTTONDOWN");
6025 case 0x00A8: return wxT("WM_NCMBUTTONUP");
6026 case 0x00A9: return wxT("WM_NCMBUTTONDBLCLK");
609da8bb
VZ
6027
6028 case 0x00B0: return wxT("EM_GETSEL");
6029 case 0x00B1: return wxT("EM_SETSEL");
6030 case 0x00B2: return wxT("EM_GETRECT");
6031 case 0x00B3: return wxT("EM_SETRECT");
6032 case 0x00B4: return wxT("EM_SETRECTNP");
6033 case 0x00B5: return wxT("EM_SCROLL");
6034 case 0x00B6: return wxT("EM_LINESCROLL");
6035 case 0x00B7: return wxT("EM_SCROLLCARET");
6036 case 0x00B8: return wxT("EM_GETMODIFY");
6037 case 0x00B9: return wxT("EM_SETMODIFY");
6038 case 0x00BA: return wxT("EM_GETLINECOUNT");
6039 case 0x00BB: return wxT("EM_LINEINDEX");
6040 case 0x00BC: return wxT("EM_SETHANDLE");
6041 case 0x00BD: return wxT("EM_GETHANDLE");
6042 case 0x00BE: return wxT("EM_GETTHUMB");
6043 case 0x00C1: return wxT("EM_LINELENGTH");
6044 case 0x00C2: return wxT("EM_REPLACESEL");
6045 case 0x00C4: return wxT("EM_GETLINE");
6046 case 0x00C5: return wxT("EM_LIMITTEXT/EM_SETLIMITTEXT"); /* ;win40 Name change */
6047 case 0x00C6: return wxT("EM_CANUNDO");
6048 case 0x00C7: return wxT("EM_UNDO");
6049 case 0x00C8: return wxT("EM_FMTLINES");
6050 case 0x00C9: return wxT("EM_LINEFROMCHAR");
6051 case 0x00CB: return wxT("EM_SETTABSTOPS");
6052 case 0x00CC: return wxT("EM_SETPASSWORDCHAR");
6053 case 0x00CD: return wxT("EM_EMPTYUNDOBUFFER");
6054 case 0x00CE: return wxT("EM_GETFIRSTVISIBLELINE");
6055 case 0x00CF: return wxT("EM_SETREADONLY");
6056 case 0x00D0: return wxT("EM_SETWORDBREAKPROC");
6057 case 0x00D1: return wxT("EM_GETWORDBREAKPROC");
6058 case 0x00D2: return wxT("EM_GETPASSWORDCHAR");
6059 case 0x00D3: return wxT("EM_SETMARGINS");
6060 case 0x00D4: return wxT("EM_GETMARGINS");
6061 case 0x00D5: return wxT("EM_GETLIMITTEXT");
6062 case 0x00D6: return wxT("EM_POSFROMCHAR");
6063 case 0x00D7: return wxT("EM_CHARFROMPOS");
6064 case 0x00D8: return wxT("EM_SETIMESTATUS");
6065 case 0x00D9: return wxT("EM_GETIMESTATUS");
6066
4a712ba3
VZ
6067 case 0x0100: return wxT("WM_KEYDOWN");
6068 case 0x0101: return wxT("WM_KEYUP");
6069 case 0x0102: return wxT("WM_CHAR");
6070 case 0x0103: return wxT("WM_DEADCHAR");
6071 case 0x0104: return wxT("WM_SYSKEYDOWN");
6072 case 0x0105: return wxT("WM_SYSKEYUP");
6073 case 0x0106: return wxT("WM_SYSCHAR");
6074 case 0x0107: return wxT("WM_SYSDEADCHAR");
6075 case 0x0108: return wxT("WM_KEYLAST");
6076
6077 case 0x010D: return wxT("WM_IME_STARTCOMPOSITION");
6078 case 0x010E: return wxT("WM_IME_ENDCOMPOSITION");
6079 case 0x010F: return wxT("WM_IME_COMPOSITION");
6080
6081 case 0x0110: return wxT("WM_INITDIALOG");
6082 case 0x0111: return wxT("WM_COMMAND");
6083 case 0x0112: return wxT("WM_SYSCOMMAND");
6084 case 0x0113: return wxT("WM_TIMER");
6085 case 0x0114: return wxT("WM_HSCROLL");
6086 case 0x0115: return wxT("WM_VSCROLL");
6087 case 0x0116: return wxT("WM_INITMENU");
6088 case 0x0117: return wxT("WM_INITMENUPOPUP");
6089 case 0x011F: return wxT("WM_MENUSELECT");
6090 case 0x0120: return wxT("WM_MENUCHAR");
6091 case 0x0121: return wxT("WM_ENTERIDLE");
609da8bb
VZ
6092
6093 case 0x0132: return wxT("WM_CTLCOLORMSGBOX");
6094 case 0x0133: return wxT("WM_CTLCOLOREDIT");
6095 case 0x0134: return wxT("WM_CTLCOLORLISTBOX");
6096 case 0x0135: return wxT("WM_CTLCOLORBTN");
6097 case 0x0136: return wxT("WM_CTLCOLORDLG");
6098 case 0x0137: return wxT("WM_CTLCOLORSCROLLBAR");
6099 case 0x0138: return wxT("WM_CTLCOLORSTATIC");
6100 case 0x01E1: return wxT("MN_GETHMENU");
6101
4a712ba3
VZ
6102 case 0x0200: return wxT("WM_MOUSEMOVE");
6103 case 0x0201: return wxT("WM_LBUTTONDOWN");
6104 case 0x0202: return wxT("WM_LBUTTONUP");
6105 case 0x0203: return wxT("WM_LBUTTONDBLCLK");
6106 case 0x0204: return wxT("WM_RBUTTONDOWN");
6107 case 0x0205: return wxT("WM_RBUTTONUP");
6108 case 0x0206: return wxT("WM_RBUTTONDBLCLK");
6109 case 0x0207: return wxT("WM_MBUTTONDOWN");
6110 case 0x0208: return wxT("WM_MBUTTONUP");
6111 case 0x0209: return wxT("WM_MBUTTONDBLCLK");
6112 case 0x020A: return wxT("WM_MOUSEWHEEL");
6113 case 0x0210: return wxT("WM_PARENTNOTIFY");
6114 case 0x0211: return wxT("WM_ENTERMENULOOP");
6115 case 0x0212: return wxT("WM_EXITMENULOOP");
6116
6117 case 0x0213: return wxT("WM_NEXTMENU");
6118 case 0x0214: return wxT("WM_SIZING");
6119 case 0x0215: return wxT("WM_CAPTURECHANGED");
6120 case 0x0216: return wxT("WM_MOVING");
6121 case 0x0218: return wxT("WM_POWERBROADCAST");
6122 case 0x0219: return wxT("WM_DEVICECHANGE");
6123
6124 case 0x0220: return wxT("WM_MDICREATE");
6125 case 0x0221: return wxT("WM_MDIDESTROY");
6126 case 0x0222: return wxT("WM_MDIACTIVATE");
6127 case 0x0223: return wxT("WM_MDIRESTORE");
6128 case 0x0224: return wxT("WM_MDINEXT");
6129 case 0x0225: return wxT("WM_MDIMAXIMIZE");
6130 case 0x0226: return wxT("WM_MDITILE");
6131 case 0x0227: return wxT("WM_MDICASCADE");
6132 case 0x0228: return wxT("WM_MDIICONARRANGE");
6133 case 0x0229: return wxT("WM_MDIGETACTIVE");
6134 case 0x0230: return wxT("WM_MDISETMENU");
6135 case 0x0233: return wxT("WM_DROPFILES");
6136
6137 case 0x0281: return wxT("WM_IME_SETCONTEXT");
6138 case 0x0282: return wxT("WM_IME_NOTIFY");
6139 case 0x0283: return wxT("WM_IME_CONTROL");
6140 case 0x0284: return wxT("WM_IME_COMPOSITIONFULL");
6141 case 0x0285: return wxT("WM_IME_SELECT");
6142 case 0x0286: return wxT("WM_IME_CHAR");
6143 case 0x0290: return wxT("WM_IME_KEYDOWN");
6144 case 0x0291: return wxT("WM_IME_KEYUP");
6145
609da8bb
VZ
6146 case 0x02A0: return wxT("WM_NCMOUSEHOVER");
6147 case 0x02A1: return wxT("WM_MOUSEHOVER");
6148 case 0x02A2: return wxT("WM_NCMOUSELEAVE");
6149 case 0x02A3: return wxT("WM_MOUSELEAVE");
6150
4a712ba3
VZ
6151 case 0x0300: return wxT("WM_CUT");
6152 case 0x0301: return wxT("WM_COPY");
6153 case 0x0302: return wxT("WM_PASTE");
6154 case 0x0303: return wxT("WM_CLEAR");
6155 case 0x0304: return wxT("WM_UNDO");
6156 case 0x0305: return wxT("WM_RENDERFORMAT");
6157 case 0x0306: return wxT("WM_RENDERALLFORMATS");
6158 case 0x0307: return wxT("WM_DESTROYCLIPBOARD");
6159 case 0x0308: return wxT("WM_DRAWCLIPBOARD");
6160 case 0x0309: return wxT("WM_PAINTCLIPBOARD");
6161 case 0x030A: return wxT("WM_VSCROLLCLIPBOARD");
6162 case 0x030B: return wxT("WM_SIZECLIPBOARD");
6163 case 0x030C: return wxT("WM_ASKCBFORMATNAME");
6164 case 0x030D: return wxT("WM_CHANGECBCHAIN");
6165 case 0x030E: return wxT("WM_HSCROLLCLIPBOARD");
6166 case 0x030F: return wxT("WM_QUERYNEWPALETTE");
6167 case 0x0310: return wxT("WM_PALETTEISCHANGING");
6168 case 0x0311: return wxT("WM_PALETTECHANGED");
4a712ba3 6169 case 0x0312: return wxT("WM_HOTKEY");
609da8bb
VZ
6170
6171 case 0x0317: return wxT("WM_PRINT");
6172 case 0x0318: return wxT("WM_PRINTCLIENT");
c085e333 6173
2d0a075d
JS
6174 // common controls messages - although they're not strictly speaking
6175 // standard, it's nice to decode them nevertheless
a02eb1d2 6176
2d0a075d 6177 // listview
4a712ba3
VZ
6178 case 0x1000 + 0: return wxT("LVM_GETBKCOLOR");
6179 case 0x1000 + 1: return wxT("LVM_SETBKCOLOR");
6180 case 0x1000 + 2: return wxT("LVM_GETIMAGELIST");
6181 case 0x1000 + 3: return wxT("LVM_SETIMAGELIST");
6182 case 0x1000 + 4: return wxT("LVM_GETITEMCOUNT");
6183 case 0x1000 + 5: return wxT("LVM_GETITEMA");
6184 case 0x1000 + 75: return wxT("LVM_GETITEMW");
6185 case 0x1000 + 6: return wxT("LVM_SETITEMA");
6186 case 0x1000 + 76: return wxT("LVM_SETITEMW");
6187 case 0x1000 + 7: return wxT("LVM_INSERTITEMA");
6188 case 0x1000 + 77: return wxT("LVM_INSERTITEMW");
6189 case 0x1000 + 8: return wxT("LVM_DELETEITEM");
6190 case 0x1000 + 9: return wxT("LVM_DELETEALLITEMS");
6191 case 0x1000 + 10: return wxT("LVM_GETCALLBACKMASK");
6192 case 0x1000 + 11: return wxT("LVM_SETCALLBACKMASK");
6193 case 0x1000 + 12: return wxT("LVM_GETNEXTITEM");
6194 case 0x1000 + 13: return wxT("LVM_FINDITEMA");
6195 case 0x1000 + 83: return wxT("LVM_FINDITEMW");
6196 case 0x1000 + 14: return wxT("LVM_GETITEMRECT");
6197 case 0x1000 + 15: return wxT("LVM_SETITEMPOSITION");
6198 case 0x1000 + 16: return wxT("LVM_GETITEMPOSITION");
6199 case 0x1000 + 17: return wxT("LVM_GETSTRINGWIDTHA");
6200 case 0x1000 + 87: return wxT("LVM_GETSTRINGWIDTHW");
6201 case 0x1000 + 18: return wxT("LVM_HITTEST");
6202 case 0x1000 + 19: return wxT("LVM_ENSUREVISIBLE");
6203 case 0x1000 + 20: return wxT("LVM_SCROLL");
6204 case 0x1000 + 21: return wxT("LVM_REDRAWITEMS");
6205 case 0x1000 + 22: return wxT("LVM_ARRANGE");
6206 case 0x1000 + 23: return wxT("LVM_EDITLABELA");
6207 case 0x1000 + 118: return wxT("LVM_EDITLABELW");
6208 case 0x1000 + 24: return wxT("LVM_GETEDITCONTROL");
6209 case 0x1000 + 25: return wxT("LVM_GETCOLUMNA");
6210 case 0x1000 + 95: return wxT("LVM_GETCOLUMNW");
6211 case 0x1000 + 26: return wxT("LVM_SETCOLUMNA");
6212 case 0x1000 + 96: return wxT("LVM_SETCOLUMNW");
6213 case 0x1000 + 27: return wxT("LVM_INSERTCOLUMNA");
6214 case 0x1000 + 97: return wxT("LVM_INSERTCOLUMNW");
6215 case 0x1000 + 28: return wxT("LVM_DELETECOLUMN");
6216 case 0x1000 + 29: return wxT("LVM_GETCOLUMNWIDTH");
6217 case 0x1000 + 30: return wxT("LVM_SETCOLUMNWIDTH");
6218 case 0x1000 + 31: return wxT("LVM_GETHEADER");
6219 case 0x1000 + 33: return wxT("LVM_CREATEDRAGIMAGE");
6220 case 0x1000 + 34: return wxT("LVM_GETVIEWRECT");
6221 case 0x1000 + 35: return wxT("LVM_GETTEXTCOLOR");
6222 case 0x1000 + 36: return wxT("LVM_SETTEXTCOLOR");
6223 case 0x1000 + 37: return wxT("LVM_GETTEXTBKCOLOR");
6224 case 0x1000 + 38: return wxT("LVM_SETTEXTBKCOLOR");
6225 case 0x1000 + 39: return wxT("LVM_GETTOPINDEX");
6226 case 0x1000 + 40: return wxT("LVM_GETCOUNTPERPAGE");
6227 case 0x1000 + 41: return wxT("LVM_GETORIGIN");
6228 case 0x1000 + 42: return wxT("LVM_UPDATE");
6229 case 0x1000 + 43: return wxT("LVM_SETITEMSTATE");
6230 case 0x1000 + 44: return wxT("LVM_GETITEMSTATE");
6231 case 0x1000 + 45: return wxT("LVM_GETITEMTEXTA");
6232 case 0x1000 + 115: return wxT("LVM_GETITEMTEXTW");
6233 case 0x1000 + 46: return wxT("LVM_SETITEMTEXTA");
6234 case 0x1000 + 116: return wxT("LVM_SETITEMTEXTW");
6235 case 0x1000 + 47: return wxT("LVM_SETITEMCOUNT");
6236 case 0x1000 + 48: return wxT("LVM_SORTITEMS");
6237 case 0x1000 + 49: return wxT("LVM_SETITEMPOSITION32");
6238 case 0x1000 + 50: return wxT("LVM_GETSELECTEDCOUNT");
6239 case 0x1000 + 51: return wxT("LVM_GETITEMSPACING");
6240 case 0x1000 + 52: return wxT("LVM_GETISEARCHSTRINGA");
6241 case 0x1000 + 117: return wxT("LVM_GETISEARCHSTRINGW");
6242 case 0x1000 + 53: return wxT("LVM_SETICONSPACING");
6243 case 0x1000 + 54: return wxT("LVM_SETEXTENDEDLISTVIEWSTYLE");
6244 case 0x1000 + 55: return wxT("LVM_GETEXTENDEDLISTVIEWSTYLE");
6245 case 0x1000 + 56: return wxT("LVM_GETSUBITEMRECT");
6246 case 0x1000 + 57: return wxT("LVM_SUBITEMHITTEST");
6247 case 0x1000 + 58: return wxT("LVM_SETCOLUMNORDERARRAY");
6248 case 0x1000 + 59: return wxT("LVM_GETCOLUMNORDERARRAY");
6249 case 0x1000 + 60: return wxT("LVM_SETHOTITEM");
6250 case 0x1000 + 61: return wxT("LVM_GETHOTITEM");
6251 case 0x1000 + 62: return wxT("LVM_SETHOTCURSOR");
6252 case 0x1000 + 63: return wxT("LVM_GETHOTCURSOR");
6253 case 0x1000 + 64: return wxT("LVM_APPROXIMATEVIEWRECT");
6254 case 0x1000 + 65: return wxT("LVM_SETWORKAREA");
c085e333 6255
2d0a075d 6256 // tree view
4a712ba3
VZ
6257 case 0x1100 + 0: return wxT("TVM_INSERTITEMA");
6258 case 0x1100 + 50: return wxT("TVM_INSERTITEMW");
6259 case 0x1100 + 1: return wxT("TVM_DELETEITEM");
6260 case 0x1100 + 2: return wxT("TVM_EXPAND");
6261 case 0x1100 + 4: return wxT("TVM_GETITEMRECT");
6262 case 0x1100 + 5: return wxT("TVM_GETCOUNT");
6263 case 0x1100 + 6: return wxT("TVM_GETINDENT");
6264 case 0x1100 + 7: return wxT("TVM_SETINDENT");
6265 case 0x1100 + 8: return wxT("TVM_GETIMAGELIST");
6266 case 0x1100 + 9: return wxT("TVM_SETIMAGELIST");
6267 case 0x1100 + 10: return wxT("TVM_GETNEXTITEM");
6268 case 0x1100 + 11: return wxT("TVM_SELECTITEM");
6269 case 0x1100 + 12: return wxT("TVM_GETITEMA");
6270 case 0x1100 + 62: return wxT("TVM_GETITEMW");
6271 case 0x1100 + 13: return wxT("TVM_SETITEMA");
6272 case 0x1100 + 63: return wxT("TVM_SETITEMW");
6273 case 0x1100 + 14: return wxT("TVM_EDITLABELA");
6274 case 0x1100 + 65: return wxT("TVM_EDITLABELW");
6275 case 0x1100 + 15: return wxT("TVM_GETEDITCONTROL");
6276 case 0x1100 + 16: return wxT("TVM_GETVISIBLECOUNT");
6277 case 0x1100 + 17: return wxT("TVM_HITTEST");
6278 case 0x1100 + 18: return wxT("TVM_CREATEDRAGIMAGE");
6279 case 0x1100 + 19: return wxT("TVM_SORTCHILDREN");
6280 case 0x1100 + 20: return wxT("TVM_ENSUREVISIBLE");
6281 case 0x1100 + 21: return wxT("TVM_SORTCHILDRENCB");
6282 case 0x1100 + 22: return wxT("TVM_ENDEDITLABELNOW");
6283 case 0x1100 + 23: return wxT("TVM_GETISEARCHSTRINGA");
6284 case 0x1100 + 64: return wxT("TVM_GETISEARCHSTRINGW");
6285 case 0x1100 + 24: return wxT("TVM_SETTOOLTIPS");
6286 case 0x1100 + 25: return wxT("TVM_GETTOOLTIPS");
c085e333 6287
2d0a075d 6288 // header
4a712ba3
VZ
6289 case 0x1200 + 0: return wxT("HDM_GETITEMCOUNT");
6290 case 0x1200 + 1: return wxT("HDM_INSERTITEMA");
6291 case 0x1200 + 10: return wxT("HDM_INSERTITEMW");
6292 case 0x1200 + 2: return wxT("HDM_DELETEITEM");
6293 case 0x1200 + 3: return wxT("HDM_GETITEMA");
6294 case 0x1200 + 11: return wxT("HDM_GETITEMW");
6295 case 0x1200 + 4: return wxT("HDM_SETITEMA");
6296 case 0x1200 + 12: return wxT("HDM_SETITEMW");
6297 case 0x1200 + 5: return wxT("HDM_LAYOUT");
6298 case 0x1200 + 6: return wxT("HDM_HITTEST");
6299 case 0x1200 + 7: return wxT("HDM_GETITEMRECT");
6300 case 0x1200 + 8: return wxT("HDM_SETIMAGELIST");
6301 case 0x1200 + 9: return wxT("HDM_GETIMAGELIST");
6302 case 0x1200 + 15: return wxT("HDM_ORDERTOINDEX");
6303 case 0x1200 + 16: return wxT("HDM_CREATEDRAGIMAGE");
6304 case 0x1200 + 17: return wxT("HDM_GETORDERARRAY");
6305 case 0x1200 + 18: return wxT("HDM_SETORDERARRAY");
6306 case 0x1200 + 19: return wxT("HDM_SETHOTDIVIDER");
c085e333 6307
2d0a075d 6308 // tab control
4a712ba3
VZ
6309 case 0x1300 + 2: return wxT("TCM_GETIMAGELIST");
6310 case 0x1300 + 3: return wxT("TCM_SETIMAGELIST");
6311 case 0x1300 + 4: return wxT("TCM_GETITEMCOUNT");
6312 case 0x1300 + 5: return wxT("TCM_GETITEMA");
6313 case 0x1300 + 60: return wxT("TCM_GETITEMW");
6314 case 0x1300 + 6: return wxT("TCM_SETITEMA");
6315 case 0x1300 + 61: return wxT("TCM_SETITEMW");
6316 case 0x1300 + 7: return wxT("TCM_INSERTITEMA");
6317 case 0x1300 + 62: return wxT("TCM_INSERTITEMW");
6318 case 0x1300 + 8: return wxT("TCM_DELETEITEM");
6319 case 0x1300 + 9: return wxT("TCM_DELETEALLITEMS");
6320 case 0x1300 + 10: return wxT("TCM_GETITEMRECT");
6321 case 0x1300 + 11: return wxT("TCM_GETCURSEL");
6322 case 0x1300 + 12: return wxT("TCM_SETCURSEL");
6323 case 0x1300 + 13: return wxT("TCM_HITTEST");
6324 case 0x1300 + 14: return wxT("TCM_SETITEMEXTRA");
6325 case 0x1300 + 40: return wxT("TCM_ADJUSTRECT");
6326 case 0x1300 + 41: return wxT("TCM_SETITEMSIZE");
6327 case 0x1300 + 42: return wxT("TCM_REMOVEIMAGE");
6328 case 0x1300 + 43: return wxT("TCM_SETPADDING");
6329 case 0x1300 + 44: return wxT("TCM_GETROWCOUNT");
6330 case 0x1300 + 45: return wxT("TCM_GETTOOLTIPS");
6331 case 0x1300 + 46: return wxT("TCM_SETTOOLTIPS");
6332 case 0x1300 + 47: return wxT("TCM_GETCURFOCUS");
6333 case 0x1300 + 48: return wxT("TCM_SETCURFOCUS");
6334 case 0x1300 + 49: return wxT("TCM_SETMINTABWIDTH");
6335 case 0x1300 + 50: return wxT("TCM_DESELECTALL");
c085e333 6336
2d0a075d 6337 // toolbar
4a712ba3
VZ
6338 case WM_USER+1: return wxT("TB_ENABLEBUTTON");
6339 case WM_USER+2: return wxT("TB_CHECKBUTTON");
6340 case WM_USER+3: return wxT("TB_PRESSBUTTON");
6341 case WM_USER+4: return wxT("TB_HIDEBUTTON");
6342 case WM_USER+5: return wxT("TB_INDETERMINATE");
6343 case WM_USER+9: return wxT("TB_ISBUTTONENABLED");
6344 case WM_USER+10: return wxT("TB_ISBUTTONCHECKED");
6345 case WM_USER+11: return wxT("TB_ISBUTTONPRESSED");
6346 case WM_USER+12: return wxT("TB_ISBUTTONHIDDEN");
6347 case WM_USER+13: return wxT("TB_ISBUTTONINDETERMINATE");
6348 case WM_USER+17: return wxT("TB_SETSTATE");
6349 case WM_USER+18: return wxT("TB_GETSTATE");
6350 case WM_USER+19: return wxT("TB_ADDBITMAP");
6351 case WM_USER+20: return wxT("TB_ADDBUTTONS");
6352 case WM_USER+21: return wxT("TB_INSERTBUTTON");
6353 case WM_USER+22: return wxT("TB_DELETEBUTTON");
6354 case WM_USER+23: return wxT("TB_GETBUTTON");
6355 case WM_USER+24: return wxT("TB_BUTTONCOUNT");
6356 case WM_USER+25: return wxT("TB_COMMANDTOINDEX");
6357 case WM_USER+26: return wxT("TB_SAVERESTOREA");
6358 case WM_USER+76: return wxT("TB_SAVERESTOREW");
6359 case WM_USER+27: return wxT("TB_CUSTOMIZE");
6360 case WM_USER+28: return wxT("TB_ADDSTRINGA");
6361 case WM_USER+77: return wxT("TB_ADDSTRINGW");
6362 case WM_USER+29: return wxT("TB_GETITEMRECT");
6363 case WM_USER+30: return wxT("TB_BUTTONSTRUCTSIZE");
6364 case WM_USER+31: return wxT("TB_SETBUTTONSIZE");
6365 case WM_USER+32: return wxT("TB_SETBITMAPSIZE");
6366 case WM_USER+33: return wxT("TB_AUTOSIZE");
6367 case WM_USER+35: return wxT("TB_GETTOOLTIPS");
6368 case WM_USER+36: return wxT("TB_SETTOOLTIPS");
6369 case WM_USER+37: return wxT("TB_SETPARENT");
6370 case WM_USER+39: return wxT("TB_SETROWS");
6371 case WM_USER+40: return wxT("TB_GETROWS");
6372 case WM_USER+42: return wxT("TB_SETCMDID");
6373 case WM_USER+43: return wxT("TB_CHANGEBITMAP");
6374 case WM_USER+44: return wxT("TB_GETBITMAP");
6375 case WM_USER+45: return wxT("TB_GETBUTTONTEXTA");
6376 case WM_USER+75: return wxT("TB_GETBUTTONTEXTW");
6377 case WM_USER+46: return wxT("TB_REPLACEBITMAP");
6378 case WM_USER+47: return wxT("TB_SETINDENT");
6379 case WM_USER+48: return wxT("TB_SETIMAGELIST");
6380 case WM_USER+49: return wxT("TB_GETIMAGELIST");
6381 case WM_USER+50: return wxT("TB_LOADIMAGES");
6382 case WM_USER+51: return wxT("TB_GETRECT");
6383 case WM_USER+52: return wxT("TB_SETHOTIMAGELIST");
6384 case WM_USER+53: return wxT("TB_GETHOTIMAGELIST");
6385 case WM_USER+54: return wxT("TB_SETDISABLEDIMAGELIST");
6386 case WM_USER+55: return wxT("TB_GETDISABLEDIMAGELIST");
6387 case WM_USER+56: return wxT("TB_SETSTYLE");
6388 case WM_USER+57: return wxT("TB_GETSTYLE");
6389 case WM_USER+58: return wxT("TB_GETBUTTONSIZE");
6390 case WM_USER+59: return wxT("TB_SETBUTTONWIDTH");
6391 case WM_USER+60: return wxT("TB_SETMAXTEXTROWS");
6392 case WM_USER+61: return wxT("TB_GETTEXTROWS");
6393 case WM_USER+41: return wxT("TB_GETBITMAPFLAGS");
c085e333 6394
42e69d6b 6395 default:
4a712ba3
VZ
6396 static wxString s_szBuf;
6397 s_szBuf.Printf(wxT("<unknown message = %d>"), message);
6398 return s_szBuf.c_str();
42e69d6b 6399 }
47cbd6da 6400}
ea57084d 6401#endif //__WXDEBUG__
4aff28fc 6402
1e6feb95 6403static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win)
f6bcfd97
BP
6404{
6405 // prepare the DC
6406 TEXTMETRIC tm;
6407 HWND hwnd = GetHwndOf(win);
6408 HDC hdc = ::GetDC(hwnd);
6409
6410#if !wxDIALOG_UNIT_COMPATIBILITY
6411 // and select the current font into it
6412 HFONT hfont = GetHfontOf(win->GetFont());
6413 if ( hfont )
6414 {
6415 hfont = (HFONT)::SelectObject(hdc, hfont);
6416 }
6417#endif
6418
6419 // finally retrieve the text metrics from it
6420 GetTextMetrics(hdc, &tm);
6421
6422#if !wxDIALOG_UNIT_COMPATIBILITY
6423 // and clean up
6424 if ( hfont )
6425 {
6426 (void)::SelectObject(hdc, hfont);
6427 }
6428#endif
6429
6430 ::ReleaseDC(hwnd, hdc);
6431
6432 return tm;
6433}
3723b7b1
JS
6434
6435// Find the wxWindow at the current mouse position, returning the mouse
6436// position.
2b5f62a0 6437wxWindow* wxFindWindowAtPointer(wxPoint& pt)
3723b7b1 6438{
2b5f62a0
VZ
6439 pt = wxGetMousePosition();
6440 return wxFindWindowAtPoint(pt);
57591e0e
JS
6441}
6442
6443wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
6444{
6445 POINT pt2;
6446 pt2.x = pt.x;
6447 pt2.y = pt.y;
3723b7b1 6448
ab3eae34 6449 HWND hWnd = ::WindowFromPoint(pt2);
3723b7b1 6450
ab3eae34 6451 return wxGetWindowFromHWND((WXHWND)hWnd);
3723b7b1
JS
6452}
6453
6454// Get the current mouse position.
6455wxPoint wxGetMousePosition()
6456{
1772ead0 6457 POINT pt;
f2325516
JS
6458#ifdef __WXWINCE__
6459 GetCursorPosWinCE(&pt);
6460#else
1772ead0 6461 GetCursorPos( & pt );
f2325516 6462#endif
5cd16c0c 6463
1772ead0 6464 return wxPoint(pt.x, pt.y);
3723b7b1
JS
6465}
6466
5048c832 6467#if wxUSE_HOTKEY
540b6b09 6468
afafd942
JS
6469#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6470static void WinCEUnregisterHotKey(int modifiers, int id)
6471{
6472 // Register hotkeys for the hardware buttons
6473 HINSTANCE hCoreDll;
6474 typedef BOOL (WINAPI *UnregisterFunc1Proc)(UINT, UINT);
6475
6476 UnregisterFunc1Proc procUnregisterFunc;
6477 hCoreDll = LoadLibrary(_T("coredll.dll"));
6478 if (hCoreDll)
6479 {
6480 procUnregisterFunc = (UnregisterFunc1Proc)GetProcAddress(hCoreDll, _T("UnregisterFunc1"));
6481 if (procUnregisterFunc)
6482 procUnregisterFunc(modifiers, id);
6483 FreeLibrary(hCoreDll);
6484 }
6485}
6486#endif
6487
540b6b09 6488bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
5048c832
JS
6489{
6490 UINT win_modifiers=0;
540b6b09
VZ
6491 if ( modifiers & wxMOD_ALT )
6492 win_modifiers |= MOD_ALT;
6493 if ( modifiers & wxMOD_SHIFT )
6494 win_modifiers |= MOD_SHIFT;
6495 if ( modifiers & wxMOD_CONTROL )
6496 win_modifiers |= MOD_CONTROL;
6497 if ( modifiers & wxMOD_WIN )
6498 win_modifiers |= MOD_WIN;
6499
afafd942
JS
6500#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6501 // Required for PPC and Smartphone hardware buttons
6502 if (keycode >= WXK_SPECIAL1 && keycode <= WXK_SPECIAL20)
6503 WinCEUnregisterHotKey(win_modifiers, hotkeyId);
6504#endif
6505
540b6b09
VZ
6506 if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) )
6507 {
6508 wxLogLastError(_T("RegisterHotKey"));
5048c832 6509
08158721 6510 return false;
540b6b09
VZ
6511 }
6512
08158721 6513 return true;
5048c832
JS
6514}
6515
6516bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
6517{
afafd942
JS
6518#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
6519 WinCEUnregisterHotKey(MOD_WIN, hotkeyId);
6520#endif
6521
540b6b09
VZ
6522 if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) )
6523 {
6524 wxLogLastError(_T("UnregisterHotKey"));
6525
08158721 6526 return false;
540b6b09
VZ
6527 }
6528
08158721 6529 return true;
5048c832
JS
6530}
6531
0b4f47a3
DS
6532#if wxUSE_ACCEL
6533
5048c832
JS
6534bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
6535{
540b6b09
VZ
6536 int hotkeyId = wParam;
6537 int virtualKey = HIWORD(lParam);
6538 int win_modifiers = LOWORD(lParam);
6539
5048c832
JS
6540 wxKeyEvent event(CreateKeyEvent(wxEVT_HOTKEY, virtualKey, wParam, lParam));
6541 event.SetId(hotkeyId);
6542 event.m_shiftDown = (win_modifiers & MOD_SHIFT) != 0;
6543 event.m_controlDown = (win_modifiers & MOD_CONTROL) != 0;
6544 event.m_altDown = (win_modifiers & MOD_ALT) != 0;
6545 event.m_metaDown = (win_modifiers & MOD_WIN) != 0;
540b6b09
VZ
6546
6547 return GetEventHandler()->ProcessEvent(event);
5048c832 6548}
540b6b09 6549
0b4f47a3
DS
6550#endif // wxUSE_ACCEL
6551
540b6b09 6552#endif // wxUSE_HOTKEY
5048c832 6553
550049c2 6554// Not tested under WinCE
d79df32c 6555#ifndef __WXWINCE__
d79df32c 6556
550049c2
VZ
6557// this class installs a message hook which really wakes up our idle processing
6558// each time a WM_NULL is received (wxWakeUpIdle does this), even if we're
6559// sitting inside a local modal loop (e.g. a menu is opened or scrollbar is
6560// being dragged or even inside ::MessageBox()) and so don't control message
6561// dispatching otherwise
6562class wxIdleWakeUpModule : public wxModule
6563{
d79df32c 6564public:
3a3c8603 6565 virtual bool OnInit()
550049c2 6566 {
3a3c8603 6567 ms_hMsgHookProc = ::SetWindowsHookEx
550049c2
VZ
6568 (
6569 WH_GETMESSAGE,
6570 &wxIdleWakeUpModule::MsgHookProc,
6571 NULL,
6572 GetCurrentThreadId()
6573 );
d79df32c 6574
550049c2
VZ
6575 if ( !ms_hMsgHookProc )
6576 {
6577 wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)"));
6578
6579 return false;
6580 }
6581
6582 return true;
3a3c8603 6583 }
550049c2 6584
3a3c8603 6585 virtual void OnExit()
550049c2 6586 {
3a3c8603
DS
6587 ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc);
6588 }
550049c2 6589
3a3c8603 6590 static LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
550049c2 6591 {
3a3c8603 6592 MSG *msg = (MSG*)lParam;
34ea3c74
VZ
6593
6594 // only process the message if it is actually going to be removed from
6595 // the message queue, this prevents that the same event from being
6596 // processed multiple times if now someone just called PeekMessage()
6597 if ( msg->message == WM_NULL && wParam == PM_REMOVE )
3a3c8603 6598 {
550049c2 6599 wxTheApp->ProcessPendingEvents();
3a3c8603 6600 }
550049c2 6601
3a3c8603
DS
6602 return CallNextHookEx(ms_hMsgHookProc, nCode, wParam, lParam);
6603 };
550049c2 6604
d79df32c 6605private:
3a3c8603 6606 static HHOOK ms_hMsgHookProc;
550049c2
VZ
6607
6608 DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule)
d79df32c 6609};
d79df32c 6610
550049c2
VZ
6611HHOOK wxIdleWakeUpModule::ms_hMsgHookProc = 0;
6612
6613IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule, wxModule)
6614
6615#endif // __WXWINCE__
3a3c8603 6616
d26e1ab2
JS
6617#ifdef __WXWINCE__
6618
6619#if wxUSE_STATBOX
6620static void wxAdjustZOrder(wxWindow* parent)
6621{
6622 if (parent->IsKindOf(CLASSINFO(wxStaticBox)))
6623 {
6624 // Set the z-order correctly
6625 SetWindowPos((HWND) parent->GetHWND(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
6626 }
35bbb0c6 6627
d26e1ab2
JS
6628 wxWindowList::compatibility_iterator current = parent->GetChildren().GetFirst();
6629 while (current)
6630 {
6631 wxWindow *childWin = current->GetData();
6632 wxAdjustZOrder(childWin);
6633 current = current->GetNext();
6634 }
6635}
6636#endif
6637
6638// We need to adjust the z-order of static boxes in WinCE, to
6639// make 'contained' controls visible
6640void wxWindowMSW::OnInitDialog( wxInitDialogEvent& event )
6641{
6642#if wxUSE_STATBOX
6643 wxAdjustZOrder(this);
6644#endif
35bbb0c6 6645
d26e1ab2
JS
6646 event.Skip();
6647}
6648#endif