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

« back to all changes in this revision

Viewing changes to src/msw/menuitem.cpp

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/msw/menuitem.cpp
 
3
// Purpose:     wxMenuItem implementation
 
4
// Author:      Vadim Zeitlin
 
5
// Modified by:
 
6
// Created:     11.11.97
 
7
// RCS-ID:      $Id: menuitem.cpp 71640 2012-06-03 19:16:59Z VZ $
 
8
// Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
 
9
// Licence:     wxWindows licence
 
10
///////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
// ===========================================================================
 
13
// declarations
 
14
// ===========================================================================
 
15
 
 
16
// ---------------------------------------------------------------------------
 
17
// headers
 
18
// ---------------------------------------------------------------------------
 
19
 
 
20
// For compilers that support precompilation, includes "wx.h".
 
21
#include "wx/wxprec.h"
 
22
 
 
23
#ifdef __BORLANDC__
 
24
    #pragma hdrstop
 
25
#endif
 
26
 
 
27
#if wxUSE_MENUS
 
28
 
 
29
#include "wx/menuitem.h"
 
30
#include "wx/stockitem.h"
 
31
 
 
32
#ifndef WX_PRECOMP
 
33
    #include "wx/app.h"
 
34
    #include "wx/dcmemory.h"
 
35
    #include "wx/font.h"
 
36
    #include "wx/bitmap.h"
 
37
    #include "wx/settings.h"
 
38
    #include "wx/window.h"
 
39
    #include "wx/accel.h"
 
40
    #include "wx/string.h"
 
41
    #include "wx/log.h"
 
42
    #include "wx/menu.h"
 
43
#endif
 
44
 
 
45
#if wxUSE_ACCEL
 
46
    #include "wx/accel.h"
 
47
#endif // wxUSE_ACCEL
 
48
 
 
49
#include "wx/msw/private.h"
 
50
#include "wx/msw/dc.h"
 
51
 
 
52
#ifdef __WXWINCE__
 
53
// Implemented in menu.cpp
 
54
UINT GetMenuState(HMENU hMenu, UINT id, UINT flags) ;
 
55
#endif
 
56
 
 
57
#if wxUSE_UXTHEME
 
58
    #include "wx/msw/uxtheme.h"
 
59
#endif
 
60
 
 
61
// ---------------------------------------------------------------------------
 
62
// macro
 
63
// ---------------------------------------------------------------------------
 
64
 
 
65
// hide the ugly cast
 
66
#define GetHMenuOf(menu)    ((HMENU)menu->GetHMenu())
 
67
 
 
68
// ----------------------------------------------------------------------------
 
69
// helper classes for temporarily changing HDC parameters
 
70
// ----------------------------------------------------------------------------
 
71
 
 
72
namespace
 
73
{
 
74
 
 
75
// This class just stores an HDC.
 
76
class HDCHandler
 
77
{
 
78
protected:
 
79
    HDCHandler(HDC hdc) : m_hdc(hdc) { }
 
80
 
 
81
    const HDC m_hdc;
 
82
};
 
83
 
 
84
class HDCTextColChanger : HDCHandler
 
85
{
 
86
public:
 
87
    HDCTextColChanger(HDC hdc, COLORREF col)
 
88
        : HDCHandler(hdc),
 
89
          m_colOld(::SetTextColor(hdc, col))
 
90
    {
 
91
    }
 
92
 
 
93
    ~HDCTextColChanger()
 
94
    {
 
95
        ::SetTextColor(m_hdc, m_colOld);
 
96
    }
 
97
 
 
98
private:
 
99
    COLORREF m_colOld;
 
100
};
 
101
 
 
102
class HDCBgColChanger : HDCHandler
 
103
{
 
104
public:
 
105
    HDCBgColChanger(HDC hdc, COLORREF col)
 
106
        : HDCHandler(hdc),
 
107
          m_colOld(::SetBkColor(hdc, col))
 
108
    {
 
109
    }
 
110
 
 
111
    ~HDCBgColChanger()
 
112
    {
 
113
        ::SetBkColor(m_hdc, m_colOld);
 
114
    }
 
115
 
 
116
private:
 
117
    COLORREF m_colOld;
 
118
};
 
119
 
 
120
class HDCBgModeChanger : HDCHandler
 
121
{
 
122
public:
 
123
    HDCBgModeChanger(HDC hdc, int mode)
 
124
        : HDCHandler(hdc),
 
125
          m_modeOld(::SetBkMode(hdc, mode))
 
126
    {
 
127
    }
 
128
 
 
129
    ~HDCBgModeChanger()
 
130
    {
 
131
        ::SetBkMode(m_hdc, m_modeOld);
 
132
    }
 
133
 
 
134
private:
 
135
    int m_modeOld;
 
136
};
 
137
 
 
138
} // anonymous namespace
 
139
 
 
140
// ============================================================================
 
141
// implementation
 
142
// ============================================================================
 
143
 
 
144
#if wxUSE_OWNER_DRAWN
 
145
 
 
146
#include "wx/fontutil.h"
 
147
#include "wx/msw/private/metrics.h"
 
148
 
 
149
#ifndef SPI_GETKEYBOARDCUES
 
150
#define SPI_GETKEYBOARDCUES 0x100A
 
151
#endif
 
152
 
 
153
#ifndef DSS_HIDEPREFIX
 
154
#define DSS_HIDEPREFIX  0x0200
 
155
#endif
 
156
 
 
157
#if wxUSE_UXTHEME
 
158
 
 
159
enum MENUPARTS
 
160
{
 
161
    MENU_MENUITEM_TMSCHEMA = 1,
 
162
    MENU_SEPARATOR_TMSCHEMA = 6,
 
163
    MENU_POPUPBACKGROUND = 9,
 
164
    MENU_POPUPBORDERS = 10,
 
165
    MENU_POPUPCHECK = 11,
 
166
    MENU_POPUPCHECKBACKGROUND = 12,
 
167
    MENU_POPUPGUTTER = 13,
 
168
    MENU_POPUPITEM = 14,
 
169
    MENU_POPUPSEPARATOR = 15,
 
170
    MENU_POPUPSUBMENU = 16,
 
171
};
 
172
 
 
173
 
 
174
enum POPUPITEMSTATES
 
175
{
 
176
    MPI_NORMAL = 1,
 
177
    MPI_HOT = 2,
 
178
    MPI_DISABLED = 3,
 
179
    MPI_DISABLEDHOT = 4,
 
180
};
 
181
 
 
182
enum POPUPCHECKBACKGROUNDSTATES
 
183
{
 
184
    MCB_DISABLED = 1,
 
185
    MCB_NORMAL = 2,
 
186
    MCB_BITMAP = 3,
 
187
};
 
