MFC 下自绘按钮

之前我有写过两篇MFC 下按钮的重绘,今天我给大家提供一种自绘方法

#pragma once
#include <string>

// ClrButton
#define  WM_LRBTNCLICK (WM_USER + 532)

class ClrButton : public CWnd
{
    DECLARE_DYNAMIC(ClrButton)

public:
    ClrButton();
    virtual ~ClrButton();
public:
    enum
    {
        State_Normal,
        State_Focus,
        State_Press,
        State_Disable
    };
    Image* GetPngStream(UINT uiID);
    BOOL SetImage(UINT uiImg);
    BOOL SetFourImage(UINT uiNormalImg, UINT uiFocusImg, UINT uiPressImg, UINT uiDisableImg);
    BOOL SetCaption( const wchar_t *szText);
    void SetCheck( BOOL bCheck);
    void SetFourPicMode(){m_bFourPicMode = TRUE;}
    BOOL GetCheck();
protected:
    BOOL DrawItem( CDC *pDC);
private:
    BOOL m_bFourPicMode;
    BOOL m_bCheck;
    DWORD m_dwState;
    BOOL m_bMouseLeave;
    BOOL m_bDowned;
    BOOL m_bFocus;
    UINT m_uiImg;
    UINT m_uiNormalImg;
    UINT m_uiFocusImg;
    UINT m_uiPressImg;
    UINT m_uiDisableImg;
    std::wstring m_strText;
protected:
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
    afx_msg void OnPaint();
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
    afx_msg void OnSetFocus(CWnd* pOldWnd);
    afx_msg void OnKillFocus(CWnd* pNewWnd);
};

实现

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

#include "stdafx.h"
#include "lrButton.h"
#pragma comment( lib, "UxTheme.lib")

// ClrButton

IMPLEMENT_DYNAMIC(ClrButton, CWnd)

ClrButton::ClrButton()
{
    m_dwState = State_Normal;
    m_bCheck = FALSE;
    m_bMouseLeave = TRUE;
    m_bDowned = FALSE;
    m_bFocus = FALSE;
    m_bFourPicMode = FALSE;
    m_uiImg = 0;
    m_uiNormalImg = 0;
    m_uiFocusImg = 0;
    m_uiPressImg = 0;
    m_uiDisableImg = 0;
}

ClrButton::~ClrButton()
{
}


BEGIN_MESSAGE_MAP(ClrButton, CWnd)
    ON_WM_PAINT()
    ON_WM_MOUSEMOVE()
    ON_MESSAGE( WM_MOUSELEAVE, OnMouseLeave)
    ON_WM_LBUTTONUP()
    ON_WM_LBUTTONDOWN()
    ON_WM_SETFOCUS()
    ON_WM_KILLFOCUS()
END_MESSAGE_MAP()



// ClrButton 消息处理程序

BOOL ClrButton::Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
    return CreateEx( 
        0, 
        AfxRegisterWndClass(0), 
        0, 
        dwStyle, 
        rect, 
        pParentWnd, 
        nID);
}

Image* ClrButton::GetPngStream(UINT uiID)
{
    HINSTANCE hInst = AfxGetResourceHandle();
    HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(uiID),_T("PNG")); // type
    if (!hRsrc)
        return NULL;

    // load resource into memory
    DWORD len = SizeofResource(hInst, hRsrc);
    BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
    if (!lpRsrc)
        return NULL;

    // Allocate global memory on which to create stream
    HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
    BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
    memcpy(pmem,lpRsrc,len);
    IStream* pstm;
    CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);

    // load from stream这是关键一句,通过FromStream返回以各Image*,然后在Graphic的DrawImage地方调用就行了!
    Image* pImg = Gdiplus::Image::FromStream(pstm);

    // free/release stuff
    GlobalUnlock(m_hMem);
    pstm->Release();
    FreeResource(lpRsrc);

    return pImg;
}

BOOL ClrButton::DrawItem( CDC *pDC )
{
    if((m_uiImg == 0) && (m_uiNormalImg == 0) && (m_uiFocusImg == 0) && (m_uiPressImg == 0) && (m_uiDisableImg == 0))
        return TRUE;

    HDC hdc = pDC->GetSafeHdc();
    HDC hMemdc = CreateCompatibleDC( hdc);

    CRect rt;
    GetClientRect( &rt);

    BYTE* pBits = NULL; 
    BITMAPINFOHEADER bmih = {  sizeof (BITMAPINFOHEADER) };
    bmih.biWidth            = rt.Width(); 
    bmih.biHeight           = rt.Height(); 
    bmih.biPlanes           = 1; 
    bmih.biBitCount         = 32; 
    bmih.biCompression      = BI_RGB; 
    bmih.biSizeImage        = 0; 
    bmih.biXPelsPerMeter    = 0; 
    bmih.biYPelsPerMeter    = 0; 
    bmih.biClrUsed          = 0; 
    bmih.biClrImportant     = 0; 
    HBITMAP hMembmp = CreateDIBSection(NULL, (BITMAPINFO *)&bmih, DIB_RGB_COLORS, (VOID**)&pBits, NULL, 0); 
    HBITMAP hOldbmp = (HBITMAP)SelectObject( hMemdc, hMembmp);

    DrawThemeParentBackground( m_hWnd,hMemdc, &rt);

    Graphics graphics( hMemdc);

    Image* img = NULL;
    if(m_bFourPicMode)
    {
        if(m_dwState == State_Normal)
            img = GetPngStream(m_uiNormalImg);
        else if(m_dwState == State_Focus)
            img = GetPngStream(m_uiFocusImg);
        else if(m_dwState == State_Press)
            img = GetPngStream(m_uiPressImg);
        else if(m_dwState == State_Disable)
            img = GetPngStream(m_uiDisableImg);

        graphics.DrawImage(img,RectF( 0, 0, rt.Width(), rt.Height()), 0, 0, img->GetWidth(), img->GetHeight(), UnitPixel);
    }
    else
    {
        img = GetPngStream(m_uiImg);
        graphics.DrawImage(img,RectF( 0, 0, rt.Width(), rt.Height()), m_dwState * img->GetWidth()/4, 0, img->GetWidth()/4, img->GetHeight(), UnitPixel);
    }

    //draw text
    FontFamily fontfamily(L"宋体");
    Gdiplus::Font font( &fontfamily, 9, FontStyleRegular, UnitPoint);
    StringFormat stringformat;
    stringformat.SetAlignment( StringAlignmentCenter);
    stringformat.SetLineAlignment(StringAlignmentCenter);
    SolidBrush brush(Color(254,159,239,255));
    RectF reF(0, 0, rt.Width(), rt.Height());
    if ( !m_strText.empty() )
        graphics.DrawString( m_strText.c_str(), -1, &font, reF, &stringformat,&brush);

    BitBlt( hdc,0,0,rt.Width(), rt.Height(), hMemdc, 0,0,SRCCOPY);

    graphics.ReleaseHDC( hMemdc);
    SelectObject( hMemdc, hOldbmp);
    DeleteDC( hMemdc);
    DeleteObject( hMembmp);

    if ( GetFocus() == (CWnd *)this 
        && (GetWindowLong( m_hWnd, GWL_STYLE) &WS_TABSTOP ) )
    {
        CRect rtFocus;
        GetClientRect( &rtFocus);
        rtFocus.DeflateRect( 3,3,3,3);
        DrawFocusRect( pDC->GetSafeHdc(), &rtFocus );
    }

    return TRUE;
}

