【MFC】添加对话框,实现D配版画图功能

2024-01-03 11:50

本文主要是介绍【MFC】添加对话框,实现D配版画图功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、什么是对话框

二、模式对话框

1.添加打开菜单

2.添加Dialog对话框资源

3.获取线条宽度

1.对话框获取线条宽度

2.滑块框获取

4.模拟动画图标

5.选项框颜色

6.示例效果


我在上篇文章中已经搞定了绘制一些简单图形的功能👉使用MFC做一个低配版画图软件,但是绘制图形的线条样式都是固定的,那么有没有方法能够保证可以随时改变这样线条样式呢?本篇,我将使用对话框来实现动态的样式改变。

最终效果

在开始撸码之前,我们要首先了解一下什么是对话框

一、什么是对话框

与用户进行交互的控件,如文件对话框,字体对话框,颜色对话捐给等,一般用于搞事,提醒等。

大体上说就是一种和用户交互的单独窗口,在这里我为大家介绍其中的一个对话框——模式对话框

二、模式对话框

模式对话框在其显示时,整个程序会暂停,直到关闭该对话框,我们上面使用的就是模式对话框。

1.添加打开菜单

首先我们添加一个打开模式对话框的菜单

编辑菜单和ID

给菜单项添加COMMAND消息事件

2.添加Dialog对话框资源

3.获取线条宽度

我们先搞定调节线条宽度的功能,在这里为大家提供两种方法,一种是通过文本对话框获取;另一种是滑块框获取。

1.对话框获取线条宽度

采用文本方式获取线条宽度Static Text 和 Edit Control

第一步:添加控件并更改控件描述,给对话框资源添加ID为 ID_DLG_SETUP

第二步:绑定对话框资源

给对话框资源添加一个类

第三步:补充消息处理函数并测试

void CMFCApplication6View::OnTypeSetup()
{//弹出对话框选项Setup conf;//调用成员函数的调用 模式对话框并返回对话框结果conf.DoModal();
}

测试

第四步:获取文本框输入内容

给文本编辑框绑定变量

第五步:补充消息处理函数,将文本框中获取数据放入设置画笔函数中

m_nLineWidth为view类成员变量,存储画笔宽度

void CMFCApplication6View::OnTypeSetup()
{//弹出对话框选项Setup conf;//调用成员函数的调用 模式对话框并返回对话框结果//conf.DoModal();//每次进入对话框时,文本框显示的是上一次设置的画笔宽度conf.m_nLineWidth = m_nLineWidth;//用户按下“确定”按钮 DoModal()返回 IDOKif (IDOK == conf.DoModal()) {m_nLineWidth = conf.m_nLineWidth;}
}

测试

2.滑块框获取

第一步:添加Slider Control控件

自动打勾:指定滑块在其值范围内对于每一个增量都有一个刻度线

打勾标记:指定滑块显示刻度线

工具提示:滑块滑到某个位置时显示其值

第二步:设置滑块范围

通过类向导添加OnInitDialog虚函数,也可以直接右击滑块控件添加(更方便)

在虚函数中

BOOL Setup::OnInitDialog()
{CDialogEx::OnInitDialog();//获得滑块控件//GetDlpItem传入ID,获得相应的控件或窗口CSliderCtrl* slider = (CSliderCtrl*)GetDlgItem(IDC_SLIDER1);//修改滑块属性slider->SetRange(1, 30);return TRUE;  // return TRUE unless you set the focus to a control// 异常: OCX 属性页应返回 FALSE
}

其中GetDlgItem返回CWnd* 类型,要将其强转成CSliderCtrl*类型

测试

第四步:获取滑块的值

剩下的操作与上面的文本对话框一样,也是给滑块和view类分别添加成员变量,用来存储画笔宽度

测试

4.模拟动画图标

完成调节线条宽度后接着就是更改画笔样式,画笔样式使用按钮来让用户选择。

第一步:添加:Group Box

在对话框中添加一个Group Box,并修改其标题为“线型”。Group Box起到一个框框的作用,让接下来添加的按钮看起来是一组的。

如下效果

第二步:添加Radio Button

接着添加三个单选按钮Radio Button,并按上面同样方法求改其描述

此时这三个按钮代表三组选项(也就是可以一次选多个),而我们只是想让用户一次只能选择一个,那么我们就要将三个按钮绑定为一组

