win32方式实现自绘按钮

来源:互联网 发布:织梦cms关闭更新 编辑:程序博客网 时间:2024/06/15 13:43
/** * \file OwnerDrawButton.h * * \brief 自绘按钮的实现类 * * \author */ #pragma onceclass COwnerDrawButton{public:    COwnerDrawButton(void);    ~COwnerDrawButton(void);private:    COwnerDrawButton(const COwnerDrawButton &OtherOwnerDrawButton);    COwnerDrawButton &operator=(const COwnerDrawButton &OtherOwnerDrawButton);public:    /** * \brief 刷新控件 */    bool InvalidataCtrl();public:    /** * \brief 创建按钮 * \param lpszCaption 参数,为按钮的显示文本     * \param lpszImage 参数,为按钮的位图路径     * \param rect 参数,为按钮的坐标     * \param hParentWnd 参数,为按钮的父窗口句柄     * \param nID 参数,为按钮的控件ID     * \param lpszImage 参数,为按钮控件一般状态位图路径 */    BOOL Create(LPCSTR lpszCaption, const RECT& rect, HWND hParentWnd,\        UINT nID, LPCSTR lpszImage);    /** * \brief 绘制按钮     * \param hDC 参数,为按钮的绘制用DC句柄 */    void Draw(HDC hDC);    void DrawFocusRect(HDC hDC,RECT &rcWnd);    /** * \brief 设置按钮     * \param fEnable 参数,为设置按钮是否可用 */    void EnableButton(bool fEnable);    void OnLbuttonDown(WPARAM wParam, LPARAM lParam);    void OnLbuttonUp(WPARAM wParam, LPARAM lParam);    void OnLbuttonDBClick(WPARAM wParam, LPARAM lParam);    void OnMouseMove(WPARAM wParam, LPARAM lParam);    void OnMouseLeave(WPARAM wParam, LPARAM lParam);private:    /** * \brief 按钮消息回调函数 */    static LRESULT CALLBACK ButtonProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);public:    enum STATE    {        STATE_UP,         STATE_DOWN,         STATE_FOCUS,         STATE_DISABLE    };    WNDPROC     m_OldProc;//!按钮的默认消息回调函数    HWND        m_hWnd;      //!此按钮的句柄private:    HBITMAP     m_hFourStateBitmap; //!按钮的普通四状态位图    BOOL        m_fRoundButton;  //!当前控件类型,TRUE为按钮类型,FALSE为一般的显示位图控件    BOOL        m_fTrackMouse;    int         m_nButtonState;//!按钮的当前状态    HFONT       m_hFont;//!控件字体};


