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