Windows编程与MFC # 4 单文档应用程序(1)

  • 整理自VC++程序设计课程课件

使用VC++的应用程序向导MFC AppWizard可以开发:
Single document(单文档)
Multiple document(多文档)
Dialog based(基于对话框)


单文档(Single Document Interface,SDI)应用程序是指程序运行后出现标准的Windows界面,并且同一时间只能打开一个文档的应用程序。
Windows界面由框架(包括菜单栏、工具栏、状态栏)和客户区组成。

【例1】利用MFC AppWizard[exe]向导生成一个SDI单文档应用程序。
【编程步骤】
(1)点菜单栏File->New->Project,弹出New Project对话框,我们可以选择工程类型。在Project name框中输入项目名称,本例为App15。

(2)设置完成后,单击OK按钮,出现MFC AppWizard-Step 1对话框。在该对话框中选择Single document项,向导将会创建一个单文档应用程序框架。
在本例中,以下的各个步骤使用向导提供的默认选项即可。Windows编程与MFC # 4 单文档应用程序(1)_第1张图片
利用MFC AppWizard[exe]向导创建应用程序App15的框架后,用户无须添加任何代码,就可以对程序进行编译、连接,生成一个应用程序并且运行。运行结果如下图所示。
Windows编程与MFC # 4 单文档应用程序(1)_第2张图片


MFC应用程序框架实质上是一个标准的Windows应用程序,它具有标准的窗口、菜单栏和工具栏。
MFC AppWizard[exe]向导为一般的SDI应用程序生成了五个核心类,它们分别是:
应用程序类CApp15App
框架窗口类CMainFrame
文档类CApp15Doc
视图类CApp15View
文档模板类CSingleDocTemplate
Windows编程与MFC # 4 单文档应用程序(1)_第3张图片
一般应用程序框架中所有类的名字由MFC AppWizard[exe]向导根据一定的规则自动命名,但用户可以在向导的第6步改变类名和有关类的文件名。
除了框架窗口类CMainFrame和文档模板类CSingleDocTemplate,应用程序框架中类的命名一般遵照如下规则:
Class Name = C + ProjectName + ClassType

应用程序框架是生成一般的应用程序所必需的各种组件的集成,是类库的一种超集。应用程序框架可以调用成百上千个不同的类,但是核心类只有上述五个。
它们的MFC基类分别是:应用程序类CWinApp、框架窗口类CFrameWnd、文档类CDocument、视图类CView以及文档模板类CDocTemplate。

(1)应用程序类CApp15App
CApp15App类是MFC的CWinApp类的派生类。它的主要功能有:
应用程序的初始化
程序的启动
程序运行结束时的清理工作
应用程序对象theApp是一个唯一的全局变量,它的主要功能是通过调用WinMain()主函数启动程序的运行。

(2)框架窗口类CMainFrame
CMainFrame类是MFC的CFrameWnd类的派生类。它主要负责创建标题栏、菜单栏、工具栏和状态栏。对于不同的SDI应用程序,框架窗口类名均为CMainFrame。
CMainFrame类中声明了框架窗口中的菜单m_wndMenuBar、工具栏m_wndToolBar、状态栏m_wndStatusBar等成员变量和若干成员函数。

(3)文档类CApp15Doc
类CApp15Doc是MFC的CDocument类的派生类,它用于管理和维护数据,包括应用程序数据的保存和装载,即实现文档的序列化。

(4)视图类CApp15View
类CApp15View是MFC的CView类的派生类,它主要负责客户区文档数据的显示,以及如何进行人机交互。

(5)文档模板类CSingleDocTemplate
框架窗口对象、文档对象、视图对象如何联系在一起为一个应用程序服务呢?
文档、视图、框架类和所涉及的资源形成了一种固定的联系,这种固定的联系就称为文档模板。也就是说,文档模板描述了相对应每一种类型文档的视图和窗口的风格类型。

