自绘菜单项
来源:互联网 发布:销售数据统计分析表 编辑:程序博客网 时间:2024/05/16 15:50
第一步:将所有菜单项设置为MF_OWNERDRAW,即自绘模式
第二步:在WM_MEASUREITEM消息中设置菜单项的大小
第三步:在WM_DRAWITEM消息中进行菜单项的绘制
问题首先出现在了第一步,我要绘制的是一个上下文菜单,即右键菜单,要将菜单项设置为MF_OWNERDRAW,需要用到ModifyMenu函数,起始由于ModifyMenu函数的参数设置错误,导致程序怎么也响应不了WM_MEASUREITEM和WM_DRAWITEM消息,所以建议在使用ModifyMenu时对返回值进行检查。
view plaincopy to clipboardprint?
void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point)
{
ClientToScreen(&point);
CMenu Menu;
Menu.LoadMenuW(IDR_MENU2);
CMenu *pMenu = Menu.GetSubMenu(0);
CString strText;
for (int i = 0; i < pMenu->GetMenuItemCount(); i++)
{
BOOL bModi = pMenu->ModifyMenuW(ID_123_456 + i, MF_BYCOMMAND|MF_OWNERDRAW, ID_123_456 + i);
if (!bModi)
{
TRACK("ModifyMenu fail!");
}
pMenu->GetMenuStringW(i, strText, MF_BYPOSITION);
}
pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTALIGN,
point.x,
point.y,
this);
}
void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point)
{
ClientToScreen(&point);
CMenu Menu;
Menu.LoadMenuW(IDR_MENU2);
CMenu *pMenu = Menu.GetSubMenu(0);
CString strText;
for (int i = 0; i < pMenu->GetMenuItemCount(); i++)
{
BOOL bModi = pMenu->ModifyMenuW(ID_123_456 + i, MF_BYCOMMAND|MF_OWNERDRAW, ID_123_456 + i);
if (!bModi)
{
TRACK("ModifyMenu fail!");
}
pMenu->GetMenuStringW(i, strText, MF_BYPOSITION);
}
pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTALIGN,
point.x,
point.y,
this);
}
第一步的问题解决后,接在在第二步的WM_MEASUREITEM消息中设置菜单项的大小:
view plaincopy to clipboardprint?
void CMainWindow::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpmis)
{
//lpmis->itemWidth = ::GetSystemMetrics(SM_CYMENU) * 4;
lpmis->itemWidth = 150;
lpmis->itemHeight = ::GetSystemMetrics(SM_CYMENU);
}
void CMainWindow::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpmis)
{
//lpmis->itemWidth = ::GetSystemMetrics(SM_CYMENU) * 4;
lpmis->itemWidth = 150;
lpmis->itemHeight = ::GetSystemMetrics(SM_CYMENU);
}
在WM_MEASUREITEM消息中设置的菜单项大小会传入WM_DRAWITEM消息中,然后再在WM_DRAWITEM消息中根据菜单项的大小来进行重绘。
到第三步也遇到了几个问题,由于最初对WM_DRAWITEM消息中的LPDRAWITEMSTRUCT结构体不了解,以致写出的程序不管在什么时候都会作同一个绘制操作,先来看看WM_DRAWITEM消息的声明:
afx_msg void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis);
在这个消息中有两个参数,在自绘菜单时,两个参数都要用到。其中nIDCtl,书上说是所属控件的ID,不太明白是什么意思,在MSDN看到,对于菜单发出的WM_DRAWITEM消息,nIDCtl为0。再说LPDRAWITEMSTRUCT结构体,该结构体中包含了菜单复选状态、选中状态以及菜单项的大小等信息。
下面是OnDrawItem消息的实现代码:
view plaincopy to clipboardprint?
void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis)
{
CBrush *brush = new CBrush;
CPen *pen = new CPen;
CString strText;
CDC *pDC = CDC::FromHandle(lpdis->hDC); //获取菜单项的设备句柄
//菜单项是否为选中状态
if ((lpdis->itemState & ODS_SELECTED))
{
//在菜单项上自绘矩形框的背景颜色
brush->CreateSolidBrush(RGB(182, 189,210));
//在菜单项自绘矩形的边框颜色
pen->CreatePen(PS_SOLID, 1, RGB(10,36,106));
//设置菜单项的文字背景颜色
pDC->SetBkColor(RGB(182,189,210));
}
else
{
brush->CreateSolidBrush(GetSysColor(COLOR_MENU));
pen->CreatePen(PS_SOLID, 0, GetSysColor(COLOR_MENU));
pDC->SetBkColor(GetSysColor(COLOR_MENU));
}
pDC->SelectObject(pen);
pDC->SelectObject(brush);
//在当前菜单项上画一个矩形框
pDC->Rectangle(lpdis->rcItem.left,
lpdis->rcItem.top,
lpdis->rcItem.right,
lpdis->rcItem.bottom);
/*--------------------------------------*/
//获取当前消息所在菜单项的文本
CMenu menu;
menu.Attach((HMENU)lpdis->hwndItem);
menu.GetMenuStringW(lpdis->itemID, strText,MF_BYCOMMAND);
/*--------------------------------------*/
//如果为菜单发出的DrawItem消息
if (nIDCtl == 0)
{
//在菜单项上输出菜单文本
pDC->TextOutW(lpdis->rcItem.left + 20, lpdis->rcItem.top + 4, strText.GetBuffer(0), strText.GetLength());
}
menu.Detach();
delete brush;
delete pen;
}
我的代码:
void CMainDlg::OnBnClickedBtnExtensions()
{
// TODO: Add your control notification handler code here
int nExtensions =5; //thenumber of extensions
CMenu menu;
menu.LoadMenu(IDR_MENU_EXTENSIONS);
CMenu* pop=menu.GetSubMenu(0);
//add bmp btn of menu
CBitmap bmp;
int nPos = 0;
//beign autonomous learning
bmp.LoadBitmap(IDB_BMP_BEGINLEARN);
pop->SetMenuItemBitmaps(nPos,MF_BYPOSITION,&bmp,&bmp);
bmp.Detach();
nPos += 2;
//stop autonomous learning
bmp.LoadBitmap(IDB_BMP_STOPLEARN);
pop->SetMenuItemBitmaps(nPos,MF_BYPOSITION,&bmp,&bmp);
bmp.Detach();
nPos += 2;
//students status
bmp.LoadBitmap(IDB_BMP_STUDENTSSTATUS);
pop->SetMenuItemBitmaps(nPos,MF_BYPOSITION,&bmp,&bmp);
bmp.Detach();
nPos += 2;
//send files
bmp.LoadBitmap(IDB_BMP_SENDFILES);
pop->SetMenuItemBitmaps(nPos,MF_BYPOSITION,&bmp,&bmp);
bmp.Detach();
nPos += 2;
//recieve homeworks
bmp.LoadBitmap(IDB_BMP_RECIEVEJOBS);
pop->SetMenuItemBitmaps(nPos,MF_BYPOSITION,&bmp,&bmp);
bmp.Detach();
nPos += 2;
HBRUSH m_BKBrush= ::CreateSolidBrush(RGB(241,245,246));
MENUINFO mnInfo;
memset(&mnInfo,0,sizeof(MENUINFO));
mnInfo.cbSize=sizeof(MENUINFO);
mnInfo.fMask=MIM_BACKGROUND;
mnInfo.hbrBack=m_BKBrush;
::SetMenuInfo(pop->m_hMenu,&mnInfo);
POINT ptMouse;
GetCursorPos(&ptMouse);
CRect Menurc,rect;
this->GetWindowRect(&rect);
if ((rect.left -MENU_WIDTH_NEARLY)>0)
{
pop->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,/*ptMouse.x*/ \
(rect.left -MENU_WIDTH_NEARLY),/*ptMouse.y*/(rect.bottom -MENU_HEIGTH_TO_BOTTOM),this);
}
else
{
pop->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,rect.right,(rect.bottom - MENU_HEIGTH_TO_BOTTOM),this);
}
pop->Detach();
pop->DestroyMenu();
}
转:http://blog.sina.com.cn/s/blog_62bb83b10100jov2.html
- 自绘菜单项
- 自绘菜单
- 自绘菜单
- 实现自绘菜单
- CMenu菜单自绘
- BCMenu 自绘菜单
- 自绘菜单
- 实现自绘菜单
- 学习自绘菜单
- BCB自绘菜单
- 自绘菜单
- MFC自绘菜单
- MFC 菜单自绘
- MFC 菜单自绘
- 菜单自绘,修改弹出菜单样式
- 自绘XP风格菜单
- 自绘菜单的实现
- 简单实现菜单自绘
- ArcEngine中实现Symbol的预览
- Android-- FragmentStatePagerAdapter分页
- Eclipse中SVN插件中英文互相转换方法
- Axis 之 Dynamic Proxy方式(WSDD方式) (转)
- java annotation
- 自绘菜单项
- Javascript中return false 的用法
- Qt中光标的形状
- [Hadoop源码解读](一)MapReduce篇之InputFormat
- 70 行 Python 代码编写一个递归下降解析器
- android EditText文本监听 (addTextChangedListener)
- OS X Mountain Lion 系统配置 Apache+Mysql+PHP 详细教程
- 安装QTP10,提示C++组件要安装
- hdu 4091