您的位置:首页 > 其它

自绘实现半透明水晶按钮 .

2013-04-03 11:02 459 查看

运行效果



实现方法

1.给按钮加上BS_OWNERDRAW样式

2.重载DrawItem函数,在这里绘制按钮

3.关键之处就是把父窗口的背景复制到按钮上,实现视觉上的透明

4.最后通过AlphaBlend实现半透明.

实现源码

[cpp]
view plaincopyprint?

// MyButton.h   
#pragma once   
  
  
// CMyButton   
  
class CMyButton : public CButton  
{  
    DECLARE_DYNAMIC(CMyButton)  
  
public:  
    CMyButton();  
    virtual ~CMyButton();  
public:  
    void SetBkColor(COLORREF color);  
    void SetTextColor(COLORREF color);  
private:  
    bool m_bOver;  
    bool m_bDown;  
    bool m_bDisable;  
    bool m_bTracking;  
    COLORREF m_bkColor;  
    COLORREF m_textColor;  
protected:  
    DECLARE_MESSAGE_MAP()  
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);  
    virtual void PreSubclassWindow();  
public:  
    virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);  
    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 LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);  
    afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);  
    afx_msg void OnEnable(BOOL bEnable);  
private:  
    void ButtonInit();  
    void DrawButton();  
    void DrawButton(HDC hDestDC);  
};  

// MyButton.h
#pragma once

// CMyButton

class CMyButton : public CButton
{
DECLARE_DYNAMIC(CMyButton)

public:
CMyButton();
virtual ~CMyButton();
public:
void SetBkColor(COLORREF color);
void SetTextColor(COLORREF color);
private:
bool m_bOver;
bool m_bDown;
bool m_bDisable;
bool m_bTracking;
COLORREF m_bkColor;
COLORREF m_textColor;
protected:
DECLARE_MESSAGE_MAP()
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual void PreSubclassWindow();
public:
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
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 LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);
afx_msg void OnEnable(BOOL bEnable);
private:
void ButtonInit();
void DrawButton();
void DrawButton(HDC hDestDC);
};


[cpp]
view plaincopyprint?

// MyButton.cpp : 实现文件   
//   
  
#include "stdafx.h"   
#include "AlphaButton.h"
  
#include "MyButton.h"   
#include "MainDlg.h"
  
  
// CMyButton   
  
IMPLEMENT_DYNAMIC(CMyButton, CButton)  
  
CMyButton::CMyButton()  
{  
    m_bkColor=0xFFFFFF;  
    m_textColor=0x000000;  
}  
  
CMyButton::~CMyButton()  
{  
}  
  
  
BEGIN_MESSAGE_MAP(CMyButton, CButton)  
    ON_WM_MOUSEMOVE()  
    ON_WM_LBUTTONDOWN()  
    ON_WM_LBUTTONUP()  
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)  
    ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)  
    ON_WM_ENABLE()  
END_MESSAGE_MAP()  
  
  
  
// CMyButton 消息处理程序   
  
void CMyButton::SetBkColor(COLORREF color)  
{  
    m_bkColor=color;  
}  
void CMyButton::SetTextColor(COLORREF color)  
{  
    m_textColor=color;  
}  
  
BOOL CMyButton::PreCreateWindow(CREATESTRUCT& cs)  
{  
    BOOL bRet=CButton::PreCreateWindow(cs);  
    ButtonInit();  
    return bRet;  
}  
  
void CMyButton::PreSubclassWindow()  
{  
    CButton::PreSubclassWindow();  
    ButtonInit();  
}  
void CMyButton::ButtonInit()  
{  
    m_bTracking=false;  
    m_bOver=m_bDown=m_bDisable=false;  
    m_bDisable=IsWindowEnabled()?FALSE:TRUE;  
    ModifyStyle(NULL,BS_OWNERDRAW);  
}  
  
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)  
{  
  
    DrawButton(lpDrawItemStruct->hDC);  
}  
  
void CMyButton::OnMouseMove(UINT nFlags, CPoint point)  
{  
    if (!m_bTracking)  
    {  
        m_bOver = TRUE;  
        TRACKMOUSEEVENT tme;  
        tme.cbSize = sizeof(tme);  
        tme.hwndTrack = m_hWnd;  
        tme.dwFlags = TME_LEAVE | TME_HOVER;  
        tme.dwHoverTime = 50;  
        m_bTracking = (bool)_TrackMouseEvent(&tme);  
    }  
  
    CButton::OnMouseMove(nFlags, point);  
}  
  
void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)  
{  
    m_bDown=TRUE;  
  
    CButton::OnLButtonDown(nFlags, point);  
}  
  
void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)  
{  
    m_bDown=FALSE;  
    CButton::OnLButtonUp(nFlags, point);  
}  
LRESULT CMyButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)  
{  
    m_bOver = FALSE;  
    m_bTracking = FALSE;  
    m_bDown=FALSE;  
    InvalidateRect(NULL, FALSE);  
    return 0;  
}  
  
