MFC用对话框获取输入

题目

在MFC调用对话框读入数据,并在客户区输出。

这是《计算机图形学基础教程》的一个习题:

使用MFC设计一个长方形类CRectangle,调用对话框读入长方形的长度和宽度,在客户区输出长方形的周长和面积。

这个书上并没有教怎么用对话框读取输入,我在这之前也完全没接触过MFC的对话框。弄了两小时,终于把这道题做出来了。以此文记录一下

如果图片转存失败,可以去我个人博客看此文

参考链接

设计对话框

找了一下,MFC似乎没有像python那样的input()或者像是VB里面的inputBox()之类的函数,所以得自己先设计对话框。

首先打开Resource View,在Dialog处右键菜单插入新的对话框。

接着就是放控件以及给控件命名了。这个比较简单,就不详细说了。

我设计的对话框有两个Edit控件,一个是IDC_LENGTH,用于输入长方形的长,一个是IDC_WIDTH,用于输入长方形的宽。

[外链图片转存失败(img-ghTlZDXq-1568120588103)(https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910194014.png)]

新建对话框类

在设计好的对话框上右键菜单打开类向导,也就是classWizard,会弹出一个对话框如下图:

MFC用对话框获取输入

大致意思是:检测到有个新建的对话框资源,你可能想要为它创建一个类,要创建吗?

点确定创建一个对应的类。

如果没有弹出这个对话框,你也可以在类向导右上角的Add Class按钮来创建一个MFC里面的类,把基类调整成CDialogDialog ID设置成你刚刚设计的对话框ID就可以了。

[外链图片转存失败(img-sPpBeQm3-1568120638663)(https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910108.png14)]

(其实命名最好在后面加个Dlg后缀以表示这是对话框,但是我懒得改了)

添加关联变量

在类向导里面选择第二个选项卡,也就是Member Bariables成员变量选项卡。

[外链图片转存失败(img-0hnIGnM1-1568119768730)(https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910195436.png)]

这里面列出了对话框上控件的ID,这些ID可以在设计对话框的时候指定。

选中用于输入数据的控件,然后点击Add Variable添加对话框类的成员变量。改变量名字,其他选项默认即可。

[外链图片转存失败(img-PKHLHFs6-1568119768730)(https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910200353.png)]

这个操作与你直接在类代码中添加的区别是,这个操作会建立起控件和这个成员变量的关联关系。这个关联关系体现在自定义对话框类的DoDataExchange()这个成员函数内:

void CInputRectangle::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CInputRectangle)
	DDX_Text(pDX, IDC_LENGTH, m_edLength);//添加关联变量之前,这里是没有这两行的
	DDX_Text(pDX, IDC_WIDTH, m_edWidth);
	//}}AFX_DATA_MAP
}

调用对话框

如图,我打算使用菜单来调用对话框输入矩形长和宽。

MFC用对话框获取输入

添加菜单的过程不详细说。

直接跳到菜单的响应函数:

void CComputerGraphicsExerciseView::OnHomework2_2() 
{
	// TODO: Add your command handler code here
	
	CInputRectangleDlg inputDlg;
	int nResponse = inputDlg.DoModal();
    if(nResponse==IDOK)
	{
        //这里获取输入并在客户区输出
    }
}

在文件开头include对话框类的头文件,声明对象,并调用对话框对象的DoModal()方法。

这个方法在对话框关闭之后,才会返回一个值,对应关闭对话框的动作,这里我用nResponse这个int变量接收返回值。

接着判断返回值,如果是点击确定按钮关闭对话框,那么获取对话框的输入,并且在客户区输出。

获取输入

绑定对话框上两个编辑框的变量分别为:m_edWidthm_edLength。默认情况下,它们是CString类型的,因此需要进行类型转换。

int width=atoi(inputDlg.m_edWidth.GetBuffer(0));
int height=atoi(inputDlg.m_edLength.GetBuffer(0));

对上面两行代码的说明:

  • 两个关联变量是public的,因此可以直接访问。
  • CString的GetBuffer()成员函数返回对应的字符数组类型的字符串
  • atoi(ASCII to integer)把字符串转换成整型数

进行输出

获取设备上下文,并调整坐标系:

CDC *pDC=GetDC();//获取设备上下文

CRect rect;
GetClientRect(&rect);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(rect.Width(),rect.Height());
pDC->SetViewportExt(rect.Width(),-rect.Height());
pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);
rect.OffsetRect(-rect.Width()/2,-rect.Height()/2);

pDC->Rectangle(rect);//清空屏幕

输出数据,并释放设备上下文:

CRectangle crect(width,height);
		
CString perimeter_text,area_text;
perimeter_text.Format("长方形的周长为:%.2f",crect.perimeter());
area_text.Format("长方形的面积为:%.2f",crect.area());

pDC->TextOut(0,0,perimeter_text);
pDC->TextOut(0,20,area_text);

ReleaseDC(pDC);//释放设备上下文

这样就完成了

菜单代码概览

void CComputerGraphicsExerciseView::OnHomework2_2() 
{
	// TODO: Add your command handler code here
	
	CInputRectangleDlg inputDlg;
	int nResponse = inputDlg.DoModal();
	
	if(nResponse==IDOK)
	{
		
		CDC *pDC=GetDC();

		CRect rect;
		GetClientRect(&rect);
		pDC->SetMapMode(MM_ANISOTROPIC);
		pDC->SetWindowExt(rect.Width(),rect.Height());
		pDC->SetViewportExt(rect.Width(),-rect.Height());
		pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);
		rect.OffsetRect(-rect.Width()/2,-rect.Height()/2);
		
		pDC->Rectangle(rect);//清空屏幕
		
		int width=atoi(inputDlg.m_edWidth.GetBuffer(0));
		int height=atoi(inputDlg.m_edLength.GetBuffer(0));
		CRectangle crect(width,height);
		
		CString perimeter_text,area_text;
		perimeter_text.Format("长方形的周长为:%.2f",crect.perimeter());
		area_text.Format("长方形的面积为:%.2f",crect.area());

		pDC->TextOut(0,0,perimeter_text);
		pDC->TextOut(0,20,area_text);
		
		ReleaseDC(pDC);

	}

}

错误思路

一开始我以为需要编写对话框的ok按钮的响应事件,写成了下面这样,试了一下不行,不知道为什么:

void CInputRectangleDlg::OnOK() 
{
	// TODO: Add extra validation here
	
	CDialog::OnOK();
	
	UpdateData();//用于将数据从对话框同步到成员变量中

	int width=atoi( m_edWidth.GetBuffer(0));
	int height=atoi( m_edLength.GetBuffer(0));
	CRectangle crect(width,height);

	
	CDC *pDC=GetDC();

	CRect rect;
	GetClientRect(&rect);
	pDC->SetMapMode(MM_ANISOTROPIC);
	pDC->SetWindowExt(rect.Width(),rect.Height());
	pDC->SetViewportExt(rect.Width(),-rect.Height());
	pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);
	rect.OffsetRect(-rect.Width()/2,-rect.Height()/2);
	
	pDC->Rectangle(rect);//清空屏幕
	
	CString perimeter_text,area_text;
	perimeter_text.Format("长方形的周长为:%.2f",crect.perimeter());
	area_text.Format("长方形的面积为:%.2f",crect.area());

	pDC->TextOut(100,100,perimeter_text);
	pDC->TextOut(100,300,area_text);

	ReleaseDC(pDC);

}

上一篇:WinHand.cpp Line 199 错误 WinHand.cpp Line 218 错误


下一篇:关于Ignition的白名单明细和IDO详情说明.