WIN32开发时,通过资源文件定义菜单,如下:
#include "Resource.hpp"MENUPAINT MENU DISCARDABLE
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "&New",        MENU_FILE_NEW
        MENUITEM "&Open",       MENU_FILE_OPEN
        MENUITEM "&Save",       MENU_FILE_SAVE
        MENUITEM "&Save As...", MENU_FILE_SAVEAS
        MENUITEM "&Exit",       MENU_FILE_EXIT
    END
    POPUP "&Edit"
    BEGIN
        MENUITEM "&Undo",       MENU_EDIT_UNDO
        MENUITEM "&Redo",       MENU_EDIT_REDO
        MENUITEM "&Copy",       MENU_EDIT_COPY
        MENUITEM "&Cut",        MENU_EDIT_CUT
        MENUITEM "&Paste",      MENU_EDIT_PASTE
        MENUITEM "&Delete",     MENU_EDIT_DELETE
    END
    POPUP "&Help"
    BEGIN
        MENUITEM "&About Paint...", MENU_HELP_ABOUT
    END
END然后在程序中:
    hMenu = LoadMenu(hThisInstance, TEXT("MENUPAINT"));
    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Paint",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           hMenu,               /* Use Menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );
这样就搞定菜单了,但问题是我想实现修改菜单资源文件后,不用重新编译程序,就可以生效,不知道如何实现,请指点一下.

