[MFC]DlgDemo1程序:基本的模态对话框

本文档详细介绍了如何在MFC应用程序中实现一个基本的模态对话框,包括步骤和代码实现。DlgDemo1程序展示了一个基于视图的MFC程序,通过菜单中的Options选项打开对话框,用户可以输入矩形的宽高和选择显示单位。对话框包含OK、Cancel和Reset按钮,重置按钮用于恢复默认设置,而OK则更新视图中的矩形并关闭对话框。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 接下来所演示的DlgDemo1程序将演示基本的模态对话框的使用:

    1) 该程序是基于视图的MFC程序;

    2) 视图左上角将显示一个粉红色的矩形;

    3) 菜单“文件”中有一个Options菜单项,点击后可以打开一个对话框;

    4) 对话框中可以输入想设定的矩形的宽和高(范围必须在1 ~ 128内);

    5) 还可以选择显示模式(英寸、厘米、像素,是一组单选按钮);

    6) 退出按钮就是默认的OK和Cancel;

    7) 还有一个重置按钮Reset,点击后会把宽、高、显示模式重置为默认值(4、2和英寸),但是不关闭对话框,仅仅是控件中的数据发生变化;

    8) OK保存后退出对话框,视图中的矩形将会按照用户在对话框中的设置重新显示;

!!工程建立的步骤还是和之前的一样,只不过需要添加一个类COptionsDlg类,以及相应的文件OptionsDlg.h和OptionsDlg.cpp


2. 资源脚本CD了刚Demo1.rc:

    1) 菜单项Options的定义:

IDR_MAINFRAME MENU PRELOAD DISCARDABLE 
BEGIN
	POPUP "文件(&F)"
	BEGIN
		MENUITEM "退出(&X)",                       ID_APP_EXIT
		MENUITEM "&Options...",			ID_FILE_OPTIONS
	END
!!注意,必须加...表示需要用户进一步输入才能进行下一步响应;

    2) COptionsDlg的框架窗口口的定义:

IDD_OPTIONS DIALOG DISCARDABLE	0, 0, 192, 121
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Options"
FONT 8, "MS Sans Serif"
BEGIN
	LTEXT			"&Width", IDC_STATIC, 16, 16, 28, 8
	EDITTEXT		IDC_WIDTH, 44, 12, 64, 12, ES_AUTOHSCROLL
	LTEXT			"&Height", IDC_STATIC, 16, 36, 28, 8
	EDITTEXT		IDC_HEIGHT, 44, 32, 64, 12, ES_AUTOHSCROLL
	GROUPBOX		"Units", IDC_STATIC, 16, 56, 92, 52
	CONTROL			"&Inches", IDC_INCHES, "Button", BS_AUTORADIOBUTTON |
					WS_GROUP, 28, 68, 52, 8
	CONTROL			"&Centimeters", IDC_CENTIMETERS, "Button", 
					BS_AUTORADIOBUTTON, 28, 80, 52, 8
	CONTROL			"&Pixels", IDC_PIXELS, "Button", BS_AUTORADIOBUTTON,
					28, 92, 52, 8
	DEFPUSHBUTTON	"OK", IDOK, 128, 12, 50, 14, WS_GROUP
	PUSHBUTTON		"Cancel", IDCANCEL, 128, 32, 50, 14, WS_GROUP
	PUSHBUTTON		"&Reset", IDC_RESET, 128, 52, 50, 14, WS_GROUP
END


3. CMainFrame的定义和过去一样,只需要自己再添加一个OnCreate函数即可(注意消息映射也需要添加一下);


4. CChildView的定义:

    1) .h文件中添加成员数据和Options菜单项的消息映射:

protected:
	// 在视图中定义相应的矩形宽、高以及显示模式,作为和对话框交换数据的基础
	int m_nWidth;
	int m_nHeight;
	int m_nUnits; // 0是英尺,1是厘米,2是像素
	//{{AFX_MSG(CChildView)
	afx_msg void OnPaint();
	afx_msg void OnFileOptions(); // 菜单项命令处理程序
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
    2) .cpp文件中的定义:OnPaint和OnFileOptions

// ChildView.cpp : implementation of the CChildView class
//

#include "stdafx.h"
#include "CDlgDemo1.h"
#include "ChildView.h"

#include "OptionsDialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CChildView

CChildView::CChildView() // 初始化要显示的矩形的相关参数
{
	m_nWidth = 4;
	m_nHeight = 2;
	m_nUnits = 0; // 初始化为英尺比例显示
}

CChildView::~CChildView()
{
}


BEGIN_MESSAGE_MAP(CChildView,CWnd )
	//{{AFX_MSG_MAP(CChildView)
	ON_WM_PAINT()
	ON_COMMAND(ID_FILE_OPTIONS, OnFileOptions)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CChildView message handlers

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) 
{
	if (!CWnd::PreCreateWindow(cs))
		return FALSE;

	cs.dwExStyle |= WS_EX_CLIENTEDGE;
	cs.style &= ~WS_BORDER;
	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
		::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL);

	return TRUE;
}

void CChildView::OnPaint() // 矩形信息由对话框传送而来,重画只要一句视图的矩形信息即可
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	CBrush brush(RGB(255, 0, 255));
	CBrush* pOldBrush = dc.SelectObject(&brush);

	switch (m_nUnits)
	{
	case 0: // 英尺比例显示
		dc.SetMapMode(MM_LOENGLISH);
		dc.Rectangle(0, 0, m_nWidth * 100, -m_nHeight * 100);
		break;

	case 1: // 厘米显示比例
		dc.SetMapMode(MM_LOMETRIC);
		dc.Rectangle(0, 0, m_nWidth * 100, -m_nHeight * 100);
		break;

	case 2: // 像素显示
		dc.SetMapMode(MM_TEXT);
		dc.Rectangle(0, 0, m_nWidth, m_nHeight);
		break;
	}
	dc.SelectObject(pOldBrush);
	// Do not call CWnd::OnPaint() for painting messages
}