上述五个SDI应用程序核心类的MFC基类的类层次关系如图所示。

Windows编程与MFC # 4 单文档应用程序(1)_第4张图片

文档/视图结构

一般的应用开发都会涉及到数据处理。为了统一和简化数据处理,基于MFC的应用程序通常采用文档/视图结构。
在MFC文档/视图结构中,有关数据处理的工作可以分为数据的处理和数据的显示两个部分。
文档负责数据的处理、数据的维护以及数据的存储;
视图则负责数据的显示和数据的编辑,客户区消息的响应和处理等工作,即充当了文档与用户之间的交互界面。

文档(document)是MFC应用程序中所处理数据的集合,包括文本、图形、图像和表格等类型。
视图(view)是文档在应用程序窗口中的一个映像。视图就如一个观景器,用户通过视图看到文档,通过视图修改文档。
一个视图是一个没有边框的窗口,它位于主框架窗口中的客户区。视图是文档对外显示的窗口,但它并不能完全独立,它必须依存在一个框架窗口内。

Windows编程与MFC # 4 单文档应用程序(1)_第5张图片
文档、视图、框架类和所涉及的资源形成了一种固定的联系,这种固定的联系就称为文档模板。也就是说,文档模板描述了对应每一种类型文档的视图和窗口的风格类型。

当打开某种类型的文件时,应用程序必须确定哪一种文档模板用于解释这种文件。在初始化程序时,必须首先注册文档模板,以便程序利用这个模板来完成主框架窗口、视图、文档对象的创建和资源的装入。

