|
|
| 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.Centoint(); //选择区中点位置 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); } |
| 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); } |
| 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); } |
| 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; } |
| 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() ) { //响应按钮操作 } } |