qq_41945416 2025-11-07 20:20 采纳率: 90.6%
浏览 4
已结题

关于在mfc中重绘按钮Button

img

1.1,如图,如何在mfc中如何重绘按钮? 按钮边框色是 7,57,142。正常状态下的背景色是204,230,255
应该怎么重绘,另外重绘 怎么画渐变色?

  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-11-07 22:05
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案能帮助您,请采纳、点赞,非常感谢!
    .
    每日一句正能量,让它带给您好心情:别让懒惰吞噬你的梦想,行动起来,一切都还来得及。
    .

    在MFC中重绘按钮需要继承CButton类并重写DrawItem方法。以下是完整的实现方案:

    1. 创建自定义按钮类

    // CustomButton.h
    #pragma once
    
    
    class CCustomButton : public CButton
    {
        DECLARE_DYNAMIC(CCustomButton)
    
    
    public:
        CCustomButton();
        virtual ~CCustomButton();
    
    
        // 设置颜色
        void SetNormalColors(COLORREF border, COLORREF bgStart, COLORREF bgEnd);
        void SetHoverColors(COLORREF border, COLORREF bgStart, COLORREF bgEnd);
        void SetPressedColors(COLORREF border, COLORREF bgStart, COLORREF bgEnd);
    
    
    protected:
        DECLARE_MESSAGE_MAP()
    
    
        // 重写绘制函数
        virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
        
        // 鼠标消息处理
        afx_msg void OnMouseMove(UINT nFlags, CPoint point);
        afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
    
    
    private:
        // 绘制渐变背景
        void DrawGradient(CDC* pDC, CRect rect, COLORREF startColor, COLORREF endColor);
        
        // 绘制边框
        void DrawBorder(CDC* pDC, CRect rect, COLORREF borderColor);
    
    
        // 按钮状态
        enum ButtonState { Normal, Hover, Pressed };
        ButtonState m_State;
    
    
        // 颜色定义
        COLORREF m_NormalBorder, m_NormalBgStart, m_NormalBgEnd;
        COLORREF m_HoverBorder, m_HoverBgStart, m_HoverBgEnd;
        COLORREF m_PressedBorder, m_PressedBgStart, m_PressedBgEnd;
    };
    

    2. 实现自定义按钮类

    // CustomButton.cpp
    #include "stdafx.h"
    #include "CustomButton.h"
    
    
    IMPLEMENT_DYNAMIC(CCustomButton, CButton)
    
    
    CCustomButton::CCustomButton()
        : m_State(Normal)
    {
        // 设置默认颜色 - 使用你提供的颜色
        SetNormalColors(RGB(7, 57, 142), RGB(204, 230, 255), RGB(180, 215, 250));
        SetHoverColors(RGB(7, 57, 142), RGB(180, 210, 245), RGB(160, 195, 235));
        SetPressedColors(RGB(7, 57, 142), RGB(160, 190, 230), RGB(140, 175, 220));
    }
    
    
    CCustomButton::~CCustomButton()
    {
    }
    
    
    BEGIN_MESSAGE_MAP(CCustomButton, CButton)
        ON_WM_MOUSEMOVE()
        ON_MESSAGE(WM_MOUSELEAVE, &CCustomButton::OnMouseLeave)
    END_MESSAGE_MAP()
    
    
    void CCustomButton::SetNormalColors(COLORREF border, COLORREF bgStart, COLORREF bgEnd)
    {
        m_NormalBorder = border;
        m_NormalBgStart = bgStart;
        m_NormalBgEnd = bgEnd;
    }
    
    
    void CCustomButton::SetHoverColors(COLORREF border, COLORREF bgStart, COLORREF bgEnd)
    {
        m_HoverBorder = border;
        m_HoverBgStart = bgStart;
        m_HoverBgEnd = bgEnd;
    }
    
    
    void CCustomButton::SetPressedColors(COLORREF border, COLORREF bgStart, COLORREF bgEnd)
    {
        m_PressedBorder = border;
        m_PressedBgStart = bgStart;
        m_PressedBgEnd = bgEnd;
    }
    
    
    void CCustomButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
        CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
        CRect rect = lpDrawItemStruct->rcItem;
        UINT state = lpDrawItemStruct->itemState;
        
        // 确定当前状态
        ButtonState drawState = Normal;
        if (state & ODS_SELECTED)
            drawState = Pressed;
        else if (m_State == Hover)
            drawState = Hover;
        else
            drawState = Normal;
    
    
        // 根据状态选择颜色
        COLORREF borderColor, bgStart, bgEnd;
        switch (drawState)
        {
        case Hover:
            borderColor = m_HoverBorder;
            bgStart = m_HoverBgStart;
            bgEnd = m_HoverBgEnd;
            break;
        case Pressed:
            borderColor = m_PressedBorder;
            bgStart = m_PressedBgStart;
            bgEnd = m_PressedBgEnd;
            break;
        default:
            borderColor = m_NormalBorder;
            bgStart = m_NormalBgStart;
            bgEnd = m_NormalBgEnd;
            break;
        }
    
    
        // 绘制渐变背景
        DrawGradient(pDC, rect, bgStart, bgEnd);
        
        // 绘制边框
        DrawBorder(pDC, rect, borderColor);
    
    
        // 绘制文本
        CString strText;
        GetWindowText(strText);
        
        pDC->SetBkMode(TRANSPARENT);
        COLORREF textColor = (drawState == Normal) ? RGB(0, 0, 0) : RGB(255, 255, 255);
        pDC->SetTextColor(textColor);
        
        CFont* pOldFont = pDC->SelectObject(GetFont());
        pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        pDC->SelectObject(pOldFont);
    }
    
    
    void CCustomButton::DrawGradient(CDC* pDC, CRect rect, COLORREF startColor, COLORREF endColor)
    {
        // 创建渐变画刷
        TRIVERTEX vert[2];
        GRADIENT_RECT gRect;
        
        vert[0].x = rect.left;
        vert[0].y = rect.top;
        vert[0].Red = GetRValue(startColor) << 8;
        vert[0].Green = GetGValue(startColor) << 8;
        vert[0].Blue = GetBValue(startColor) << 8;
        vert[0].Alpha = 0xFF00;
        
        vert[1].x = rect.right;
        vert[1].y = rect.bottom;
        vert[1].Red = GetRValue(endColor) << 8;
        vert[1].Green = GetGValue(endColor) << 8;
        vert[1].Blue = GetBValue(endColor) << 8;
        vert[1].Alpha = 0xFF00;
        
        gRect.UpperLeft = 0;
        gRect.LowerRight = 1;
        
        // 使用GradientFill绘制渐变
        pDC->GradientFill(vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
    }
    
    
    void CCustomButton::DrawBorder(CDC* pDC, CRect rect, COLORREF borderColor)
    {
        CPen pen(PS_SOLID, 1, borderColor);
        CPen* pOldPen = pDC->SelectObject(&pen);
        CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
        
        pDC->Rectangle(rect);
        
        pDC->SelectObject(pOldPen);
        pDC->SelectObject(pOldBrush);
    }
    
    
    void CCustomButton::OnMouseMove(UINT nFlags, CPoint point)
    {
        if (m_State != Hover)
        {
            m_State = Hover;
            Invalidate();
            
            // 跟踪鼠标离开
            TRACKMOUSEEVENT tme;
            tme.cbSize = sizeof(TRACKMOUSEEVENT);
            tme.dwFlags = TME_LEAVE;
            tme.hwndTrack = m_hWnd;
            tme.dwHoverTime = 0;
            TrackMouseEvent(&tme);
        }
        
        CButton::OnMouseMove(nFlags, point);
    }
    
    
    LRESULT CCustomButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
    {
        m_State = Normal;
        Invalidate();
        return 0;
    }
    

    3. 在对话框中使用

    // 在对话框头文件中
    #include "CustomButton.h"
    
    
    class CMyDialog : public CDialogEx
    {
        // ...
    private:
        CCustomButton m_btnCustom;
    };
    
    
    // 在对话框cpp文件中
    BOOL CMyDialog::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
        
        // 子类化按钮
        m_btnCustom.SubclassDlgItem(IDC_BUTTON1, this);
        
        // 可选:设置自定义颜色
        m_btnCustom.SetNormalColors(RGB(7, 57, 142), RGB(204, 230, 255), RGB(180, 215, 250));
        
        return TRUE;
    }
    

    4. 资源设置

    在资源编辑器中,将按钮的Owner Draw属性设置为True

    关键点说明:

    1. 渐变绘制:使用GradientFillAPI实现垂直渐变效果
    2. 边框颜色:使用你指定的RGB(7, 57, 142)
    3. 背景色:使用RGB(204, 230, 255)作为起始颜色,并添加渐变效果
    4. 状态管理:处理正常、悬停、按下三种状态
    5. 鼠标跟踪:使用TrackMouseEvent来检测鼠标离开

    这样实现的按钮将具有渐变背景、自定义边框颜色,并支持鼠标悬停和按下状态的效果。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月20日
  • 已采纳回答 11月12日
  • 修改了问题 11月7日
  • 创建了问题 11月7日