MFC界面美化第三篇----自绘按钮(重绘按钮)

1.前言

最近发现读者对我的mfc美化的专栏比较感兴趣,因此在这里进行续写,这里我会计划写几个连续的篇章,包括对MFC按钮的美化,菜单栏的美化,标题栏的美化,list列表的美化,直到最后形成一个完整的成品效果。

2.最终效果展示

点击启动按钮之后,能响应功能。

博主不会UI设计图片显示的效果比较差,用更好的图片贴上去,就能显示更好的效果的

3.思路分析

1.使用我们设计好的图片,来美化按钮。把图片贴到按钮上

2.创建一个按钮类,继承CButton,来重绘按钮

3.核心还是重写了 DrawItem,函数来实现重绘的效果

4.实现过程

1.在MFC的界面那里,创建两个按钮,启动和停止按钮。

2.找到按钮的属性那里,把所有者描述改成true,不然重绘是不能成功的,这一步是一定要做的

3.核心代码

头文件里面声明按钮变量

public:CMyButton m_button_start;CMyButton m_button_stop;afx_msg void OnBnClickedButton2();afx_msg void OnBnClickedButton1();

OnInitDialog()函数

BOOL CMFCDrawnTitleDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != nullptr){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标// TODO: 在此添加额外的初始化代码//退出按钮绘制CRect rtBtnClo;GetClientRect(&rtBtnClo);rtBtnClo.left = rtBtnClo.right - 20;m_btnExit.SetImagePath(_T(".\\res\\icon_popup_off.png"), _T(".\\res\\icon_popup_off.png"), _T(".\\res\\icon_popup_off.png"));m_btnExit.InitMyButton(rtBtnClo.left, 5, 16, 16, true);//最大化按钮绘制GetClientRect(&rtBtnClo);rtBtnClo.left = rtBtnClo.right - 50;m_btnMax.SetImagePath(_T(".\\res\\icon_square.png"), _T(".\\res\\icon_square.png"), _T(".\\res\\icon_square.png"));m_btnMax.InitMyButton(rtBtnClo.left, 5, 16, 16, true);//最小化按钮// GetClientRect(&rtBtnClo);rtBtnClo.left = rtBtnClo.right - 80;m_btnMin.SetImagePath(_T(".\\res\\icon_minimiz.png"), _T(".\\res\\icon_minimiz.png"), _T(".\\res\\icon_minimiz.png"));m_btnMin.InitMyButton(rtBtnClo.left, 5, 16, 16, true);return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

5.button重绘的头文件和cpp文件

mybutton.h

pch.h, 和framework.h这两个文件的路径,可以改的。根据你的项目文件实际放置情况

#pragma once#include <afxwin.h>
#include "../pch.h"
#include "../framework.h"
// CMyButtonclass CMyButton : public CButton
{DECLARE_DYNAMIC(CMyButton)public:CMyButton();virtual ~CMyButton();protected://正常状态图像路径CString m_strNormalImgPath;//按下状态图像路径CString m_strPressImgPath;//悬浮状态图像路径CString m_strFloatImgPath;//正常状态图像CImage m_imgNormal;//按下状态图像CImage m_imgPress;//悬浮状态图像CImage m_imgFloat;//窗口背景图片CImage m_BkImg;public://设置按钮图片路径void SetImagePath(CString strNoramlImgPath, CString strPressImgPath, CString strFloatImgPath);//初始化按钮,主要是调整按钮的位置,处理透明色  bool InitMyButton(int nX/*左上角X坐标*/, int nY/*左上角Y坐标*/, int nW/*图像宽*/, int nH/*图像高*/, bool bIsPng/*是否是PNG图片*/);//自绘制函数  void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);//初始化窗口背景void SetBkImg(CString strBkImg);//释放图片资源,方便最大化 void ReleaseImg();
protected://光标是否在窗口内BOOL m_bIsInWnd;DECLARE_MESSAGE_MAP()
public:afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnMouseHover(UINT nFlags, CPoint point);afx_msg void OnMouseLeave();};

mybutton.cpp

// MyButton.cpp : 实现文件
//#include "pch.h"
#include "MyButton.h"// CMyButtonIMPLEMENT_DYNAMIC(CMyButton, CButton)CMyButton::CMyButton()
{m_bIsInWnd = FALSE;
}CMyButton::~CMyButton()
{
}BEGIN_MESSAGE_MAP(CMyButton, CButton)ON_WM_MOUSEMOVE()ON_WM_MOUSEHOVER()ON_WM_MOUSELEAVE()
END_MESSAGE_MAP()// CMyButton 消息处理程序//设置按钮图片路径
void CMyButton::SetImagePath(CString strNoramlImgPath, CString strPressImgPath, CString strFloatImgPath)
{m_strNormalImgPath = strNoramlImgPath;m_strPressImgPath = strPressImgPath;m_strFloatImgPath = strFloatImgPath;
}void CMyButton::SetBkImg(CString strBkImg)
{if (strBkImg.IsEmpty())return;m_BkImg.Load(strBkImg);
}//初始化按钮,主要是调整按钮的位置,处理透明色 
void CMyButton::ReleaseImg()
{if (m_imgNormal){m_imgNormal.Destroy();}if (m_imgPress){m_imgPress.Destroy();}if (m_imgFloat){m_imgFloat.Destroy();}
}
bool CMyButton::InitMyButton(int nX/*左上角X坐标*/, int nY/*左上角Y坐标*/, int nW/*图像宽*/, int nH/*图像高*/, bool bIsPng/*是否是PNG图片*/)
{HRESULT hr = 0;if (m_strNormalImgPath.IsEmpty())return false;if (m_strPressImgPath.IsEmpty())return false;if (m_strFloatImgPath.IsEmpty())return false;hr = m_imgNormal.Load(m_strNormalImgPath);int a = GetLastError();if (FAILED(hr))return false;hr = m_imgPress.Load(m_strPressImgPath);if (FAILED(hr))return false;hr = m_imgFloat.Load(m_strFloatImgPath);if (FAILED(hr))return false;if (bIsPng){if (m_imgNormal.GetBPP() == 32){int i = 0;int j = 0;for (i = 0; i < m_imgNormal.GetWidth(); i++){for (j = 0; j < m_imgNormal.GetHeight(); j++){byte * pbyte = (byte *)m_imgNormal.GetPixelAddress(i, j);pbyte[0] = pbyte[0] * pbyte[3] / 255;pbyte[1] = pbyte[1] * pbyte[3] / 255;pbyte[2] = pbyte[2] * pbyte[3] / 255;}}}if (m_imgPress.GetBPP() == 32){int i = 0;int j = 0;for (i = 0; i < m_imgPress.GetWidth(); i++){for (j = 0; j < m_imgPress.GetHeight(); j++){byte * pbyte = (byte *)m_imgPress.GetPixelAddress(i, j);pbyte[0] = pbyte[0] * pbyte[3] / 255;pbyte[1] = pbyte[1] * pbyte[3] / 255;pbyte[2] = pbyte[2] * pbyte[3] / 255;}}}if (m_imgFloat.GetBPP() == 32){int i = 0;int j = 0;for (i = 0; i < m_imgFloat.GetWidth(); i++){for (j = 0; j < m_imgFloat.GetHeight(); j++){byte * pbyte = (byte *)m_imgFloat.GetPixelAddress(i, j);pbyte[0] = pbyte[0] * pbyte[3] / 255;pbyte[1] = pbyte[1] * pbyte[3] / 255;pbyte[2] = pbyte[2] * pbyte[3] / 255;}}}}MoveWindow(nX, nY, nW, nH);return true;}
//自绘制函数  
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{if (!lpDrawItemStruct)return;HDC hMemDC;HBITMAP bmpMem;HGDIOBJ hOldObj;bmpMem = CreateCompatibleBitmap(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top);if (!bmpMem)return;hMemDC = CreateCompatibleDC(lpDrawItemStruct->hDC);if (!hMemDC){if (bmpMem){::DeleteObject(bmpMem);bmpMem = NULL;}return;}hOldObj = ::SelectObject(hMemDC, bmpMem);int nW = lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left;int nH = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top;RECT rectTmp = { 0 };rectTmp = lpDrawItemStruct->rcItem;MapWindowPoints(GetParent(), &rectTmp);if (m_BkImg.IsNull() == false)m_BkImg.Draw(hMemDC, 0, 0, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top, rectTmp.left, rectTmp.top, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top);if (lpDrawItemStruct->itemState & ODS_SELECTED){//按钮被选择  m_imgPress.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);}else{//默认状态  m_imgNormal.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);}::BitBlt(lpDrawItemStruct->hDC, 0, 0, nW, nH, hMemDC,0,0,SRCCOPY);SelectObject(hMemDC, hOldObj);if (bmpMem){::DeleteObject(bmpMem);bmpMem = NULL;}if (hMemDC){::DeleteDC(hMemDC);hMemDC = NULL;}return;
}void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{// TODO:  在此添加消息处理程序代码和/或调用默认值CButton::OnMouseMove(nFlags, point);if (!m_bIsInWnd){TRACKMOUSEEVENT       tme;tme.cbSize = sizeof(TRACKMOUSEEVENT);tme.dwFlags = TME_HOVER | TME_LEAVE;tme.dwHoverTime = 10;tme.hwndTrack = m_hWnd;_TrackMouseEvent(&tme);m_bIsInWnd = TRUE;}
}void CMyButton::OnMouseHover(UINT nFlags, CPoint point)
{// TODO:  在此添加消息处理程序代码和/或调用默认值HDC hMemDC;HBITMAP bmpMem;HGDIOBJ hOldObj;HDC hDC = ::GetDC(GetSafeHwnd());CRect rcItem;GetClientRect(&rcItem);if (hDC){bmpMem = CreateCompatibleBitmap(hDC, rcItem.Width(), rcItem.Height());if (!bmpMem){::ReleaseDC(GetSafeHwnd(), hDC);return;}hMemDC = CreateCompatibleDC(hDC);if (!hMemDC){if (bmpMem){::DeleteObject(bmpMem);bmpMem = NULL;}::ReleaseDC(GetSafeHwnd(), hDC);return;}hOldObj = ::SelectObject(hMemDC, bmpMem);RECT rectTmp = { 0 };rectTmp = rcItem;MapWindowPoints(GetParent(), &rectTmp);if (m_BkImg.IsNull() == false)m_BkImg.Draw(hMemDC, 0, 0, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top, rectTmp.left, rectTmp.top, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top);int nW = rcItem.right - rcItem.left;int nH = rcItem.bottom - rcItem.top;m_imgFloat.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0,nW,nH);::BitBlt(hDC, 0, 0, nW, nH, hMemDC, 0, 0, SRCCOPY);SelectObject(hMemDC, hOldObj);if (bmpMem){::DeleteObject(bmpMem);bmpMem = NULL;}if (hMemDC){::DeleteDC(hMemDC);hMemDC = NULL;}::ReleaseDC(GetSafeHwnd(), hDC);}CButton::OnMouseHover(nFlags, point);
}void CMyButton::OnMouseLeave()
{// TODO:  在此添加消息处理程序代码和/或调用默认值CButton::OnMouseLeave();InvalidateRect(NULL);m_bIsInWnd = FALSE;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/279738.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

S2-066漏洞分析与复现(CVE-2023-50164)

Foreword 自struts2官方纰漏S2-066漏洞已经有一段时间&#xff0c;期间断断续续地写&#xff0c;直到最近才完成&#xff0c;o(╥﹏╥)o。羞愧地回顾一下官方通告&#xff1a; 2023.12.9发布&#xff0c;编号CVE-2023-50164&#xff0c;主要影响版本是 2.5.0-2.5.32 以及 6.0…

[薅羊毛活动]体验AI编码和开盲盒

​​​​​​​通义灵码 体验 AI 编码&#xff0c;开 AI 盲盒 上面是我的邀请码,直接点击 活动说明 【活动玩法一】“体验AI编码、领取AI盲盒”活动玩法 玩法简述&#xff1a;用户进入活动页面后&#xff0c;随机参与或体验活动页面中通义灵码的任一场景&#xff0c;即可获…

软件测评中心:进行科技成果鉴定测试的注意事项和好处简析

软件产品科技成果鉴定是有效评价科技成果质量和水平的方法之一&#xff0c;也是鼓励科技成果通过市场竞争等方式得到有效的评价和认可&#xff0c;可以推动科技成果的进步和转化。 一、进行科技成果鉴定测试时的注意事项&#xff1a;   1、应由具备一定资质和能力的专业机构…

VS code配置免密连接Linux服务器

1. 服务器端 1.1 安装OpensSSH sudo apt install openssh-server 1.2 开启ssh服务 使用下面的命令查看是否开启了ssh&#xff1a; service ssh status 或者 sudo systemctl status ssh 只要看到绿色高亮的active(running)就是开启了ssh 如果没有开启&#xff0c;则使用…

如何用 Rust Reqwest 写一个Web 爬虫?

用 Rust Reqwest 编写 Web 爬虫 您是否曾考虑过建立自己的 潜在业务数据库&#xff0c;用于潜在客户开发或产品价格数据&#xff0c;以便您可以毫不费力地以最便宜的价格获得产品&#xff1f;网络爬虫可以让您无需亲自执行任何手动工作即可做到这一点。Rust通过允许显式地处理错…

MD5算法:密码学中的传奇

title: MD5算法&#xff1a;密码学中的传奇 date: 2024/3/15 20:08:07 updated: 2024/3/15 20:08:07 tags: MD5起源算法原理安全分析优缺点比较技术改进示例代码应用趋势 MD5算法起源&#xff1a; MD5&#xff08;Message Digest Algorithm 5&#xff09;算法是由MIT的计算机…

【数据结构】哈希表与哈希桶

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.概念 2.哈希冲突…

Vulnhub靶机渗透:DC-7打靶记录

前言 自信自强&#xff0c;来自于不怕苦、不怕难的积淀。宝剑锋从磨砺出&#xff0c;梅花香自苦寒来&#xff1b;任何美好理想&#xff0c;都离不开筚路蓝缕、手胼足胝的艰苦奋斗&#xff01; 靶场介绍 DC-7是一个初中级的靶场&#xff0c;需要具备以下前置知识&#xff1a;…

DevEco Studio 项目创建

安装DevEco Studio后开始使用&#xff0c;双击桌面DevEco Studio 快捷方式弹出界面&#xff1a; 选择Application —> Empty Ability&#xff0c;点击Next 项目配置 Project name&#xff1a;工程的名称&#xff0c;可以自定义&#xff0c;由大小写字母、数字和下划线组成。…

『运维心得』BPC-EPM-AddIn专家看过来

目录 系统版本问题 安装顺序问题 framework问题 vstor_redis问题 dll问题 一个小彩蛋 总结 最近在搞BPC&#xff0c;安装Office所需的EPM-AddIn的过程中&#xff0c;碰到了一些奇怪的问题。 查了BPC专家提供的安装说明文档&#xff0c;文档里要么没有提到我们碰到的问题…

简介:使用TensorFlow实现python简版神经网络模型

如果你想进一步深入AI编程的魔法世界&#xff0c;那么TensorFlow和PyTorch这两个深度学习框架将是你的不二之选。它们可以帮助你构建更加复杂的神经网络模型&#xff0c;实现图像识别、语音识别等高级功能。 模型原理&#xff1a;神经网络是一种模拟人脑神经元结构的计算模型&a…

osgEarth学习笔记3-第二个Osg QT程序

原文链接 打开QT Creator&#xff0c;新建一个窗口项目。 QT版本如下&#xff1a; 修改pro文件 QT core gui greaterThan(QT_MAJOR_VERSION, 4): QT widgets CONFIG c11 DEFINES QT_DEPRECATED_WARNINGS SOURCES \main.cpp \mainwindow.cpp HEADERS \mainwindow…

长安链团队论文入选国际顶会Usenix Security 2024

零知识证明是区块链扩容和隐私保护的关键前沿技术&#xff0c;其天然具备完备性、可靠性和零知识性的特点&#xff0c;是提升区块链交易吞吐量与可扩展性、在验证用户身份的同时保护用户数据隐私&#xff0c;实现复杂计算不可或缺的关键技术。基于零知识证明技术实现高兼容性、…

Linux——进程信号(二)

目录 1、阻塞信号 1.1、信号其他相关常见概念 1.2、在内核中的表示 1.3、sigset_t 1.4、信号集操作函数 2、捕捉信号 2.1、内核如何捕捉信号 5.2、sigaction 1、阻塞信号 1.1、信号其他相关常见概念 实际执行信号的处理动作被称为信号递达&#xff08;Delivery&#x…

迈向容错新时代!PASQAL发布最新技术路线图

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨慕一 编译/排版丨沛贤 深度好文&#xff1a;1200字丨8分钟阅读 近日&#xff0c;法国中性原子量子计算公司PASQAL发布了最新技术路线图&#xff0c;概述了其在硬件、业务场景用例及进一…

v3-admin-vite 整合pont

需求 目前后端的Admin模板使用的是v3-admin-vite&#xff0c;需要整合pont接口&#xff0c;方便前后端统一一体化开发 安装PONT 按照官方的文档&#xff0c;将pont engine安装好&#xff0c;然后在项目根目录执行pont start。注意生成代码路径要修改一下&#xff0c;因为v3-a…

【区间、栈】算法例题

目录 六、区间 48. 汇总区间 ① 49. 合并区间 ② 50. 插入区间 ② 51. 用最少数量的箭引爆气球 ② 七、栈 52. 有效的括号 ① 53. 简化路径 ② 54. 最小栈 ② 55. 逆波兰表达式求值 ② √- 56. 基本计算器 ③ 六、区间 48. 汇总区间 ① 给定一个 无重复元素 的 …

外键约束

目录 外键约束 对数据表进行初期设计&#xff0c;暂时不使用外键 验证限制三 验证级联删除 设置级联更新 Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 外键约束 外键约束主要是在父子表关系中体现的一种约束操作。…

matlab 基于小波变换的油气管道泄露信号检测

1、内容简介 略 71-可以交流、咨询、答疑 基于小波变换的油气管道泄露信号检测 去噪、小波变换、油气管道泄露、信号检测 2、内容说明 摘 要&#xff1a; 油气管道泄漏会造成严重危害&#xff0c;因此&#xff0c;亟需寻找一种能快速检测油气管道信号的技术。传统的 傅里…

Java多线程实战-CompletableFuture异步编程优化查询接口响应速度

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️本系列源码仓库&#xff1a;多线程并发编程学习的多个代码片段(github) &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正…