继承CWnd自绘按钮

头文件:

//头文件

#pragma once

// CLhsButton

#define MYWM_BTN_CLICK WM_USER+3001        //关闭按钮单击响应

//tab按钮的状态
enum ButtonState
{
    BTN_STATE_NOR            = 0,
    BTN_STATE_DOWN            = 1,
};

class CLhsButton : public CWnd
{
    DECLARE_DYNAMIC(CLhsButton)

public:
    CLhsButton();
    virtual ~CLhsButton();

     bool Create(CWnd* pParent,CRect rc,CString text,DWORD id = 0,DWORD style = WS_VISIBLE|WS_CHILD);  

    DECLARE_MESSAGE_MAP()

public:

protected:
    CString szClassName;
    bool m_isMouseHover;        //鼠标是否悬浮
    bool m_isMouseClicked;        //鼠标是否单击
    CString m_strShowText;        //要显示的文字

    Image*                        m_pImgNor;            //正常时的图片
    Image*                        m_pImgHot;            //鼠标悬浮时的图片
    Image*                        m_pImgDown;            //单击按下时的图片

    void PostClickEvent();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnMouseHover(UINT nFlags, CPoint point);
    afx_msg void OnMouseLeave();
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnPaint();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    virtual BOOL PreTranslateMessage(MSG* pMsg);
public:
    void SetTabState(ButtonState state){m_btnState = state; Invalidate();}    //设置tab状态
    ButtonState GetTabState(){return m_btnState;}
    void SetToolTipText(CString spText, BOOL bActivate = TRUE);
    void LoadBtnImg(LPCTSTR tType, UINT nNorID, UINT nHotID, UINT nDownID);        //加载按钮图片

private:
    ButtonState m_btnState;                            //tab的状态
    CToolTipCtrl*    m_pToolTip;
    CString m_tooltext;

public:
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};

//源文件
// CLhsButton.cpp : 实现文件
//

#include "stdafx.h"
#include "../Lander_mini.h"
#include "memdc.h"
#include "../Utility.h"
#include "LhsButton.h"
// CLhsButton

IMPLEMENT_DYNAMIC(CLhsButton, CWnd)

CLhsButton::CLhsButton()
{
    m_isMouseHover = false;
    m_isMouseClicked = false;
    // 注册控件类
    szClassName = AfxRegisterWndClass(0);
    m_pImgNor = NULL;
    m_pImgHot = NULL;
    m_pImgDown = NULL;
    m_btnState = BTN_STATE_NOR;
    m_pToolTip = NULL;
}

CLhsButton::~CLhsButton()
{
    SAFE_RELEASE(m_pToolTip);
    SAFE_RELEASE(m_pImgNor);
    SAFE_RELEASE(m_pImgHot);
    SAFE_RELEASE(m_pImgDown);
}

BEGIN_MESSAGE_MAP(CLhsButton, CWnd)
    ON_WM_MOUSEMOVE()
    ON_WM_MOUSEHOVER()  // 此消息系统并不会给我们发送
    ON_WM_MOUSELEAVE()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_PAINT()
    ON_WM_SIZE()
    ON_WM_ERASEBKGND()
    ON_WM_CREATE()
    ON_WM_CTLCOLOR()
END_MESSAGE_MAP()

// CLhsButton 消息处理程序
bool CLhsButton::Create(CWnd* pParent,CRect rc,CString text,DWORD id /* = 0 */,DWORD style /* = WS_VISIBLE|WS_CHILD */)
{
    // 动态创建控件
    BOOL ret = CWnd::CreateEx(0, szClassName, text, style, rc, pParent, id);
    return ret ? true : false;
}  

int CLhsButton::OnCreate(LPCREATESTRUCT lpCreateStruct)
{

    //::SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED);

    //ModifyStyle(WS_CLIPCHILDREN, 0);
    //ModifyStyle(0, WS_CLIPCHILDREN , 0);

    return 0;
}

void CLhsButton::PostClickEvent()
{
    // 该函数用来向父窗口发送 单击 消息
    CWnd* parent = GetParent();
    if(parent)
        parent->SendMessage(MYWM_BTN_CLICK, 0,0);
}  

void CLhsButton::OnMouseHover(UINT nFlags, CPoint point)
{
    // 鼠标进入
    Invalidate();
}  

