MFC用对话框获取输入

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

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

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

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

参考链接

设计对话框

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

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

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

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

新建对话框类

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

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

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

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

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

添加关联变量

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

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

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

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

1
2
3
4
5
6
7
8
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
}

调用对话框

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

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

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

1
2
3
4
5
6
7
8
9
10
11
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 类型的,因此需要进行类型转换。

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

对上面两行代码的说明:

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

进行输出

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

1
2
3
4
5
6
7
8
9
10
11
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);//清空屏幕

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

1
2
3
4
5
6
7
8
9
10
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);//释放设备上下文

这样就完成了

菜单代码概览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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按钮的响应事件,写成了下面这样,试了一下不行,不知道为什么:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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);

}

作者

憧憬少

发布于

2019-09-10

更新于

2019-09-10

许可协议