188
 
 
189
enum POPUPCHECKSTATES
 
190
{
 
191
    MC_CHECKMARKNORMAL = 1,
 
192
    MC_CHECKMARKDISABLED = 2,
 
193
    MC_BULLETNORMAL = 3,
 
194
    MC_BULLETDISABLED = 4,
 
195
};
 
196
 
 
197
const int TMT_MENUFONT       = 803;
 
198
const int TMT_BORDERSIZE     = 2403;
 
199
const int TMT_CONTENTMARGINS = 3602;
 
200
const int TMT_SIZINGMARGINS  = 3601;
 
201
 
 
202
#endif // wxUSE_UXTHEME
 
203
 
 
204
#endif // wxUSE_OWNER_DRAWN
 
205
 
 
206
// ----------------------------------------------------------------------------
 
207
// dynamic classes implementation
 
208
// ----------------------------------------------------------------------------
 
209
 
 
210
// ----------------------------------------------------------------------------
 
211
// wxMenuItem
 
212
// ----------------------------------------------------------------------------
 
213
 
 
214
#if wxUSE_OWNER_DRAWN
 
215
 
 
216
namespace
 
217
{
 
218
 
 
219
// helper class to keep information about metrics and other stuff
 
220
// needed for measuring and drawing menu item
 
221
class MenuDrawData
 
222
{
 
223
public:
 
224
    // Wrapper around standard MARGINS structure providing some helper
 
225
    // functions and automatically initializing the margin fields to 0.
 
226
    struct Margins : MARGINS
 
227
    {
 
228
        Margins()
 
229
        {
 
230
            cxLeftWidth =
 
231
            cxRightWidth =
 
232
            cyTopHeight =
 
233
            cyBottomHeight = 0;
 
234
        }
 
235
 
 
236
        int GetTotalX() const { return cxLeftWidth + cxRightWidth; }
 
237
        int GetTotalY() const { return cyTopHeight + cyBottomHeight; }
 
238
 
 
239
        void ApplyTo(RECT& rect) const
 
240
        {
 
241
            rect.top += cyTopHeight;
 
242
            rect.left += cxLeftWidth;
 
243
            rect.right -= cyTopHeight;
 
244
            rect.bottom -= cyBottomHeight;
 
245
        }
 
246
 
 
247
        void UnapplyFrom(RECT& rect) const
 
248
        {
 
249
            rect.top -= cyTopHeight;
 
250
            rect.left -= cxLeftWidth;
 
251
            rect.right += cyTopHeight;
 
252
            rect.bottom += cyBottomHeight;
 
253
        }
 
254
    };
 
255
 
 
256
    Margins ItemMargin;         // popup item margins
 
257
 
 
258
    Margins CheckMargin;        // popup check margins
 
259
    Margins CheckBgMargin;      // popup check background margins
 
260
 
 
261
    Margins ArrowMargin;        // popup submenu arrow margins
 
262
 
 
263
    Margins SeparatorMargin;    // popup separator margins
 
264
 
 
265
    SIZE CheckSize;             // popup check size metric
 
266
    SIZE ArrowSize;             // popup submenu arrow size metric
 
267
    SIZE SeparatorSize;         // popup separator size metric
 
268
 
 
269
    int TextBorder;             // popup border space between
 
270
                                // item text and gutter
 
271
 
 
272
    int AccelBorder;            // popup border space between
 
273
                                // item text and accelerator
 
274
 
 
275
    int ArrowBorder;            // popup border space between
 
276
                                // item accelerator and submenu arrow
 
277
 
 
278
    int Offset;                 // system added space at the end of the menu,
 
279
                                // add this offset for remove the extra space
 
280
 
 
281
    wxFont Font;                // default menu font
 
282
 
 
283
    bool AlwaysShowCues;        // must keyboard cues always be shown?
 
284
 
 
285
    bool Theme;                 // is data initialized for FullTheme?
 
286
 
 
287
    static const MenuDrawData* Get()
 
288
    {
 
289
        // notice that s_menuData can't be created as a global variable because
 
290
        // it needs a window to initialize and no windows exist at the time of
 
291
        // globals initialization yet
 
292
        if ( !ms_instance )
 
293
        {
 
294
            static MenuDrawData s_menuData;
 
295
            ms_instance = &s_menuData;
 
296
        }
 
297
 
 
298
    #if wxUSE_UXTHEME
 
299
        bool theme = MenuLayout() == FullTheme;
 
300
        if ( ms_instance->Theme != theme )
 
301
            ms_instance->Init();
 
302
    #endif // wxUSE_UXTHEME
 
303
        return ms_instance;
 
304
    }
 
305
 
 
306
    MenuDrawData()
 
307
    {
 
308
        Init();
 
309
    }
 
310
 
 
311
 
 
312
    // get the theme engine or NULL if themes
 
313
    // are not available or not supported on menu
 
314
    static wxUxThemeEngine *GetUxThemeEngine()
 
315
    {
 
316
    #if wxUSE_UXTHEME
 
317
        if ( MenuLayout() == FullTheme )
 
318
            return wxUxThemeEngine::GetIfActive();
 
319
    #endif // wxUSE_UXTHEME
 
320
        return NULL;
 
321
    }
 
322
 
 
323
 
 
324
    enum MenuLayoutType
 
325
    {
 
326
        FullTheme,      // full menu themes (Vista or new)
 
327
        PseudoTheme,    // pseudo menu themes (on XP)
 
328
        Classic
 
329
    };
 
330
 
 
331
    static MenuLayoutType MenuLayout()
 
332
    {
 
333
        MenuLayoutType menu = Classic;
 
334
    #if wxUSE_UXTHEME
 
335
        if ( wxUxThemeEngine::GetIfActive() != NULL )
 
336
        {
 
337
            static wxWinVersion ver = wxGetWinVersion();
 
338
            if ( ver >= wxWinVersion_Vista )
 
339
                menu = FullTheme;
 
340
            else if ( ver == wxWinVersion_XP )
 
341
                menu = PseudoTheme;
 
342
        }
 
343
    #endif // wxUSE_UXTHEME
 
344
        return menu;
 
345
    }
 
346
 
 
347
private:
 
348
    void Init();
 
349
 
 
350
    static MenuDrawData* ms_instance;
 
351
};
 
352
 
 
353
MenuDrawData* MenuDrawData::ms_instance = NULL;
 
354
 
 
355
void MenuDrawData::Init()
 
356
{
 
357
#if wxUSE_UXTHEME
 
358
    wxUxThemeEngine* theme = GetUxThemeEngine();
 
359
    if ( theme )
 
360
    {
 
361
        wxWindow* window = static_cast<wxApp*>(wxApp::GetInstance())->GetTopWindow();
 
362
        wxUxThemeHandle hTheme(window, L"MENU");
 
363
 
 
364
        theme->GetThemeMargins(hTheme, NULL, MENU_POPUPITEM, 0,
 
365
                               TMT_CONTENTMARGINS, NULL,
 
366
                               &ItemMargin);
 
367
 
 
368
        theme->GetThemeMargins(hTheme, NULL, MENU_POPUPCHECK, 0,
 
369
                               TMT_CONTENTMARGINS, NULL,
 
370
                               &CheckMargin);
 
371
        theme->GetThemeMargins(hTheme, NULL, MENU_POPUPCHECKBACKGROUND, 0,
 
372
                               TMT_CONTENTMARGINS, NULL,
 
373
                               &CheckBgMargin);
 
374
 
 
375
        theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSUBMENU, 0,
 
376
                               TMT_CONTENTMARGINS, NULL,
 
377
                               &ArrowMargin);
 
378
 
 
379
        theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSEPARATOR, 0,
 
380
                               TMT_SIZINGMARGINS, NULL,
 
381
                               &SeparatorMargin);
 
382
 
 
383
        theme->GetThemePartSize(hTheme, NULL, MENU_POPUPCHECK, 0,
 
384
                                NULL, TS_TRUE, &CheckSize);
 
385
 
 
386
        theme->GetThemePartSize(hTheme, NULL, MENU_POPUPSUBMENU, 0,
 
387
                                NULL, TS_TRUE, &ArrowSize);
 
388
 
 
389
        theme->GetThemePartSize(hTheme, NULL, MENU_POPUPSEPARATOR, 0,
 
390
                                NULL, TS_TRUE, &SeparatorSize);
 
391
 
 
392
        theme->GetThemeInt(hTheme, MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &TextBorder);
 
393
 
 
394
        AccelBorder = 34;
 
395
        ArrowBorder = 0;
 
396
 
 
397
        Offset = -14;
 
398
 
 
399
        wxUxThemeFont themeFont;
 
400
        theme->GetThemeSysFont(hTheme, TMT_MENUFONT, themeFont.GetPtr());
 
401
        Font = wxFont(themeFont.GetLOGFONT());
 
402
 
 
403
        Theme = true;
 
404
 
 
405
        // native menu doesn't uses the vertical margins
 
406
        ItemMargin.cyTopHeight =
 
407
        ItemMargin.cyBottomHeight = 0;
 
408
 
 
409
        // native menu uses small top margin for separator
 
410
        if ( SeparatorMargin.cyTopHeight >= 2 )
 
411
            SeparatorMargin.cyTopHeight -= 2;
 
412
    }
 
