1. 程式人生 > >自繪式按鈕COwnerDrawBtn:可設定文字字型、文字顏色、按鈕背景圖片

自繪式按鈕COwnerDrawBtn:可設定文字字型、文字顏色、按鈕背景圖片

使用MFC做介面的程式設計師,一定很痛苦,因為其預設效果比較古老呆板,實現好的UI效果往往需要費大力氣

但是花了精力去做,收穫比起只是拖拖介面設定引數的程式設計師,自然是更多的,最重要的收穫,就是靈活和自由,

到最後發現想要什麼效果,都可以去自定義實現

最近需要自繪按鈕,需求是:能設定背景圖、能設定字型、能改文字顏色,

上網找到的都不能完全滿足,最後參照著自己實現了一個,經驗證可用,貼程式碼:

//使用示例
COwnerDrawBtn m_btn;
m_btn.MoveWindow(xGap,yGap,BTN_W,BTN_H);
m_btn.SetBkSkin(_T("res\\Btn.bmp"));
m_btn.SetTextFont(120, "宋體");
m_btn.SetTextColor(RGB(255,0,0));

OwnerDrawBtn.h

#ifndef _OWNERDRAW_BTN_H_
#define _OWNERDRAW_BTN_H_

#if _MSC_VER > 1000
#pragma once
#endif 

class COwnerDrawBtn : public CButton
{
public:
	COwnerDrawBtn();
	virtual ~COwnerDrawBtn();
	
private: 
	enum{
		BS_NORMAL=0,	
		BS_HOVER,		
		BS_PUSHDOWN,	
		BS_DISABLE
	};
    int         m_nStatus;			//按鈕狀態
    BOOL        m_bInRect;          //滑鼠進入標誌 
    CString     m_strText;          //按鈕文字 
    COLORREF    m_BackColor;        //背景色 
    COLORREF    m_TextColor;        //文字顏色 
    CRect       m_BtnRect;          //按鈕尺寸 
	CFont		m_font;				//字型
	HBITMAP		m_hBkBmp;			//背景圖片
	
public:
	void DrawButton(CDC *pDC);				 //畫按鈕  
	void DrawBkBmp(CDC *pDC);
	void DrawTxt(CDC *pDC);
	void SetText(CString str); 
    void SetTextColor(COLORREF color);       //設定文字顏色 
    void SetBkColor(COLORREF color);         //設定背景顏色 
	void SetTextFont(int FontHight,LPCTSTR FontName);   //設定字型
	void SetTextFont(CFont* pFont);
	void SetBkSkin(HBITMAP hBkBmp);			//設定按鈕底圖,傳(五態)圖片控制代碼
	void SetBkSkin(LPCTSTR pBmpFile);		//傳相對exe路徑

	//{{AFX_VIRTUAL(COwnerDrawBtn)
	virtual void PreSubclassWindow();
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
	//}}AFX_VIRTUAL
protected:
	//{{AFX_MSG(COwnerDrawBtn)
	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()
};

#endif 
OwnerDrawBtn.cpp
#include "stdafx.h"
#include "OwnerDrawBtn.h"
#pragma comment(lib,"msimg32.lib")

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

COwnerDrawBtn::COwnerDrawBtn() 
{ 
    m_nStatus = BS_NORMAL;         
    m_bInRect = FALSE; 
    m_strText = _T("");   
    m_TextColor = RGB(0,0,0);      
    m_BackColor = RGB(243,243,243); 
    m_hBkBmp = NULL;
}

COwnerDrawBtn::~COwnerDrawBtn() 
{ 
}

BEGIN_MESSAGE_MAP(COwnerDrawBtn, CButton)
	//{{AFX_MSG_MAP(COwnerDrawBtn)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// PreSubclassWindow()在按鈕建立前自動執行,所以我們可以在其中做一些初始工作,此處為按鈕設定屬性“自繪”
void COwnerDrawBtn::PreSubclassWindow()  
{ 
    ModifyStyle( 0, BS_OWNERDRAW );        //設定按鈕屬性為自繪
    CButton::PreSubclassWindow(); 
}

// DrawItem()函式是一個關鍵函式,按鈕的繪製工作就在這裡進行,它的作用相當於對話方塊中的OnPaint()函式和檢視中的OnDraw()函式
// 這裡做了三項工作:獲取按鈕尺寸、獲取按鈕文字、繪製按鈕。其中繪製工作在自定義函式DrawButton()中完成
void COwnerDrawBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)  
{ 
    m_BtnRect = lpDrawItemStruct->rcItem;    //獲取按鈕尺寸

    if( m_strText.IsEmpty() )
        GetWindowText( m_strText );          //獲取按鈕文字

    CDC *pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
	int nSaveDC = pDC->SaveDC();
	if (pDC)
	{
		DrawButton( pDC );                //繪製按鈕
		pDC->RestoreDC( nSaveDC );
	}
}

void COwnerDrawBtn::DrawButton(CDC *pDC) 
{ 	
    if(BS_DISABLE == m_nStatus) m_nStatus = BS_NORMAL;  //狀態  
    if( GetStyle() & WS_DISABLED ) m_nStatus = BS_DISABLE;
    
	DrawBkBmp(pDC);    //繪製按鈕背景
    
	DrawTxt(pDC); 	//繪製按鈕文字
}

