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