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