413
    else
 
414
#endif // wxUSE_UXTHEME
 
415
    {
 
416
        const NONCLIENTMETRICS& metrics = wxMSWImpl::GetNonClientMetrics();
 
417
 
 
418
        CheckMargin.cxLeftWidth =
 
419
        CheckMargin.cxRightWidth  = ::GetSystemMetrics(SM_CXEDGE);
 
420
        CheckMargin.cyTopHeight =
 
421
        CheckMargin.cyBottomHeight = ::GetSystemMetrics(SM_CYEDGE);
 
422
 
 
423
        CheckSize.cx = ::GetSystemMetrics(SM_CXMENUCHECK);
 
424
        CheckSize.cy = ::GetSystemMetrics(SM_CYMENUCHECK);
 
425
 
 
426
        ArrowSize = CheckSize;
 
427
 
 
428
        // separator height with margins
 
429
        int sepFullSize = metrics.iMenuHeight / 2;
 
430
 
 
431
        SeparatorMargin.cxLeftWidth =
 
432
        SeparatorMargin.cxRightWidth = 1;
 
433
        SeparatorMargin.cyTopHeight =
 
434
        SeparatorMargin.cyBottomHeight = sepFullSize / 2 - 1;
 
435
 
 
436
        SeparatorSize.cx = 1;
 
437
        SeparatorSize.cy = sepFullSize - SeparatorMargin.GetTotalY();
 
438
 
 
439
        TextBorder = 0;
 
440
        AccelBorder = 8;
 
441
        ArrowBorder = 6;
 
442
 
 
443
        Offset = -12;
 
444
 
 
445
        Font = wxFont(wxNativeFontInfo(metrics.lfMenuFont));
 
446
 
 
447
        Theme = false;
 
448
    }
 
449
 
 
450
    int value;
 
451
    if ( ::SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &value, 0) == 0 )
 
452
    {
 
453
        // if it's not supported, we must be on an old Windows version
 
454
        // which always shows them
 
455
        value = 1;
 
456
    }
 
457
 
 
458
    AlwaysShowCues = value == 1;
 
459
 
 
460
}
 
461
 
 
462
} // anonymous namespace
 
463
 
 
464
#endif // wxUSE_OWNER_DRAWN
 
465
 
 
466
 
 
467
// ctor & dtor
 
468
// -----------
 
469
 
 
470
wxMenuItem::wxMenuItem(wxMenu *pParentMenu,
 
471
                       int id,
 
472
                       const wxString& text,
 
473
                       const wxString& strHelp,
 
474
                       wxItemKind kind,
 
475
                       wxMenu *pSubMenu)
 
476
          : wxMenuItemBase(pParentMenu, id, text, strHelp, kind, pSubMenu)
 
477
{
 
478
    Init();
 
479
}
 
480
 
 
481
#if WXWIN_COMPATIBILITY_2_8
 
482
wxMenuItem::wxMenuItem(wxMenu *parentMenu,
 
483
                       int id,
 
484
                       const wxString& text,
 
485
                       const wxString& help,
 
486
                       bool isCheckable,
 
487
                       wxMenu *subMenu)
 
488
          : wxMenuItemBase(parentMenu, id, text, help,
 
489
                           isCheckable ? wxITEM_CHECK : wxITEM_NORMAL, subMenu)
 
490
{
 
491
    Init();
 
492
}
 
493
#endif
 
494
 
 
495
void wxMenuItem::Init()
 
496
{
 
497
#if  wxUSE_OWNER_DRAWN
 
498
 
 
499
    // when the color is not valid, wxOwnerDraw takes the default ones.
 
500
    // If we set the colors here and they are changed by the user during
 
501
    // the execution, then the colors are not updated until the application
 
502
    // is restarted and our menus look bad
 
503
    SetTextColour(wxNullColour);
 
504
    SetBackgroundColour(wxNullColour);
 
505
 
 
506
    // setting default colors switched ownerdraw on: switch it off again
 
507
    SetOwnerDrawn(false);
 
508
 
 
509
    //  switch ownerdraw back on if using a non default margin
 
510
    if ( !IsSeparator() )
 
511
        SetMarginWidth(GetMarginWidth());
 
512
 
 
513
#endif // wxUSE_OWNER_DRAWN
 
514
}
 
