用VC製作帶彈出式選單的按鈕(整理以後的擴充套件類)
//標頭檔案
#if !defined(AFX_MENUBUTTON_H__B0745FB2_A382_4B46_8C67_B5369E51CB91__INCLUDED_)
#define AFX_MENUBUTTON_H__B0745FB2_A382_4B46_8C67_B5369E51CB91__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// MenuButton.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CMenuButton window
class CMenuButton : public CButton
{
// Construction
public:
CMenuButton();
// Attributes
public:
CRect m_ButRect;
CRect m_LRect;
CRect m_RRect;
int m_State;
BOOL b_InFlag;
BOOL b_ClickFlag;
BOOL b_ClickBut;
CMenu m_Menu;
COLORREF m_BackColor;
COLORREF m_ForeColor;
CString m_strText;
int m_MenuID;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMenuButton)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL
// Implementation
public:
BOOL isClick();
void SetBkColor(COLORREF color);
void SetForeColor(COLORREF color);
void SetText(CString str);
void SetMenuID(int nID);
void DrawButton(CDC *pDC);
virtual ~CMenuButton();
// Generated message map functions
protected:
//{{AFX_MSG(CMenuButton)
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MENUBUTTON_H__B0745FB2_A382_4B46_8C67_B5369E51CB91__INCLUDED_)
//CPP檔案
// MenuButton.cpp : implementation file
//
#include "stdafx.h"
#include "對話方塊選單禁用.h"
#include "MenuButton.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMenuButton
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 ); //背景色
}
CMenuButton::~CMenuButton()
{
}
BEGIN_MESSAGE_MAP(CMenuButton, CButton)
//{{AFX_MSG_MAP(CMenuButton)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMenuButton message handlers
void CMenuButton::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
ModifyStyle( 0, BS_OWNERDRAW ); //設定按鈕屬性為自繪式
CButton::PreSubclassWindow();
}
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);
}
void CMenuButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
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)
{
// TODO: Add your message handler code here and/or call default
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)
{
// TODO: Add your message handler code here and/or call default
m_State = 0; //恢復為正常按鈕
Invalidate(); //重繪按鈕
CButton::OnLButtonUp(nFlags, point);
}
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;
this->Invalidate();
}
BOOL CMenuButton::isClick()
{
return b_ClickBut;
}
void CMenuButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
CDC *pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
m_ButRect = lpDrawItemStruct->rcItem; //獲取按鈕尺寸
int nSavedDC = pDC->SaveDC();
VERIFY( pDC );
DrawButton(pDC); //繪製按鈕
pDC->RestoreDC( nSavedDC );
}
//呼叫
m_1.SetMenuID(IDR_MENU1);
m_1.SetText("彈出選單按鈕");
m_1.SetBkColor(RGB(125,236,123));
m_1.SetForeColor(RGB(0,0,255));
//執行效果圖