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