赞助

MFC 重绘CButton 支持透明背景的png

转载:https://blog.csdn.net/songyimin1208/article/details/54408296

1.InitInstance初始化GDI

#include <gdiplus.h>
#pragma comment(lib,"gdiplus.lib")
class CtestMFCButtonApp : public CWinApp
{
public:
    CtestMFCButtonApp();

// 重写
public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
// 实现

    DECLARE_MESSAGE_MAP()

private:
    Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
    ULONG_PTR m_pGdiToken;
};
BOOL CtestMFCButtonApp::InitInstance()
{
    .......................

    CWinApp::InitInstance();

    GdiplusStartup(&m_pGdiToken, &m_gdiplusStartupInput, NULL);
    .......................
}

int CtestMFCButtonApp::ExitInstance()
{
Gdiplus::GdiplusShutdown(m_pGdiToken);

return 0;
}

2.自定义Button类

PicButton.h

#pragma once
#include "afxwin.h"
#include <gdiplus.h>
#pragma comment(lib,"gdiplus.lib")


class CPicButton :public CButton
{
    DECLARE_DYNAMIC(CPicButton)
public:
    CPicButton();
    ~CPicButton();

    enum BUTTON_STATE
    {
        BUTTON_ENABLE = 0,
        BUTTON_HOVER = 1,
        BUTTON_CLICK = 2,
        BUTTON_DISABLE = 3
    };

protected:
    afx_msg LRESULT OnMouseLeave(WPARAM wparam, LPARAM lparam);
    afx_msg LRESULT OnMouseHover(WPARAM wparam, LPARAM lparam);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
protected:
    virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
    void CPicButton::PreSubclassWindow();
    DECLARE_MESSAGE_MAP()
public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    void SetButtonImage(Gdiplus::Image* img);

private:
    BOOL m_bDisable; // 按钮是否禁用 
    BOOL m_bCursorOnButton; // 鼠标是否在按钮上
    BOOL m_bPress; // 按钮是否被按下

    int m_nWidth;       //图片宽
    int m_nHeight;     //图片高
    int m_nSliceWidth;  //每一块图片的宽

    Gdiplus::Image* m_btnImage;//按钮图片
    CRect m_rectButton;//按钮区域
};

PicButton.cpp

#include "stdafx.h"
#include "PicButton.h"

IMPLEMENT_DYNAMIC(CPicButton, CButton)
CPicButton::CPicButton()
{
    m_bDisable = FALSE;
    m_bCursorOnButton = FALSE;
    m_bPress = FALSE;
}


CPicButton::~CPicButton()
{
    if (m_btnImage)
    {
        delete m_btnImage;
        m_btnImage = NULL;
    }

}

}

BEGIN_MESSAGE_MAP(CPicButton, CButton)
    ON_WM_MOUSEMOVE()
    ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_ERASEBKGND()
END_MESSAGE_MAP()




void CPicButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    Gdiplus::Graphics graphics(pDC->m_hDC);

    if (m_bDisable == TRUE)
    {
        graphics.DrawImage(m_btnImage, Gdiplus::Rect(0, 0, m_nSliceWidth, m_nHeight),
            BUTTON_DISABLE * m_nSliceWidth, 0, m_nSliceWidth, m_nHeight, Gdiplus::UnitPixel, NULL, NULL, NULL);
    }
    else
    {
        // click state
        if (lpDrawItemStruct->itemState & ODS_SELECTED)
        {
            graphics.DrawImage(m_btnImage, Gdiplus::Rect(0, 0, m_nSliceWidth, m_nHeight),
                BUTTON_CLICK * m_nSliceWidth, 0, m_nSliceWidth, m_nHeight, Gdiplus::UnitPixel, NULL, NULL, NULL);
        }
        // hover state
        else if (m_bPress)
        {
            graphics.DrawImage(m_btnImage, Gdiplus::Rect(0, 0, m_nSliceWidth, m_nHeight),
                BUTTON_HOVER * m_nSliceWidth, 0, m_nSliceWidth, m_nHeight, Gdiplus::UnitPixel, NULL, NULL, NULL);
        }
        // enable state
        else
        {
            graphics.DrawImage(m_btnImage, Gdiplus::Rect(0, 0, m_nSliceWidth, m_nHeight),
                BUTTON_ENABLE*m_nSliceWidth, 0, m_nSliceWidth, m_nHeight, Gdiplus::UnitPixel, NULL, NULL, NULL);
        }
    }
}