void CLhsButton::OnMouseMove(UINT nFlags, CPoint point)
{
    // 只处理鼠标第一次进入时的情况
    if(!m_isMouseHover)
    {
        m_isMouseHover = true;  

        TRACKMOUSEEVENT evt = { sizeof(evt), TME_LEAVE|TME_HOVER, m_hWnd, 0 };
        TrackMouseEvent(&evt);  

        OnMouseHover(0,CPoint());
    }
}

void CLhsButton::OnMouseLeave()
{
    // 鼠标离开
    m_isMouseHover = false;
    m_isMouseClicked = false;
    Invalidate();
}  

void CLhsButton::OnLButtonDown(UINT nFlags, CPoint point)
{
    // 鼠标按下
    m_isMouseClicked = true;
    Invalidate();
}  

void CLhsButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    // 鼠标松开
    if(m_isMouseClicked)
    {
        m_isMouseClicked = false;
        Invalidate();
        PostClickEvent();
    }
}  

BOOL CLhsButton::OnEraseBkgnd(CDC* pDC)
{
//    return CWnd::OnEraseBkgnd(pDC);
    return TRUE;    // 阻止擦除背景,防止闪烁
}  

void CLhsButton::OnPaint()
{
    CPaintDC dc(this);
    CRect rc;
    GetClientRect(&rc); 

    // 采用双缓存,防止闪烁
    CMemDC memdc(&dc,&rc,TRUE);
    Graphics graphic(memdc);
    if (!m_pImgNor || !m_pImgHot || !m_pImgDown)
    {//没有提供按钮图片就刷下背景
        // 刷背景
        COLORREF bkgnd = RGB(100,0,0);
        if(m_isMouseHover)
        {
            if(m_isMouseClicked)
                bkgnd = RGB(250,0,0);
            else
                bkgnd = RGB(180,0,0);
        }
        memdc.FillSolidRect(&rc,bkgnd);
    }

    if (m_isMouseClicked || m_btnState == BTN_STATE_DOWN)
    {//单击一定画单击状态
        graphic.DrawImage(m_pImgDown, 0, 0, m_pImgDown->GetWidth(), m_pImgDown->GetHeight());
    }
    else if (m_isMouseHover && !m_isMouseClicked)
    {
        //悬浮,但是没单击
        graphic.DrawImage(m_pImgHot, 0, 0, m_pImgHot->GetWidth(), m_pImgHot->GetHeight());
    }
    else
    {
        graphic.DrawImage(m_pImgNor, 0, 0, m_pImgNor->GetWidth(), m_pImgNor->GetHeight());
    }

    // 使绘制生效
    graphic.ReleaseHDC(memdc);
}  

BOOL CLhsButton::PreTranslateMessage(MSG* pMsg)
{
    if (m_pToolTip)
    {
        if (::IsWindow(m_pToolTip->m_hWnd))
        {
            m_pToolTip->RelayEvent(pMsg);
        }
    }

    return CWnd::PreTranslateMessage(pMsg);
}

void CLhsButton::OnSize(UINT nType, int cx, int cy)
{

}

void CLhsButton::SetToolTipText(CString spText, BOOL bActivate)
{
    if (m_pToolTip == NULL)
    {
        m_pToolTip = new CToolTipCtrl;
        // Create ToolTip control
        m_pToolTip->Create(this);
        m_pToolTip->Activate(TRUE);
    }

    m_tooltext = spText;

    // If there is no tooltip defined then add it
    if (m_pToolTip->GetToolCount() == 0)
    {
        CRect rectBtn;
        GetClientRect(rectBtn);
        m_pToolTip->AddTool(this, m_tooltext, rectBtn, 1);
    }

    // Set text for tooltip
    m_pToolTip->UpdateTipText(m_tooltext, this, 1);
    m_pToolTip->SetDelayTime(2000);
    m_pToolTip->Activate(bActivate);
}

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

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

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

//加载按钮图片
void CLhsButton::LoadBtnImg(LPCTSTR tType, UINT nNorID, UINT nHotID, UINT nDownID)
{
    m_pImgNor = CQYUtility::LoadImgFromRes(_T("PNG"), nNorID);
    m_pImgHot = CQYUtility::LoadImgFromRes(_T("PNG"), nHotID);
    m_pImgDown = CQYUtility::LoadImgFromRes(_T("PNG"), nDownID);
}