BOOL CMyTextOutApp::InitInstance()
{
…  
CSingleDocTemplate* pDocTemplate;    //声明文档模板指针
pDocTemplate = new CSingleDocTemplate( //创建文档模板对象
		IDR_MAINFRAME,               //文档模板使用的资源ID
		RUNTIME_CLASS(CApp15Doc), //创建文档对象
		RUNTIME_CLASS(CMainFrame),  // 创建主SDI框架窗口对象
		RUNTIME_CLASS(CApp15View)); //创建视图对象
AddDocTemplate(pDocTemplate); //将文档模板加入文档模板链表}

Windows编程与MFC # 4 单文档应用程序(1)_第6张图片

在客户区显示文本

以【例1】的单文档应用程序App15为基础,添加代码实现文本输出。
程序运行后在视图窗口显示文本串“这是第一个单文档应用程序!”。

【编程步骤】
(1)本例需要在视图类的成员函数OnDraw()中添加显示文本的代码来实现屏幕输出。
打开类视图窗口,找到CApp15View类,展开该类,双击其成员函数OnDraw(),在编辑窗口出现该成员函数代码,在指定位置手工添加如下代码。

Windows编程与MFC # 4 单文档应用程序(1)_第7张图片
Windows编程与MFC # 4 单文档应用程序(1)_第8张图片
GetDocument()是视图类的成员函数,调用它可以返回与视图相关联的文档对象的指针,利用这个指针可以访问文档类及其派生类的公有成员。通常的用法如下:
CMyTextOutDoc* pDoc = GetDocument();

TextOut()是CDC类的成员函数。其功能是在指定的位置输出文本串。函数原型如下:
CDC: TextOut( int x, int y, const CString& str )
其中参数x,y指定文本输出位置坐标。
参数str指定输出内容。

ASSERT_VALID()是MFC库中的断言 。ASSERT_VALID()的用法是:
ASSERT_VALID(一个从CObject类派生的类对象指针)
功能:用于对C++对象或指针进行有效性判断,如果出错,会弹出带断言信息(程序,模块, assertion行)的对话框。对话框有3个按钮:“Break”,“Repeat”(“Debug”), 和“Continue”(“Ignore”)。“Break”结束程序,“Continue”忽略断言,最有用的是“Repeat”按钮。按下它会在断言的地方打开源代码编辑器. 在这里可以测试相关的变量值并找出问题所在。

编译连接程序,程序运行后将在程序视图区域显示文本串。程序运行结果如图所示。

Windows编程与MFC # 4 单文档应用程序(1)_第9张图片

Windows的设备环境DC

在Windows中,凡绘图操作之前一定要先获得一个DC(Device Context)。DC是一种包含设备信息的数据结构,它可能代表全部屏幕,也可能代表一个窗口。DC包含了物理设备所需的各种状态信息。
DC实际上是一个关于如何绘制图形的方法的集合。它可以确立在应用窗口中绘制图形的方式,包括坐标系统(映射模式)、绘图工具(如画笔、画刷、颜色)等等。
当应用程序需要在某个图形设备上绘图时,首先要获取绘图窗口区域的一个设备环境DC,之后才能选取合适的绘图工具进行绘图工作。

图形设备接口GDI

为了方便图形绘制,Windows把与绘图相关的操作都制作成函数,这些函数的集合称为图形设备接口(graphical device interface,GDI)。
GDI提供了各种绘图函数,例如GDI中有绘制矩形的函数Rectangle()、绘制文本的函数DrawText()等。GDI还提供了一套绘图工具,如Pen(画笔)、Brush(画刷)、Font(字体)等。
由于在Windows屏幕上看到的所有内容都是图形,所以在应用窗口中每次进行显示和编辑操作时,都必须调用特定的GDI函数。

CDC类

MFC将DC和GDI函数封装到一起形成了两种重要的图形处理的类:
设备环境类(CDC类),用于访问设备属性、设置绘图属性和绘制图形;
绘图对象类,封装了各种GDI绘图对象,包括画笔、画刷、字体、位图、调色板和区域。
MFC中,设备环境DC是由CDC类对象来表示的,并且可以调用CDC类的成员函数来完成各种各样的绘图操作,它提供了170多个成员函数。

Windows编程与MFC # 4 单文档应用程序(1)_第10张图片
设备环境描述类
CDC类是CObject的直接派生类,CDC类除了作为通用的设备环境类来使用,还派生了几种特定的设备环境描述类,包括:
CClientDC类
CPaintDC类
CMetaFileDC类
CWindowDC类

Windows编程与MFC # 4 单文档应用程序(1)_第11张图片
WM_PAINT消息

当用户改变了应用程序窗口的大小,或者当窗口恢复了先前被覆盖的部分,应用程序窗口都会收到Windows发来的WM_PAINT消息,
然后应用程序框架自动调用视图类CView的成员函数OnPaint()或程序员添加的函数OnPaint()来处理WM_PAINT消息,
在OnPaint()函数中重绘窗口中需要恢复的部分图形,更简单的方法是重绘整个窗口。

CPaintDC类

CPaintDC类是OnPaint()函数使用的设备环境类,它代表一个窗口的绘图画面。
如果添加WM_PAINT的消息处理函数OnPaint(),就需要使用CPaintDC类来定义一个设备环境对象。
在CView类的成员函数OnPaint()中就这样定义了一个设备环境对象。

void CView::OnPaint()
{
//standard paint routine
CPaintDC paintDC; //定义一个设备环境对象paintDC
OnPrepareDC(&paintDC);
OnDraw(&paintDC);
}

OnDraw()函数

由于基类CView的OnPaint()函数调用了OnDraw()函数,因此编程时经常在OnDraw()函数中绘制图形。
OnDraw()函数的声明为:
OnDraw(CDC *pDC);
这个函数的参数pDC就是指向CPaintDC类对象的指针,在OnDraw()函数中可以使用CDC类的成员函数对这个对象进行绘图操作。

GDI坐标系和映射模式
GDI支持两种类型的坐标系:
逻辑坐标系:一般GDI的文本和图形输出函数使用的是逻辑坐标。
设备坐标系:在客户区移动或按下鼠标所得到的鼠标位置使用的是设备坐标。
逻辑坐标系是面向设备环境DC的坐标系,这种坐标不考虑具体的设备类型,但在实际绘图时GDI会根据当前设置的映射模式将逻辑坐标转换为设备坐标。

映射模式规定了逻辑单位的实际大小、坐标轴的正方向,所有的映射模式的坐标原点都设在设备输出区域(如客户区或打印区)的左上角。
GDI定义了8种映射模式。使用映射模式使得程序员不必考虑输出设备的设备坐标系,只需在一个统一的逻辑坐标系中进行图形的绘制。
Windows编程与MFC # 4 单文档应用程序(1)_第12张图片
SetMapMode()设置映射模式
例如:dc.SetMapMode(MM_LOMETRIC);
GetMapMode()获得当前映射模式

在MFC开发中经常会使用GDI来输出文本或图形图像。
文本实际上就是一种特殊的图形,它只不过是根据事先指定的“字体”绘制出来的图形。
字体通常用来为字符集中每一个字符,如字母、数字、标点符号等,指定其形状等外表特征。
窗口创建后,如果没有专门指定,一般会采用系统字体作为默认字体。我们可以使用API函数GetStockObject(SYSTEM_FONT)获得系统字体的句柄。

CFont类封装了一个Windows图形设备接口(GDI)字体,并为操作字体提供了成员函数。
首先要构造一个CFont对象,通过调用CreateFont、CreateFontIndirect、CreatePointFont或CreatePointFontIndirect将一个Windows字体与此CFont对象关联,然后使用此CFont对象的成员函数就可以操作字体了。

1、CFont( )
构造一个CFont对象。此对象在使用之前应该先使用CreateFont、CreateFontIndirect、CreatePointFont或CreatePointFontIndirect初始化。

Windows编程与MFC # 4 单文档应用程序(1)_第13张图片

BOOL CreateFont(
   int nHeight,
   int nWidth,
   int nEscapement,
   int nOrientation,
   int nWeight,
   BYTE bItalic,
   BYTE bUnderline,
   BYTE cStrikeOut,
   BYTE nCharSet,
   BYTE nOutPrecision,
   BYTE nClipPrecision,
   BYTE nQuality,
   BYTE nPitchAndFamily,
   LPCTSTR lpszFacename );

CreateFont函数初始化CFont对象后,就能够使用CDC::SelectObject函数来为设备上下文选择字体了,并且还能够在不再使用此CFont对象时删除它。
此函数并不会创建一个新的Windows GDI字体,只是从GDI的物理字体中选择了一个最匹配的字体。

CFont font;
font.CreateFont(0, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T(“Times New Roman”));

3、BOOL CreateFontIndirect(const LOGFONT* lpLogFont);
通过一个LOGFONT结构体变量给出的特征来初始化CFont对象。参数lpLogFont是指向LOGFONT结构体变量的指针,此LOGFONT结构体变定义了逻辑字体的特征。
4、int GetLogFont(LOGFONT * pLogFont);
获取CFont对象的LOGFONT结构体的拷贝。参数pLogFont指向用来接收字体信息的LOGFONT结构体变量。成功则返回非零值,否则返回零。

CFont font ;
LOGFONT lf;
::ZeroMemory(&lf, sizeof(lf));
lf.lfHeight = 120;
lf.lfWeight = FW_BOLD;
lf.lfItalic = TRUE;
font.CreateFontIndirect(&lf);

ZeroMemory是美国微软公司的软件开发包SDK中的一个宏。 其作用是用0来填充一块内存区域。

5、BOOL CreatePointFont(int nPointSize,LPCTSTR lpszFaceName,CDC* pDC = NULL);
此函数提供了一种由指定字样和点数创建字体的简单方式。参数的意义如下:
nPointSize:指定字体高度,以十分之一点为单位。例如,nPointSize为120则表示是12点的字体。
lpszFacename:指定字体的字样名的字符串。此字符串的长度不应超过30个字符。
Windows函数EnumFontFamilies可以枚举出当前所有可用字体的字样名。

执行文本输出操作
使用设备上下文类CDC的成员函数TextOut来输出,CDC::TextOut函数的两种重载形式如下:
virtual BOOL TextOut(int x,int y,LPCTSTR lpszString,int nCount);BOOL TextOut(int x,int y,const CString& str);
参数x指定文本起始点的x坐标;参数y指定文本起始点的y坐标;参数lpszString为要输出的文本字符串;参数nCount指定字符串中的字节个数;参数str为包含要输出的字符的CString对象。

设计两个变量:

CFont newFont;   // 新字体   
CFont *pOldFont; // 选择新字体之前的字体newFont.CreatePointFont(180, _T("隶书")); 
    // 创建一种新的字体(18点,隶书)  
    pOldFont = (CFont*)dc.SelectObject(&newFont);  

SelectObject()函数的功能是,选择一对象到指定的设备环境中,该新对象替换先前的相同类型的对象。函数原型是:
HGDIOBJ SelectObject(HGDIOBJ hgdiobj)
参数hgdiobj指的是被选择的对象的句柄。
返回值:如果函数执行成功,那么返回值是被取代的对象的句柄。否则返回NULL。

当应用程序需要使用用户自己定制的Windows GDI对象时,首先要将其选入设备环境。MFC的CDC类提供了成员函数SelectObject()用于将用户自己创建的GDI对象选入设备环境。

void CApp15View::OnDraw(CDC* pDC)
{
    CApp15Doc* pDoc = GetDocument();
     ASSERT_VALID(pDoc);
     if (!pDoc)      return;
    CFont newFont;     // 新字体   
    CFont *pOldFont;   // 选择新字体之前的字体
    newFont.CreatePointFont(180, _T("隶书")); // 创建一种新的字体  
    pOldFont=(CFont*)pDC->SelectObject(&newFont);
    // 在指定位置输出文本   
    pDC->TextOut(40,10,_T("你好!"));   
    // 恢复以前的字体   
    pDC->SelectObject(pOldFont);   
    pDC->TextOut(50,50, _T("这是我的第一个单文档应用程序!"));
}

Windows编程与MFC # 4 单文档应用程序(1)_第14张图片
Windows编程与MFC # 4 单文档应用程序(1)_第15张图片

void CApp15View::OnDraw(CDC* pDC)
{
    CApp15Doc* pDoc = GetDocument();
     ASSERT_VALID(pDoc);
     if (!pDoc)      return;
    CFont newFont;     // 新字体   
    CFont *pOldFont;   // 选择新字体之前的字体
    newFont.CreatePointFont(180, _T("隶书")); // 创建一种新的字体  
    pOldFont=(CFont*)pDC->SelectObject(&newFont);
    // 设置文本颜色为红色   
    pDC->SetTextColor(RGB(255,0,0));   
    // 在指定位置输出文本   
    pDC->TextOut(40,10,_T("你好!"));   
    // 设置文本颜色为绿色   
    pDC->SetTextColor(RGB(0,255,0));   
    // 在指定位置输出文本   
    pDC->TextOut(10,80, _T("学习总是有收获的"));   
    // 恢复以前的字体    
    pDC->SelectObject(pOldFont);   
    pDC->TextOut(50,50, _T("这是我的第一个单文档应用程序!"));
}

COLORREF是一个32bit整型数值,代表了一种颜色,其格式为0x00bbggrr,其中bb、gg和rr分别代表蓝、绿和红颜色的分量,每种颜色分量的取值范围为0~255。
通常使用RGB函数来初始化COLORREF类型数据。其使用形式是:
RGB(byRed,byGreen,byBlue)
其中参数byRed、byGreen和byBlue分别表示红、绿、蓝分量值。
Windows编程与MFC # 4 单文档应用程序(1)_第16张图片

菜单

改进【例1】的单文档应用程序,程序运行后使用菜单命令,调用字体对话框,设置字体字号等。
为了方便灵活地使用字体,Windows提供了一个通用字体对话框,应用程序可以使用它来选择不同的字体,设置字号和字体颜色等。该对话框的MFC类是CFontDialog类。

MFC使用CFontDialog类封装了字体对话框的所有操作。字体对话框也是一种模态对话框。

【编程步骤】
(1)建立菜单资源。在向导生成的程序框架中修改菜单资源,添加“文本”|“设置字体”菜单。
在ResourceView中找到IDR_MAINFRAME资源,双击之,在显示出来的主菜单项最后的虚线空白框处双击,在弹出的properties对话框中填写Caption项为“文本(&T)”,可以看到主菜单最后一个菜单项即为“文本”,字符“&”用于在显示字母“T”时加下划线,表示该菜单命令的快捷键是“Alt+T”。

Windows编程与MFC # 4 单文档应用程序(1)_第17张图片
Windows编程与MFC # 4 单文档应用程序(1)_第18张图片
接着为主菜单添加菜单项。在“文本”菜单下面的虚线空白框处双击,在弹出的properties对话框中填写Caption项为“设置字体”,在ID框中填写此菜单项的ID_FONTDLG_MENU。
在Prompt文本框中输入状态栏提示语“使用字体对话框设置字体”。如图所示。

Windows编程与MFC # 4 单文档应用程序(1)_第19张图片
(2) 添加菜单项命令处理函数。
在菜单项“字体对话框”上右击鼠标,在快捷菜单上点击“添加事件处理程序”,在弹出的对话框“事件处理程序向导”中,“类列表”选择视图类CApp15View,在“消息类型”列表框中选择COMMAND,单击“添加编辑”按钮,为“字体对话框”菜单项添加命令处理函数CApp15View::OnFontdlgMenu()
。该函数名是自动生成的。如图所示。
Windows编程与MFC # 4 单文档应用程序(1)_第20张图片
Windows编程与MFC # 4 单文档应用程序(1)_第21张图片

(3)在视图类中添加字体和字体颜色成员变量。
CFont m_font; //用户所选择的字体
COLORREF m_TextColor; //用户所选择的字体颜色
(4)编写“设置字体”菜单项的响应函数。
void CApp15View::OnFontdlgMenu()
{ // TODO: 在此添加命令处理程序代码
CFontDialog dlgFont; //通用字体对话框
if(dlgFont.DoModal() == IDOK)
{
LOGFONT LogFnt;
m_font.DeleteObject();
// 使用选定字体的LOGFONT创建新的字体
dlgFont.GetCurrentFont(&LogFnt);
m_font.CreateFontIndirect(&LogFnt);
m_TextColor = dlgFont.GetColor();
Invalidate(FALSE);
}
}

创建字体必须使用CFont类的成员函数。利用CFont创建字体的方法之一是:
BOOL CreateFontIndirect(const LOGFONT* lpLogFont )

该对象通过LOGFONT结构创建字体,LOGFONT结构的定义如下。
typedef struct tagLOGFONT {
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
TCHAR lfFaceName[LF_FACESIZE];
} LOGFONT;

当不再使用选入的GDI对象时需要释放该GDI对象。使用CDC类的方法DeleteObject将设备环境中的GDI对象删除。
m_font.DeleteObject();
为什么在CApp15View::OnFontdlgMenu()中要使用DeleteObject删除m_font关联的对象资源?
因为m_font对象原来已与某种字体资源相关联,现在m_font又试图与新字体资源相关联时,就会出错。而使用DeleteObject(),切断这种关联,释放该字体资源,再与新资源相关联就没有问题了。

Invalidate()是强制系统进行重画,但是不一定就马上进行重画。因为Invalidate()只是通知系统,此时的窗口已经变为无效。强制系统调用WM_PAINT,而这个消息只是Post就是将该消息放入消息队列。当执行到WM_PAINT消息时才会对敞口进行重绘。
UpdateWindow()只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT。
RedrawWindow()则是具有Invalidate()和UpdateWindow()的双特性。声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。

(5)修改OnDraw()函数。在OnDraw()函数里设置字体、字体颜色并输出文本。

void App15View::OnDraw(CDC* pDC)
{
    CApp15Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
         return;
    CFont *pfntOld=(CFont*)pDC ->SelectObject(&m_font);    //设置字体
    pDC->SetTextColor(m_TextColor);        //设置字体颜色
    pDC->TextOut(40,10,_T("你好!"));   
    pDC->TextOut(10,80,_T("学习总是有收获的"));   
    pDC->TextOut(50,50,"这是我的第一个单文档应用程序!");
    pDC->SelectObject(pfntOld);   //恢复以前的字体
}

添加自定义对话框
【例2】程序运行后使用菜单命令,调用自定义对话框输入要在客户区显示的文本内容和坐标位置,在视图区按照所给的坐标位置显示文本。
【编程步骤】
(1)在“文本”下添加一个新的菜单项“显示文本”。修改属性。提示语“在视图区给定位置显示输入的文本内容”。添加消息处理函数。
(2)添加新的对话框资源,ID为IDD_TEXT_DIALOG 。Caption为“输入显示文本和位置”。
(3)在对话框上放置静态控件、编辑框控件和按钮控件。修改三个编辑框的ID,使之分别为IDC_EDIT_TEXT、IDC_TEXT_X、IDC_TEXT_Y。为编辑框IDC_EDIT_TEXT勾选“Multiline(多行)”、“Vertical Scroll(垂直滚动条)”、“Want return”选项。如图所示。
Windows编程与MFC # 4 单文档应用程序(1)_第22张图片
(4)为对话框资源创建对应的对话框类 CTextDialog。向导为该类自动生成两个文件TextDialog.h和TextDialog.cpp。

(5)为三个编辑框控件添加成员变量m_strText、m_nX、m_nY。如图所示。

Windows编程与MFC # 4 单文档应用程序(1)_第23张图片
(6)建立文本对话框与视图类的关联。
下面在视图类中加入与上述控件变量对应的三个成员变量,即在文件App15View.h中加入如下代码。
class CApp15View : public CView
{
protected: // 仅从序列化创建
CEx16_1View();
DECLARE_DYNCREATE(CEx16_1View)
// 特性
CFont m_font; //用户所选择的字体
COLORREF m_TextColor; //用户所选择的字体颜色
int m_nX;
int m_nY;
CString m_strText;
(7)在App15View.cpp文件中编写菜单命令响应函数CApp15View::OnShowtextMenu()的代码。
注意: 在文件开始处加入:#include “TextDialog.h”
void CApp15View::OnShowtextMenu()
{
// TODO: 在此添加命令处理程序代码
CTextDialog tdlg; //定义一个对话框对象
if(tdlg.DoModal()==IDOK) //显示对话框
{
m_nX=tdlg.m_nX;
m_nY=tdlg.m_nY;
m_strText=tdlg.m_strText;
}
Invalidate(FALSE);
}

将文本对话框的成员变量值赋给视图类的相应的成员变量m_strText, m_nTextX, m_nTextY,视图类已经获得了对话框控件上的数据,怎么将其显示在客户区呢?
这时需要调用视图类CDrawView的方法OnDraw(),该方法负责数据在客户区的显示。

(8)修改App15View.cpp中OnDraw()函数的代码,将原来的
pDC->TextOut(50,50,“这是我的第一个单文档应用程序!”);
替换为:
pDC->TextOut(m_nX,m_nY,m_strText);

编译、连接并运行程序后,单击菜单命令,在对话框中输入相应的内容,其运行结果如图所示。

Windows编程与MFC # 4 单文档应用程序(1)_第24张图片

你可能感兴趣的:(Windows编程)