Menu

How to change the pop-up menu style

Help
2023-02-10
2023-02-23
  • Yinzhong Zhang

    Yinzhong Zhang - 2023-02-10

    Hi David,

    I found that the style of popup menu in win32++ is very close to xp, it may be related to the following code,

    inline void CMenuMetrics::Initialize(HWND frame)
        {
            assert(IsWindow(frame));
            m_frame = frame;
    
            if (m_uxTheme == 0)
                m_uxTheme = ::LoadLibrary(_T("UXTHEME.DLL"));
    
            if (m_uxTheme != 0)
            {
                m_pfnCloseThemeData = reinterpret_cast<CLOSETHEMEDATA*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "CloseThemeData")));
                m_pfnDrawThemeBackground = reinterpret_cast<DRAWTHEMEBACKGROUND*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "DrawThemeBackground")));
                m_pfnDrawThemeText = reinterpret_cast<DRAWTHEMETEXT*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "DrawThemeText")));
                m_pfnGetThemePartSize = reinterpret_cast<GETTHEMEPARTSIZE*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "GetThemePartSize")));
                m_pfnGetThemeInt = reinterpret_cast<GETTHEMEINT*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "GetThemeInt")));
                m_pfnGetThemeMargins = reinterpret_cast<GETTHEMEMARGINS*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "GetThemeMargins")));
                m_pfnGetThemeTextExtent = reinterpret_cast<GETTHEMETEXTEXTENT*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "GetThemeTextExtent")));
                m_pfnIsThemeBGPartTransparent = reinterpret_cast<ISTHEMEBGPARTTRANSPARENT*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "IsThemeBackgroundPartiallyTransparent")));
                m_pfnOpenThemeData = reinterpret_cast<OPENTHEMEDATA*>(
                    reinterpret_cast<void*>(::GetProcAddress(m_uxTheme, "OpenThemeData")));
            }
    
            if (m_theme != 0)
            {
                CloseThemeData();
                m_theme = 0;
            }
    
            m_theme = OpenThemeData(m_frame, VSCLASS_MENU);
    
            if (m_theme != 0)
            {
                int borderSize = 0;    // Border space between item text and accelerator
                int bgBorderSize = 0;  // Border space between item text and gutter
                GetThemePartSize(0, MENU_POPUPCHECK, 0, NULL, TS_TRUE, &m_sizeCheck);
                GetThemePartSize(0, MENU_POPUPSEPARATOR, 0, NULL, TS_TRUE, &m_sizeSeparator);
                GetThemeInt(MENU_POPUPITEM, 0, TMT_BORDERSIZE, &borderSize);
                GetThemeInt(MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &bgBorderSize);
                GetThemeMargins(0, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &m_marCheck);
                GetThemeMargins(0, MENU_POPUPCHECKBACKGROUND, 0, TMT_CONTENTMARGINS, NULL, &m_marCheckBackground);
                GetThemeMargins(0, MENU_POPUPITEM, 0, TMT_CONTENTMARGINS, NULL, &m_marItem);
    
                // Popup text margins
                m_marText = m_marItem;
                m_marText.cxRightWidth = borderSize;
                m_marText.cxLeftWidth = bgBorderSize;
            }
            else
            {
                m_sizeCheck.SetSize(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
                m_sizeSeparator.SetSize(1, 7);
                m_marCheck.SetMargins(4, 4, 2, 2);
                m_marCheckBackground.SetMargins(0, 0, 0, 0);
                m_marItem.SetMargins(0, 0, 0, 0);
                m_marText.SetMargins(8, 16, 0, 0);
            }
        }
    

    How can I change its style, such as the native style of Win11?
    Looking forward to your answer, thank you!

    Thanks,
    Zhang

     
  • David

    David - 2023-02-12

    Hi Zhang,

    The code you've quoted is what provides the Win11 style, using the VSCLASS_MENU theme data. To compare this with the XP style you can comment out the following lines:

    if (m_uxTheme == 0)
         m_uxTheme = ::LoadLibrary(_T("UXTHEME.DLL"));
    

    That will stop the VSCLASS_MENU theme data from being loaded.

    If you download the latest snapshot from the code section you will find the following entries in CMainFrame::OnCreate in the Frame sample:

    // UseIndicatorStatus(FALSE);    // Don't show keyboard indicators in the StatusBar.
    // UseMenuStatus(FALSE);         // Don't show menu descriptions in the StatusBar.
    // UseOwnerDrawnMenu(FALSE);     // Don't use owner draw for popup menu items.
    // UseReBar(FALSE);              // Don't use a ReBar.
    // UseStatusBar(FALSE);          // Don't use a StatusBar.
    // UseThemes(FALSE);             // Don't use themes.
    // UseToolBar(FALSE);            // Don't use a ToolBar.
    

    If you remove the comment from in from of UseOwnerDrawnMenu, the popup menu will be drawn in its native style without any owner draw. Note that the native style doesn't draw any icons from the toolbar in the popup menu.

    Best regards,
    David

     
  • Yinzhong Zhang

    Yinzhong Zhang - 2023-02-17

    How can I implement a menu theme like notepad++?

     
  • David

    David - 2023-02-18

    Notpad++ doesn't use owner draw for its menus.

    In Win32++, we can turn off owner draw for menu items by removing the comment in front of UseOwnerDrawnMenu in CMainFrame::OnCreate (as described in the previous post).

    When we turn off the owner draw for the menu items in Win32++, the style will match the Notepad++ menu style precisely.

    Best regards,
    David

     
  • Yinzhong Zhang

    Yinzhong Zhang - 2023-02-23

    Thank you very much David.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.