// 选中Options菜单项后创建相应对话框
// 并且视图窗口和对话框中的数据就在该函数中交换
void CChildView::OnFileOptions()
{
	COptionsDialog dlg;

	// 打开对话框之前先用视图中正确的数据初始化对话框中的数据
	dlg.m_nWidth = m_nWidth;
	dlg.m_nHeight = m_nHeight;
	dlg.m_nUnits = m_nUnits;

	if (dlg.DoModal() == IDOK) { // 用户相应完对话框后将数据回送至视图并重画视图中的矩形
		m_nWidth = dlg.m_nWidth;
		m_nHeight = dlg.m_nHeight;
		m_nUnits = dlg.m_nUnits;

		Invalidate(); // 无效导致重画
	}
}

5. 对话框COptionsDlg的定义:

    1) .h文件:

#if !defined(AFX_OPTIONSDIALOG_H__5F0F17AA_D0C2_4CCC_A53D_3A3CC1284F9B__INCLUDED_)
#define AFX_OPTIONSDIALOG_H__5F0F17AA_D0C2_4CCC_A53D_3A3CC1284F9B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// OptionsDialog.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// COptionsDialog dialog

class COptionsDialog : public CDialog
{
// Construction
public:
	COptionsDialog(CWnd* pParent = NULL);   // standard constructor

// Dialog Data
	//{{AFX_DATA(COptionsDialog)

	enum { IDD = IDD_OPTIONS }; // COptionsDialog可以由ClassWizard自动生成
	// 并且选择从逻辑上链接到.rc中定义的对话框模板上
	// 逻辑上链接的方法就是定义IDD这个枚举值,之后可以在派生类的构造函数中作为
	// 该类的数据成员传给构造函数作为参数(构造时需要用到对话框模板的ID)

	// 三个成员变量,因为可以从ClassWizard中生成(并且是可以和控件交换数据的)
	// 因此处于AFX_DATA注释宏的包围中,作为MFC自动生成的数据成员看待
	int		m_nHeight;
	int		m_nWidth;
	int		m_nUnits;
	//}}AFX_DATA


// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(COptionsDialog)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:

	// Generated message map functions
	//{{AFX_MSG(COptionsDialog)
		// NOTE: the ClassWizard will add member functions here
	afx_msg void OnReset(); // Reset按钮的处理程序
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_OPTIONSDIALOG_H__5F0F17AA_D0C2_4CCC_A53D_3A3CC1284F9B__INCLUDED_)

    2) .cpp文件:

// OptionsDialog.cpp : implementation file
//

#include "stdafx.h"
#include "CDlgDemo1.h"
#include "OptionsDialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// COptionsDialog dialog


COptionsDialog::COptionsDialog(CWnd* pParent /*=NULL*/)
	: CDialog(COptionsDialog::IDD, // 之前定义的枚举值作为构造函数的默认参数,实在是巧妙而安全,因为该枚举值成为了成员变量!
		pParent)
{
	//{{AFX_DATA_INIT(COptionsDialog)
	// 该初始值是MFC默认设定的,依据就是所这些数据成员所链接的控件
	// 一般链接编辑框的int类型的数据成员都会初始化成0
	// 链接单选按钮的int类型的数据成员都会初始化成-1,表示谁都没有选上
	// 由于这些初始化都可以由MFC的ClassWizard自动生成,因此包含在AFX_DATA_INIT的注释宏中
	m_nHeight = 0;
	m_nWidth = 0;
	m_nUnits = -1;
	//}}AFX_DATA_INIT

	// 但是问题就来了,我们定义宽和高的有效范围为1 ~ 128,而显示模式的有效范围为0 ~ 2,这个默认的初始化明显不符合要求
	// 会直接在DDV中报错
	// 但不过对话框中的数据是要和CChildView中相应的数据做交换的
	// CChildView中创建对话框时会将CChildView中初始的在有效范围内的值(4, 2, 0)赋给对话框中的数据成员
	// 而在关闭对话框后会将用户输入的对话框中的数据再回送到CChildView中
}


void COptionsDialog::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(COptionsDialog)
	DDX_Text(pDX, IDC_HEIGHT, m_nHeight);
	DDV_MinMaxInt(pDX, m_nHeight, 1, 128);

	DDX_Text(pDX, IDC_WIDTH, m_nWidth);
	DDV_MinMaxInt(pDX, m_nWidth, 1, 128);

	// 因为单选按钮在界面中是固定的
	// 在界面中有几个就是几个,不可能选择最大个数以外的按钮
	// 所以无需进行DDV校验
	DDX_Radio(pDX, IDC_INCHES, m_nUnits); 
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(COptionsDialog, CDialog)
	//{{AFX_MSG_MAP(COptionsDialog)
		// NOTE: the ClassWizard will add message map macros here
	ON_BN_CLICKED(IDC_RESET, OnReset)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// COptionsDialog message handlers

// 复位按钮处理程序
void COptionsDialog::OnReset()
{ // 成员变量重置为默认值
	m_nWidth = 4;
	m_nHeight = 2;
	m_nUnits = 0;

	// 需要将重置后的值回显到控件中
	UpdateData(FALSE);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值