• 继承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

  • 相关阅读:
    Visual Studio 20**自动添加头部注释信息
    开发使用混合式Winform模块
    java 下拉框级联及相关(转)
    Redhat关闭SELinux和防火墙的办法(转)
    icmp的报文,Destination Host Unreachable
    负载均衡-lvs
    深入浅出交换类排序算法(转)
    单源最短路径(dijkstra算法)php实现
    垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
    oracle递归函数
  • 原文地址:https://www.cnblogs.com/guobbs/p/4936217.html
Copyright © 2020-2023  润新知