内存DC

<pre name="code" class="cpp">#ifndef _MEMDC_H_
#define _MEMDC_H_

//////////////////////////////////////////////////
// CMemDC - memory DC
//
class CMemDC : public CDC {
private:
    CBitmap        m_bitmap;        // Offscreen bitmap
    CBitmap*    m_oldBitmap;    // bitmap originally found in CMemDC
    CDC*        m_pDC;            // Saves CDC passed in constructor
    CRect        m_rect;            // Rectangle of drawing area.
    BOOL        m_bMemDC;        // TRUE if CDC really is a Memory DC.
public:
       void Build( CDC* pDC )
   {
        ASSERT(pDC != NULL); 

        m_pDC        = pDC;
        m_oldBitmap = NULL;
        m_bMemDC    = !pDC->IsPrinting();

        if( m_bMemDC )
        {
            CreateCompatibleDC(pDC);
            pDC->LPtoDP(&m_rect);

            m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
            m_oldBitmap = SelectObject(&m_bitmap);

            SetMapMode(pDC->GetMapMode());
            pDC->DPtoLP(&m_rect);
            SetWindowOrg(m_rect.left, m_rect.top);
        }
        else
        {
            m_bPrinting = pDC->m_bPrinting;
            m_hDC       = pDC->m_hDC;
            m_hAttribDC = pDC->m_hAttribDC;
        }

        FillSolidRect( m_rect, pDC->GetBkColor() );
    }

    CMemDC(CDC* pDC, const CRect* pRect = NULL, BOOL bBg = FALSE) : CDC()
    {
        ASSERT(pDC != NULL); 

        // Some initialization
        m_pDC = pDC;
        m_oldBitmap = NULL;
        m_bMemDC = !pDC->IsPrinting();

        // Get the rectangle to draw
        if (pRect == NULL) {
            pDC->GetClipBox(&m_rect);
        } else {
            m_rect = *pRect;
        }

        if (m_bMemDC) {
            // Create a Memory DC
            CreateCompatibleDC(pDC);
            pDC->LPtoDP(&m_rect);

            m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
            m_oldBitmap = SelectObject(&m_bitmap);

            SetMapMode(pDC->GetMapMode());

            SetWindowExt(pDC->GetWindowExt());
            SetViewportExt(pDC->GetViewportExt());

            pDC->DPtoLP(&m_rect);
            SetWindowOrg(m_rect.left, m_rect.top);
        } else {
            // Make a copy of the relevent parts of the current DC for printing
            m_bPrinting = pDC->m_bPrinting;
            m_hDC       = pDC->m_hDC;
            m_hAttribDC = pDC->m_hAttribDC;
        }

        // Fill background
        if( bBg )
            BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
                m_pDC, m_rect.left, m_rect.top, SRCCOPY);
        else
            FillSolidRect(m_rect, pDC->GetBkColor());
    }

    ~CMemDC()
    {
        if (m_bMemDC) {
            // Copy the offscreen bitmap onto the screen.
            m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
                this, m_rect.left, m_rect.top, SRCCOPY);            

            //Swap back the original bitmap.
            SelectObject(m_oldBitmap);
        } else {
            // All we need to do is replace the DC with an illegal value,
            // this keeps us from accidently deleting the handles associated with
            // the CDC that was passed to the constructor.
            m_hDC = m_hAttribDC = NULL;
        }
    }

    // Allow usage as a pointer
    CMemDC* operator->()
    {
        return this;
    }    

    // Allow usage as a pointer
    operator CMemDC*()
    {
        return this;
    }
       CMemDC( HDC hDC )
       : CDC()
   {
       CDC::FromHandle( hDC )->GetClipBox( &m_rect );
       Build( CDC::FromHandle( hDC ) );
   }

};

#endif

调用方法:

//使用例子
RECT rc = {0, 0, 20, 20};
    m_btnClose.LoadBtnImg(_T("PNG"),IDB_PNG_TAB_CLOSE_NOR, IDB_PNG_TAB_CLOSE_HOT,IDB_PNG_TAB_CLOSE_HOT);
    m_btnClose.Create(this, rc, L"",ID_BTN_MYTAB_CLOSE);
    m_btnClose.SetToolTipText(_T("关闭"));         