515
 
 
516
wxMenuItem::~wxMenuItem()
 
517
{
 
518
}
 
519
 
 
520
// misc
 
521
// ----
 
522
 
 
523
// return the id for calling Win32 API functions
 
524
WXWPARAM wxMenuItem::GetMSWId() const
 
525
{
 
526
    // we must use ids in unsigned short range with Windows functions, if we
 
527
    // pass ids > USHRT_MAX to them they get very confused (e.g. start
 
528
    // generating WM_COMMAND messages with negative high word of wParam), so
 
529
    // use the cast to ensure the id is in range
 
530
    return m_subMenu ? wxPtrToUInt(m_subMenu->GetHMenu())
 
531
                     : static_cast<unsigned short>(GetId());
 
532
}
 
533
 
 
534
// get item state
 
535
// --------------
 
536
 
 
537
bool wxMenuItem::IsChecked() const
 
538
{
 
539
    // fix that RTTI is always getting the correct state (separators cannot be
 
540
    // checked, but the Windows call below returns true
 
541
    if ( IsSeparator() )
 
542
        return false;
 
543
 
 
544
    // the item might not be attached to a menu yet
 
545
    //
 
546
    // TODO: shouldn't we just always call the base class version? It seems
 
547
    //       like it ought to always be in sync
 
548
    if ( !m_parentMenu )
 
549
        return wxMenuItemBase::IsChecked();
 
550
 
 
551
    HMENU hmenu = GetHMenuOf(m_parentMenu);
 
552
    int flag = ::GetMenuState(hmenu, GetMSWId(), MF_BYCOMMAND);
 
553
 
 
554
    return (flag & MF_CHECKED) != 0;
 
555
}
 
556
 
 
557
// change item state
 
558
// -----------------
 
559
 
 
560
void wxMenuItem::Enable(bool enable)
 
561
{
 
562
    if ( m_isEnabled == enable )
 
563
        return;
 
564
 
 
565
    if ( m_parentMenu )
 
566
    {
 
567
        long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
 
568
                                 GetMSWId(),
 
569
                                 MF_BYCOMMAND |
 
570
                                 (enable ? MF_ENABLED : MF_GRAYED));
 
571
 
 
572
        if ( rc == -1 )
 
573
        {
 
574
            wxLogLastError(wxT("EnableMenuItem"));
 
575
        }
 
576
    }
 
577
 
 
578
    wxMenuItemBase::Enable(enable);
 
579
}
 
580
 
 
581
void wxMenuItem::Check(bool check)
 
582
{
 
583
    wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
 
584
 
 
585
    if ( m_isChecked == check )
 
586
        return;
 
587
 
 
588
    if ( m_parentMenu )
 
589
    {
 
590
        int flags = check ? MF_CHECKED : MF_UNCHECKED;
 
591
        HMENU hmenu = GetHMenuOf(m_parentMenu);
 
592
 
 
593
        if ( GetKind() == wxITEM_RADIO )
 
594
        {
 
595
            // it doesn't make sense to uncheck a radio item -- what would this
 
596
            // do?
 
597
            if ( !check )
 
598
                return;
 
599
 
 
600
            // get the index of this item in the menu
 
601
            const wxMenuItemList& items = m_parentMenu->GetMenuItems();
 
602
            int pos = items.IndexOf(this);
 
603
            wxCHECK_RET( pos != wxNOT_FOUND,
 
604
                         wxT("menuitem not found in the menu items list?") );
 
605
 
 
606
            // get the radio group range
 
607
            int start,
 
608
                end;
 
609
 
 
610
            if ( !m_parentMenu->MSWGetRadioGroupRange(pos, &start, &end) )
 
611
            {
 
612
                wxFAIL_MSG( wxT("Menu radio item not part of radio group?") );
 
613
                return;
 
614
            }
 
615
 
 
616
#ifdef __WIN32__
 
617
            // calling CheckMenuRadioItem() with such parameters hangs my system
 
618
            // (NT4 SP6) and I suspect this could happen to the others as well,
 
619
            // so don't do it!
 
620
            wxCHECK_RET( start != -1 && end != -1,
 
621
                         wxT("invalid ::CheckMenuRadioItem() parameter(s)") );
 
622
 
 
623
            if ( !::CheckMenuRadioItem(hmenu,
 
624
                                       start,   // the first radio group item
 
625
                                       end,     // the last one
 
626
                                       pos,     // the one to check
 
627
                                       MF_BYPOSITION) )
 
628
            {
 
629
                wxLogLastError(wxT("CheckMenuRadioItem"));
 
630
            }
 
631
#endif // __WIN32__
 
632
 
 
633
            // also uncheck all the other items in this radio group
 
634
            wxMenuItemList::compatibility_iterator node = items.Item(start);
 
635
            for ( int n = start; n <= end && node; n++ )
 
636
            {
 
637
                if ( n != pos )
 
638
                {
 
639
                    node->GetData()->m_isChecked = false;
 
640
                }
 
641
 
 
642
                node = node->GetNext();
 
643
            }
 
644
        }
 
645
        else // check item
 
646
        {
 
647
            if ( ::CheckMenuItem(hmenu,
 
648
                                 GetMSWId(),
 
649
                                 MF_BYCOMMAND | flags) == (DWORD)-1 )
 
650
            {
 
651
                wxFAIL_MSG(wxT("CheckMenuItem() failed, item not in the menu?"));
 
652
            }
 
653
        }
 
654
    }
 
655
 
 
656
    wxMenuItemBase::Check(check);
 
657
}
 
658
 
 
659
void wxMenuItem::SetItemLabel(const wxString& txt)
 
