MFC uses dialog boxes to get input

Posted by Harry57 on Tue, 10 Sep 2019 14:54:10 +0200

subject

The MFC call dialog reads in the data and outputs it in the client area.

This is an exercise in the Basic Course of Computer Graphics:

Using MFC to design a rectangular class CRectangle, call the dialog box to read in the length and width of the rectangle, and output the perimeter and area of the rectangle in the client area.

This book doesn't teach you how to read input using dialog boxes, and I haven't touched MFC dialog boxes at all before. After two hours, I finally worked out the problem. Record it in this article.

Reference link

Design dialog box

Look, MFC doesn't seem to have input() like python or inputBox() like VB, so you have to design your own dialog first.

First, open the Resource View and insert a new dialog box into the right-click menu at the Dialog.

Then you put the control and name it. This is relatively simple, let's not go into details.

The dialog I designed has two Edit controls, one is IDC_LENGTH, which is used to input rectangle's rectangle, and the other is IDC_WIDTH, which is used to input rectangle's width.

[Img-CuwiOdfT-1568119768728 (https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910194014.png)]

New dialog box class

On the designed dialog box, right-click menu to open the class wizard, that is, classWizard, and a dialog box will pop up as follows:

[Img-IEIiMgvC-1568119768729 (https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910194429.png)]

Generally speaking, a new dialog resource has been detected. You may want to create a class for it. Do you want to create a class for it?

Point determination creates a corresponding class.

If this dialog does not pop up, you can also create a class in MFC by using the Add Class button in the upper right corner of the class wizard, adjust the base class to CDialog, and set the Dialog ID to the dialog ID you just designed.

[External Link Picture Transfer Failure (img-c0Z6TtpN-1568119768730)(https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910195108.png)]

(Actually, it's better to add a Dlg suffix after the name to indicate that this is a dialog box, but I'm too lazy to change it.)

Adding Associated Variables

In the class wizard, select the second tab, the Member Bariables member variable tab.

[External Link Picture Transfer Failure (img-0hnIGnM1-1568119768730)(https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910195436.png)]

This lists the ID s of the controls on the dialog box, which can be specified when designing the dialog box.

Select the control used to input data, and then click Add Variable to add the member variables of the dialog class. Change the quantity name, other options are default.

[Img-PKHLHFs6-1568119768730 (https://raw.githubusercontent.com/HaneChiri/PicBed/master/blog_images/20190910200353.png)]

The difference between this operation and what you add directly to the class code is that it establishes a relationship between the control and the member variable. This association is reflected in the member function DoDataExchange() of the custom dialog class:

void CInputRectangle::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CInputRectangle)
	DDX_Text(pDX, IDC_LENGTH, m_edLength);//There are no two lines before adding the associated variable
	DDX_Text(pDX, IDC_WIDTH, m_edWidth);
	//}}AFX_DATA_MAP
}

Call dialog box

As shown in the figure, I intend to use the menu to call the dialog box to enter the rectangle length and width.

The process of adding menus is not detailed.

Jump directly to the menu response function:

void CComputerGraphicsExerciseView::OnHomework2_2() 
{
	// TODO: Add your command handler code here
	
	CInputRectangleDlg inputDlg;
	int nResponse = inputDlg.DoModal();
    if(nResponse==IDOK)
	{
        //Get the input here and output it in the client area.
    }
}

At the beginning of the file, include the header file of the dialog box class, declare the object, and call the DoModal() method of the dialog box object.

This method returns a value only after the dialog box is closed, corresponding to the action of closing the dialog box. Here I use the nResponse int variable to receive the return value.

Then determine the return value. If you click the confirmation button to close the dialog box, then get the input of the dialog box and output it in the client area.

Get input

The variables of the two edit boxes on the binding dialog are m_edWidth and m_edLength. By default, they are CString types, so type conversion is required.

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

Description of the above two lines of code:

  • The two associated variables are public, so they can be accessed directly.
  • CString's GetBuffer() member function returns a string of the corresponding character array type
  • atoi (ASCII to integer) converts strings into integers

Output

Get the device context and adjust the coordinate system:

CDC *pDC=GetDC();//Getting device context

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);//screen

Output data and release device context:

CRectangle crect(width,height);
		
CString perimeter_text,area_text;
perimeter_text.Format("The circumference of a rectangle is:%.2f",crect.perimeter());
area_text.Format("The area of the rectangle is:%.2f",crect.area());

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

ReleaseDC(pDC);//Release device context

That's it.

Menu Code Overview

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);//screen
		
		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("The circumference of a rectangle is:%.2f",crect.perimeter());
		area_text.Format("The area of the rectangle is:%.2f",crect.area());

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

	}

}

Wrong thinking

At first, I thought I needed to write the response event of the ok button in the dialog box. I wrote it as follows. I tried it, but I don't know why.

void CInputRectangleDlg::OnOK() 
{
	// TODO: Add extra validation here
	
	CDialog::OnOK();
	
	UpdateData();//Used to synchronize data from dialog boxes to member variables

	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);//screen
	
	CString perimeter_text,area_text;
	perimeter_text.Format("The circumference of a rectangle is:%.2f",crect.perimeter());
	area_text.Format("The area of the rectangle is:%.2f",crect.area());

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

	ReleaseDC(pDC);

}

Topics: Python ascii