~ubuntu-dev/wxwidgets2.6/upstream-debian

« back to all changes in this revision

Viewing changes to src/msw/window.cpp

  • Committer: Daniel T Chen
  • Date: 2006-06-26 10:15:11 UTC
  • Revision ID: crimsun@ubuntu.com-20060626101511-a4436cec4c6d9b35
ImportĀ DebianĀ 2.6.3.2.1

Show diffs side-by-side

added added

removed removed

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