第三步:按钮绑定为一组

选择第一个按钮,将其“组”属性改为TRUE,那么从这个按钮往下都会成为一组,直到有下一个“组”出现。这个时候这三个选项就会变成一组,每次也只能选择一项。

第四步:添加成员变量

这个时候我们就可以为这一组添加一个成员变量来记录用户选择的是哪一个按钮。

 同样在view文件中也按此方式添加,用来接收对话框中的值

第五步:补充消息处理函数

void CMFCApplication6View::OnTypeSetup()
{//弹出对话框选项Setup conf;//调用成员函数的调用 模式对话框并返回对话框结果//conf.DoModal();//每次进入对话框时,文本框显示的是上一次设置的画笔宽度conf.m_nLineWidth = m_nLineWidth;conf.m_nLineStyle = m_nLineStyle;//用户按下“确定”按钮 DoModal()返回 IDOKif (IDOK == conf.DoModal()) {m_nLineWidth = conf.m_nLineWidth;m_nLineStyle = conf.m_nLineStyle;}
}

当用户选择了第一个按钮会返回0,选择第二个按钮会返回1,依次类推,而PS_SOLID定义的表示也正好是从0开始的,所以我们可以直接将m_nLineStyle填入所有的画笔设置函数中即可

最终效果

5.选项框颜色

选项框颜色我决定不直接将显示在对话框内,而是通过一个按钮,当用户点击按钮时才去打开颜色对话框

添加一个按钮Button,修改其标题为“颜色”

下面就是给按钮添加相应事件,添加相应事件对快捷的方法就是双击按钮,当然也可以通过类向导来添加

void Setup::OnBnClickedButton1()
{//打开颜色对话框CColorDialog colDlg;colDlg.DoModal();
}

测试

按照同样的方法,分别给控件和view 类添加成员变量,再将相应函数补充完整。

void Setup::OnBnClickedButton1()
{//打开颜色对话框CColorDialog colDlg;colDlg.DoModal();if (IDOK == colDlg.DoModal()) {//返回选中的颜色m_color = colDlg.m_cc.rgbResult;}
}
void CMFCApplication6View::OnTypeSetup()
{//弹出对话框选项Setup conf;//调用成员函数的调用 模式对话框并返回对话框结果//conf.DoModal();//每次进入对话框时,文本框显示的是上一次设置的画笔宽度conf.m_nLineWidth = m_nLineWidth;conf.m_nLineStyle = m_nLineStyle;conf.m_color = m_color;//用户按下“确定”按钮 DoModal()返回 IDOKif (IDOK == conf.DoModal()) {m_nLineWidth = conf.m_nLineWidth;m_nLineStyle = conf.m_nLineStyle;m_color = conf.m_color;}
}

 再将程序中设置画笔颜色改为m_color就可以了

与上面添加控件不同的是,我们使用按钮进行颜色选择时是弹出了一个新的对话框,这就导致我们不能像上面那样在view里的相应事件函数中使用conf.m_color = m_color;来保证每次打开都会显示上一次的选择结果(上面那种方式每次打开颜色对话框时都会停留在黑色位置)

我们需要在对应的颜色框响应函数中修改(内容也略微有所不同)

void Setup::OnBnClickedButton1()
{//打开颜色对话框CColorDialog colDlg;colDlg.m_cc.Flags |= CC_RGBINIT;colDlg.m_cc.rgbResult = m_color;if (IDOK == colDlg.DoModal()) {//返回选中的颜色m_color = colDlg.m_cc.rgbResult;}
}

这样就能保证每次打开颜色框时都是保留上次选择的颜色

6.示例效果

每次用户更改线条样式时都会在“示例”区绘制出线条样式。

给对话框添加Group Box,并更改其标题为“示例”

当我们修改线型或者粗细或者颜色时,示例框中的线条也要跟着改变,这就需要我们给这些调整线条样式的控件添加响应函数

我们先给选择线条样式的三个按钮添加

void Setup::OnBnClickedRadio1()
{}void Setup::OnBnClickedRadio2()
{}void Setup::OnBnClickedRadio3()
{}

 每当这些控件发生改变时,就要在“示例”区重新绘制线条,所谓重新绘制,也就是说之气的那个“页面”(对话框页面)不需要了,可以去掉了。Invalidate() 默认参数为TRUE,也就是先发送背景刷新消息,再刷新前景