LRESULT CMyButton::OnMouseHover(WPARAM wParam, LPARAM lParam)  
{  
    m_bOver = TRUE;  
    InvalidateRect(NULL);  
    return 0;  
}  
void CMyButton::DrawButton()  
{  
    HDC hDC=::GetDC(m_hWnd);  
    DrawButton(hDC);  
    ::ReleaseDC(m_hWnd,hDC);  
}  
void CMyButton::DrawButton(HDC hDestDC)  
{  
    CRect rc;  
    GetClientRect(rc);  
    int nWindth=rc.Width();  
    int nHeight=rc.Height();  
    HDC hDC=CreateCompatibleDC(hDestDC);//创建兼容DC,采用双缓冲画出
  
    HDC hMaskDC=CreateCompatibleDC(hDestDC);  
    HBITMAP hBitmap=CreateCompatibleBitmap(hDestDC,nWindth,nHeight);  
    HBITMAP hMaskBitmap=CreateCompatibleBitmap(hDestDC,nWindth,nHeight);  
    HBITMAP hOldBitmap=(HBITMAP)SelectObject(hDC,hBitmap);  
    HBITMAP hOldMaskBitmap=(HBITMAP)SelectObject(hMaskDC,hMaskBitmap);  
    SetBkMode(hDC,TRANSPARENT);  
  
    //把父窗口的背景图复制到按钮的DC上,实现视觉透明----------------
  
    CMainDlg* pParent=(CMainDlg*)GetParent();  
    CPoint pt(0,0);  
    MapWindowPoints(pParent,&pt,1);  
    pParent->m_bkImage.BitBlt(hDC,rc,pt,SRCCOPY);  
  
  
    //-------------------------------------------------------------
  
    int nAlpha=100;//0--255
  
    int nOffset=0;  
  
    HBRUSH hbr=CreateSolidBrush(m_bkColor);  
    FillRect(hMaskDC,&rc,hbr);  
    DeleteObject(hbr);  
  
    if(m_bDisable){  
        nAlpha=100;  
    }else if(m_bDown){  
        nAlpha=180;  
        nOffset=1;  
    }else if(m_bOver){  
        nAlpha=150;  
    }else{  
        nAlpha=100;  
    }  
    BLENDFUNCTION blend;  
    memset( &blend, 0, sizeof( blend) );  
    blend.BlendOp= AC_SRC_OVER;  
    blend.SourceConstantAlpha= nAlpha; // 透明度 最大255
  
  
    HRGN hRgn=CreateRoundRectRgn(0,0,nWindth,nHeight,3,3);  
    SelectClipRgn (hDC,hRgn);  
    AlphaBlend (hDC,0,0,nWindth,nHeight,hMaskDC, 0,0,nWindth,nHeight,blend);  
  
    CString strText;  
    GetWindowText(strText);  
    if(strText!=_T("")){  
        rc.InflateRect(-2,-2);  
        rc.OffsetRect(nOffset,nOffset);  
        HFONT hFont=(HFONT)SendMessage(WM_GETFONT);  
        if(!hFont)hFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT);  
        HFONT hOldFont=(HFONT)SelectObject(hDC,hFont);  
        ::SetTextColor(hDC,m_textColor);  
        ::DrawText(hDC,strText,-1,&rc,DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_WORD_ELLIPSIS);  
        ::SelectObject(hDC,hOldFont);  
    }  
    SelectClipRgn (hDC,NULL);  
    DeleteObject(hRgn);  
    //复制到控件的DC上------------------------
  
    BitBlt(hDestDC,0,0,nWindth,nHeight,hDC,0,0,SRCCOPY);  
    //删除资源,释放内存-----------------------
  
    SelectObject(hDC,hOldBitmap);  
    DeleteObject(hBitmap);  
    DeleteDC(hDC);  
    SelectObject(hMaskDC,hOldMaskBitmap);  
    DeleteObject(hMaskBitmap);  
    DeleteDC(hMaskDC);  
  
}  
void CMyButton::OnEnable(BOOL bEnable)  
{  
    CButton::OnEnable(bEnable);  
    m_bDisable=IsWindowEnabled()?FALSE:TRUE;  
    DrawButton();  
}  

// MyButton.cpp : 实现文件
//

#include "stdafx.h"
#include "AlphaButton.h"
#include "MyButton.h"
#include "MainDlg.h"

// CMyButton

IMPLEMENT_DYNAMIC(CMyButton, CButton)

CMyButton::CMyButton()
{
m_bkColor=0xFFFFFF;
m_textColor=0x000000;
}

CMyButton::~CMyButton()
{
}

BEGIN_MESSAGE_MAP(CMyButton, CButton)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
ON_WM_ENABLE()
END_MESSAGE_MAP()

// CMyButton 消息处理程序

void CMyButton::SetBkColor(COLORREF color)
{
m_bkColor=color;
}
void CMyButton::SetTextColor(COLORREF color)
{
m_textColor=color;
}

