+#if wxUSE_OWNER_DRAWN
+
+namespace
+{
+
+// helper class to keep information about metrics and other stuff
+// needed for measuring and drawing menu item
+class MenuDrawData
+{
+public:
+ // Wrapper around standard MARGINS structure providing some helper
+ // functions and automatically initializing the margin fields to 0.
+ struct Margins : MARGINS
+ {
+ Margins()
+ {
+ cxLeftWidth =
+ cxRightWidth =
+ cyTopHeight =
+ cyBottomHeight = 0;
+ }
+
+ int GetTotalX() const { return cxLeftWidth + cxRightWidth; }
+ int GetTotalY() const { return cyTopHeight + cyBottomHeight; }
+
+ void ApplyTo(RECT& rect) const
+ {
+ rect.top += cyTopHeight;
+ rect.left += cxLeftWidth;
+ rect.right -= cyTopHeight;
+ rect.bottom -= cyBottomHeight;
+ }
+
+ void UnapplyFrom(RECT& rect) const
+ {
+ rect.top -= cyTopHeight;
+ rect.left -= cxLeftWidth;
+ rect.right += cyTopHeight;
+ rect.bottom += cyBottomHeight;
+ }
+ };
+
+ Margins ItemMargin; // popup item margins
+
+ Margins CheckMargin; // popup check margins
+ Margins CheckBgMargin; // popup check background margins
+
+ Margins ArrowMargin; // popup submenu arrow margins
+
+ Margins SeparatorMargin; // popup separator margins
+
+ SIZE CheckSize; // popup check size metric
+ SIZE ArrowSize; // popup submenu arrow size metric
+ SIZE SeparatorSize; // popup separator size metric
+
+ int TextBorder; // popup border space between
+ // item text and gutter
+
+ int AccelBorder; // popup border space between
+ // item text and accelerator
+
+ int ArrowBorder; // popup border space between
+ // item accelerator and submenu arrow
+
+ int Offset; // system added space at the end of the menu,
+ // add this offset for remove the extra space
+
+ wxFont Font; // default menu font
+
+ bool AlwaysShowCues; // must keyboard cues always be shown?
+
+ bool Theme; // is data initialized for FullTheme?
+
+ static const MenuDrawData* Get()
+ {
+ // notice that s_menuData can't be created as a global variable because
+ // it needs a window to initialize and no windows exist at the time of
+ // globals initialization yet
+ if ( !ms_instance )
+ {
+ static MenuDrawData s_menuData;
+ ms_instance = &s_menuData;
+ }
+
+ #if wxUSE_UXTHEME
+ bool theme = MenuLayout() == FullTheme;
+ if ( ms_instance->Theme != theme )
+ ms_instance->Init();
+ #endif // wxUSE_UXTHEME
+ return ms_instance;
+ }
+
+ MenuDrawData()
+ {
+ Init();
+ }
+
+
+ // get the theme engine or NULL if themes
+ // are not available or not supported on menu
+ static wxUxThemeEngine *GetUxThemeEngine()
+ {
+ #if wxUSE_UXTHEME
+ if ( MenuLayout() == FullTheme )
+ return wxUxThemeEngine::GetIfActive();
+ #endif // wxUSE_UXTHEME
+ return NULL;
+ }
+
+
+ enum MenuLayoutType
+ {
+ FullTheme, // full menu themes (Vista or new)
+ PseudoTheme, // pseudo menu themes (on XP)
+ Classic
+ };
+
+ static MenuLayoutType MenuLayout()
+ {
+ MenuLayoutType menu = Classic;
+ #if wxUSE_UXTHEME
+ if ( wxUxThemeEngine::GetIfActive() != NULL )
+ {
+ static wxWinVersion ver = wxGetWinVersion();
+ if ( ver >= wxWinVersion_Vista )
+ menu = FullTheme;
+ else if ( ver == wxWinVersion_XP )
+ menu = PseudoTheme;
+ }
+ #endif // wxUSE_UXTHEME
+ return menu;
+ }
+
+private:
+ void Init();
+
+ static MenuDrawData* ms_instance;
+};
+
+MenuDrawData* MenuDrawData::ms_instance = NULL;
+
+void MenuDrawData::Init()
+{
+#if wxUSE_UXTHEME
+ wxUxThemeEngine* theme = GetUxThemeEngine();
+ if ( theme )
+ {
+ wxWindow* window = static_cast<wxApp*>(wxApp::GetInstance())->GetTopWindow();
+ wxUxThemeHandle hTheme(window, L"MENU");
+
+ theme->GetThemeMargins(hTheme, NULL, MENU_POPUPITEM, 0,
+ TMT_CONTENTMARGINS, NULL,
+ &ItemMargin);
+
+ theme->GetThemeMargins(hTheme, NULL, MENU_POPUPCHECK, 0,
+ TMT_CONTENTMARGINS, NULL,
+ &CheckMargin);
+ theme->GetThemeMargins(hTheme, NULL, MENU_POPUPCHECKBACKGROUND, 0,
+ TMT_CONTENTMARGINS, NULL,
+ &CheckBgMargin);
+
+ theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSUBMENU, 0,
+ TMT_CONTENTMARGINS, NULL,
+ &ArrowMargin);
+
+ theme->GetThemeMargins(hTheme, NULL, MENU_POPUPSEPARATOR, 0,
+ TMT_SIZINGMARGINS, NULL,
+ &SeparatorMargin);
+
+ theme->GetThemePartSize(hTheme, NULL, MENU_POPUPCHECK, 0,
+ NULL, TS_TRUE, &CheckSize);
+
+ theme->GetThemePartSize(hTheme, NULL, MENU_POPUPSUBMENU, 0,
+ NULL, TS_TRUE, &ArrowSize);
+
+ theme->GetThemePartSize(hTheme, NULL, MENU_POPUPSEPARATOR, 0,
+ NULL, TS_TRUE, &SeparatorSize);
+
+ theme->GetThemeInt(hTheme, MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &TextBorder);
+
+ AccelBorder = 34;
+ ArrowBorder = 0;
+
+ Offset = -14;
+
+ wxUxThemeFont themeFont;
+ theme->GetThemeSysFont(hTheme, TMT_MENUFONT, themeFont.GetPtr());
+ Font = wxFont(themeFont.GetLOGFONT());
+
+ Theme = true;
+
+ // native menu doesn't uses the vertical margins
+ ItemMargin.cyTopHeight =
+ ItemMargin.cyBottomHeight = 0;
+
+ // native menu uses small top margin for separator
+ if ( SeparatorMargin.cyTopHeight >= 2 )
+ SeparatorMargin.cyTopHeight -= 2;
+ }
+ else
+#endif // wxUSE_UXTHEME
+ {
+ const NONCLIENTMETRICS& metrics = wxMSWImpl::GetNonClientMetrics();
+
+ CheckMargin.cxLeftWidth =
+ CheckMargin.cxRightWidth = ::GetSystemMetrics(SM_CXEDGE);
+ CheckMargin.cyTopHeight =
+ CheckMargin.cyBottomHeight = ::GetSystemMetrics(SM_CYEDGE);
+
+ CheckSize.cx = ::GetSystemMetrics(SM_CXMENUCHECK);
+ CheckSize.cy = ::GetSystemMetrics(SM_CYMENUCHECK);
+
+ ArrowSize = CheckSize;
+
+ // separator height with margins
+ int sepFullSize = metrics.iMenuHeight / 2;
+
+ SeparatorMargin.cxLeftWidth =
+ SeparatorMargin.cxRightWidth = 1;
+ SeparatorMargin.cyTopHeight =
+ SeparatorMargin.cyBottomHeight = sepFullSize / 2 - 1;
+
+ SeparatorSize.cx = 1;
+ SeparatorSize.cy = sepFullSize - SeparatorMargin.GetTotalY();
+
+ TextBorder = 0;
+ AccelBorder = 8;
+ ArrowBorder = 6;
+
+ Offset = -12;
+
+ Font = wxFont(wxNativeFontInfo(metrics.lfMenuFont));
+
+ Theme = false;
+ }
+
+ int value;
+ if ( ::SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &value, 0) == 0 )
+ {
+ // if it's not supported, we must be on an old Windows version
+ // which always shows them
+ value = 1;
+ }
+
+ AlwaysShowCues = value == 1;
+
+}
+
+} // anonymous namespace
+
+#endif // wxUSE_OWNER_DRAWN
+
+