图标、菜单项绘制

1、在view中加入:

void CDrawMyMenuView::OnContextMenu(CWnd* pWnd, CPoint point)
{
// TODO: 在此处添加消息处理程序代码


//初始化菜单标题
CString strTitle[]=
{
_T("第一"),
_T("第二"),
_T("第三"),
_T("程序文档"),
_T("设置"),
_T("文档"),
_T("搜索"),
_T("帮助和支持"),
_T("运行"),
_T("关机")
};


//获取左栏位图大小
CBitmap bitmapTrans;
BITMAP bitmap;
bitmapTrans.LoadBitmap(IDB_LEFT);
bitmapTrans.GetBitmap(&bitmap);


int bmpHight = bitmap.bmHeight;
int bmpWidth = bitmap.bmWidth;


ItemData* menuItemData[10];
CRect leftBmpTranRect(0, 0, bmpWidth, 0);


CMenuMy menuMy;
menuMy.CreatePopupMenu();


for(int i = 0;i < 10;++i)
{
menuItemData[i] = new ItemData;
//设置背景色
menuItemData[i]->m_backCol = RGB(255, 255, 255);
//设置选中颜色
menuItemData[i]->m_selectCol = RGB(9, 51, 255);
//设置菜单标题
menuItemData[i]->m_title = strTitle[i];
//将位图切分成很多块
leftBmpTranRect.bottom = (i+1)*37;
menuItemData[i]->rect = leftBmpTranRect;
menuItemData[i]->m_id = IDB_ICON1;
menuMy.AppendMenu(MF_OWNERDRAW|MF_BYCOMMAND|MF_STRING, IDB_ICON1, (LPCTSTR)menuItemData[i]);
}


menuMy.TrackPopupMenu(TPM_CENTERALIGN |TPM_RIGHTBUTTON, point.x, point.y, pWnd);






for(int i = 0;i < 10;++i)
{
delete menuItemData[i];
menuItemData[i] = NULL;
}





}



//可响应一组消息处理,同ON_COMMAND
void CDrawMyMenuView::OnCommandRange(UINT nID)
{
CString message;
message.Format(_T("nid == %d\n"), nID);
MessageBox(message);
}

2、自绘菜单

void CMenuMy::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{

// TODO:  添加您的代码以确定指定项的大小
lpMeasureItemStruct->itemWidth = 140;
lpMeasureItemStruct->itemHeight = 37;


}


void CMenuMy::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
//获取dc
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);

CDC mem;
BITMAP bitmap;
CBitmap leftBitMap;
leftBitMap.LoadBitmap(IDB_LEFT);
leftBitMap.GetBitmap(&bitmap);
pDC->SetBkMode(TRANSPARENT);
mem.CreateCompatibleDC(pDC);
CBitmap* pOldBitMap = (CBitmap*)mem.SelectObject(&leftBitMap);
ItemData* menuItemData = (ItemData*) lpDrawItemStruct->itemData;


//接受菜单项色彩信息
COLORREF clrbgGround = menuItemData->m_backCol;
COLORREF clrselect = menuItemData->m_selectCol;

CBrush backBrush(clrbgGround);
pDC->FillRect(&lpDrawItemStruct->rcItem, &backBrush);


CRect leftRect = menuItemData->rect;
//绘制左栏位图
pDC->BitBlt(leftRect.left, leftRect.top, leftRect.right, leftRect.bottom, &mem, 0, 0, SRCCOPY);
mem.SelectObject(pOldBitMap);


//绘制菜单图标,图标与左栏图标间隔为5
HBITMAP hbitmap = (HBITMAP)::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(menuItemData->m_id));

CBitmap icon_map;
icon_map.Attach(hbitmap);


CBitmap* pOldBitMap1 = (CBitmap*)mem.SelectObject(&icon_map);
pDC->BitBlt(lpDrawItemStruct->rcItem.left+bitmap.bmWidth+5, lpDrawItemStruct->rcItem.top, lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom, &mem, 0, 0, SRCCOPY);
mem.SelectObject(pOldBitMap1);


//绘制菜单项文本
CString strMenuTitle;
strMenuTitle = menuItemData->m_title;
CRect rect(lpDrawItemStruct->rcItem);
CBitmap iconBitMap;
BITMAP bitmap1;
iconBitMap.LoadBitmap(IDB_ICON1);
iconBitMap.GetBitmap(&bitmap1);
rect.left = lpDrawItemStruct->rcItem.left+bitmap.bmWidth + bitmap1.bmWidth + 8;
pDC->DrawText(strMenuTitle, rect, DT_SINGLELINE|DT_LEFT|DT_VCENTER);


