VC 制作带弹出式菜单的按钮

带有弹出式菜单的按钮可以使一个按钮具有多项选择功能,扩展了按钮的功能,相当于把多个按钮集成于一体,可以减少按钮数目。

这种按钮的按钮体分为两个区域,单击主体区域时,执行主体按钮的功能,单击选择区域时,弹出一个菜单,可从中选择要执行的功能。

下面,我们看一下它的制作过程:

一、新建一个以CButton类为基类的新类

单击“Insert”→“New Class”,建立一个新类。基类设置为CButton,新类起名为CMenuButton。

二、利用自绘方法绘制按钮,主体区显示按钮文本,选择区画一个小箭头

在CMenuButton类中用ClassWizard添加函数:PreSubclassWindow()和DrawItem()。

PreSubclassWindow()函数在建立按钮时执行,可用于做一些准备工作。在这里我给按钮添加自绘属性:

void CMenuButton::PreSubclassWindow()
{
ModifyStyle( 0, BS_OWNERDRAW ); //设置按钮属性为自绘式

CButton::PreSubclassWindow();
}

DrawItem()函数用于绘制按钮,左边绘制按钮文字,作为主体区,右边绘制一个小箭头,作为选择区。实际应用中,可根据具体需要绘制想要的形状和内容。

void CMenuButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC *pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
m_ButRect = lpDrawItemStruct->rcItem; //获取按钮尺寸
int nSavedDC = pDC->SaveDC();
VERIFY( pDC );

DrawButton(pDC); //绘制按钮

pDC->RestoreDC( nSavedDC );
}

其中m_ButRect都是CRect型对象,在头文件中进行定义。DrawButton()为绘制按钮的函数,把它定义在外边的目的是方便用户修改,如果你想改变按钮形状,只需修改DrawButton()函数即可。

void CMenuButton::DrawButton(CDC *pDC)
{
m_LRect.SetRect( m_ButRect.left, m_ButRect.top,
m_ButRect.right-21, m_ButRect.bottom ); //按钮主体区尺寸
m_RRect.SetRect( m_ButRect.right-20, m_ButRect.top,
m_ButRect.right, m_ButRect.bottom ); //按钮选择区尺寸

CPen Pen;
Pen.CreatePen(PS_SOLID, 1, RGB(192,192,192) );
pDC->SelectObject( &Pen );

pDC->FillSolidRect( m_ButRect, m_BackColor ); //画背景
switch( m_State ) //不同状态画不同边框
{
case 0: //正常按钮
pDC->DrawEdge( &m_LRect, BDR_RAISEDINNER, BF_RECT );
pDC->DrawEdge( &m_RRect, BDR_RAISEDINNER, BF_RECT );
break;
case 1: //鼠标进入时的按钮
pDC->DrawEdge( &m_LRect, BDR_RAISEDINNER, BF_RECT );
pDC->DrawEdge( &m_RRect, BDR_RAISEDINNER, BF_RECT );
pDC->MoveTo( m_ButRect.TopLeft() );
pDC->LineTo( m_ButRect.right, m_ButRect.top );
break;
case 2: //单击按钮主体区时的按钮
pDC->DrawEdge( &m_RRect, BDR_RAISEDINNER, BF_RECT );
break;
case 3: //单击按钮选择区时的按钮
pDC->DrawEdge( &m_LRect, BDR_RAISEDINNER, BF_RECT );
break;
}

POINT m_pt[3], m_ptCentre; //箭头坐标(三个顶点)
m_ptCentre = m_RRect.CenterPoint(); //选择区中点位置
m_pt[0].x = m_ptCentre.x-3; //计算箭头坐标
m_pt[0].y = m_ptCentre.y-2;
m_pt[1].x = m_ptCentre.x+4;
m_pt[1].y = m_ptCentre.y-2;
m_pt[2].x = m_ptCentre.x;
m_pt[2].y = m_ptCentre.y+2;

pDC->SelectStockObject( BLACK_BRUSH ); //定义画刷(黑色)
CRgn rgn;
rgn.CreatePolygonRgn( m_pt, 3, ALTERNATE );
pDC->PaintRgn( &rgn ); //画选择区箭头

pDC->SetTextColor( m_ForeColor ); //画主体区文字
pDC->SetBkMode( TRANSPARENT );
pDC->DrawText( m_strText, &m_LRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS);
}

m_State是个标志,其值为0表示正常按钮;1表示鼠标进入按钮,绘制暗线边框;2表示在按钮主体区按下鼠标左键;3表示在按钮选择区按下鼠标左键。

在m_State的不同取值下,绘制不同的按钮边框,可以增加按钮的动态效果。

三、添加鼠标响应函数

在CMenuButton类中用ClassWizard添加函数:OnMouseMove()、OnLButtonDown()、OnLButtonUp()。

OnMouseMove()函数用于响应鼠标移动消息,当鼠标进入按钮时,设置相应标志,并重绘按钮边框,当鼠标离开按钮时,清除标志,恢复原边框。

  • 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、付费专栏及课程。

余额充值