📄 menuext.cpp
字号:
为此,我们需要提供菜单文本和图标的宽度之和以及图标的高度
*/
void CMenuExt::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
UINT state = (((CMenuExtData*)(lpMIS->itemData))->nFlags);
if(state & MF_SEPARATOR)
{
lpMIS->itemWidth = 0;
lpMIS->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
}
else
{
CFont fontMenu;
LOGFONT logfont;
ZeroMemory ((PVOID) &logfont,sizeof (LOGFONT));
NONCLIENTMETRICS nm;
nm.cbSize = sizeof (NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0);
logfont = nm.lfMenuFont;
fontMenu.CreateFontIndirect (&logfont);
CWnd *pWnd = AfxGetMainWnd();
CDC *pDC = pWnd->GetDC();
CFont* pFont = NULL;
if(IsNewShell()) //win95,NT4以后
pFont = pDC->SelectObject (&fontMenu);
const wchar_t *lpstrText = ((CMenuExtData*)(lpMIS->itemData))->GetWideString();
SIZE size;
if(g_Shell != Win32s)
::GetTextExtentPoint32W(pDC->m_hDC,lpstrText,wcslen(lpstrText),&size);
#ifndef UNICODE
else
{
RECT rect;
rect.left = rect.top = 0;
size.cy = DrawText( pDC->m_hDC,(LPCTSTR)lpstrText,
wcslen(lpstrText),&rect,
DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT );
//到菜单项的边至少留有3个像素的空间
size.cx = rect.right - rect.left + 3;
size.cx += 3 * (size.cx/wcslen(lpstrText));
}
#endif
if(IsNewShell()) pDC->SelectObject(pFont);
AfxGetMainWnd()->ReleaseDC(pDC);
lpMIS->itemWidth = m_iconX + size.cx + m_iconX + GAP;
int nCYMenu = GetSystemMetrics(SM_CYMENU);
lpMIS->itemHeight = nCYMenu>m_iconY+4 ? nCYMenu : m_iconY+4;
fontMenu.DeleteObject();
}
}
void CMenuExt::SetIconSize (int width, int height)
{
m_iconX = width;
m_iconY = height;
}
BOOL CMenuExt::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,int nIconNormal)
{
USES_CONVERSION;
return AppendODMenuW(A2W(lpstrText),nFlags,nID,nIconNormal);
}
BOOL CMenuExt::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,int nIconNormal)
{
// 所有的菜单项全部标记为MF_OWNERDRAW风格
if(!nID) nFlags = MF_SEPARATOR|MF_OWNERDRAW;
else if(!(nFlags & MF_OWNERDRAW)) nFlags |= MF_OWNERDRAW;
if(nFlags & MF_POPUP)
{
// 记录下弹出菜单HMENU
m_AllSubMenus.Add((HMENU)nID);
m_SubMenus.Add((HMENU)nID);
}
// 下面的代码组织一个菜单项(可能是弹出菜单)的数据
CMenuExtData *mdata = new CMenuExtData;
m_MenuList.Add(mdata);
mdata->SetWideString(lpstrText);
mdata->menuIconNormal = nIconNormal;
mdata->xoffset = -1;
if(nIconNormal >= 0)
{
mdata->xoffset = 0;
LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
if(mdata->bitmap)
mdata->bitmap->DeleteImageList();
else
mdata->bitmap = new CImageList;
mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
if(!AddBitmapToImageList(mdata->bitmap,nIconNormal))
{
mdata->bitmap->DeleteImageList();
delete mdata->bitmap;
mdata->bitmap = NULL;
mdata->menuIconNormal = nIconNormal = -1;
mdata->xoffset = -1;
}
}
mdata->nFlags = nFlags;
mdata->nID = nID;
return CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata);
}
BOOL CMenuExt::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,CImageList *il,int xoffset)
{
USES_CONVERSION;
return AppendODMenuW(A2W(lpstrText),nFlags,nID,il,xoffset);
}
BOOL CMenuExt::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,CImageList *il,int xoffset)
{
// Add the MF_OWNERDRAW flag if not specified:
if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW;
else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
if(nFlags & MF_POPUP){
m_AllSubMenus.Add((HMENU)nID);
m_SubMenus.Add((HMENU)nID);
}
CMenuExtData *mdata = new CMenuExtData;
m_MenuList.Add(mdata);
mdata->SetWideString(lpstrText); //SK: modified for dynamic allocation
if(il){
mdata->menuIconNormal = 0;
mdata->xoffset=0;
if(mdata->bitmap)mdata->bitmap->DeleteImageList();
else mdata->bitmap=new(CImageList);
ImageListDuplicate(il,xoffset,mdata->bitmap);
}
else{
mdata->menuIconNormal = -1;
mdata->xoffset = -1;
}
mdata->nFlags = nFlags;
mdata->nID = nID;
return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
}
BOOL CMenuExt::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
int nIconNormal)
{
USES_CONVERSION;
return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,nIconNormal);
}
BOOL CMenuExt::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
int nIconNormal)
{
// Add the MF_OWNERDRAW flag if not specified:
if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW;
else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
if(nFlags & MF_POPUP){
m_AllSubMenus.Add((HMENU)nID);
m_SubMenus.InsertAt(nPosition,(HMENU)nID);
}
CMenuExtData *mdata = new CMenuExtData;
m_MenuList.InsertAt(nPosition,mdata);
mdata->SetWideString(lpstrText); //SK: modified for dynamic allocation
mdata->menuIconNormal = nIconNormal;
mdata->xoffset=-1;
if(nIconNormal>=0){
mdata->xoffset=0;
LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
if(mdata->bitmap)mdata->bitmap->DeleteImageList();
else mdata->bitmap=new(CImageList);
mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
mdata->bitmap->DeleteImageList();
delete mdata->bitmap;
mdata->bitmap=NULL;
mdata->menuIconNormal = nIconNormal = -1;
mdata->xoffset = -1;
}
}
mdata->nFlags = nFlags;
mdata->nID = nID;
return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
}
BOOL CMenuExt::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
CImageList *il,int xoffset)
{
USES_CONVERSION;
return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,il,xoffset);
}
BOOL CMenuExt::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
CImageList *il,int xoffset)
{
// Add the MF_OWNERDRAW flag if not specified:
if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW;
else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
if(nFlags & MF_POPUP){
m_AllSubMenus.Add((HMENU)nID);
m_SubMenus.InsertAt(nPosition,(HMENU)nID);
}
CMenuExtData *mdata = new CMenuExtData;
m_MenuList.InsertAt(nPosition,mdata);
mdata->SetWideString(lpstrText); //SK: modified for dynamic allocation
if(il){
mdata->menuIconNormal = 0;
mdata->xoffset=0;
if(mdata->bitmap)mdata->bitmap->DeleteImageList();
else mdata->bitmap=new(CImageList);
ImageListDuplicate(il,xoffset,mdata->bitmap);
}
else{
mdata->menuIconNormal = -1;
mdata->xoffset = -1;
}
mdata->nFlags = nFlags;
mdata->nID = nID;
return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
}
BOOL CMenuExt::ModifyODMenuA(const char * lpstrText,UINT nID,int nIconNormal)
{
USES_CONVERSION;
return ModifyODMenuW(A2W(lpstrText),nID,nIconNormal);
}
BOOL CMenuExt::ModifyODMenuW(wchar_t *lpstrText,UINT nID,int nIconNormal)
{
int nLoc;
CMenuExtData *mdata;
// 采用递归方法遍历所有的菜单,查找nID
CMenuExt *pSubMenu = FindMenuOption(nID,nLoc);
if(pSubMenu && nLoc>=0)
mdata = pSubMenu->m_MenuList[nLoc];
else
{
mdata = new CMenuExtData;
m_MenuList.Add(mdata);
}
if(lpstrText) mdata->SetWideString(lpstrText);
mdata->menuIconNormal = nIconNormal;
mdata->xoffset = -1;
if(nIconNormal >= 0)
{
mdata->xoffset = 0;
// 找出nID命令菜单项在nIconNormal工具条中的位图偏移量(本行代码放在了mdata->xoffset)
LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
if(mdata->bitmap)
mdata->bitmap->DeleteImageList();
else
mdata->bitmap = new CImageList;
mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
if(!AddBitmapToImageList(mdata->bitmap,nIconNormal))
{
mdata->bitmap->DeleteImageList();
delete mdata->bitmap;
mdata->bitmap=NULL;
mdata->menuIconNormal = nIconNormal = -1;
mdata->xoffset = -1;
}
}
mdata->nFlags = MF_BYCOMMAND | MF_OWNERDRAW;
mdata->nID = nID;
return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
}
BOOL CMenuExt::ModifyODMenuA(const char * lpstrText,UINT nID,CImageList *il,int xoffset)
{
USES_CONVERSION;
return ModifyODMenuW(A2W(lpstrText),nID,il,xoffset);
}
BOOL CMenuExt::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CImageList *il,int xoffset)
{
int nLoc;
CMenuExtData *mdata;
// Find the old CMenuExtData structure:
CMenuExt *psubmenu = FindMenuOption(nID,nLoc);
if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
else{
// Create a new CMenuExtData structure:
mdata = new CMenuExtData;
m_MenuList.Add(mdata);
}
ASSERT(mdata);
if(lpstrText)
mdata->SetWideString(lpstrText); //SK: modified for dynamic allocation
if(il){
mdata->menuIconNormal = 0;
mdata->xoffset=0;
if(mdata->bitmap)mdata->bitmap->DeleteImageList();
else mdata->bitmap=new(CImageList);
ImageListDuplicate(il,xoffset,mdata->bitmap);
}
else{
mdata->menuIconNormal = -1;
mdata->xoffset = -1;
}
mdata->nFlags = MF_BYCOMMAND | MF_OWNERDRAW;
mdata->nID = nID;
return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
}
BOOL CMenuExt::ModifyODMenuA(const char * lpstrText,UINT nID,CBitmap *bmp)
{
USES_CONVERSION;
return ModifyODMenuW(A2W(lpstrText),nID,bmp);
}
BOOL CMenuExt::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CBitmap *bmp)
{
if(bmp){
CImageList temp;
temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
return ModifyODMenuW(lpstrText,nID,&temp,0);
}
return ModifyODMenuW(lpstrText,nID,NULL,0);
}
BOOL CMenuExt::ModifyODMenuA(const char *lpstrText,const char *OptionText,
int nIconNormal)
{
USES_CONVERSION;
return ModifyODMenuW(A2W(lpstrText),A2W(OptionText),nIconNormal);//SK: see MFC Tech Note 059
}
BOOL CMenuExt::ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,
int nIconNormal)
{
CMenuExtData *mdata;
// Find the old CMenuExtData structure:
CString junk=OptionText;
mdata=FindMenuOption(OptionText);
if(mdata){
if(lpstrText)
mdata->SetWideString(lpstrText);//SK: modified for dynamic allocation
mdata->menuIconNormal = nIconNormal;
mdata->xoffset=-1;
if(nIconNormal>=0){
mdata->xoffset=0;
if(mdata->bitmap)mdata->bitmap->DeleteImageList();
else mdata->bitmap=new(CImageList);
mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
mdata->bitmap->DeleteImageList();
delete mdata->bitmap;
mdata->bitmap=NULL;
mdata->menuIconNormal = nIconNormal = -1;
mdata->xoffset = -1;
}
}
return(TRUE);
}
return(FALSE);
}
CMenuExtData *CMenuExt::NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string)
{
CMenuExtData *mdata;
mdata = new CMenuExtData;
mdata->menuIconNormal = -1;
mdata->xoffset=-1;
#ifdef UNICODE
mdata->SetWideString((LPCTSTR)string);//SK: modified for dynamic allocation
#else
mdata->SetAnsiString(string);
#endif
mdata->nFlags = nFlags;
mdata->nID = nID;
if(nFlags & MF_POPUP)m_AllSubMenus.Add((HMENU)nID);
if (nFlags&MF_OWNERDRAW){
ASSERT(!(nFlags&MF_STRING));
ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
}
else if (nFlags&MF_STRING){
ASSERT(!(nFlags&MF_OWNERDRAW));
ModifyMenu(pos,nFlags,nID,mdata->GetString());
}
else{
ASSERT(nFlags&MF_SEPARATOR);
ModifyMenu(pos,nFlags,nID);
}
return(mdata);
};
BOOL CMenuExt::LoadToolbars(const UINT *arID,int n)
{
ASSERT(arID);
BOOL returnflag=TRUE;
for(int i=0;i<n;++i){
if(!LoadToolbar(arID[i]))returnflag=FALSE;
}
return(returnflag);
}
BOOL CMenuExt::LoadToolbar(UINT nToolBar)
{
UINT nID;
CToolBar Toolbar;
Toolbar.Create(AfxGetMainWnd());
if(Toolbar.LoadToolBar(nToolBar))
{
for(int i=0;i<Toolbar.GetCount();++i)
{
nID = Toolbar.GetItemID(i); //从工具条里找命令nID
if(nID && GetMenuState(nID, MF_BYCOMMAND) != 0xFFFFFFFF)
{
// 菜单中也发现了命令nID,因此可以修改了(主要目的是加上相应的位图)
ModifyODMenu(NULL,nID,nToolBar);
}
}
return TRUE;
}
return FALSE;
}
BOOL CMenuExt::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
{
int xset,offset;
UINT nStyle;
CToolBar Toolbar;
Toolbar.Create(AfxGetMainWnd());
if(Toolbar.LoadToolBar(nToolBar))
{
offset = Toolbar.CommandToIndex(nID); //命令nID的偏移量
if(offset >= 0)
{
Toolbar.GetButtonInfo(offset,nID,nStyle,xset);
if(xset > 0) xoffset = xset; //图形在位图中的偏移量
return TRUE;
}
}
return FALSE;
}
CMenuExtData *CMenuExt::FindMenuItem(UINT nID)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -