~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to src/msw/window.cpp

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

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