BOOL ClrButton::SetImage(UINT uiImg)
{
    m_uiImg = uiImg;
    Invalidate( FALSE);
    return TRUE;
}

BOOL ClrButton::SetFourImage(UINT uiNormalImg, UINT uiFocusImg, UINT uiPressImg, UINT uiDisableImg)
{
    m_uiNormalImg = uiNormalImg;
    m_uiFocusImg = uiFocusImg;
    m_uiPressImg = uiPressImg;
    m_uiDisableImg = uiDisableImg;
    Invalidate(FALSE);
    return TRUE;
}

void ClrButton::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    DrawItem( &dc);
}

void ClrButton::OnMouseMove(UINT nFlags, CPoint point)
{
    if ( m_bMouseLeave )
    {
        TRACKMOUSEEVENT evt = { 0 };
        evt.cbSize = sizeof(evt);
        evt.dwFlags = TME_LEAVE;
        evt.hwndTrack = m_hWnd;
        TrackMouseEvent( &evt);
        m_bMouseLeave = FALSE;
        m_dwState = State_Focus;
        Invalidate(FALSE);
    }

    CWnd::OnMouseMove(nFlags, point);
}

void ClrButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    if ( m_bDowned )
    {
        m_dwState = State_Focus;
        Invalidate(FALSE );
        GetParent()->PostMessage( WM_LRBTNCLICK, GetDlgCtrlID(), 0);
        m_bDowned = FALSE;
    }

    CWnd::OnLButtonUp(nFlags, point);
}

void ClrButton::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_bDowned = TRUE;
    m_dwState = State_Press;
    if ( (GetWindowLong( m_hWnd, GWL_STYLE) &WS_TABSTOP ) )
        SetFocus();
    Invalidate(FALSE);
    CWnd::OnLButtonDown(nFlags, point);
}

BOOL ClrButton::SetCaption( const wchar_t *szText )
{
    m_strText = szText;
    Invalidate(FALSE);
    return TRUE;
}

void ClrButton::SetCheck( BOOL bCheck )
{
    m_bCheck = bCheck;
    Invalidate(FALSE);
}

BOOL ClrButton::GetCheck()
{
    return m_bCheck;
}


LRESULT ClrButton::OnMouseLeave( WPARAM wParam, LPARAM lParam )
{
    m_bMouseLeave = TRUE;
    m_dwState = State_Normal;
    Invalidate(FALSE);

    return 0;
}

void ClrButton::OnSetFocus(CWnd* pOldWnd)
{
    CWnd::OnSetFocus(pOldWnd);

    m_bFocus = TRUE;
    Invalidate(FALSE);
}

void ClrButton::OnKillFocus(CWnd* pNewWnd)
{
    CWnd::OnKillFocus(pNewWnd);

    m_bFocus = FALSE;
    Invalidate(FALSE);
}

使用示例,最小化和关闭按钮

///定义
ClrButton* m_plrBtn;
///声明
if(m_plrBtn == NULL)
    m_plrBtn = new ClrButton[2];
CRect rtClose(m_rcClient.right - 45, 0,m_rcClient.right, 26);
m_plrBtn[0].Create( WS_CHILD|WS_VISIBLE, rtClose, this, IDC_BTNCLOSE);
m_plrBtn[0].ShowWindow(SW_SHOW);
m_plrBtn[0].UpdateWindow();
m_plrBtn[0].SetImage(IDD_PNG_CLOSE);

CRect rtMin( rtClose.left-31, 0, rtClose.left, 26);
m_plrBtn[1].Create( WS_CHILD|WS_VISIBLE, rtMin, this, IDC_BTNMIN);
m_plrBtn[1].ShowWindow(SW_SHOW);
m_plrBtn[1].UpdateWindow();
m_plrBtn[1].SetImage(IDD_PNG_MIN);

有空我会把添加一些注释,方便大家阅读。欢迎评论、指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值