660
{
 
661
    wxString text = txt;
 
662
 
 
663
    // don't do anything if label didn't change
 
664
    if ( m_text == txt )
 
665
        return;
 
666
 
 
667
    // wxMenuItemBase will do stock ID checks
 
668
    wxMenuItemBase::SetItemLabel(text);
 
669
 
 
670
    // the item can be not attached to any menu yet and SetItemLabel() is still
 
671
    // valid to call in this case and should do nothing else
 
672
    if ( !m_parentMenu )
 
673
        return;
 
674
 
 
675
#if wxUSE_ACCEL
 
676
    m_parentMenu->UpdateAccel(this);
 
677
#endif // wxUSE_ACCEL
 
678
 
 
679
    const UINT id = GetMSWId();
 
680
    HMENU hMenu = GetHMenuOf(m_parentMenu);
 
681
    if ( !hMenu || ::GetMenuState(hMenu, id, MF_BYCOMMAND) == (UINT)-1 )
 
682
        return;
 
683
 
 
684
#if wxUSE_OWNER_DRAWN
 
685
    if ( IsOwnerDrawn() )
 
686
    {
 
687
        // we don't need to do anything for owner drawn items, they will redraw
 
688
        // themselves using the new text the next time they're displayed
 
689
        return;
 
690
    }
 
691
#endif // owner drawn
 
692
 
 
693
    // update the text of the native menu item
 
694
    WinStruct<MENUITEMINFO> info;
 
695
 
 
696
    // surprisingly, calling SetMenuItemInfo() with just MIIM_STRING doesn't
 
697
    // work as it resets the menu bitmap, so we need to first get the old item
 
698
    // state and then modify it
 
699
    const bool isLaterThanWin95 = wxGetWinVersion() > wxWinVersion_95;
 
700
    info.fMask = MIIM_STATE |
 
701
                 MIIM_ID |
 
702
                 MIIM_SUBMENU |
 
703
                 MIIM_CHECKMARKS |
 
704
                 MIIM_DATA;
 
705
    if ( isLaterThanWin95 )
 
706
        info.fMask |= MIIM_BITMAP | MIIM_FTYPE;
 
707
    else
 
708
        info.fMask |= MIIM_TYPE;
 
709
    if ( !::GetMenuItemInfo(hMenu, id, FALSE, &info) )
 
710
    {
 
711
        wxLogLastError(wxT("GetMenuItemInfo"));
 
712
        return;
 
713
    }
 
714
 
 
715
    if ( isLaterThanWin95 )
 
716
        info.fMask |= MIIM_STRING;
 
717
    //else: MIIM_TYPE already specified
 
718
    info.dwTypeData = wxMSW_CONV_LPTSTR(m_text);
 
719
    info.cch = m_text.length();
 
720
    if ( !::SetMenuItemInfo(hMenu, id, FALSE, &info) )
 
721
    {
 
722
        wxLogLastError(wxT("SetMenuItemInfo"));
 
723
    }
 
724
}
 
725
 
 
726
#if wxUSE_OWNER_DRAWN
 
727
 
 
728
int wxMenuItem::MeasureAccelWidth() const
 
729
{
 
730
    wxString accel = GetItemLabel().AfterFirst(wxT('\t'));
 
731
 
 
732
    wxMemoryDC dc;
 
733
    wxFont font;
 
734
    GetFontToUse(font);
 
735
    dc.SetFont(font);
 
736
 
 
737
    wxCoord w;
 
738
    dc.GetTextExtent(accel, &w, NULL);
 
739
 
 
740
    return w;
 
741
}
 
742
 
 
743
wxString wxMenuItem::GetName() const
 
744
{
 
745
    return GetItemLabelText();
 
746
}
 
747
 
 
748
bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height)
 
749
{
 
750
    const MenuDrawData* data = MenuDrawData::Get();
 
751
 
 
752
    if ( IsOwnerDrawn() )
 
753
    {
 
754
        *width  = data->ItemMargin.GetTotalX();
 
755
        *height = data->ItemMargin.GetTotalY();
 
756
 
 
757
        if ( IsSeparator() )
 
758
        {
 
759
            *width  += data->SeparatorSize.cx
 
760
                     + data->SeparatorMargin.GetTotalX();
 
761
            *height += data->SeparatorSize.cy
 
762
                     + data->SeparatorMargin.GetTotalY();
 
763
            return true;
 
764
        }
 
765
 
 
766
        wxString str = GetName();
 
767
 
 
768
        wxMemoryDC dc;
 
769
        wxFont font;
 
770
        GetFontToUse(font);
 
771
        dc.SetFont(font);
 
772
 
 
773
        wxCoord w, h;
 
774
        dc.GetTextExtent(str, &w, &h);
 
775
 
 
776
        *width = data->TextBorder + w + data->AccelBorder;
 
777
        *height = h;
 
778
 
 
779
        w = m_parentMenu->GetMaxAccelWidth();
 
780
        if ( w > 0 )
 
781
            *width += w + data->ArrowBorder;
 
782
 
 
783
        *width += data->Offset;
 
784
        *width += data->ArrowMargin.GetTotalX() + data->ArrowSize.cx;
 
785
    }
 
786
    else // don't draw the text, just the bitmap (if any)
 
787
    {
 
788
        *width = 0;
 
789
        *height = 0;
 
790
    }
 
791
 
 
792
    // bitmap
 
793
 
 
794
    if ( IsOwnerDrawn() )
 
795
    {
 
796
        // width of menu icon with margins in ownerdrawn menu
 
797
        // if any bitmap is not set, the width of space reserved for icon
 
798
        // image is equal to the width of std check mark,
 
799
        // if bitmap is set, then the width is set to the width of the widest
 
800
        // bitmap in menu (GetMarginWidth()) unless std check mark is wider,
 
801
        // then it's is set to std mark's width
 
802
        int imgWidth = wxMax(GetMarginWidth(), data->CheckSize.cx)
 
803
                     + data->CheckMargin.GetTotalX();
 
804
 
 
805
        *width += imgWidth + data->CheckBgMargin.GetTotalX();
 
806
    }
 
807
 
 
808
    if ( m_bmpChecked.IsOk() || m_bmpUnchecked.IsOk() )
 
809
    {
 
810
        // get size of bitmap always return valid value (0 for invalid bitmap),
 
811
        // so we don't needed check if bitmap is valid ;)
 
812
        size_t heightBmp = wxMax(m_bmpChecked.GetHeight(), m_bmpUnchecked.GetHeight());
 
813
        size_t widthBmp = wxMax(m_bmpChecked.GetWidth(),  m_bmpUnchecked.GetWidth());
 
814
 
 
815
        if ( IsOwnerDrawn() )
 
816
        {
 
817
            heightBmp += data->CheckMargin.GetTotalY();
 
818
        }
 
819
        else
 
820
        {
 
821
            // we must allocate enough space for the bitmap
 
822
            *width += widthBmp;
 
823
        }
 
824
 
 
825
        // Is BMP height larger than text height?
 
826
        if ( *height < heightBmp )
 
827
            *height = heightBmp;
 
828
    }
 
829
 
 
830
    // make sure that this item is at least as tall as the system menu height
 
831
    const size_t menuHeight = data->CheckMargin.GetTotalY()
 
832
                            + data->CheckSize.cy;
 
833
    if (*height < menuHeight)
 
834
        *height = menuHeight;
 
835
 
 
836
    return true;
 
837
}
 
