首页 > 其他分享 >MFC自定义按钮实现

MFC自定义按钮实现

时间:2024-08-15 19:05:52浏览次数:8  
标签:MFC 自定义 rc bOne 按钮 DT pDC rect

MFC中要实现自定义按钮,首先要创建一个类并继承自CButton。我这里创建的类名为CMainButton

class CMainButton : public CButton
{
	DECLARE_DYNAMIC(CMainButton)

public:
	CMainButton(UINT nID,CRect rcWnd,CWnd* pParent=nullptr);//nID为按钮ID,rcWnd为按钮位置
	virtual ~CMainButton();
	void SetInvalid();   //调用了_SetInvalidPt(m_clickPoint)
protected:
	bool IsValidPt(const CPoint& pt) const;  //pt是否有效,当pt的x和y都大于等于0时,程序认为有效。
        // 主要为m_clickPoint服务,因为是在客户区点击,故不可能点击到x小于0或y小于0的位置
        // 返回true表示之前点击了鼠标左键
	int GetFontPtSize() const;//自定义实现的按钮默认可以调整大小,根据按钮大小返回自适应内容字体大小
	void _SetInvalidPt(CPoint& pt); //让pt无效
	CString m_strOne;  //单态(m_bOne为true)下,显示的窗口内容

	/// <summary>
	/// 3-triState
	/// </summary>
	CString m_strLeft;   //三态(m_bOne为false)下,最左边显示的窗口内容
	CString m_strCenter; //三态(m_bOne为false)下,中间显示的窗口内容
	CString m_strRight;  //三态(m_bOne为false)下,最右边显示的窗口内容
	BOOL m_bOne;    //m_bOne为true,表示单态,为false,表示多态
	CRect m_rcLeft;  //三态(m_bOne为false)下,最左边显示的窗口区域
	CRect m_rcCenter;//三态(m_bOne为false)下,中间显示的窗口区域
	CRect m_rcRight;//三态(m_bOne为false)下,最右边显示的窗口区域
protected:
	DECLARE_MESSAGE_MAP()
public:
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
private:
	CPoint m_clickPoint; // 鼠标点击位置
public:
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
};

要实现自绘,还需要在调用Create时传窗口风格,传递的风格中要加上BS_OWNERDRAW风格,如果没有BS_OWNERDRAW风格,窗口不会调用DrawItem实现程序员的自绘操作。在我实现的控件中,将类与窗口绑定,类创建时窗口也创建了,类消亡时窗口也销毁了。实现如下:

CMainButton::CMainButton(UINT nID, CRect rcWnd, CWnd* pParent)
{
	m_strOne = _T("选择");
	m_strLeft = _T("分割文件");
	m_strCenter = _T("取消");
	m_strRight = _T("合并文件");
	DWORD dwStyle =WS_VISIBLE | BS_PUSHBUTTON | BS_OWNERDRAW;
	if (pParent){
		dwStyle |= WS_CHILD;
	}
	Create(m_strOne, dwStyle, rcWnd, pParent, nID);
	m_bOne = TRUE;
	SetInvalid();
}
CMainButton::~CMainButton()
{
	DestroyWindow();
}

加上了这个风格后,下面我们来看看自绘操作DrawItem

void CMainButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); // 获取设备上下文
	RECT rect = lpDrawItemStruct->rcItem; // 获取绘制区域
	UINT state = lpDrawItemStruct->itemState; // 获取按钮状态

	CFont wndFont;
	int ptFontSize = GetFontPtSize(); //根据窗口大小计算窗口内容文字大小
	wndFont.CreatePointFont(ptFontSize, _T("微软雅黑"));
	CFont* pOldFont = pDC->SelectObject(&wndFont);
	COLORREF buttonColor = GetSysColor(COLOR_BTNFACE); //获取按钮背景色
	if (m_bOne){//单态按钮状态下的绘制
	  if (state & ODS_SELECTED) {
		pDC->DrawText(m_strOne, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 绘制文本
		pDC->DrawEdge(&rect, EDGE_SUNKEN, BF_RECT); // 按钮按下时的边框
		if (IsValidPt(m_clickPoint)){
		  m_bOne = FALSE;
		}
	  }
	  else {
		pDC->FillSolidRect(&rect, buttonColor);
		pDC->DrawText(m_strOne, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 绘制文本
		pDC->DrawEdge(&rect, EDGE_RAISED, BF_RECT); // 按钮未按下时的边框
	  }
	}
	else {
		int width = rect.right - rect.left;
		int perWidth = width / 3;
		if (state & ODS_SELECTED) {
			if (m_rcCenter.PtInRect(m_clickPoint)) {
				m_bOne = TRUE;
			}
			if (IsValidPt(m_clickPoint)) { //说明经过了LButtonDown,左键单机了
				for (int i = 0; i < 3; i++) {
					CRect rc(rect.left + perWidth *i, rect.top, rect.left + perWidth * (i + 1), rect.bottom);
					if (i == 0) {
						pDC->DrawText(m_strLeft, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 绘制文本
					}
					else if (i == 1) {
						pDC->DrawText(m_strCenter, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 绘制文本
					}
					else if (i == 2) {
						pDC->DrawText(m_strRight, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 绘制文本
					}
					if (rc.PtInRect(m_clickPoint)) {
						pDC->DrawEdge(&rc, EDGE_SUNKEN, BF_RECT); // 按钮按下时的边框
						_SetInvalidPt(m_clickPoint);
					}
				}
			}
		}
		else {
			for (int i = 0; i < 3; i++) {
				CRect rc(rect.left + perWidth * i, rect.top, rect.left + perWidth * (i + 1), rect.bottom);
				if (i==0){
					pDC->DrawText(m_strLeft, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 绘制文本
					m_rcLeft = rc;
				}
				else if (i == 1) {
					pDC->DrawText(m_strCenter, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 绘制文本
					m_rcCenter = rc;
				}
				else if (i == 2) {
					pDC->DrawText(m_strRight, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 绘制文本
					m_rcRight = rc;
				}
				pDC->DrawEdge(&rc, EDGE_RAISED, BF_RECT); // 按钮未按下时的边框
			}
		}
	}
}

标签:MFC,自定义,rc,bOne,按钮,DT,pDC,rect
From: https://www.cnblogs.com/dxy-blog/p/18361519

相关文章

  • C语言学习笔记 Day13(复合类型/自定义类型)
    Day13 内容梳理:目录Chapter9 复合类型(自定义类型)9.1结构体(1)结构体变量定义、初始化(2)嵌套结构体(3)结构体赋值(4)结构体和指针(5)结构体做函数参数9.2共用体(联合体)9.3枚举9.4typedef关键字Chapter9 复合类型(自定义类型)9.1结构体有时需要将不同类型的数组......
  • allure报告自定义logo图片和文字
    有时根据项目需要把allure报告的logo换成公司的,步骤如下:1、将自定义的logo图片放到static文件夹中,尺寸大小100*100D:\allure-2.13.9\plugins\custom-logo-plugin\static      2、编辑styles.css文件。    修改和增加如下css:.side-nav__brand{......
  • 全面掌握 Spring Cloud LoadBalancer:从自定义到策略优化的实战教程
    引言在微服务架构中,负载均衡是保障系统高效运行的关键技术之一。无论是服务端负载均衡还是客户端负载均衡,合理的负载均衡策略都能显著提升系统的稳定性和响应速度。本文将从基础概念入手,详细讲解如何在SpringCloud中实现和优化负载均衡,并结合实际案例,帮助读者快速上手并......
  • 自定义JSON名
    lSer:=TMVCJsonDataObjectsSerializer.Create;trylSer.DataSetToJsonArray(MasterDBHelper.Query,lJObj.a['m'],TMVCNameCase.ncLowerCase,[],procedure(constaField:TField;constaJsonObject:TJSONObject......
  • 【Qt笔记】键盘控制Qt按钮
    目录一、前言二、初始化三、键盘移动后需要选中哪个按钮四、键盘按键处理函数五、实现效果一、前言Qt框架支持通过键盘输入来间接控制界面元素,如按钮,实现无需鼠标操作的交互方式。这通常涉及到键盘事件的监听与处理,比如监听特定的按键事件(如空格键、回车键等),并在这些......
  • 自定义Starter
    pom.xml<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://mave......
  • 点击识别按钮调用后端接口,中途按下结束识别,但是识别还是进行啦js
    在JavaScript中,如果你想要在点击按钮后调用一个接口,并且在这个过程中按下一个按钮来中断或取消这个请求,你可以使用fetchAPI来发起请求,并使用AbortController来取消这个请求。以下是一个简单的例子://获取按钮元素conststartButton=document.getElementById('startButton');......
  • 自定义小灯状态翻转函数
    一、函数原理   函数主要是通过 uint8_tGPIO_ReadInputDataBit(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin)这个读取指定的I/O口的电平,来实现小灯状态的翻转。二、示例代码voidLED_Blue_Turn(void){ if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0) { GPIO_Se......
  • apisix-dashboard上添加自定义插件
    参考:https://overstarry.vip/posts/apisix如何添加自定义插件/首先,我们需要向自定义的插件user-remote-auth添加到apisix中,对这块不清楚的同学,可以参考我这篇文章:【apisix~lua插件开发与插件注册】,添加成功之后,通过curlhttp://apisix-admin.apisix:9180/apisix/admin/plugins/us......
  • WebApi 简单使用 JObject,可以省掉自定义的class类
    post提交的json数据:{"name":"Jason","age":18,"color":"blue"}usingNewtonsoft.Json.Linq;[HttpPost("testpost")]publicstringTestPost([FromBody]Objectinput){......