MFC绘图——金刚石
2022-09-18
运行结果图:
点击上面的红色图标后:
点击“确定”后:
绘图步骤:
(1)打开vs,点击“文件”,点击“新建”,点击“项目”。填写项目名称,例如:“adamas”,修改存放的路径,点击“下一步”。“应用程序类型”选择“单个文档”,“项目样式”选择“MFC standard”,点击“完成”。
(2)为运行结果图添加菜单与按钮的步骤:
创建菜单:
首先,找到“资源”,点击,找到“其他窗口”,点击“资源视图”。在“资源视图”栏中点击“adamas”,展开后,点击“adamas.rc”,找到“menu”文件夹后点击,展开后,点击“IDR_MAINFRAME”。
将“IDR_MAINFRAME”中的菜单栏多余的部分删除,只留下“文件(F)”,“帮助(H)”。在“文件”的下拉菜单中只留下“退出(X)”。在“文件”,“帮助”菜单的后面添加“图形(D)”,在“图形(D)”的下拉框中添加“绘图”。样式如下:
改变菜单中“绘图”的属性。选中“绘图”,右击,“属性”,在右面的属性栏中找到ID,将其ID改为“IDM_DRAWPIC”。
---------------------------------------------------------------------
创建图标:
在“资源视图”中,点击“toolbar”文件夹,在出现的图标中,第一行不需要的图标都拖到第二行的坐标去掉,在最后一个空白的图标中使用工具栏中的铅笔工具绘制一个红色的绘图图标。之后选中该图标,右击“属性”,在右边的属性栏中找到"ID",将“ID”改为“IDM_DRAWPIC”。
(3)添加一个对话框的步骤:
找到“资源视图”,点击“Dialog”文件夹,右击“添加资源”,点击“新建”。在对话框中添加工具,找到左边的“工具栏”,点击。将“Static Text”拖动到对话框中,要添加两回,因此拖动两次。先随意放到对话框中的任意位置。将工具栏中的“Edit Control”同理也添加两次。在对话框中有一个“确定”和一个“取消”按钮。选中“取消”按钮,按键盘上的“Delete”键删除。
在对话框中,选中其中一个“Static Text”,右击“属性”,找到“Caption”,将其右边的“static”改为“等分点的个数”。同样的方式,将另一个“Static Text”的显示名称改为“圆的半径”。如下图:
双击此对话框,在弹出的“添加MFC类”框中,输入要添加的类,例如:“CInputDlg”,点击“确定”。
为输入对话框成员变量,点击“项目”,点击“类向导”。将“类名”定位到“CInputDlg”,点击“成员变量”,双击第一个控件“IDC_EDIT1”,在弹出的“添加控件”的框中,“类别”选择“值”、“名称”写为“m_n”、“变量类型”写为“int”,在“控件”的下面点击“其他”,在这儿,“最小值”设为“5”、“最大值”设为“50”,点击“完成”。如下:
控件2按照同样的方式,双击“IDC_EDIT2”,在弹出的“添加控件”的框中,“类别”选择“值”、“名称”写为“m_r”、“变量类型”写为“double”,在“控件”的下面点击“其他”,在这儿,“最小值”设为“200.0”、“最大值”设为“320.0”,点击“完成”。
(4)给对话框的源文件编写代码
首先在构造函数中,设置“圆的半径”为“300.0”,“圆的等分点”为“30”。找到“解决方案资源管理器”,点击“源文件”文件夹,点击“CInputDlg.cpp”。在构造函数中初始化内容。
1 CInputDlg::CInputDlg(CWnd* pParent /*=nullptr*/) 2 : CDialogEx(IDD_DIALOG1, pParent) 3 , m_n(0) 4 , m_r(0) 5 { 6 m_n = 30; 7 m_r = 300.0; 8 }
设计“编辑框”的初始状态为选中状态。步骤:
点击“项目”,点击“类向导”,将类名定位到“CInputDlg”,点击“消息”,在“搜索框”中搜索“ShowWindow”,在下面的栏中,双击出现的选项“WM_SHOWWINDOW”,将其添加到右边的“现有处理程序”中。在右边的“现有处理程序”中选中“OnShowWindow”,点击右边的“编辑代码”的选项。代码如下:
1 void CInputDlg::OnShowWindow(BOOL bShow, UINT nStatus) 2 { 3 CDialogEx::OnShowWindow(bShow, nStatus); 4 5 // TODO: 在此处添加消息处理程序代码 6 GetDlgItem(IDC_EDIT1)->SetFocus();//将光标移动到控件1(IDC_EDIT1)的编辑框()edit中 7 ((CEdit *)GetDlgItem(IDC_EDIT1))->SetSel(0, -1);//表示编辑控件中的全部文本被选中 8 9 }
(5)添加一个二维点类
点击“项目”,点击“添加类”,类名设置为“CP2”。在头文件中添加成员变量x、y,在它的源文件中的构造函数,设置x、y的初始值为0.
CP2.h文件
1 #pragma once 2 class CP2 3 { 4 public: 5 CP2(void); 6 ~CP2(void); 7 public: 8 double x; 9 double y; 10 };
CP2.cpp文件
1 #include "pch.h" 2 #include "CP2.h" 3 CP2::CP2(void) { 4 x = 0; 5 y = 0; 6 } 7 8 CP2::~CP2(void) { 9 }
(6)打开“adamasView.h”文件,添加成员变量与函数
添加“CP2.h”头文件
#include"CP2.h"
添加成员变量,在第三个“protected:”下面添加
1 protected: 2 CP2 *p;//动态数组p 3 int n;//等分点的个数 4 double r;//圆的半径
添加绘制金刚石的函数,在从上往下数的第二个“public:”下面添加一行代码
void Diamond();
(7)对菜单栏中的“绘图”选项添加“事件处理程序”,并编写代码
选择“资源视图”,点击“Menu”文件夹,点击“IDR_MAINFRAME”,找到“绘图”,选中,右击“添加事件处理程序”,在弹出的框中“类列表”选择“CadamasView”,点击“确定”。
OnDrawpic函数
1 void CadamasView::OnDrawpic() 2 { 3 // TODO: 在此添加命令处理程序代码 4 CInputDlg dlg; 5 if (IDOK == dlg.DoModal()) { 6 n = dlg.m_n; 7 r = dlg.m_r; 8 } 9 else 10 { 11 return; 12 } 13 RedrawWindow(); 14 p = new CP2[n]; 15 Diamond(); 16 delete[]p; 17 }
说明:
第4行代码,定义了一个“CInputDlg”类(对话框)的对象。
第5行代码“dlg.DoModal”是指显示一个“模态对话框”,“模态对话框”是值如果我们想要执行其他的应用程序时,必须点击该弹出来的“模态对话框”中的“确定”或者点击“叉号”,对该对话框进行相应。“IDOK”是指如果用户点击了“确定”后执行的代码。
第6,7行代码指的是将对话框接收到的“等分点的个数”与“圆的半径”传到内部函数中,进行信息处理。第9-12行代码表示,如果用户在弹出的“模态对话框”中选择点击模态对话框的“叉号”,则不做操作。
第13行代码“RedrawWindow()”表重绘窗口函数,应该是指在弹出的“模态对话框”选择后,进行对函数后台的处理,按照不同的选择进行重新刷新。
第14行代码指的是按照在对话框中输入的“等分点的个数n”进行动态的创建一个一维数组,存放传进来的数字。
第15行绘制金刚石的函数。
第16行在程序末尾,将动态数组占用的空间释放。
Diamond函数代码:
1 void CadamasView::Diamond() { 2 CDC *pDC = GetDC(); 3 CRect rect; 4 GetClientRect(&rect); 5 pDC->SetMapMode(MM_ANISOTROPIC); 6 pDC->SetWindowExt(rect.Width(), rect.Height()); 7 pDC->SetViewportExt(rect.Width(), -rect.Height()); 8 pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2); 9 rect.OffsetRect(-rect.Width() / 2,-rect.Height() / 2); 10 CPen NewPen, *pOldPen; 11 NewPen.CreatePen(PS_SOLID, 1, RGB(255,215 , 0)); 12 pOldPen = pDC->SelectObject(&NewPen); 13 double Alpha, Theta; 14 Theta = 2 * PI / n; 15 Alpha = PI / 2 - Theta; 16 for (int i = 0; i < n; i++) { 17 p[i].x = r * cos(i*Theta + Alpha); 18 p[i].y = r * sin(i*Theta + Alpha); 19 } 20 for (int i = 0; i <= n - 2; i++) { 21 for (int j = i + 1; j <= n - 1; j++) { 22 pDC->MoveTo(round(p[i].x), round(p[i].y)); 23 pDC->LineTo(round(p[j].x), round(p[j].y)); 24 } 25 } 26 pDC->SelectObject(pOldPen); 27 NewPen.DeleteObject(); 28 ReleaseDC(pDC); 29 }
说明:
第2行代码中使用GetDC()函数创建了一个CDC类的对象,CDC类的对象调用CDC内部的成员函数可以完成大部分的绘图操作。*pDC是一个指针,可用于将其他内容选入设备上下文。
第3行代码创建了一个矩形,第4行代码是将创建好的矩形作为参数传入“GetClientRect”客户区矩形的函数中。此处,客户区矩形与窗口矩形的区别是:窗口矩形包含客户区矩形,客户区矩形是不包含外框和菜单栏的。
第5行代码“SetMapMode”表示的是设置映射模式。什么是映射模式?通俗地说,映射模式就是指将输入内容x,y大小与显示器和打印机输出的图形的大小转变为一致。即将输入的逻辑单位(一般是英尺或者毫米)与输出的物理单位(一般数像素或者是点阵数)转化为一致的。“ MM_ANISOTROPIC”是一种映射模式,指的是“ 用户定义的值,但是x和y方向任意”。
第6行代码“SetWindowExt”是指设置窗口的宽和高。是逻辑单位的大小。
第7行代码“SetViewportExt”是指设置视图的尺寸。指的是物理单位。此处,将x轴的方向设置为从左向右,将y轴的方向设置为从下到上。
第8行代码,设置视图中心点的位置,中心点位于客户区宽度的一半,客户区高度的一半。
第9行代码,是指客户区与矩形重合。
第10行代码定义了一个新画笔、一个旧画笔的指针。第11行创建了一个新画笔,实线、1像素、金色。第12行将新画笔选入设备上下文即显示在显示器上,不使用系统默认的画笔(系统默认的画笔是实线、1像素、黑色)。
第13行定义了两个变量。Theta:等分角的度数。Alpha:起始角。第14行,使用PI时,要在上面声明一个宏。
#define PI 3.14
第16-19行,依次找到所有等分点的x、y坐标。
第20-25行,依次将各个等分点与其他等分点连接。第22行,使用round函数时,要添加一个头文件。
#include<math.h>
第26行恢复设备上下文,即将原来系统默认的画笔恢复。第27行删除新创建的画笔。第28行释放设备上下文占用的资源。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南