动态菜单的问题

coolnick 2007-04-18 07:42:46
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 "©", 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 */
);
这样就搞定菜单了,但问题是我想实现修改菜单资源文件后,不用重新编译程序,就可以生效,不知道如何实现,请指点一下.
...全文
242 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
abuseyoudna1981 2007-04-20
  • 打赏
  • 举报
回复
然后在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"));


//--------------------当然这个类还没全部写完整,不过可以用.
abuseyoudna1981 2007-04-20
  • 打赏
  • 举报
回复
//.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();
}
abuseyoudna1981 2007-04-20
  • 打赏
  • 举报
回复
我写过一个动态菜单添加的类,

//.h

#pragma once
#include <vector>
#include <map>
#include <algorithm>

#define MIN_MENU_ID 8888
#define MAX_MENU_ID 9999

typedef 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;
};
菜牛 2007-04-19
  • 打赏
  • 举报
回复
如果你指的是修改已经编译好的程序里面的资源,可以用一些资源编辑工具。不过添加什么的就不行了,因为你程序中根本没有响应的代码啊。
ks_gq 2007-04-18
  • 打赏
  • 举报
回复
用 AppendMenu,ModifyMenu 等API可以实现对菜单的动态修改。
项目名称:[精仿]360安全卫士-10.30更新(CSkin Demo) 界面库版本号:10.30 最新版本 下载内容: 精仿360安全卫士源码一份, 可引用至工具箱最新版CSkin.dll一份 实现功能: 1.发光标题。 2.直角边框和阴影。 3.360安全卫士主界面模仿。 4.多系统支持,不需要win8系统,即可实现win8风格的360。 5.自定义控件的美化使用。 界面库更新文档: CC2013-10.30 1.由于SkinForm名字太多人使用,界面库命名正式改为CSkin.dll,官网www.cskin.net。 2.SkinTabControl标签中添加菜单箭头,可点击展开菜单。 3.SkinTabControl添加标签关闭按钮。 4.修复部分中文乱码问题。 5.优化好友列表右键菜单。 6.将窗体自定义系统按钮改为集合模式,可添加无数个自定义系统按钮。自定义系统按钮事件中可以 e.参数 来判断。 7.增加360安全卫士-DEMO案例。 8.增加SkinAnimatorImg控件,用于支持位图动画的播放。如360的动态logo。 9.各种细节BUG优化。 CC2013-10.11 1.添加SkinTabControlEx,加入更加自定义的美化属性和动画效果。 2.添加SkinAnimator,通用动画控件。 3.添加Html编辑器控件 4.修复SkinButton图标和文本相对位置的BUG CC2013-9.26 1.优化好友列表CPU占用 2.好友列表加入好友登录平台属性:安卓 苹果 WEBQQ PC 3.优化标题绘制模式,新添标题绘制模式属性。 4.新添标题偏移度属性。 5.加入圆形进度条控件:ProgressIndicator。 CC2013-9.5.2 1.优化截图控件,截图工具栏加入新功能。 2.解决个人信息卡和天气窗体显示后不会消失的问题。 3.各种细节BUG优化。 CC2013-9.5.1 1.解决贴边左右隐藏的BUG。 2.解决窗体点击事件不能触发的问题。 3.优化SkinButton继承父容器背景色的代码。 4.解决SkinButton异常错误。 CC2013-9.3 1.好友列表右键菜单没反应问题。 2.新增美化控件SkinDatagridview。 3.密码软件盘回删不了文字问题。 4.双击窗体最大化,最大化后再双击恢复原大小,(win7)。 5.部分细节调优。 小编:下载不要分,DEMO教你如何熟练使用CSkin界面库美化自己的窗体。 友情链接: http://bbs.csdn.net/topics/390510544 (精仿QQ2013局域通讯) http://download.csdn.net/detail/lyx_520/5710799 (C#实现Win8窗体)

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