838
 
 
839
bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc,
 
840
                            wxODAction WXUNUSED(act), wxODStatus stat)
 
841
{
 
842
    const MenuDrawData* data = MenuDrawData::Get();
 
843
 
 
844
    wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
 
845
    HDC hdc = GetHdcOf(*impl);
 
846
 
 
847
    RECT rect;
 
848
    wxCopyRectToRECT(rc, rect);
 
849
 
 
850
    int imgWidth = wxMax(GetMarginWidth(), data->CheckSize.cx);
 
851
 
 
852
    if ( IsOwnerDrawn() )
 
853
    {
 
854
        // font and colors to use
 
855
        wxFont font;
 
856
        GetFontToUse(font);
 
857
 
 
858
        wxColour colText, colBack;
 
859
        GetColourToUse(stat, colText, colBack);
 
860
 
 
861
        // calculate metrics of item parts
 
862
        RECT rcSelection = rect;
 
863
        data->ItemMargin.ApplyTo(rcSelection);
 
864
 
 
865
        RECT rcSeparator = rcSelection;
 
866
        data->SeparatorMargin.ApplyTo(rcSeparator);
 
867
 
 
868
        RECT rcGutter = rcSelection;
 
869
        rcGutter.right = data->ItemMargin.cxLeftWidth
 
870
                       + data->CheckBgMargin.cxLeftWidth
 
871
                       + data->CheckMargin.cxLeftWidth
 
872
                       + imgWidth
 
873
                       + data->CheckMargin.cxRightWidth
 
874
                       + data->CheckBgMargin.cxRightWidth;
 
875
 
 
876
        RECT rcText = rcSelection;
 
877
        rcText.left = rcGutter.right + data->TextBorder;
 
878
 
 
879
        // we draw the text label vertically centered, but this results in it
 
880
        // being 1px too low compared to native menus for some reason, fix it
 
881
        if ( data->MenuLayout() != MenuDrawData::FullTheme )
 
882
            rcText.top--;
 
883
 
 
884
#if wxUSE_UXTHEME
 
885
        // If a custom background colour is explicitly specified, we should use
 
886
        // it instead of the default theme background.
 
887
        wxUxThemeEngine* const theme = GetBackgroundColour().IsOk()
 
888
                                        ? NULL
 
889
                                        : MenuDrawData::GetUxThemeEngine();
 
890
        if ( theme )
 
891
        {
 
892
            POPUPITEMSTATES state;
 
893
            if ( stat & wxODDisabled )
 
894
            {
 
895
                state = (stat & wxODSelected) ? MPI_DISABLEDHOT
 
896
                                              : MPI_DISABLED;
 
897
            }
 
898
            else if ( stat & wxODSelected )
 
899
            {
 
900
                state = MPI_HOT;
 
901
            }
 
902
            else
 
903
            {
 
904
                state = MPI_NORMAL;
 
905
            }
 
906
 
 
907
            wxUxThemeHandle hTheme(GetMenu()->GetWindow(), L"MENU");
 
908
 
 
909
            if ( theme->IsThemeBackgroundPartiallyTransparent(hTheme,
 
910
                    MENU_POPUPITEM, state) )
 
911
            {
 
912
                theme->DrawThemeBackground(hTheme, hdc,
 
913
                                           MENU_POPUPBACKGROUND,
 
914
                                           0, &rect, NULL);
 
915
            }
 
916
 
 
917
            theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPGUTTER,
 
918
                                       0, &rcGutter, NULL);
 
919
 
 
920
            if ( IsSeparator() )
 
921
            {
 
922
                rcSeparator.left = rcGutter.right;
 
923
                theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPSEPARATOR,
 
924
                                           0, &rcSeparator, NULL);
 
925
                return true;
 
926
            }
 
927
 
 
928
            theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPITEM,
 
929
                                       state, &rcSelection, NULL);
 
930
 
 
931
        }
 
932
        else
 
933
#endif // wxUSE_UXTHEME
 
934
        {
 
935
            if ( IsSeparator() )
 
936
            {
 
937
                DrawEdge(hdc, &rcSeparator, EDGE_ETCHED, BF_TOP);
 
938
                return true;
 
939
            }
 
940
 
 
941
            AutoHBRUSH hbr(colBack.GetPixel());
 
942
            SelectInHDC selBrush(hdc, hbr);
 
943
            ::FillRect(hdc, &rcSelection, hbr);
 
944
        }
 
945
 
 
946
 
 
947
        // draw text label
 
948
        // using native API because it recognizes '&'
 
949
 
 
950
        HDCTextColChanger changeTextCol(hdc, colText.GetPixel());
 
951
        HDCBgColChanger changeBgCol(hdc, colBack.GetPixel());
 
952
        HDCBgModeChanger changeBgMode(hdc, TRANSPARENT);
 
953
 
 
954
        SelectInHDC selFont(hdc, GetHfontOf(font));
 
955
 
 
956
 
 
957
        // item text name without mnemonic for calculating size
 
958
        wxString text = GetName();
 
959
 
 
960
        SIZE textSize;
 
961
        ::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &textSize);
 
962
 
 
963
        // item text name with mnemonic
 
964
        text = GetItemLabel().BeforeFirst('\t');
 
965
 
 
966
        int flags = DST_PREFIXTEXT;
 
967
        // themes menu is using specified color for disabled labels
 
968
        if ( data->MenuLayout() == MenuDrawData::Classic &&
 
969
             (stat & wxODDisabled) && !(stat & wxODSelected) )
 
970
            flags |= DSS_DISABLED;
 
971
 
 
972
        if ( (stat & wxODHidePrefix) && !data->AlwaysShowCues )
 
973
            flags |= DSS_HIDEPREFIX;
 
974
 
 
975
        int x = rcText.left;
 
976
        int y = rcText.top + (rcText.bottom - rcText.top - textSize.cy) / 2;
 
977
 
 
978
        ::DrawState(hdc, NULL, NULL, wxMSW_CONV_LPARAM(text),
 
979
                    text.length(), x, y, 0, 0, flags);
 
980
 
 
981
        // ::SetTextAlign(hdc, TA_RIGHT) doesn't work with DSS_DISABLED or DSS_MONO
 
982
        // as the last parameter in DrawState() (at least with Windows98). So we have
 
983
        // to take care of right alignment ourselves.
 
984
        wxString accel = GetItemLabel().AfterFirst(wxT('\t'));
 
985
        if ( !accel.empty() )
 
