• 网络学院
  • IT资讯
  • 操作系统
  • 网络技术
  • 软件应用
  • 办公软件
  • 编程技术
  • 网站架设
  • 数据库类
  • 平面设计
  • 多媒体类
  • 游戏资讯
  • 教学论文
  • 认证考试
用VC制作带弹出式菜单的按钮
  站点:
  • 首 页
  • 最新软件
  • 文章教程
  • 国内软件
  • 国外软件
  • 绿色软件
  • 源码下载
  • 字体下载
用VC制作带弹出式菜单的按钮
软件发布 用VC制作带弹出式菜单的按钮
网络软件 系统工具 应用软件 联络聊天 图形图像 多媒体类 行业软件 游戏娱乐 编程开发 安全相关 教育教学 数码软件 绿软下载
热门软件: QQ 瑞星 pplive e话通 木马克星 千千静听 office2000 五笔字根 Photoshop 视频分割
返回文章教程首页 >> 编程技术 >> VC教程 >> 用VC制作带弹出式菜单的按钮

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

添加时间: 2006-2-10 23:45:33  作者: VC教程  阅读次数:695   来源: http://www.d9soft.com

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

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

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

  一、新建一个以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()函数用于响应鼠标移动消息,当鼠标进入按钮时,设置相应标志,并重绘按钮边框,当鼠标离开按钮时,清除标志,恢复原边框。

void CMenuButton::OnMouseMove(UINT nFlags, CPoint point)
{
 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标志;当单击的是按钮选择区时,要根据单击次数,决定是否弹出菜单。

void CMenuButton::OnLButtonDown(UINT nFlags, CPoint point)
{
 if( m_LRect.PtInRect(point) ) //单击按钮主体区
 {
  m_State = 2; //置按钮状态(2-正常按钮)
  b_ClickBut = true; //设置单击按钮标志
  Invalidate(); //重绘按钮
 }
 else if( m_RRect.PtInRect(point) && m_MenuID ) //单击选择区
 {
  m_State = 3;
  b_ClickBut = false; //清除单击按钮标志
  Invalidate(); //重绘按钮
  b_ClickFlag = !b_ClickFlag; //单击选择区标志
  if( b_ClickFlag ) //一次单击,弹出菜单
  {
   CRect rect = 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()函数响应按钮弹起消息,这是只要恢复按钮正常状态即可,以产生单击动画效果。

void CMenuButton::OnLButtonUp(UINT nFlags, CPoint point)
{
 m_State = 0; //恢复为正常按钮
 Invalidate(); //重绘按钮

 CButton::OnLButtonUp(nFlags, point);
}

四、自定义接口函数

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

//设置关联菜单ID
void CMenuButton::SetMenuID(int nID)
{
 m_MenuID = nID;
}

//设置按钮文本
void CMenuButton::SetText(CString str)
{
 m_strText = str;
}

//设置文本颜色
void CMenuButton::SetForeColor(COLORREF color)
{
 m_ForeColor = color;
 Invalidate();
}

//设置背景颜色
void CMenuButton::SetBkColor(COLORREF color)
{
 m_BackColor = color;
 Invalidate();
}

//是否单击主按钮区
BOOL CMenuButton::isClick()
{
 return b_ClickBut;
}

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

  五、变量的初始化

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

MenuButton.h

private:
 int m_State; //按钮状态
 BOOL b_InFlag; //鼠标进入标志
 BOOL b_ClickFlag; //单击选择区
 BOOL b_ClickBut; //单击主体区
 CString m_strText; //按钮文字
 COLORREF m_ForeColor; //文本颜色
 COLORREF m_BackColor; //背景色
 CRect m_ButRect; //按钮尺寸
 CRect m_LRect; //按钮左部尺寸
 CRect m_RRect; //按钮右部尺寸
 CMenu m_Menu; //弹出菜单
 int m_MenuID; //菜单ID

void DrawButton(CDC *pDC); //绘制按钮

public:
 CMenuButton(); //构造函数
 void SetMenuID(int nID); //设置关联菜单ID
 void SetForeColor(COLORREF color); //设置文本颜色
 void SetBkColor(COLORREF color); //设置背景颜色
 void SetText(CString str); //设置按钮文本
 BOOL isClick(); //是否单击主按钮区

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

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添加按钮的响应函数和各菜单项的响应函数。

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

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

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

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

 

上下文章:

 

上一篇文章: 用VC实现多串口多线程工业控制 下一篇文章: 用VC纯资源DLL解决国际化问题

相关文章:

  • DoNews制作人刘韧涉嫌敲诈被刑拘
  • ps教程:教你用Photoshop制作出:失落美女照片胶片
  • 冲上云霄 3dmax制作爆炸燃烧效果
  • 3dsMAX教程:3dsMAX茶杯建模制作逼真茶杯全过程
  • 与众不同 Windows XP开始菜单也要VIP

相关软件:

  • 大头贴制作大师 V2.5.0
  • CHM电子书制作大师 v2.1
  • 书吧手机电子书制作工具 2.0
  • Flash相册制作大师 2008 6.3
  • 金影电子相册制作系统 2008 6.0
  • 有声数码MTV电子相册制作系统 2008 6.6

 

快速导航

  • 网络学院
  • 精品汇聚
  • 字体下载
  • 教程下载
  • ASP源码
  • PHP源码
  • Net源码
  • JSP 源码

编程技术分类导航

  • ASP & ASP.NET教程
  • PHP教程
  • JSP教程
  • C/C++教程
  • VB & VB.NET教程
  • VC教程
  • Delphi教程
  • BCB教程
  • VFP教程
  • PB教程
  • JAVA教程
  • XML教程
  • C#教程
  • CGI教程

本类经典文章推荐

  • VC++之Button控件
  • VC++之Static Box控件
  • VC++之Edit Box控件
  • VC++之Static Box控件
  • VC++之Edit Box控件
  • VC++之Scroll Bar
  • VC++之Scroll Bar
  • VC++之List Box/Check List Box控...
  • VC++ Combo Box/Combo Box Ex控件
  • VC++ List Ctrl控件

VC教程阅读排行

  • VC++之List Box/Check List Box控...
  • VC++ List Ctrl控件
  • VC++ Combo Box/Combo Box Ex控件
  • VC++之Button控件
  • VC++之Tab Ctrl控件
  • VC++之Edit Box控件
  • VC++之Edit Box控件
  • VC遍历整个目录树查找文件
  • VC++之Scroll Bar
  • VC使用ActiveX控件常见问题

编程技术阅读总排行

  • VB入门教程之一
  • Java连接数据库实例
  • VC++之List Box/Check List Box控...
  • 第二章 PowerBuilder 入门之创建新...
  • VC++ List Ctrl控件
  • 第一章 什么是PowerBuilder
  • VC++ Combo Box/Combo Box Ex控件
  • 学C++不得不看的一篇文章
  • VB入门教程之二
  • VC++之Button控件

广告位置

字母检索 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 回到顶部

关于我们 | 版权声明 | 免责条款 | 广告联系 | 软件发布 | 下载帮助 | 下载排行 | 网站地图 | 特别鸣谢 | 友情连接

copyright; 2005-2008 D9soft.com 第九软件网 版权所有