void COwnerDrawBtn::DrawBkBmp(CDC *pDC) 
{
	if (m_hBkBmp)
	{
		int nWidth=m_BtnRect.Width();
		int nHeight=m_BtnRect.Height();
		HDC hBkDC = CreateCompatibleDC(pDC->m_hDC);
		HBITMAP hOld = (HBITMAP)::SelectObject(hBkDC, m_hBkBmp);
		
		int bmpLeft = 0;
		if (BS_HOVER == m_nStatus)
			bmpLeft = nWidth*3;
		else if (BS_PUSHDOWN == m_nStatus)
			bmpLeft = nWidth;
		else if (BS_DISABLE == m_nStatus)
			bmpLeft = nWidth*2;
		TransparentBlt(pDC->m_hDC,0,0,nWidth,nHeight, hBkDC, bmpLeft,0,nWidth,nHeight, RGB(255,0,255));
		::SelectObject(hBkDC,hOld);
		::DeleteDC(hBkDC);
	}
	else
	{
		COLORREF  clrBorder;
		switch( m_nStatus ) 
		{ 
		case BS_NORMAL: 
			clrBorder = RGB(192,192,192);
			break;  
		case BS_HOVER: 
			clrBorder = RGB(255,255,255);
			break;  
		case BS_PUSHDOWN: 
			clrBorder = RGB(192,192,192);
			break;
		case BS_DISABLE: 
			clrBorder = RGB(243,243,243);
			break; 
		}

		CBrush Brush; 
		Brush.CreateSolidBrush( m_BackColor );    //背景刷
		pDC->SelectObject( &Brush ); 
		CPen Pen; 
		Pen.CreatePen(PS_SOLID, 1, clrBorder ); 
		pDC->SelectObject( &Pen ); 
		pDC->RoundRect(&m_BtnRect,CPoint(5,5));   //畫圓角矩形

		if( m_nStatus!=BS_PUSHDOWN)//繪製按鈕按下時的邊框
		{ 
			CRect Rect; 
			Rect.SetRect( m_BtnRect.left+2, m_BtnRect.top+1, m_BtnRect.right, m_BtnRect.bottom ); 
			pDC->DrawEdge( &Rect, BDR_RAISEDINNER, BF_RECT );    //畫邊框
		} 

		if( GetFocus()==this )//繪製擁有焦點按鈕的虛線框 
		{ 
			CRect Rect; 
			Rect.SetRect( m_BtnRect.left+3, m_BtnRect.top+2, m_BtnRect.right-3, m_BtnRect.bottom-2 ); 
			pDC->DrawFocusRect( &Rect ); 
		} 
	}
}

void COwnerDrawBtn::DrawTxt(CDC *pDC)
{
    COLORREF txtColor;
	switch( m_nStatus ) 
    { 
    case BS_NORMAL: 
		txtColor = m_TextColor; 
		break;  
    case BS_HOVER: 
		txtColor = m_TextColor; 
		break;  
    case BS_PUSHDOWN: 
		txtColor = m_TextColor; 
		break;
    case BS_DISABLE: 
		txtColor = GetSysColor(COLOR_GRAYTEXT); 
		break; 
    } 
	
    pDC->SetTextColor( txtColor ); 
    pDC->SetBkMode( TRANSPARENT ); 
    pDC->DrawText( m_strText, &m_BtnRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS); 
}

void COwnerDrawBtn::OnMouseMove(UINT nFlags, CPoint point)  
{ 
    if( !m_bInRect || GetCapture()!=this )    //滑鼠進入按鈕
    { 
		m_bInRect = TRUE;		//設定進入標誌
        SetCapture();			//捕獲滑鼠
        m_nStatus = BS_HOVER;   //設定按鈕狀態
        Invalidate();			//重繪按鈕
    } 
    else 
    { 
        if (m_bInRect && !m_BtnRect.PtInRect(point))    //滑鼠離開按鈕
        { 
		    m_bInRect = FALSE;		//清除進入標誌
            ReleaseCapture();		//釋放滑鼠
            m_nStatus = BS_NORMAL;  //設定按鈕狀態
            Invalidate();			//重繪按鈕
        } 
    } 
     
    CButton::OnMouseMove(nFlags, point); 
}

void COwnerDrawBtn::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_nStatus = BS_PUSHDOWN; 
    Invalidate();        //重繪按鈕
    
	CButton::OnLButtonDown(nFlags, point); 
}

void COwnerDrawBtn::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_nStatus = BS_HOVER; 
    Invalidate();        //重繪按鈕
     
    CButton::OnLButtonUp(nFlags, point);
}

void COwnerDrawBtn::SetText(CString str) 
{ 
    m_strText = _T(""); 
    SetWindowText(str); 
}

void COwnerDrawBtn::SetTextColor(COLORREF color) 
{
    m_TextColor = color; 
    Invalidate(); 
}

void COwnerDrawBtn::SetBkColor(COLORREF color) 
{ 
    m_BackColor = color; 
    Invalidate(); 
}

void COwnerDrawBtn::SetTextFont(int FontHight,LPCTSTR FontName) 
{ 
	m_font.DeleteObject();
	m_font.CreatePointFont(FontHight, FontName);
	SetFont(&m_font);
}

void COwnerDrawBtn::SetTextFont(CFont* pFont)
{
	SetFont(pFont);
}

void COwnerDrawBtn::SetBkSkin(HBITMAP hBkBmp)
{
	if (!m_hBkBmp)
	{
		m_hBkBmp = hBkBmp;
	}
}

void COwnerDrawBtn::SetBkSkin(LPCTSTR pBmpFile)
{
	if (!m_hBkBmp)
	{
		m_hBkBmp = (HBITMAP)LoadImage(AfxGetInstanceHandle(), pBmpFile, 
					IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
	}
}