986
        {
 
987
            SIZE accelSize;
 
988
            ::GetTextExtentPoint32(hdc, accel.c_str(), accel.length(), &accelSize);
 
989
 
 
990
            int flags = DST_TEXT;
 
991
            // themes menu is using specified color for disabled labels
 
992
            if ( data->MenuLayout() == MenuDrawData::Classic &&
 
993
                 (stat & wxODDisabled) && !(stat & wxODSelected) )
 
994
                flags |= DSS_DISABLED;
 
995
 
 
996
            int x = rcText.right - data->ArrowMargin.GetTotalX()
 
997
                                 - data->ArrowSize.cx
 
998
                                 - data->ArrowBorder;
 
999
 
 
1000
            // right align accel on FullTheme menu, left otherwise
 
1001
            if ( data->MenuLayout() == MenuDrawData::FullTheme)
 
1002
                x -= accelSize.cx;
 
1003
            else
 
1004
                x -= m_parentMenu->GetMaxAccelWidth();
 
1005
 
 
1006
            int y = rcText.top + (rcText.bottom - rcText.top - accelSize.cy) / 2;
 
1007
 
 
1008
            ::DrawState(hdc, NULL, NULL, wxMSW_CONV_LPARAM(accel),
 
1009
                        accel.length(), x, y, 0, 0, flags);
 
1010
        }
 
1011
    }
 
1012
 
 
1013
 
 
1014
    // draw the bitmap
 
1015
 
 
1016
    RECT rcImg;
 
1017
    SetRect(&rcImg,
 
1018
            rect.left   + data->ItemMargin.cxLeftWidth
 
1019
                        + data->CheckBgMargin.cxLeftWidth
 
1020
                        + data->CheckMargin.cxLeftWidth,
 
1021
            rect.top    + data->ItemMargin.cyTopHeight
 
1022
                        + data->CheckBgMargin.cyTopHeight
 
1023
                        + data->CheckMargin.cyTopHeight,
 
1024
            rect.left   + data->ItemMargin.cxLeftWidth
 
1025
                        + data->CheckBgMargin.cxLeftWidth
 
1026
                        + data->CheckMargin.cxLeftWidth
 
1027
                        + imgWidth,
 
1028
            rect.bottom - data->ItemMargin.cyBottomHeight
 
1029
                        - data->CheckBgMargin.cyBottomHeight
 
1030
                        - data->CheckMargin.cyBottomHeight);
 
1031
 
 
1032
    if ( IsCheckable() && !m_bmpChecked.IsOk() )
 
1033
    {
 
1034
        if ( stat & wxODChecked )
 
1035
        {
 
1036
            DrawStdCheckMark((WXHDC)hdc, &rcImg, stat);
 
1037
        }
 
1038
    }
 
1039
    else
 
1040
    {
 
1041
        wxBitmap bmp;
 
1042
 
 
1043
        if ( stat & wxODDisabled )
 
1044
        {
 
1045
            bmp = GetDisabledBitmap();
 
1046
        }
 
1047
 
 
1048
        if ( !bmp.IsOk() )
 
1049
        {
 
1050
            // for not checkable bitmaps we should always use unchecked one
 
1051
            // because their checked bitmap is not set
 
1052
            bmp = GetBitmap(!IsCheckable() || (stat & wxODChecked));
 
1053
 
 
1054
#if wxUSE_IMAGE
 
1055
            if ( bmp.IsOk() && stat & wxODDisabled )
 
1056
            {
 
1057
                // we need to grey out the bitmap as we don't have any specific
 
1058
                // disabled bitmap
 
1059
                wxImage imgGrey = bmp.ConvertToImage().ConvertToGreyscale();
 
1060
                if ( imgGrey.IsOk() )
 
1061
                    bmp = wxBitmap(imgGrey);
 
1062
            }
 
1063
#endif // wxUSE_IMAGE
 
1064
        }
 
1065
 
 
1066
        if ( bmp.IsOk() )
 
1067
        {
 
1068
            wxMemoryDC dcMem(&dc);
 
1069
            dcMem.SelectObjectAsSource(bmp);
 
1070
 
 
1071
            // center bitmap
 
1072
            int nBmpWidth  = bmp.GetWidth(),
 
1073
                nBmpHeight = bmp.GetHeight();
 
1074
 
 
1075
            int x = rcImg.left + (imgWidth - nBmpWidth) / 2;
 
1076
            int y = rcImg.top  + (rcImg.bottom - rcImg.top - nBmpHeight) / 2;
 
1077
            dc.Blit(x, y, nBmpWidth, nBmpHeight, &dcMem, 0, 0, wxCOPY, true);
 
1078
        }
 
1079
    }
 
1080
 
 
1081
    return true;
 
1082
 
 
1083
}
 
1084
 
 
1085
namespace
 
1086
{
 
1087
 
 
1088
// helper function for draw coloured check mark
 
1089
void DrawColorCheckMark(HDC hdc, int x, int y, int cx, int cy, HDC hdcCheckMask, int idxColor)
 
1090
{
 
1091
    const COLORREF colBlack = RGB(0, 0, 0);
 
1092
    const COLORREF colWhite = RGB(255, 255, 255);
 
1093
 
 
1094
    HDCTextColChanger changeTextCol(hdc, colBlack);
 
1095
    HDCBgColChanger changeBgCol(hdc, colWhite);
 
1096
    HDCBgModeChanger changeBgMode(hdc, TRANSPARENT);
 
1097
 
 
1098
    // memory DC for color bitmap
 
1099
    MemoryHDC hdcMem(hdc);
 
1100
    CompatibleBitmap hbmpMem(hdc, cx, cy);
 
1101
    SelectInHDC selMem(hdcMem, hbmpMem);
 
1102
 
 
1103
    RECT rect = { 0, 0, cx, cy };
 
1104
    ::FillRect(hdcMem, &rect, ::GetSysColorBrush(idxColor));
 
1105
 
 
1106
    const COLORREF colCheck = ::GetSysColor(idxColor);
 
1107
    if ( colCheck == colWhite )
 
1108
    {
 
1109
        ::BitBlt(hdc, x, y, cx, cy, hdcCheckMask, 0, 0, MERGEPAINT);
 
1110
        ::BitBlt(hdc, x, y, cx, cy, hdcMem, 0, 0, SRCAND);
 
1111
    }
 
1112
    else
 
1113
    {
 
1114
        if ( colCheck != colBlack )
 
1115
        {
 
1116
            const DWORD ROP_DSna = 0x00220326;  // dest = (NOT src) AND dest
 
1117
            ::BitBlt(hdcMem, 0, 0, cx, cy, hdcCheckMask, 0, 0, ROP_DSna);
 
1118
        }
 
1119
 
 
1120
        ::BitBlt(hdc, x, y, cx, cy, hdcCheckMask, 0, 0, SRCAND);
 
1121
        ::BitBlt(hdc, x, y, cx, cy, hdcMem, 0, 0, SRCPAINT);
 
1122
    }
 
1123
}
 
1124
 
 
1125
} // anonymous namespace
 
