• 【MFC】Button控件美化(自绘)


    MFC中Button控件不能通过OnCtlColor()函数对外观做太多的改变。

    HBRUSH C按钮控件自绘Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    
    	switch (pWnd->GetDlgCtrlID())
    	{
    
    	case IDC_BUTTON1:
    	{
    		pDC->SetBkMode(TRANSPARENT);
    		pDC->SetBkColor(RGB(255, 0, 255));
    		pDC->SetTextColor(RGB(255, 0, 0));
    		static CBrush brush(RGB(255, 0, 255));
    		return brush;
    	}
    	break;
    	return hbr;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    欲设置按钮的背景为紫色,文字为红色,但是通过OnCtlColor()函数并不能实现预期的结果
    在这里插入图片描述
    为了能够修改Button控件字体、字体大小、背景色、背景图片,需要对Button控件进行自绘。

    设置Button控件的自绘属性

    方法一:在资源视图中将所有者描述设置为true
    在这里插入图片描述
    方法二:在OnInitDialog函数里给按钮添加BS_OWNERDRAW风格

    GetDlgItem(IDC_BUTTON1)->ModifyStyle(0, BS_OWNERDRAW);
    
    • 1

    建立一个以CButton为基类的派生类并重载DrawItem()函数

    在这里插入图片描述
    通过类向导添加DrawItem()函数
    在这里插入图片描述

    为按钮添加关联变量

    变量类型将CButton改成MyButton
    在这里插入图片描述

    MyButton类的设计

    #pragma once
    #include 
    class MyButton :
        public CButton
    {
    
    
    public:
        virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);
    public:
        //三种颜色分别为文字,Button Down的背景颜色,Button Up的背景颜色
        COLORREF m_TextColor, m_DownColor, m_UpColor;
        //Button Down的背景颜色,Button Up的背景颜色标志位
        bool bDownColor, bUpColor;
        //设置文字大小
        int nWordSize = 100;
        UINT    imageID;//记录图片ID
    public:
        //设置Button Down的背景颜色
        void SetDownColor(COLORREF color);
        //设置Button Up的背景颜色
        void SetUpColor(COLORREF color);
        //设置背景图片
        void SetBkImage(UINT ID);
        //设置文字大小,默认为10号
        void SetWordSize(int wordsize);
        //设置文字颜色默认为黑色
        void SetWordColor(COLORREF wordColor);
        // 文字处理
        void SetWord(CRect rect, CDC* pDc, int size);
        //绘制背景图片
        void DrawBkImage(CRect rect, CDC* pDc, UINT ID);
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    #include "pch.h"
    #include "MyButton.h"
    
    void MyButton::SetDownColor(COLORREF color)
    {
    	m_DownColor = color;
    	bDownColor = TRUE;//颜色是否设置标志位
    }
    void MyButton::SetUpColor(COLORREF color)
    {
    	m_UpColor = color;
    	bUpColor = TRUE;
    }
    void MyButton::SetBkImage(UINT ID)
    {
    	imageID = ID;
    }
    void MyButton::SetWordSize(int wordsize)
    {
    	nWordSize = wordsize;
    }
    void MyButton::SetWordColor(COLORREF wordColor = RGB(255, 255, 255))
    {
    	m_TextColor = wordColor;
    }
    void MyButton::DrawBkImage(CRect rect, CDC* pDc, UINT ID)
    {
    	CDC   dcBmp;             //定义并创建一个内存设备环境
    	dcBmp.CreateCompatibleDC(pDc);             //创建兼容性DC
    	CBitmap   bmpBackground;
    	bmpBackground.LoadBitmap(ID);    //载入资源中图片
    	BITMAP   m_bitmap;                         //图片变量               
    	bmpBackground.GetBitmap(&m_bitmap);       //将图片载入位图中
    	//将位图选入临时内存设备环境
    	CBitmap* pbmpOld = dcBmp.SelectObject(&bmpBackground);
    	//调用函数显示图片StretchBlt显示形状可变
    	pDc->SetStretchBltMode(HALFTONE);
    	pDc->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dcBmp, 0, 0, m_bitmap.bmWidth, m_bitmap.bmHeight, SRCCOPY);
    }
    // 文字处理
    void MyButton::SetWord(CRect rect, CDC* pDc, int nWordSize)
    {
    	CString str;
    	GetWindowText(str);//获取文字
    	CFont font;
    	font.CreatePointFont(nWordSize, L"仿宋");//设置控件文字大小与字体
    	pDc->SelectObject(&font);
    	pDc->SetTextColor(m_TextColor);//设置文字颜色
    	// dc.SetBkColor(RGB(255, 0, 0));//设置文字背景颜色
    	pDc->SetBkMode(TRANSPARENT);//设置文字背景透明
    	pDc->DrawText(str, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_TABSTOP);//绘制文字
    }
    void MyButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
    {
    	CDC dc;
    	dc.Attach(lpDIS->hDC);//得到绘制的设备环境CDC
    	dc.SelectStockObject(NULL_BRUSH);//按钮为默认颜色
    	dc.Rectangle(&lpDIS->rcItem);//画出按钮框
    	CString str;
    	CRect rect = lpDIS->rcItem;
    	GetClientRect(&rect);//得到客户端坐标 //ScreenToClient();将屏幕坐标转换为客户端坐标
    	//加载背景图片,判断是否加载背景图片,没有则使用默认背景
    	if (imageID != 0) DrawBkImage(rect, &dc, imageID);
    	//按钮按下时改变背景色
    	if (lpDIS->itemState & ODS_SELECTED)
    	{
    		if (bDownColor)
    		{
    			CBrush brush(m_DownColor);
    			dc.FillRect(&(lpDIS->rcItem), &brush);//利用画刷brush,填充矩形框
    		}
    	}
    	else//当按钮不操作或者弹起时改变背景色
    	{
    		if (bUpColor)
    		{
    			CBrush brush(m_UpColor);
    			dc.FillRect(&(lpDIS->rcItem), &brush);//利用画刷brush,填充矩形框
    		}
    	}
    	//文字处理(绘制文字)
    	SetWord(rect, &dc, nWordSize);
    	dc.Detach();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    效果

    /*放在OnInitDialog函数或OnPaint函数里*/
    
    m_button1.SetUpColor(RGB(255, 0, 0));
    m_button1.SetDownColor(RGB(0, 0, 255));
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    如果要在按钮上显示图片,不要设置按钮按下和弹起的颜色,这会覆盖图片

    void C按钮控件自绘Dlg::OnPaint()
    {
    	CPaintDC dc(this);
    	CRect rect;
    	GetDlgItem(IDC_BUTTON1)->GetWindowRect(&rect);//获取控件的屏幕坐标
    	ScreenToClient(&rect);//转换为窗口的的客户区坐标
    	m_button1.SetBkImage(IDB_BITMAP1);
    	m_button1.DrawBkImage(rect, &dc, IDB_BITMAP1); 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    这个时候点击按钮并没有什么变化(这里指视觉上的变化,消息还是有的)
    那么可以在DrawItem()函数里添加一些功能,比如按钮按下的时候绘制边框,弹起时销毁边框

    if ((lpDIS->itemState & ODS_SELECTED) && (lpDIS->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
    	{
    		//设置按钮边框颜色为蓝色
    		COLORREF color = RGB(0, 0, 255);
    		CBrush brush(color);
    		dc.FrameRect(&(lpDIS->rcItem), &brush);//用画刷brush,填充矩形边框
    	}
    	//控制的选中状态结束,去掉边框
    if (!(lpDIS->itemState & ODS_SELECTED) && (lpDIS->itemAction & ODA_SELECT))
    	{
    		CBrush brush(m_UpColor);
    		dc.FrameRect(&lpDIS->rcItem, &brush);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    LPDRAWITEMSTRUCT结构体
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    .NET Core Web API 实现图形验证码
    【python】Python 常见文件格式 .py .pyc .pyw .pyo .pyd简介
    wsl kali-linux 安装记录
    【精选】代码Ai生成,
    03路由策略
    968. 监控二叉树
    二苯基环辛炔DBCO修饰InP量子点,多巴胺Dopamine修饰SiO2量子点,二茂铁Ferrocene修饰Ag2Te量子点
    Ubuntu环境下安装OWT (Open WebRTC Toolkit)
    抓住这几个关键点,做薪酬数据分析并不难
    12.1 使用键盘鼠标监控钩子
  • 原文地址:https://blog.csdn.net/m0_72895175/article/details/132738673