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