void CPicButton::SetButtonImage(Gdiplus::Image* img)
{
    if (m_btnImage != NULL)
    {
        delete m_btnImage;
        m_btnImage = img;
    }
    else
    {
        m_btnImage = img;
    }

    if (m_btnImage)
    {
        m_nWidth = m_btnImage->GetWidth();
        m_nHeight = m_btnImage->GetHeight();
        m_nSliceWidth = m_nWidth;   //图片切成四分

        CWnd *pWnd = this->GetParent();
        GetWindowRect(&m_rectButton);
        pWnd->ScreenToClient(m_rectButton);
        m_rectButton.right = m_rectButton.left + m_nSliceWidth;
        m_rectButton.bottom = m_rectButton.top + m_nHeight;
        MoveWindow(m_rectButton);      //调整按钮大小以适应图片
    }
    Invalidate();
}

void CPicButton::PreSubclassWindow()
{
    ModifyStyle(0, BS_OWNERDRAW);
    CButton::PreSubclassWindow();
}


LRESULT CPicButton::OnMouseLeave(WPARAM wparam, LPARAM lparam)
{
    m_bCursorOnButton = FALSE;
    m_bPress = FALSE;
    Invalidate();
    return 0L;
}

LRESULT CPicButton::OnMouseHover(WPARAM wparam, LPARAM lparam)
{
    m_bPress = TRUE;
    Invalidate();
    return 0L;
}

BOOL CPicButton::OnEraseBkgnd(CDC* pDC)
{
    return TRUE;
}

void CPicButton::OnMouseMove(UINT nFlags, CPoint point)
{
    if (m_bCursorOnButton == FALSE)
    {
        TRACKMOUSEEVENT tme;
        ZeroMemory(&tme, sizeof(TRACKMOUSEEVENT));
        tme.cbSize = sizeof(tme);
        tme.hwndTrack = m_hWnd;
        tme.dwFlags = TME_LEAVE | TME_HOVER;
        tme.dwHoverTime = 1;
        m_bCursorOnButton = _TrackMouseEvent(&tme);
    }
}

void CPicButton::OnLButtonDown(UINT nFlags, CPoint point)
{
    Invalidate();
    CButton::OnLButtonDown(nFlags, point);
}

void CPicButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    Invalidate();
    CButton::OnLButtonUp(nFlags, point);
}

LRESULT CPicButton::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message == WM_LBUTTONDBLCLK)
    {
        message = WM_LBUTTONDOWN;
    }
    return CButton::DefWindowProc(message, wParam, lParam);//很重要,消除双击没反应
}

3.修改资源文件中button的属性

 

 4.给控件添加变量,把CButton  改成自定义的CPicButton

 

 5.在OnInitDialog函数中给button设置png

BOOL CtestMFCButtonDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

   '''''''''''''''''''''''''''''''''''''''''''''''''
    Gdiplus::Image* pImg = Gdiplus::Image::FromFile(_T("C:\\Users\\Administrator\\Desktop\\touming.png"));

    m_btn.SetButtonImage(pImg);
  return TRUE;
}

 

二、给对话框指定区域设置背景色

在WM_ERASEBKGND消息函数里处理

BOOL CtestMFCButtonDlg::OnEraseBkgnd(CDC* pDC)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    CBrush brush(RGB(196,196,198));

    CBrush* pOldBrush = pDC->SelectObject(&brush);
    CRect rc;
    GetClientRect(&rc);
    pDC->PatBlt(0, 0, rc.Width() - 200, rc.Height(), PATCOPY);

    pDC->SelectObject(pOldBrush);

    return TRUE;
}

三、对话框背景色不是纯白色的时候,设置对话框上控件背景色透明

在WM_CTLCOLOR消息函数里处理中

HBRUSH CtestMFCButtonDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);

    // TODO:  在此更改 DC 的任何特性

    // TODO:  如果默认的不是所需画笔,则返回另一个画笔

    //静态文本
    if (pWnd->GetDlgCtrlID() == IDC_STATIC)
    {
        pDC->SetBkMode(TRANSPARENT);

        return (HBRUSH)::GetStockObject(NULL_BRUSH);
    }
    //Radio按钮背景 
    TCHAR szClassName[MAX_PATH] = { 0 };
    ::GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName) / sizeof(TCHAR) - 2);
    if (lstrcmpi(szClassName, _T("Button")) == 0)
    {
        UINT uStyle = ((CButton*)pWnd)->GetButtonStyle();
        switch (uStyle)
        {
        case BS_AUTORADIOBUTTON:
        {
            static HBRUSH hbrSatic = ::CreateSolidBrush(RGB(196, 196, 198));
            pDC->SetBkMode(TRANSPARENT);
            pDC->SetTextColor(RGB(0, 0, 0)); //字体颜色 
            return hbrSatic;
        }
        break;
        default:
            break;
        }
    }

    return hbr;
}

 

posted @ 2021-06-10 21:38  车臣  阅读(1413)  评论(0编辑  收藏  举报