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