void Setup::OnBnClickedRadio1()
{//指定是否清除在更新区域内的背景//使窗口内容无效//每当这些控件发生改变时就要去重新绘制线,所谓重新绘制,就是之前的不需要了,可以去掉了//Invalidate( )可以使得当前的区域无效,就要去重新绘制Invalidate();
}void Setup::OnBnClickedRadio2()
{Invalidate();
}void Setup::OnBnClickedRadio3()
{Invalidate();
}

给控件类(Setup)添加WM_PAINT消息

void Setup::OnPaint()
{CPaintDC dc(this); // device context for painting// TODO: 在此处添加消息处理程序代码// 不为绘图消息调用 CDialogEx::OnPaint()//在示例区域绘制一条线CPen pen(m_nLineStyle, m_nLineWidth, m_color);CPen* pOldPen = dc.SelectObject(&pen);//获得“示例”区位置(通过“示例”的ID)“示例”区ID为IDC_SAMPLECRect rect;//得到对话框某一组件或控件的实例,并通过GetWindowRect将组件坐标信息存入到rect中GetDlgItem(IDC_SAMPLE)->GetWindowRect(&rect);//GetWindowRect得到的是屏幕坐标,而我们想要的是工作区坐标,因此需要转换ScreenToClient(rect);//不要太靠近左右边,与左右边相差20距离dc.MoveTo(rect.left + 20, rect.top + rect.Height() / 2);dc.LineTo(rect.right - 20, rect.top + rect.Height() / 2);dc.SelectObject(pOldPen);
}

这个时候在“示例”区中已经显示了直线,但是当我们选择线型时直线却没有改变,原因在于虽然我们在下面代码中已经 将控件ID和成员变量绑定,但是在OnPaint()函数中这个还没有生效

void Setup::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);//数据交换,传入控件ID和变量,将控件值绑定到变量中DDX_Slider(pDX, IDC_SLIDER1, m_nLineWidth);DDX_Radio(pDX, IDC_RADIO1, m_nLineStyle);
}

我们需要在OnPaint()中增添UpdateData(); 实现同步控件和绑定的成员变量

void Setup::OnPaint()
{CPaintDC dc(this); // device context for painting// TODO: 在此处添加消息处理程序代码// 不为绘图消息调用 CDialogEx::OnPaint()//同步控件和绑定的成员变量UpdateData();//在示例区域绘制一条线CPen pen(m_nLineStyle, m_nLineWidth, m_color);CPen* pOldPen = dc.SelectObject(&pen);//获得“示例”区位置(通过“示例”的ID)CRect rect;//得到对话框某一组件或控件的实例,并通过GetWindowRect将组件坐标信息存入到rect中GetDlgItem(IDC_SAMPLE)->GetWindowRect(&rect);//GetWindowRect得到的是屏幕坐标,而我们想要的是工作区坐标,因此需要转换ScreenToClient(rect);//不要太靠近左右边,与左右边相差20距离dc.MoveTo(rect.left + 20, rect.top + rect.Height() / 2);dc.LineTo(rect.right - 20, rect.top + rect.Height() / 2);dc.SelectObject(pOldPen);
}

接下来就是同样的方法,当颜色或者线条粗细发生改变时也要去重新绘制线条

在颜色对话框中,当有colDlg.DoModal() = IDOK就要重新绘制,添加Invalidate( )

void Setup::OnBnClickedButton1()
{//打开颜色对话框CColorDialog colDlg;colDlg.m_cc.Flags |= CC_RGBINIT;colDlg.m_cc.rgbResult = m_color;if (IDOK == colDlg.DoModal()) {//返回选中的颜色m_color = colDlg.m_cc.rgbResult;Invalidate();}
}

滑块有水平滑动和垂直滑动两个事件,而我们的调节线条粗细使用的是水平滑动。如果我们要捕获这个动作,则需要添加WM_HSCROLL消息处理函数

void Setup::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{//响应滑块控件的水平移动消息Invalidate();CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}

最后这个对话框功能就大功告成了

这篇关于【MFC】添加对话框,实现D配版画图功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/565603

相关文章

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、