BOOL CMyButton::PreCreateWindow(CREATESTRUCT& cs)
{
BOOL bRet=CButton::PreCreateWindow(cs);
ButtonInit();
return bRet;
}

void CMyButton::PreSubclassWindow()
{
CButton::PreSubclassWindow();
ButtonInit();
}
void CMyButton::ButtonInit()
{
m_bTracking=false;
m_bOver=m_bDown=m_bDisable=false;
m_bDisable=IsWindowEnabled()?FALSE:TRUE;
ModifyStyle(NULL,BS_OWNERDRAW);
}

void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{

DrawButton(lpDrawItemStruct->hDC);
}

void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bTracking)
{
m_bOver = TRUE;
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 50;
m_bTracking = (bool)_TrackMouseEvent(&tme);
}

CButton::OnMouseMove(nFlags, point);
}

void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bDown=TRUE;

CButton::OnLButtonDown(nFlags, point);
}

void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bDown=FALSE;
CButton::OnLButtonUp(nFlags, point);
}
LRESULT CMyButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
m_bOver = FALSE;
m_bTracking = FALSE;
m_bDown=FALSE;
InvalidateRect(NULL, FALSE);
return 0;
}

LRESULT CMyButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
m_bOver = TRUE;
InvalidateRect(NULL);
return 0;
}
void CMyButton::DrawButton()
{
HDC hDC=::GetDC(m_hWnd);
DrawButton(hDC);
::ReleaseDC(m_hWnd,hDC);
}
void CMyButton::DrawButton(HDC hDestDC)
{
CRect rc;
GetClientRect(rc);
int nWindth=rc.Width();
int nHeight=rc.Height();
HDC hDC=CreateCompatibleDC(hDestDC);//创建兼容DC,采用双缓冲画出
HDC hMaskDC=CreateCompatibleDC(hDestDC);
HBITMAP hBitmap=CreateCompatibleBitmap(hDestDC,nWindth,nHeight);
HBITMAP hMaskBitmap=CreateCompatibleBitmap(hDestDC,nWindth,nHeight);
HBITMAP hOldBitmap=(HBITMAP)SelectObject(hDC,hBitmap);
HBITMAP hOldMaskBitmap=(HBITMAP)SelectObject(hMaskDC,hMaskBitmap);
SetBkMode(hDC,TRANSPARENT);

//把父窗口的背景图复制到按钮的DC上,实现视觉透明----------------
CMainDlg* pParent=(CMainDlg*)GetParent();
CPoint pt(0,0);
MapWindowPoints(pParent,&pt,1);
pParent->m_bkImage.BitBlt(hDC,rc,pt,SRCCOPY);

//-------------------------------------------------------------
int nAlpha=100;//0--255
int nOffset=0;

HBRUSH hbr=CreateSolidBrush(m_bkColor);
FillRect(hMaskDC,&rc,hbr);
DeleteObject(hbr);

if(m_bDisable){
nAlpha=100;
}else if(m_bDown){
nAlpha=180;
nOffset=1;
}else if(m_bOver){
nAlpha=150;
}else{
nAlpha=100;
}
BLENDFUNCTION blend;
memset( &blend, 0, sizeof( blend) );
blend.BlendOp= AC_SRC_OVER;
blend.SourceConstantAlpha= nAlpha; // 透明度 最大255

HRGN hRgn=CreateRoundRectRgn(0,0,nWindth,nHeight,3,3);
SelectClipRgn (hDC,hRgn);
AlphaBlend (hDC,0,0,nWindth,nHeight,hMaskDC, 0,0,nWindth,nHeight,blend);

CString strText;
GetWindowText(strText);
if(strText!=_T("")){
rc.InflateRect(-2,-2);
rc.OffsetRect(nOffset,nOffset);
HFONT hFont=(HFONT)SendMessage(WM_GETFONT);
if(!hFont)hFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT);
HFONT hOldFont=(HFONT)SelectObject(hDC,hFont);
::SetTextColor(hDC,m_textColor);
::DrawText(hDC,strText,-1,&rc,DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_WORD_ELLIPSIS);
::SelectObject(hDC,hOldFont);
}
SelectClipRgn (hDC,NULL);
DeleteObject(hRgn);
//复制到控件的DC上------------------------
BitBlt(hDestDC,0,0,nWindth,nHeight,hDC,0,0,SRCCOPY);
//删除资源,释放内存-----------------------
SelectObject(hDC,hOldBitmap);
DeleteObject(hBitmap);
DeleteDC(hDC);
SelectObject(hMaskDC,hOldMaskBitmap);
DeleteObject(hMaskBitmap);
DeleteDC(hMaskDC);

}
void CMyButton::OnEnable(BOOL bEnable)
{
CButton::OnEnable(bEnable);
m_bDisable=IsWindowEnabled()?FALSE:TRUE;
DrawButton();
}

源码下载:http://download.csdn.net/detail/cometnet/4955726
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MFC VC