if ( lpDrawItemStruct->itemState & ODS_SELECTED )
{
//左栏图像在光标移动时不被刷新
CRect selectRect(lpDrawItemStruct->rcItem);
selectRect.left += bitmap.bmWidth;
CBrush brushSelect(clrselect);
pDC->FillRect(&selectRect, &brushSelect);
//重新绘制菜单项图标
CBitmap* pOldBitMap2 = (CBitmap*)mem.SelectObject(&icon_map);
//pDC->BitBlt(lpDrawItemStruct->rcItem.left+bitmap.bmWidth+5, lpDrawItemStruct->rcItem.top, lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom, &mem, 0, 0, SRCCOPY);
TransparentBlt2(pDC->m_hDC,lpDrawItemStruct->rcItem.left+bitmap.bmWidth+5, lpDrawItemStruct->rcItem.top, bitmap1.bmWidth, bitmap1.bmHeight,mem.m_hDC,0,0,bitmap1.bmWidth, bitmap1.bmHeight,clrbgGround);


mem.SelectObject(pOldBitMap2);

//重新绘制文本
rect.left = lpDrawItemStruct->rcItem.left+bitmap.bmWidth + bitmap1.bmWidth + 8;
pDC->SetTextColor(RGB(255, 255, 255));
pDC->DrawText(strMenuTitle, rect, DT_SINGLELINE|DT_LEFT|DT_VCENTER);


}


// TODO:  添加您的代码以绘制指定项
}


void CMenuMy::TransparentBlt2( HDC hdcDest,      // 目标DC
int nXOriginDest,   // 目标X偏移
int nYOriginDest,   // 目标Y偏移
int nWidthDest,     // 目标宽度
int nHeightDest,    // 目标高度
HDC hdcSrc,         // 源DC
int nXOriginSrc,    // 源X起点
int nYOriginSrc,    // 源Y起点
int nWidthSrc,      // 源宽度
int nHeightSrc,     // 源高度
UINT crTransparent  // 透明色,COLORREF类型
)
{
HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 创建兼容位图
HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 创建单色掩码位图
HDC hImageDC = CreateCompatibleDC(hdcDest);
HDC hMaskDC = CreateCompatibleDC(hdcDest);
hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);


// 将源DC中的位图拷贝到临时DC中
if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
else
StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, 
hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);


// 设置透明色
SetBkColor(hImageDC, crTransparent);


// 生成透明区域为白色,其它区域为黑色的掩码位图
BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);


// 生成透明区域为黑色,其它区域保持不变的位图
SetBkColor(hImageDC, RGB(0,0,0));
SetTextColor(hImageDC, RGB(255,255,255));
BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);


// 透明部分保持屏幕不变,其它部分变成黑色
SetBkColor(hdcDest,RGB(255,255,255));
SetTextColor(hdcDest,RGB(0,0,0));
BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);


// "或"运算,生成最终效果
BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);


// 清理、恢复    
SelectObject(hImageDC, hOldImageBMP);
DeleteDC(hImageDC);
SelectObject(hMaskDC, hOldMaskBMP);
DeleteDC(hMaskDC);
DeleteObject(hImageBMP);
DeleteObject(hMaskBMP);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
从VC++项目中的菜单资源建立结构相同的自绘弹出式菜单,原理和步骤如下: (1)CMenu::LoadMenu读入菜单资源; (2)CImageList::Create读入工具栏位图; (3)CMenu::CreatePopupMenu和CMenu::AppendMenu拷贝菜单资源,建立弹出式菜单。其中CMenu::AppendMenu第1个参数设置成MF_OWNERDRAW(自绘), 第四个参数设置成一个附加结构的指针,包括菜单项文字和位图索引等信息。通过这个结构,在自绘制时,可以获取对应的菜单项文字和位图位置索引,其中位图保存在第(2)步中的CImageList变量中; (4)在对右鼠标键的响应函数里,使用CMenu::TrackPopupMenu启动显示弹出式菜单; (5)在弹出式菜单的拥有者窗口(CxxxView)里,处理WM_MEASUREITEM消息和WM_DRAWITEM消息,分别调用CMenuEx::MeasureItem和CMenuEx::DrawItem, 分别用来定义菜单项的尺寸,对菜单项进行自绘; (6)在自绘函数CMenuEx::DrawItem里,通过每个菜单项的附加结构lpDIS->itemData,获得其文字和位图索引,然后分别使用CDC::DrawText和CImageList::Draw,画出该菜单项的文字和位图,从而实现自绘制。 程序在VC6下编译通过。 没有处理的地方:如果菜单项状态是checked或者radio,程序没做处理。另外,弹出式菜单的激活/禁止时,不会自动触发其拥有者窗口的ON_UPDATE_COMMAND_UI宏。不过,可以处理owner窗口的WM_INITMEMUPOPUP消息(在弹出式菜单的每个子菜单弹出时,都会发出此消息),为每个子菜单项单独生成一个CCmdUI对象,调用其CCmdUI::DoUpdate函数,来手动触发ON_UPDATE_COMMAND_UI宏中对应的消息处理函数,使得菜单项能够根据应用环境进行激活和禁止。详见博客: http://oliver.zheng.blog.163.com/blog/static/14241159520143210595266/

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值