您的位置:首页 > 其它

自绘式按钮COwnerDrawBtn:可设置文本字体、文本颜色、按钮背景图片

2014-07-18 16:54 603 查看
使用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);
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