用VC制作带弹出式菜单的按钮.doc_第1页
用VC制作带弹出式菜单的按钮.doc_第2页
用VC制作带弹出式菜单的按钮.doc_第3页
用VC制作带弹出式菜单的按钮.doc_第4页
用VC制作带弹出式菜单的按钮.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

用VC制作带弹出式菜单的按钮 vchelp2005-11-23 10:31分享到:我要吐槽带有弹出式菜单的按钮可以使一个按钮具有多项选择功能,扩展了按钮的功能,相当于把多个按钮集成于一体,可以减少按钮数目。 这种按钮的按钮体分为两个区域,单击主体区域时,执行主体按钮的功能,单击选择区域时,弹出一个菜单,可从中选择要执行的功能。下面,我们看一下它的制作过程:一、新建一个以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_pt3, m_ptCentre; /箭头坐标(三个顶点)m_ptCentre = m_RRect.CenterPoint(); /选择区中点位置m_pt0.x = m_ptCentre.x-3; /计算箭头坐标m_pt0.y = m_ptCentre.y-2; m_pt1.x = m_ptCentre.x+4; m_pt1.y = m_ptCentre.y-2; m_pt2.x = m_ptCentre.x; m_pt2.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); 四、自定义接口函数提供用户使用按钮的接口。/设置关联菜单IDvoid 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.hprivate: 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; /菜单IDvoid DrawButton(CDC *pDC); /绘制按钮public: CMenuButton(); /构造函数void SetMenuID(int nID); /设置关联菜单IDvoid SetForeColor(COLORREF color); /设置文本颜色void SetBkColor(COLORREF color); /设置背景颜色void SetText(CString str); /设置按钮文本BOOL isClick(); /是否单击主按钮区各变量的初始化在构造函数中进行:CMenuButton:CMenuButton() m_MenuID = 0; /菜单IDb_InFlag = false; /进入标志m_State = 0; /初始状态b_ClickFlag = false; /单击选择区

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论