源文地址:http://blog.csdn.net/huasonl88/article/details/43226011

时间: 2024-10-29 19:34:23

继承CWnd自绘按钮的相关文章

VC自绘按钮

看了吕鑫老师的视频,自己试着编写了一个自绘按钮控件.YuButton.h头文件如下: #pragma once   #include "afxwin.h"   class CYuButton :public CWnd   {       private:           BOOL  m_bIsDown;           BOOL  m_bIsMove;           BOOL  _bMouseTrack;//鼠标追踪状态              CString  m_s

vc++6.0工具栏自绘按钮程序

实现按钮自绘,界面. 主对话框文件: // TitleBarDlg.cpp : implementation file // #include "stdafx.h" #include "TitleBar.h" #include "TitleBarDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif

win32自绘按钮,使用GDI+(二)

解决上一篇的两个问题. 一,按钮背景透明 方法是,在绘制按钮之前,向按钮的父窗口发生WM_CTLCOLORBTN消息.该消息返回一个画刷句柄,系统使用该画刷句柄画出按钮的背景.所以我们在处理这个消息的时候,为系统返回一个空的画刷句柄就可以了. 直接在回调函数中添加代码 1 case WM_CTLCOLORBTN: 2 { 3 HBRUSH hBrush; 4 //hBrush = CreateSolidBrush(RGB(255, 0, 0)); 5 hBrush=(HBRUSH)GetStoc

MFC 自绘按钮 消息响应

单检测到按下消息时,发送一个消息 m_pParent->PostMessage(WM_COMMAND, IDC_BUTTON1); 然后再在消息映射里建立映射. ON_COMMAND(IDC_BUTTON1, &CMyDlg::OnBUTTON1)

mfc 按钮自绘

MFC  按钮自绘 :songyanwu 如果你是大神就没必要看这个文章了! 说明 源码下载:mfc 按钮自绘 先说说自己的一些想法:我就想把按钮封装成一个类,每次在使用的时候会很方便,当然在自己的类中去重载也可以! 此文章可借鉴学习:MFC基础,MFC自绘控件学习总结. (我也主要研究了自绘控件的子类化方法  ),看完前面推荐的文章,你似乎有何种感觉呢? 先实际操作吧;原理在后面介绍: 1 新建一个对画框 应用程序 2 新添加一个CMyButton继承CButton 3 为你自己添加的类 添加

VC++ WIN32 sdk实现按钮自绘详解.

网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片: 首先建立一个标准的Win32 Application 工程.选择a simple Win32 Application. 然后建立我们的资源文件首先新建一个对话框资源,资源ID改为IDD_MAIN_DLG 然后在其上新建一个按钮控件资源ID改为IDC_ODBUTTON,此按钮的styles中必须选中owenerdraw属性. 然后将其保存为.rc的资源文件.并将其导入我们的工程.同理新建一个

VC++ WIN32 sdk实现按钮自绘详解 之二.

网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片: 首先建立一个标准的Win32 Application 工程.选择a simple Win32 Application. 然后建立我们的资源文件首先新建一个对话框资源,资源ID改为IDD_MAIN_DLG 然后在其上新建一个按钮控件资源ID改为IDC_ODBUTTON,此按钮的styles中必须选中owenerdraw属性. 然后将其保存为.rc的资源文件.并将其导入我们的工程.同理新建一个

VC++ WIN32 sdk实现按钮自绘详解 之二(关键是BS_OWNERDRAW和WM_DRAWITEM)

网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片: 首先建立一个标准的Win32 Application 工程.选择a simple Win32 Application. 然后建立我们的资源文件首先新建一个对话框资源,资源ID改为IDD_MAIN_DLG 然后在其上新建一个按钮控件资源ID改为IDC_ODBUTTON,此按钮的styles中必须选中owenerdraw属性. 然后将其保存为.rc的资源文件.并将其导入我们的工程.同理新建一个

MFC按钮重绘

1 //按钮重绘函数 2 void CWeather091001Dlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { 3 CDC buttonDC; 4 CBitmap bitmapTrans; 5 BITMAP bmp; 6 CDC mem; 7 CRect rc; 8 buttonDC.Attach(lpDrawItemStruct->hDC); 9 //得到用于绘制按钮的DC 10 mem.CreateCompat