第三章 单文档应用程序.docx
- 文档编号:9605437
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:13
- 大小:221.65KB
第三章 单文档应用程序.docx
《第三章 单文档应用程序.docx》由会员分享,可在线阅读,更多相关《第三章 单文档应用程序.docx(13页珍藏版)》请在冰豆网上搜索。
第三章单文档应用程序
第三章单文档应用程序
在本学习情境中主要学习:
(1)单文档应用框架
(2)文档与视图
3.1MFC消息处理
3.1.1事件驱动程序设计
事件驱动程序设计是一种全新的程序设计方法,它不是由事件的顺序来控制,而是由事件的发生来控制,而这种事件的发生是随机的、不确定的,并没有预定的顺序,这样就允许程序的的用户用各种合理的顺序来安排程序的流程。
对于需要用户交互的应用程序来说,事件驱动的程序设计有着过程驱动方法无法替代的优点。
它是一种面向用户的程序设计方法,它在程序设计过程中除了完成所需功能之外,更多的考虑了用户可能的各种输入,并针对性的设计相应的处理程序。
它是一种“被动”式程序设计方法,程序开始运行时,处于等待用户输入事件状态,然后取得事件并作出相应反应,处理完毕又返回并处于等待事件状态。
它的框图如图1所示:
图1事件驱动程序模型
3.1.2MFC的消息处理
在DOS应用程序下,可以通过getchar()、getch()等函数直接等待键盘输入,并直接向屏幕输出。
而在Windows下,由于允许多个任务同时运行,应用程序的输入输出是由Windows来统一管理的。
Windows操作系统包括三个内核基本元件:
GDI,KERNEL,USER。
其中GDI(图形设备接口)负责在屏幕上绘制像素、打印硬拷贝输出,绘制用户界面包括窗口、菜单、对话框等。
系统内核KERNEL支持与操作系统密切相关的功能:
如进程加载,文本切换、文件I/O,以及内存管理、线程管理等。
USER为所有的用户界面对象提供支持,它用于接收和管理所有输入消息、系统消息并把它们发给相应的窗口的消息队列。
消息队列是一个系统定义的内存块,用于临时存储消息;或是把消息直接发给窗口过程。
每个窗口维护自己的消息队列,并从中取出消息,利用窗口函数进行处理。
框图2如下:
图2消息驱动模型
从消息的发送途径上看,消息分两种:
队列消息和非队列消息。
队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
Windows维护一个系统消息队列(Systemmessagequeue),每个GUI线程有一个线程消息队列(Threadmessagequeue)。
鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。
Windows每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口创建线程的线程消息队列。
线程消息队列接收送给该线程所创建窗口的消息。
线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。
除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。
这些队列消息以外的绝大多数消息是非队列消息。
通过消息映射,我们可以把消息和它的消息处理函数联系起来。
VC++为我们提供了ClassWizard来为用户添加一个消息映射关系,而用户只需编写该消息发生响应的函数即可。
从View菜单中选择“ClassWizard”命令,便可调出如图3所示的ClassWizard对话框,它一共分为五个选项卡,依次分别是消息映射、成员变量、自动化、ActiveX事件和类信息。
最常用的是消息映射和成员变量两个选项卡,如果程序中使用了ActiveX控件,那么还需要使用ActiveX事件选项卡来添加事件处理函数,类信息选项卡可用来了解各个类的文件名、基类和资源等信息,自动化选项卡只有在编写OLE自动化服务器时才用得着。
下面我们就来看看消息映射和成员变量两个选项卡的特点和用途。
消息映射选项卡主要用途是为选中的类添加消息处理函数。
其中,Projects组合框用于选择Workspace中的一个工程,Classname组合框用于选择工程中的一个类。
ObjectsIDs中列出了所选择的类的名称及属于它的一系列ID,对于CXXXView类来说,列出的ID基本上都是菜单命令,对于一个对话框类来说,列出的ID多数对应着对话框模板中的控件。
从ObjectsIDs选择不同的类名或ID后,右边的Messages列表框中的内容也会跟着改变,选中类名时,Messages列表框中会显示出所有该类能处理的标准Windows消息以及该类可以重载的成员函数,选中一个ID时,Messages列表框中会显示出这个ID对应的对象(菜单选项或控件)所能引发的命令消息和通知消息。
在Messages列表框中选择一条消息(或一个可以重载的成员函数)后,如果该消息还没有相应的消息处理函数(或还未重载该成员函数),那么ClassWizard对话框右上角的AddFunction按钮就会变为有效,提示我们可以添加一个消息处理函数(或重载该成员函数),按下AddFunction按钮后,ClassWizard就会在所选的类中添加一个处理函数(为一个ID添加处理函数时,还会弹出一个对话框,要求输入函数名),并在Memberfuntions列表框中显示出刚添加的函数,在这个列表框中双击该函数名后,ClassWizard对话框将自动关闭,文本编辑器会定位在函数的实现代码处,这些代码及它在类定义中的声明都是由ClassWizard自动生成的。
图3Classwizard对话框
Memberfunctions列表框并没有列出类的所有成员函数,而只是列出了消息处理函数和重载的成员函数,其中每个函数的左边都有一个小图标,如果小图标为“W”字样,表示该函数是一个消息处理函数,除了Addfunction按钮外,消息映射选项卡中还有三个按钮,其中DeleteFunction用来删除一个消息处理函数或重载的成员函数,但是此按钮只能删除函数在类定义中的声明,函数的实现代码还需要手工来删除;EditCode按钮的用途相当于在Memberfunctions中双击一个成员函数;AddClass按钮则可用于向工程中添加一个新的类。
3.1.3文档与视图
先利用Appwizard来新建一个单文档工程。
在SDI框架程序中,主要包含四个类:
主框架类:
CMainFrame用于管理主程序窗口,从MFC类的CFrameWnd派生。
应用类:
CXXXApp负责初始化及程序结束前的整理工作,从MFC类的CWinApp派生。
文档类:
CXXXDoc负责存放程序数据和在磁盘上读写数据,从MFC类的CDocment派生。
视图类:
CXXXView负责数据的显示及处理用户的输入,从MFC类的CView派生。
用户对话框类:
CAboutDlg负责用户对话框的设置,从MFC类的CDialog类派生。
文档是存储的对象.文档类负责数据的维护,包括数据的读取、存储和修改,并将更改的数据通知相关视图,另外它还负责将数据存储到文件及从文件中读取数据。
文档是一种数据源,数据源有很多种,最常见的是磁盘文件,但它不必是一个磁盘文件,文档的数据源也可以来自串行口、网络或摄像机输入信号等。
文档对象负责来自所有数据源的数据的管理。
视图类的作用是与用户交互。
视图对象负责对保存在文挡对象中的数据以某种方式进行显示,并接受用户的输入,将这些输入交文挡类进行处理。
视图是数据的用户窗口,为用户提供了文档的可视的数据显示,它把文档的部分或全部内容在窗口中显示出来。
视图还给用户提供了一个与文档中的数据交互的界面,它把用户的输入转化为对文档中数据的操作。
每个文档都会有一个或多个视图显示,一个文档可以有多个不同的视图。
比如,在Excel电子表格中,我们可以将数据以表格方式显示,也可以将数据以图表方式显示。
一个视图既可以输出到窗口中,也可以输出到打印机上。
图文档与视图关系
3.1.4鼠标消息举例
我们先通过一个例子来说明如何用classwizard来实现捕获鼠标消息,进行消息映射和定义消息处理函数.
利用classwizard来设置消息选项。
选择ClassName中的CXXXView,选择其中相对应的WM_LBUTTONDOWN,双击选中的消息,单击EditCode按纽,如图4所示,并增加相关代码,如图5所示。
图4增加鼠标消息映射
图5增加代码
图6运行结果
3.1.4键盘消息举例
键盘的输入是从扫描码开始的,windows键盘驱动程序将这些扫描码转换成为与硬件无关的形式,即虚拟键码.
WM_CHAR:
此消息在键被按下时产生,通常用于处理非打印键中的按键消息.
图7在工程中增加相关变量
图8增加变量Text
图9初始化变量为空
图10增加键盘的消息影射
图11编写Onchar处理函数
图12输出接收到的字符
图13运行结果
为了能够实现输入字符的换行功能,在CXXXDoc类中增加一个用来计算行数的成员变量m_Line,如图14所示,并初始化变量m_Line,如图15所示。
图增加成员变量
图15初始化成员变量
为了保存字符串行的数据,定义一个字符串列表变量m_strList,如图16所示。
图16定义字符串列表变量
修改CXXXView类中的OnChar函数,如下所示。
voidCSDIView:
:
OnChar(UINTnChar,UINTnRepCnt,UINTnFlags)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CSDIDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
if(nChar==VK_RETURN)
{
pDoc->m_Line++;
pDoc->m_strList.AddTail(pDoc->Text);
pDoc->Text.Empty();
Invalidate();
}
else
{
pDoc->Text+=nChar;
CClientDCdc(this);
TEXTMETRICtm;
dc.GetTextMetrics(&tm);
intnLineHeight=tm.tmHeight+tm.tmExternalLeading;
dc.TextOut(0,pDoc->m_Line*nLineHeight,pDoc->Text);
}
CView:
:
OnChar(nChar,nRepCnt,nFlags);
}
为了保证能够将CXXXDoc类中m_strList的数据输出出来,增加一个DrawText函数,如图17所示和图18所示。
图17在CXXXDoc类中增加成员函数
图18增加DrawText函数
实现CXXXDoc类中的DrawText函数,如下所示。
voidCSDIDoc:
:
DrawText(CDC*pDC)
{
TEXTMETRICtm;
CStringstr;
intline=0;
pDC->GetTextMetrics(&tm);
intnLineHeight=tm.tmHeight+tm.tmExternalLeading;
POSITIONpos=m_strList.GetHeadPosition();
for(;pos!
=NULL;m_strList.GetNext(pos))
{
str=m_strList.GetAt(pos);
pDC->TextOut(0,line*nLineHeight,str);
line++;
}
}
修改CXXXView类中的OnDraw函数,如下所示。
voidCSDIView:
:
OnDraw(CDC*pDC)
{
CSDIDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
pDoc->DrawText(pDC);
//TODO:
adddrawcodefornativedatahere
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第三章 单文档应用程序 第三 文档 应用程序