1126
 
 
1127
void wxMenuItem::DrawStdCheckMark(WXHDC hdc_, const RECT* rc, wxODStatus stat)
 
1128
{
 
1129
    HDC hdc = (HDC)hdc_;
 
1130
 
 
1131
#if wxUSE_UXTHEME
 
1132
    wxUxThemeEngine* theme = MenuDrawData::GetUxThemeEngine();
 
1133
    if ( theme )
 
1134
    {
 
1135
        wxUxThemeHandle hTheme(GetMenu()->GetWindow(), L"MENU");
 
1136
 
 
1137
        const MenuDrawData* data = MenuDrawData::Get();
 
1138
 
 
1139
        // rect for background must be without check margins
 
1140
        RECT rcBg = *rc;
 
1141
        data->CheckMargin.UnapplyFrom(rcBg);
 
1142
 
 
1143
        POPUPCHECKBACKGROUNDSTATES stateCheckBg = (stat & wxODDisabled)
 
1144
                                                    ? MCB_DISABLED
 
1145
                                                    : MCB_NORMAL;
 
1146
 
 
1147
        theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPCHECKBACKGROUND,
 
1148
                                   stateCheckBg, &rcBg, NULL);
 
1149
 
 
1150
        POPUPCHECKSTATES stateCheck;
 
1151
        if ( GetKind() == wxITEM_CHECK )
 
1152
        {
 
1153
            stateCheck = (stat & wxODDisabled) ? MC_CHECKMARKDISABLED
 
1154
                                               : MC_CHECKMARKNORMAL;
 
1155
        }
 
1156
        else
 
1157
        {
 
1158
            stateCheck = (stat & wxODDisabled) ? MC_BULLETDISABLED
 
1159
                                               : MC_BULLETNORMAL;
 
1160
        }
 
1161
 
 
1162
        theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPCHECK,
 
1163
                                   stateCheck, rc, NULL);
 
1164
    }
 
1165
    else
 
1166
#endif // wxUSE_UXTHEME
 
1167
    {
 
1168
        int cx = rc->right - rc->left;
 
1169
        int cy = rc->bottom - rc->top;
 
1170
 
 
1171
        // first create mask of check mark
 
1172
        MemoryHDC hdcMask(hdc);
 
1173
        MonoBitmap hbmpMask(cx, cy);
 
1174
        SelectInHDC selMask(hdcMask,hbmpMask);
 
1175
 
 
1176
        // then draw a check mark into it
 
1177
        UINT stateCheck = (GetKind() == wxITEM_CHECK) ? DFCS_MENUCHECK
 
1178
                                                      : DFCS_MENUBULLET;
 
1179
        RECT rect = { 0, 0, cx, cy };
 
1180
        ::DrawFrameControl(hdcMask, &rect, DFC_MENU, stateCheck);
 
1181
 
 
1182
        // first draw shadow if disabled
 
1183
        if ( (stat & wxODDisabled) && !(stat & wxODSelected) )
 
1184
        {
 
1185
            DrawColorCheckMark(hdc, rc->left + 1, rc->top + 1,
 
1186
                               cx, cy, hdcMask, COLOR_3DHILIGHT);
 
1187
        }
 
1188
 
 
1189
        // then draw a check mark
 
1190
        int color = COLOR_MENUTEXT;
 
1191
        if ( stat & wxODDisabled )
 
1192
            color = COLOR_BTNSHADOW;
 
1193
        else if ( stat & wxODSelected )
 
1194
            color = COLOR_HIGHLIGHTTEXT;
 
1195
 
 
1196
        DrawColorCheckMark(hdc, rc->left, rc->top, cx, cy, hdcMask, color);
 
1197
    }
 
1198
}
 
1199
 
 
1200
void wxMenuItem::GetFontToUse(wxFont& font) const
 
1201
{
 
1202
    font = GetFont();
 
1203
    if ( !font.IsOk() )
 
1204
        font = MenuDrawData::Get()->Font;
 
1205
}
 
1206
 
 
1207
void wxMenuItem::GetColourToUse(wxODStatus stat, wxColour& colText, wxColour& colBack) const
 
1208
{
 
1209
#if wxUSE_UXTHEME
 
1210
    wxUxThemeEngine* theme = MenuDrawData::GetUxThemeEngine();
 
1211
    if ( theme )
 
1212
    {
 
1213
        wxUxThemeHandle hTheme(GetMenu()->GetWindow(), L"MENU");
 
1214
 
 
1215
        if ( stat & wxODDisabled)
 
1216
        {
 
1217
            wxRGBToColour(colText, theme->GetThemeSysColor(hTheme, COLOR_GRAYTEXT));
 
1218
        }
 
1219
        else
 
1220
        {
 
1221
            colText = GetTextColour();
 
1222
            if ( !colText.IsOk() )
 
1223
                wxRGBToColour(colText, theme->GetThemeSysColor(hTheme, COLOR_MENUTEXT));
 
1224
        }
 
1225
 
 
1226
        if ( stat & wxODSelected )
 
1227
        {
 
1228
            wxRGBToColour(colBack, theme->GetThemeSysColor(hTheme, COLOR_HIGHLIGHT));
 
1229
        }
 
1230
        else
 
1231
        {
 
1232
            colBack = GetBackgroundColour();
 
1233
            if ( !colBack.IsOk() )
 
1234
                wxRGBToColour(colBack, theme->GetThemeSysColor(hTheme, COLOR_MENU));
 
1235
        }
 
1236
    }
 
1237
    else
 
1238
#endif // wxUSE_UXTHEME
 
1239
    {
 
1240
        wxOwnerDrawn::GetColourToUse(stat, colText, colBack);
 
1241
    }
 
1242
}
 
1243
#endif // wxUSE_OWNER_DRAWN
 
1244
 
 
1245
// ----------------------------------------------------------------------------
 
1246
// wxMenuItemBase
 
1247
// ----------------------------------------------------------------------------
 
1248
 
 
1249
wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
 
1250
                                int id,
 
1251
                                const wxString& name,
 
1252
                                const wxString& help,
 
1253
                                wxItemKind kind,
 
1254
                                wxMenu *subMenu)
 
1255
{
 
1256
    return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
 
1257
}
 
1258
 
 
1259
#endif // wxUSE_MENUS