`
huozheleisi
  • 浏览: 1235146 次
文章分类
社区版块
存档分类
最新评论

制作带弹出式菜单的按钮

 
阅读更多

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

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

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

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

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

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

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

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

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

CButton::PreSubclassWindow();
}

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

voidCMenuButton::DrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct)
{
CDC*pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
m_ButRect=lpDrawItemStruct->rcItem;//获取按钮尺寸
intnSavedDC=pDC->SaveDC();
VERIFY(pDC);

DrawButton(pDC);//绘制按钮

pDC->RestoreDC(nSavedDC);
}

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

voidCMenuButton::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);//按钮选择区尺寸

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

pDC->FillSolidRect(m_ButRect,m_BackColor);//画背景
switch(m_State)//不同状态画不同边框
{
case0://正常按钮
pDC->DrawEdge(&m_LRect,BDR_RAISEDINNER,BF_RECT);
pDC->DrawEdge(&m_RRect,BDR_RAISEDINNER,BF_RECT);
break;
case1://鼠标进入时的按钮
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;
case2://单击按钮主体区时的按钮
pDC->DrawEdge(&m_RRect,BDR_RAISEDINNER,BF_RECT);
break;
case3://单击按钮选择区时的按钮
pDC->DrawEdge(&m_LRect,BDR_RAISEDINNER,BF_RECT);
break;
}

POINTm_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);//定义画刷(黑色)
CRgnrgn;
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()函数用于响应鼠标移动消息,当鼠标进入按钮时,设置相应标志,并重绘按钮边框,当鼠标离开按钮时,清除标志,恢复原边框。

voidCMenuButton::OnMouseMove(UINTnFlags,CPointpoint)
{
if(!b_InFlag||GetCapture()!=this)//鼠标进入按钮
{
b_InFlag=true;//设置进入标志
SetCapture();//捕获鼠标
m_State=1;//置按钮状态(1-当前按钮)
if(b_ClickFlag)//检测单击选择区标志
{
m_Menu.Detach();//清除打开的菜单
m_Menu.DestroyMenu();
b_ClickFlag=false;
}
Invalidate();//重绘按钮
}
else
{
if(!m_ButRect.PtInRect(point))//鼠标离开按钮
{
b_InFlag=false;//清除进入标志
ReleaseCapture();//释放鼠标捕获
b_ClickBut=false;//清除单击标志
m_State=0;//置按钮状态(0-正常按钮)
if(b_ClickFlag)//检测单击选择区标志
{
m_Menu.Detach();//清除打开的菜单
m_Menu.DestroyMenu();
b_ClickFlag=false;
}
Invalidate();//重绘按钮
}
}

CButton::OnMouseMove(nFlags,point);
}

b_InFlag是个BOOL型量,鼠标进入时设置,离开时清除,目的是防止鼠标在按钮上移动时重复刷新按钮,以避免闪烁。

b_ClickFlag是单击按钮选择区标志,当它为true时,表示弹出菜单已打开,为false时表示菜单未弹出。当菜单已经弹出,而鼠标又移回按钮单击时,应清除菜单。

b_ClickBut是单击按钮主体区标志。

OnLButtonDown()函数响应按钮单击消息,当单击的是按钮主体区时,设置b_ClickBut标志;当单击的是按钮选择区时,要根据单击次数,决定是否弹出菜单。

voidCMenuButton::OnLButtonDown(UINTnFlags,CPointpoint)
{
if(m_LRect.PtInRect(point))//单击按钮主体区
{
m_State=2;//置按钮状态(2-正常按钮)
b_ClickBut=true;//设置单击按钮标志
Invalidate();//重绘按钮
}
elseif(m_RRect.PtInRect(point)&&m_MenuID)//单击选择区
{
m_State=3;
b_ClickBut=false;//清除单击按钮标志
Invalidate();//重绘按钮
b_ClickFlag=!b_ClickFlag;//单击选择区标志
if(b_ClickFlag)//一次单击,弹出菜单
{
CRectrect=m_RRect;
ClientToScreen(rect);//转换为屏幕坐标
point=rect.BottomRight();
point.x-=rect.Width();//设置弹出菜单的位置

VERIFY(m_Menu.LoadMenu(m_MenuID));//装入菜单资源

CMenu*pPopup=m_Menu.GetSubMenu(0);
ASSERT(pPopup!=NULL);
CWnd*pWndPopupOwner=this;

while(pWndPopupOwner->GetStyle()&WS_CHILD)
pWndPopupOwner=pWndPopupOwner->GetParent();

pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,
point.x,point.y,pWndPopupOwner);//弹出菜单
}
else//再次单击,清除菜单
{
m_Menu.Detach();
m_Menu.DestroyMenu();
}
}

CButton::OnLButtonDown(nFlags,point);
}

当单击按钮选择区时,在选择区的左下角弹出菜单,函数中的point是鼠标的屏幕坐标,求菜单位置时也使用屏幕坐标。

m_MenuID是与按钮关联的弹出菜单的ID,它在创建按钮时进行设置。

OnLButtonUp()函数响应按钮弹起消息,这是只要恢复按钮正常状态即可,以产生单击动画效果。

voidCMenuButton::OnLButtonUp(UINTnFlags,CPointpoint)
{
m_State=0;//恢复为正常按钮
Invalidate();//重绘按钮

CButton::OnLButtonUp(nFlags,point);
}

四、自定义接口函数

提供用户使用按钮的接口。

//设置关联菜单ID
voidCMenuButton::SetMenuID(intnID)
{
m_MenuID=nID;
}

//设置按钮文本
voidCMenuButton::SetText(CStringstr)
{
m_strText=str;
}

//设置文本颜色
voidCMenuButton::SetForeColor(COLORREFcolor)
{
m_ForeColor=color;
Invalidate();
}

//设置背景颜色
voidCMenuButton::SetBkColor(COLORREFcolor)
{
m_BackColor=color;
Invalidate();
}

//是否单击主按钮区
BOOLCMenuButton::isClick()
{
returnb_ClickBut;
}

由于这种按钮分为两个区域,使用时要根据单击区域决定要做的工作,所以设置了isClick()接口函数。

五、变量的初始化

在CMenuButton类的头文件中,定义有以下变量和函数:

MenuButton.h

private:
intm_State;//按钮状态
BOOLb_InFlag;//鼠标进入标志
BOOLb_ClickFlag;//单击选择区
BOOLb_ClickBut;//单击主体区
CStringm_strText;//按钮文字
COLORREFm_ForeColor;//文本颜色
COLORREFm_BackColor;//背景色
CRectm_ButRect;//按钮尺寸
CRectm_LRect;//按钮左部尺寸
CRectm_RRect;//按钮右部尺寸
CMenum_Menu;//弹出菜单
intm_MenuID;//菜单ID

voidDrawButton(CDC*pDC);//绘制按钮

public:
CMenuButton();//构造函数
voidSetMenuID(intnID);//设置关联菜单ID
voidSetForeColor(COLORREFcolor);//设置文本颜色
voidSetBkColor(COLORREFcolor);//设置背景颜色
voidSetText(CStringstr);//设置按钮文本
BOOLisClick();//是否单击主按钮区

各变量的初始化在构造函数中进行:

CMenuButton::CMenuButton()
{
m_MenuID=0;//菜单ID
b_InFlag=false;//进入标志
m_State=0;//初始状态
b_ClickFlag=false;//单击选择区标志
b_ClickBut=false;//单击主体区标志
m_strText=_T("");//按钮文本
m_ForeColor=RGB(0,0,0);//文字颜色
m_BackColor=GetSysColor(COLOR_3DFACE);//背景色
}

这样,带菜单的按钮类就做好了,用它定义的按钮实例可以连接一个弹出式按钮,下面我们就看看怎样定义按钮实例。

六、生成按钮实例

1、在对话框中放置按钮,把它的大小调整合适;

2、用ClassWizard为按钮添加变量,把变量的类型设置为CMenuButton;

3、定义按钮的关联菜单

关联菜单就是普通的弹出式菜单,用VC的菜单编辑器生成即可。

进入资源的“Menu”项,插入一个新的菜单,根据需要添加菜单项。

4、设置按钮

在对话框的OnInitial()函数中初始化按钮:

按钮变量.SetMenuID(菜单ID);
按钮变量.SetText(按钮文本);
按钮变量.SetBkColor(按钮背景色);

七、按钮的响应

对按钮的响应包括单击按钮主体区的响应和单击菜单项的响应两部分。

用ClassWizard添加按钮的响应函数和各菜单项的响应函数。

在按钮的响应函数中要做如下工作:

voidCMBTestView::OnMenubutton1()
{
if(m_MenuButton1.isClick())
{
//响应按钮操作
}
}

这里要求只有单击按钮的主体区时才进行响应。

至于单击菜单项的响应与普通菜单一样,这里不再详述。

这个按钮类还有几点可考虑改进:

①增加无效状态(变灰)按钮;

②设置按钮文字字体。

相应方法可参考文章《可设置字体和颜色的按钮》。

示例程序界面:

示例程序界面

文本所用MFC函数速查:

CDC::DrawEdge
CDC::DrawText
CDC::FillSolidRect
CDC::PaintRgn
CDC::RestoreDC
CDC::SaveDC
CDC::SelectObject
CDC::SelectStockObject
CDC::SetBkMode
CDC::SetTextColor
CMenu::DestoryMenu
CMenu::Detach
CMenu::LoadMenu
CMenu::TrackPopupMenu
CPen::CreatePen
CRect::BottomRight
CRect::CenterPoint
CRect::PtInRect
CRect::SetRect
CRect::Width
CRgn::CreatePolygonRgn
CWnd::ClientToScreen
CWnd::GetCapture
CWnd::GetParent
CWnd::GetStyle
CWnd::Invalidate
CWnd::ModifyStyle
CWnd::ReleaseCapture
CWnd::SetCapture

http://221.199.150.103/jsj/Html/vc/wen/vcwen09.htm
分享到:
评论

相关推荐

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

    visual c++制作带弹出式菜单的按钮

    微信小程序实现炫酷的弹出式菜单特效

    今天给大家带来一个微信小程序的弹出是菜单效果,老规矩先上效果图。(录制的gif动画有点卡,实际真机或是模拟器上很顺畅) 先简单说下思路: 1、首先在屏幕的某个位置放几个悬浮按钮,放几个看你需要的功能 2、点击...

    如何在Dreamweaver 制作弹出菜单

    想不想在Dreamweaver中制作一个弹出菜单,如何在Dreamweaver 制作弹出菜单呢,下面小编给大家分享一个方法,有需要的朋友可以看看。

    超级简洁的jquery弹出式左右菜单

    纯div+css+jquery制作,大家可以收藏下.

    自动生成VBA窗体菜单

    Public Popup_Menu As CommandBar '指定弹出式菜单 Public LastSelect_Menu As MSForms.Image '最后选择的菜单 Public MenuCount As Integer '子菜单数量 Public hForm As Long '窗口句柄 Public intLevel As ...

    vc++编程技巧集

    1,窗体的标题是如何改变的,不要出现无标题字样? <br/>2,利用Visual C++设置桌面墙纸 <br/>3,用Visual C++设计屏幕抓图程序 <br/>4,VC++实现显示... <br/>17,用VC制作带弹出式菜单的按钮

    Visual C++高级界面特效制作百例

    实例40 可弹出菜单的按钮 第11章 图文按钮风格大全 实例41 各种图文按钮风格 实例42 图标浮动按钮 实例43 图钉按钮 实例44 计数器按钮 第12章 不规则按钮大全 实例45 各种不规则按钮 实例46 环形按钮 实例...

    网页设计与制作——Flash.Dreamweaver.Firework

    8.2 创建热区和弹出式菜单 小结 习题 第9章 制作“网站首页”网页 9.1 用FlashMX制作动画中的“影片剪辑 9.2 用:FlashMX制作主场景中的动画 9.3 制作“网站首页”网页 小结 习题 第10章 设计留言簿页面 10.1 设计...

    界面辅助工具的应用

    1.利用外部加载的一组控件,MS windows common controls ...3.弹出式菜单,修改老师提供的源程序,以实现双边均可实现相同功能。需要用到两个外部控件即:MS Common Dialog Control 6.0和MS Rich Textbox Control 6.0。

    JQuery&CSS;&CSS;+DIV实例大全.rar

    常用jQuery弹出式链接提示效果Tooltip源码下载 10.相当牛的jQuery动感TipBox,鼠标移上去会动的提示框哦 11.简单实用jQuery用于登录弹出层例子代码(带动画的弹出层) 12.综合jquery实现表格隔行换色和鼠标经过...

    【VB】VB通用开发金典(完整版)学VB的必备资料,实例,源码。

    范例1-22 右键弹出式菜单 ∷相关函数:PopupMenu 范例1-23 下拉式菜单 范例1-24 动态显示菜单 范例1-25 系统菜单DIY ∷相关函数:GetSystemMenucAppendMenu 范例1-26 炫彩菜单 ∷相关函数:RGB 范例1-27...

    Dreamweaver 扩展

    chromeless_win_wind 制作弹出无边浏览小窗口,现在网上最为流行的 scrollablearea 使用层制作IE中可控制上下滚动的看板 right_click_menu_builder 右键菜单扩展功能 flashtext 制作仿Flash的文字效果 typewriter 让...

    Visual C++ 程序开发范例宝典光盘源码 (第二版)1/7

     1.2 弹出菜单应用实例   实例005 在控件上单击右键弹出菜单   实例006 个性化的弹出菜单   实例007 任务栏托盘弹出菜单   1.3 工具栏应用实例   实例008 带背景的工具栏   实例009 带图标的...

    Visual C++ 程序开发范例宝典光盘源码 (第二版) 3/7

     1.2 弹出菜单应用实例   实例005 在控件上单击右键弹出菜单   实例006 个性化的弹出菜单   实例007 任务栏托盘弹出菜单   1.3 工具栏应用实例   实例008 带背景的工具栏   实例009 带图标的...

    Visual C++ 程序开发范例宝典光盘源码 (第二版) 6/7

     1.2 弹出菜单应用实例   实例005 在控件上单击右键弹出菜单   实例006 个性化的弹出菜单   实例007 任务栏托盘弹出菜单   1.3 工具栏应用实例   实例008 带背景的工具栏   实例009 带图标的...

    Visual C++ 程序开发范例宝典光盘源码 (第二版) 5/7

     1.2 弹出菜单应用实例   实例005 在控件上单击右键弹出菜单   实例006 个性化的弹出菜单   实例007 任务栏托盘弹出菜单   1.3 工具栏应用实例   实例008 带背景的工具栏   实例009 带图标的...

    Visual C++ 程序开发范例宝典光盘源码 (第二版) 2/7

     1.2 弹出菜单应用实例   实例005 在控件上单击右键弹出菜单   实例006 个性化的弹出菜单   实例007 任务栏托盘弹出菜单   1.3 工具栏应用实例   实例008 带背景的工具栏   实例009 带图标的...

    Visual C++ 程序开发范例宝典光盘源码 (第二版) 7/7

     1.2 弹出菜单应用实例   实例005 在控件上单击右键弹出菜单   实例006 个性化的弹出菜单   实例007 任务栏托盘弹出菜单   1.3 工具栏应用实例   实例008 带背景的工具栏   实例009 带图标的...

    Visual C++ 程序开发范例宝典光盘源码 (第二版) 4/7

     1.2 弹出菜单应用实例   实例005 在控件上单击右键弹出菜单   实例006 个性化的弹出菜单   实例007 任务栏托盘弹出菜单   1.3 工具栏应用实例   实例008 带背景的工具栏   实例009 带图标的...

Global site tag (gtag.js) - Google Analytics