#include <Windows.h>#include "OwnerDrawButton.h"const int g_nCaptionLen = 50;COwnerDrawButton::COwnerDrawButton(void): m_hWnd(NULL), m_hFourStateBitmap(NULL), \m_fTrackMouse(FALSE){}COwnerDrawButton::~COwnerDrawButton(void){    if (m_hFourStateBitmap)    {        DeleteObject(m_hFourStateBitmap);    }    if (m_hFont)    {        DeleteObject(m_hFont);    }}BOOL COwnerDrawButton::Create(LPCSTR lpszCaption, const RECT& rect, HWND hParentWnd,\                         UINT nID, LPCSTR lpszImage){    if(m_hWnd)        return FALSE;    m_hFourStateBitmap = (HBITMAP)LoadImage(NULL, lpszImage, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);    if( NULL == m_hFourStateBitmap)    {        goto CREATE_FAIL;    }    m_hWnd = CreateWindow("BUTTON", lpszCaption, \        WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_OWNERDRAW, \        rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, \        hParentWnd,(HMENU)nID,NULL,NULL);    if( NULL == m_hWnd)    {        goto CREATE_FAIL;    }    m_OldProc = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)ButtonProc);    SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);    m_hFont = CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, \        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial" );     return TRUE;CREATE_FAIL:    if (m_hFourStateBitmap)    {        DeleteObject(m_hFourStateBitmap);    }    return FALSE;}LRESULT CALLBACK COwnerDrawButton::ButtonProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    PAINTSTRUCT ps;    HDC hdc;    COwnerDrawButton *_this = (COwnerDrawButton *)GetWindowLong(hWnd, GWL_USERDATA);    _this->m_hWnd = hWnd;    switch (message)    {    case WM_PAINT:        hdc = BeginPaint(hWnd, &ps);        // TODO: Add any drawing code here...        _this->Draw(hdc);        EndPaint(hWnd, &ps);        break;    case WM_ERASEBKGND:        return TRUE;    case WM_DRAWITEM:        {            DRAWITEMSTRUCT *pDrawItemSturct = (DRAWITEMSTRUCT *)lParam;            if(pDrawItemSturct->itemState & ODS_FOCUS)            {                RECT rtFocus = pDrawItemSturct->rcItem;                rtFocus.left += 3;                rtFocus.top += 3;                rtFocus.right -= 3;                rtFocus.bottom -= 3;                _this->DrawFocusRect(pDrawItemSturct->hDC, rtFocus);            }            //_this->Draw(pDrawItemSturct->hDC);        }        break;    case WM_LBUTTONDOWN:        {            _this->OnLbuttonDown(wParam, lParam);        }        break;    case WM_LBUTTONUP:        {            _this->OnLbuttonUp(wParam, lParam);        }        break;    case WM_LBUTTONDBLCLK:        {            _this->OnLbuttonDBClick(wParam, lParam);        }        break;    case WM_MOUSEMOVE:        {            _this->OnMouseMove(wParam, lParam);        }        break;    case WM_MOUSELEAVE:        {            _this->OnMouseLeave(wParam, lParam);        }        break;    default:        return CallWindowProc(_this->m_OldProc, hWnd, message, wParam, lParam);    }    return 0;}void COwnerDrawButton::OnLbuttonDown(WPARAM wParam, LPARAM lParam){    SetCapture(m_hWnd);    m_nButtonState = STATE_DOWN;    InvalidataCtrl();}void COwnerDrawButton::OnLbuttonUp(WPARAM wParam, LPARAM lParam){    if(m_nButtonState == STATE_DOWN)    {        ReleaseCapture();        POINT pt = {};        GetCursorPos(&pt);        RECT rcWnd = {};        GetWindowRect(m_hWnd, &rcWnd);        if(PtInRect(&rcWnd, pt))        {            m_fTrackMouse = TRUE;            m_nButtonState = STATE_FOCUS;            SendMessage(GetParent(m_hWnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(m_hWnd), \                BN_CLICKED), (LPARAM)m_hWnd);        }        else        {            m_fTrackMouse = FALSE;            m_nButtonState = STATE_UP;                  }        InvalidataCtrl();    }}void COwnerDrawButton::OnLbuttonDBClick(WPARAM wParam, LPARAM lParam){    SendMessage(m_hWnd, WM_LBUTTONDOWN, NULL, NULL);}void COwnerDrawButton::OnMouseMove(WPARAM wParam, LPARAM lParam){    if(!m_fTrackMouse)    {        TRACKMOUSEEVENT MouseEvent = {sizeof(TRACKMOUSEEVENT)};        MouseEvent.dwFlags = TME_LEAVE;        MouseEvent.hwndTrack = m_hWnd;        MouseEvent.dwHoverTime = 1000;        TrackMouseEvent(&MouseEvent);        m_fTrackMouse = TRUE;        m_nButtonState = STATE_FOCUS;        InvalidataCtrl();    }}void COwnerDrawButton::OnMouseLeave(WPARAM wParam, LPARAM lParam){    m_fTrackMouse = FALSE;    m_nButtonState = STATE_UP;    InvalidataCtrl();}void COwnerDrawButton::Draw(HDC hDC){    HDC hMemDC = CreateCompatibleDC(hDC);    HBITMAP hOldBmp = NULL;    BITMAP bmpInfo = {};        hOldBmp= (HBITMAP)SelectObject(hMemDC, m_hFourStateBitmap);        GetObject(m_hFourStateBitmap, sizeof(bmpInfo), &bmpInfo);       RECT rcWnd = {};    GetClientRect(m_hWnd, &rcWnd);    int nWidth = rcWnd.right - rcWnd.left;    int nHeight = rcWnd.bottom - rcWnd.top;    int nBmpWidth = bmpInfo.bmWidth / 4;    int nBmpHeight = bmpInfo.bmHeight;    //绘制背景图    SetStretchBltMode(hDC, HALFTONE);    StretchBlt(hDC, 0, 0, nWidth, nHeight, hMemDC, nBmpWidth * m_nButtonState,\        0, nBmpWidth, nBmpHeight, SRCCOPY);    if(m_nButtonState == STATE_DOWN)    {        rcWnd.top += 2;    }    //绘制文本    char szCaption[g_nCaptionLen] = {};    GetWindowText(m_hWnd, szCaption, g_nCaptionLen - 1);    if(strlen(szCaption) > 0)    {        SetBkMode(hDC, TRANSPARENT);        char *pReturnPos = NULL;        HFONT hOldFont = (HFONT)SelectObject(hDC, m_hFont);        if(pReturnPos = strstr(szCaption, "\\r\\n"))        {            //pReturnPos[0] = '\r';            //pReturnPos[1] = '\n';            //strcpy(&pReturnPos[2], &pReturnPos[4]);            char *pszSecondLine = pReturnPos + 4;            rcWnd.bottom = (rcWnd.bottom + rcWnd.top) / 2;            rcWnd.top += 1;            DrawText(hDC, szCaption, pReturnPos -  szCaption, &rcWnd, DT_CENTER);            rcWnd.top -= 1;            rcWnd.bottom = rcWnd.bottom * 2 - rcWnd.top;            rcWnd.top = (rcWnd.bottom + rcWnd.top) / 2;            rcWnd.top -= 1;            DrawText(hDC, pszSecondLine, strlen(pszSecondLine), &rcWnd, DT_CENTER);        }        else        {            DrawText(hDC, szCaption, strlen(szCaption), &rcWnd, DT_CENTER|DT_VCENTER|DT_SINGLELINE);        }        SelectObject(hDC, hOldFont);    }    SelectObject(hMemDC, hOldBmp);    DeleteDC(hMemDC);}void COwnerDrawButton::DrawFocusRect(HDC hDC,RECT &rcWnd){    HPEN hOldPen = NULL;    HPEN hDrawPen = CreatePen(PS_DOT, 2, RGB(0,0,0));    HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);    HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);    hOldPen = (HPEN)SelectObject(hDC, hDrawPen);    Rectangle(hDC, rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom);    SelectObject(hDC,hOldBrush);    SelectObject(hDC,hOldPen);    DeleteObject(hDrawPen);}bool COwnerDrawButton::InvalidataCtrl(){    //RECT rcWnd = {};    //GetClientRect(m_hWnd, &rcWnd);    //InvalidateRect(m_hWnd, &rcWnd, bErase);    HDC hDC = GetDC(m_hWnd);    Draw(hDC);    ReleaseDC(m_hWnd, hDC);    return true;}void COwnerDrawButton::EnableButton(bool fEnable){    if(fEnable)    {        m_nButtonState = STATE_UP;    }    else    {        m_nButtonState = STATE_DISABLE;    }    EnableWindow(m_hWnd, fEnable);    InvalidataCtrl();}


原创粉丝点击