解决方案 »

  1.   

    用 AppendMenu,ModifyMenu 等API可以实现对菜单的动态修改。
      

  2.   

    我写过一个动态菜单添加的类,//.h#pragma once
    #include <vector>
    #include <map>
    #include <algorithm>#define MIN_MENU_ID 8888
    #define MAX_MENU_ID 9999typedef struct
    {
    void (*lpHandler)();
    void (*lpUpdate)(CCmdUI*);
    }FUNC,*LPFUNC;
    typedef struct
    {
    CString m_strMenuName;
    UINT m_dMenuID;
    FUNC m_menuHandler;
    }DYNAMIC_MENUINFO,*LPDYNAMIC_MENUINFO;
    class CDynamicMenuManager
    {
    public:
    CDynamicMenuManager(void);
    ~CDynamicMenuManager(void); void Initialize(); void AddPopupMenu(CMenu& targetMenu,std::vector<DYNAMIC_MENUINFO> rgpMenuItemInfos,CString strPopupMenuName);
    void AddMenuItems(CMenu& targetMenu,std::vector<DYNAMIC_MENUINFO> rgpMenuItemInfos); void RemovePopupMenu(CMenu& fromMenu,CString strPopupMenuName);
    void RemoveMenuItems(CMenu& fromMenu,std::vector<DYNAMIC_MENUINFO> rgpMenuItemInfos);
    void RemoveAllAddedMenu(); void UpdateMenuItemUI(CCmdUI* pCmdUI); UINT GetValidMenuID();
    static LRESULT CALLBACK newWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);protected:
    int FindMenuInfoPosFromID(UINT uMenuID,bool bErase = false); 
    CMenu* GetMenuHandle(CMenu& targetMenu,CString strMenuName,int& nPos);private:
    static std::map<UINT,FUNC> m_rgpHandlers;
    std::map<CString,CMenu*> m_rgpPopupMenu;
    std::vector<DYNAMIC_MENUINFO> m_rgpMenuItemInfos;
    std::vector<UINT> m_rgpMenuID;
    HWND m_hWnd;
    };
      

  3.   

    //.cpp#include "StdAfx.h"
    #include ".\dynamicmenumanager.h"
    WNDPROC oldWndProc = NULL;
    std::map<UINT,FUNC>  CDynamicMenuManager::m_rgpHandlers;LRESULT CALLBACK CDynamicMenuManager::newWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
    {
    switch(uMsg)
    {
    case WM_COMMAND:
    {
    WORD nId =LOWORD(wParam) ;
    if((nId >= MIN_MENU_ID) && (nId <= MAX_MENU_ID))
    {
    CDynamicMenuManager::m_rgpHandlers[nId].lpHandler();
    }
    }
    break;
    }
    return CallWindowProc(oldWndProc,hWnd,uMsg,wParam,lParam);
    }
    CDynamicMenuManager::CDynamicMenuManager(void)
    :m_hWnd(NULL)
    {
    try
    {
    Initialize();
    m_hWnd = AfxGetMainWnd()->GetSafeHwnd();
    _ASSERTE(m_hWnd);
    if(m_hWnd)
    oldWndProc = (WNDPROC)SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)newWndProc);
    }
    catch (...)
    {
    AfxMessageBox(_T("Error in CDynamicMenuManager::Constructor!"));
    }

    }CDynamicMenuManager::~CDynamicMenuManager(void)
    {
    if(m_hWnd)
    SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)oldWndProc);
    std::map<CString,CMenu*>::iterator iter = m_rgpPopupMenu.begin();
    for(;iter != m_rgpPopupMenu.end();++iter)
    {
    delete (*iter).second;
    }
    m_rgpPopupMenu.clear();
    m_rgpMenuID.clear();
    m_rgpHandlers.clear();
    m_rgpMenuItemInfos.clear();
    }
    void CDynamicMenuManager::Initialize()
    {
    m_rgpMenuID.clear();
    m_rgpHandlers.clear();
    m_rgpMenuItemInfos.clear();
    m_rgpPopupMenu.clear();
    for(UINT i = MIN_MENU_ID;i< MAX_MENU_ID;++i)
    {
    m_rgpMenuID.push_back(i);
    }
    }void CDynamicMenuManager::AddPopupMenu(CMenu& targetMenu,std::vector<DYNAMIC_MENUINFO> rgpMenuItemInfos,CString strPopupMenuName)
    {
    if(!(targetMenu.GetSafeHmenu() && strPopupMenuName.GetLength()) || rgpMenuItemInfos.empty())
    return;

    CMenu* PopupMenu = new CMenu;
    PopupMenu->CreatePopupMenu(); AddMenuItems(*PopupMenu,rgpMenuItemInfos);
    m_rgpPopupMenu.insert(std::make_pair(strPopupMenuName,PopupMenu));
    targetMenu.AppendMenu(MF_POPUP,(UINT)(PopupMenu->m_hMenu) ,strPopupMenuName);
    }
    void CDynamicMenuManager::AddMenuItems(CMenu& targetMenu,std::vector<DYNAMIC_MENUINFO> rgpMenuItemInfos)
    {
    if(!(targetMenu.GetSafeHmenu()) || rgpMenuItemInfos.empty())
    return; std::vector<DYNAMIC_MENUINFO>::iterator iter = rgpMenuItemInfos.begin();
    for(;iter != rgpMenuItemInfos.end();++iter)
    {
    targetMenu.AppendMenu(MF_STRING,(*iter).m_dMenuID,(*iter).m_strMenuName);
    m_rgpMenuItemInfos.push_back(*iter);
    m_rgpHandlers.insert(std::make_pair((*iter).m_dMenuID,(*iter).m_menuHandler));
    }
    }void CDynamicMenuManager::RemovePopupMenu(CMenu& fromMenu,CString strPopupMenuName)
    {
    if(!(strPopupMenuName.GetLength() && fromMenu.GetSafeHmenu()))
    return; CMenu* pMenu = NULL;
    int nPos = -1;
    pMenu = GetMenuHandle(fromMenu,strPopupMenuName,nPos); if(!pMenu->GetSafeHmenu())
    return; for(UINT i = 0;i< pMenu->GetMenuItemCount();++i)
    {
    int iPos = FindMenuInfoPosFromID(pMenu->GetMenuItemID(i),true);
    if(iPos != -1)
    {
    m_rgpHandlers.erase(pMenu->GetMenuItemID(i));
    m_rgpMenuID.push_back(pMenu->GetMenuItemID(i));
    }
    }
    if(nPos != -1)
    {
    fromMenu.RemoveMenu(nPos,MF_BYPOSITION);
    m_rgpPopupMenu.erase(strPopupMenuName);
    }
    }void CDynamicMenuManager::RemoveMenuItems(CMenu& fromMenu,std::vector<DYNAMIC_MENUINFO> rgpMenuItemInfos)
    {
    if(!fromMenu.GetSafeHmenu() && rgpMenuItemInfos.empty())
    return;

    std::vector<DYNAMIC_MENUINFO>::iterator iter = rgpMenuItemInfos.begin();
    for (;iter != rgpMenuItemInfos.end();++iter)
    {
    fromMenu.RemoveMenu((*iter).m_dMenuID,MF_BYCOMMAND);
    FindMenuInfoPosFromID((*iter).m_dMenuID,true);
    }
    }
    void CDynamicMenuManager::RemoveAllAddedMenu()
    {
    //Need to code!!
    #pragma message(_T("Notice!!!!! RemoveAllAddedMenu func"))
    }
    int CDynamicMenuManager::FindMenuInfoPosFromID(UINT uMenuID,bool bErase/*=false*/)
    {
    if(m_rgpMenuItemInfos.empty())
    return -1; std::vector<DYNAMIC_MENUINFO>::iterator iter = m_rgpMenuItemInfos.begin();
    int menuItemCount = (int)m_rgpMenuItemInfos.size();
    for(int i = 0;i<menuItemCount;++i)
    {
    if(m_rgpMenuItemInfos.at(i).m_dMenuID == uMenuID)
    {
    if(bErase)
    {
    m_rgpMenuItemInfos.erase(m_rgpMenuItemInfos.begin()+i);
    m_rgpHandlers.erase(uMenuID);
    }
    return i;
    }
    }
    return -1;
    }
    CMenu* CDynamicMenuManager::GetMenuHandle(CMenu& targetMenu,CString strMenuName,int& nPos)
    {
    if(!(targetMenu.GetSafeHmenu()&&strMenuName.GetLength()))
    return NULL; int nMenuItemCount = targetMenu.GetMenuItemCount();
    for(int i = 0;i< nMenuItemCount;++i)
    {
    CString str = _T("");
    targetMenu.GetMenuString(i,str,MF_BYPOSITION);
    if(str.CompareNoCase(strMenuName) == 0)
    {
    nPos = i;
    return targetMenu.GetSubMenu(i);
    }
    }
    nPos = -1;
    return NULL;
    }
    UINT CDynamicMenuManager::GetValidMenuID()
    {
    if(m_rgpMenuID.empty())
    return 0;
    else
    {
    UINT menuID = m_rgpMenuID.front();
    m_rgpMenuID.erase(m_rgpMenuID.begin());
    return menuID;
    }
    }void CDynamicMenuManager::UpdateMenuItemUI(CCmdUI* pCmdUI)
    {
    pCmdUI->Enable();
    }
      

  4.   

    然后在MAINFRAME里面的ACTIVEFRAME函数里面
    // CMainFrame message handlers
    void A()
    {
    AfxMessageBox(_T("A menu function!"));
    }void B()
    {
    AfxMessageBox(_T("B menu function!"));
    }
    当时做试验,加了两个全局函数作为菜单项响应用的
    //
    m_menuManager = new CDynamicMenuManager;
    m_menuManager->Initialize(); std::vector<DYNAMIC_MENUINFO> rgpMenuInfos;
    DYNAMIC_MENUINFO menuinfo;
    menuinfo.m_dMenuID = m_menuManager->GetValidMenuID();
    menuinfo.m_strMenuName = _T("A");
    menuinfo.m_menuHandler.lpHandler = A;
    menuinfo.m_menuHandler.lpUpdate = up;
    rgpMenuInfos.push_back(menuinfo); menuinfo.m_dMenuID = m_menuManager->GetValidMenuID();
    menuinfo.m_strMenuName = _T("B");
    menuinfo.m_menuHandler.lpHandler = B;
    menuinfo.m_menuHandler.lpUpdate = up;
    rgpMenuInfos.push_back(menuinfo); CMenu* pMenu = NULL;
    pMenu = AfxGetMainWnd()->GetMenu()->GetSubMenu(1);
    m_menuManager->AddPopupMenu(*pMenu,rgpMenuInfos,_T("Popup"));
    //--------------------当然这个类还没全部写完整,不过可以用.