📄 learnvc.html
字号:
<P>生成一个新的文档的时候,MFC程序同时生成一个框架窗口,并且在框架窗口的客户区中生成一个视窗对象作为框架窗口的子窗口,这个子窗口以可视化的方式表现文档中的内容。视窗的重要功能就是负责处理用户的鼠标、键盘等操作,通过对视窗对象的处理达到处理文档对象的目的。</P>
<P>要指出的一点是,WINDOWS应用程序分单文档界面SDI和多文档界面MDI两种,在单文档界面中,文档窗口与主框架窗口是同一概念。而这时的视窗对象则是显示在文档窗口的客户区当中。我们先前生成的TEST程序使用的就是单文档界面方式,此时文档窗口是主框架窗口,即类CMAINFRAME的对象。</P>
<P>下面将以一个例子来说明这两个类之间的关系。</P>
<P>前面已经提到,文档类是用来存放程序中的数据的,所以我们首先在文档类CMyDoc中加入一个成员变量用来存放数据。</P>
<P>在左边的工作区用右键单击CMyDoc选项,在弹出的菜单中选中Add member variable菜单项。</P>
<P ALIGN="CENTER"><IMG SRC="Image22.gif" WIDTH=432 HEIGHT=324>图2.2</P>
<P> </P>
<P>系统弹出Add Member Variable对话框。Variable Type一栏用来输入成员变量的类型。这里设置为CString,即字符串类型,Variable Declaration一栏用来输入变量的名字,这里不妨输入为mystring,Access组合框用来设置成员变量的访问权限,缺省为Public,设好后单击OK按钮关闭对话框。如下图2.3所示:</P>
<P ALIGN="CENTER"><IMG SRC="Image23.gif" WIDTH=403 HEIGHT=173>图2.3</P>
<P> </P>
<P>这时,如果打开类CMyDoc的头文件、可以发现其中已经自动加入了我们定义的公有变量mystring。这个变量就可以作为我们的文档类的数据存储空间,因为mystring是公有成员,它就可以被文档对应的视窗所处理了。</P>
<P>在VIEW菜单中选择ClassWizard菜单项,系统打开MFC ClassWizard对话框,接下来我们要为视窗类添加处理键盘事件的成员函数。在Classname一栏中选中类CMyView,然后在messages一栏中选中消息wm_char,单击add function按钮,系统就自动往CMyView类中添加了处理wm_char消息的成员函数的框架。单击edit code按钮,接下来对OnChar这个成员函数进行编辑和修改。</P>
<P>可以看出系统已经自动在这个成员函数中添加了CMyView的基类CView的WM_CHAR消息的处理函数。注意这一行代码:</P>
</FONT><FONT FACE="Courier New" SIZE=3><P>BEGIN_MESSAGE_MAP(CMyView, CView)</P>
<P>//{{AFX_MSG_MAP(CMyView)</P>
<B><P>ON_WM_CHAR()</P>
</B><P>ON_WM_LBUTTONDOWN()</P>
<P>ON_WM_CANCELMODE()</P>
<P>//}}AFX_MSG_MAP</P>
<P>// Standard printing commands</P>
<P>ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)</P>
<P>ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)</P>
<P>ON_COMMAND(ID_FILE_PRINT_PREVIEW, </P>
<P> CView::OnFilePrintPreview)</P>
<P>END_MESSAGE_MAP()</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P>它被放在mfc的消息映射宏BEGIN_MESSAGE_MAP中,它的作用就是把windows系统发来的WM_CHAR消息连接到CMyView类的成员函数OnChar上,即把这个成员函数作为处理WM_CHAR消息的过程。接下来我们就往这个成员函数中添加处理WM_CHAR消息的具体代码。</P>
<P>首先在OnChar函数中添加如下的代码:</P>
</FONT><FONT FACE="Courier New" SIZE=3><P>void CMyView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) </P>
<P>{</P>
<P>// TODO: Add your message handler code here and/or call default</P>
<P> CMyDoc * pdoc;</P>
<P> pdoc=GetDocument();</P>
<P>}</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P>这段代码的作用是首先定义一个指向文档类对象的指针pdoc,然后利用CMyView类的成员函数getdocument()获取指向当前视窗类所对应的文档类对象的指针,并把这个指针赋给定义的文档类型指针pdoc,这样我们在后面就可以用“pdoc_>mystring”的方式访问文档类中定义的公有数据成员mystring了。</P>
<P>接着往函数OnChar中添加如下的代码:</P>
</FONT><FONT FACE="Courier New" SIZE=3><P>pdoc_>mystring=nChar;</P>
<P>CClientDC mydc(this);</P>
<P>mydc.TextOut(0,0,pdoc_>mystring,</P>
<P>pdoc_>mystring.GetLength());</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN"><P>	</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P>这段代码中的第一行代码的作用是根据从消息WM_CHAR中传来的参数nchar,也就是键盘中输入的字符的ASCII码,把输入的字符添加到文档中的字符串对象mystring中。</P>
<P>在介绍第二行代码前要先介绍设备描述表的概念。设备描述表也称为设备上下文,在windows环境中,当需要对一个对象,如打印机,屏幕,窗口等进行输出时,就必须先获取这个对象的设备描述表,然后通过这个设备描述表来进行输出。使用设备描述表带来的最大的好处就是输出格式的一致性,因为输出不再是直接针对具体的设备,而是通过统一格式的设备描述表间接地实现。第二行代码的作用就是定义并生成了一个当前视窗的客户区的设备描述表对象MYDC,其中的参数THIS是面向对象语言中的一个重要的关键字。指代成员函数所在类的对象的指针。在生成了视窗的客户区的设备描述表MYDC之后,我们可以利用它在视窗的客户区中输出数据了。</P>
<P>这段代码的第三行就是调用设备描述表MYDC的方法TEXTOUT,在视窗的客户区中输出文档中的字符串MYSTRING了。</P>
<P>我们在前面曾经指出,一个文档可以对应多个视窗。如果用户通过某个视窗更改了文档中的数据,就比如上面的代码当中,我们通过视窗CMYWIVE更改了文档中的字符串对象MYSTRING,那么系统又如何维护同一文档的不同的视窗显示的数据的一致性呢?我们接着在OnChar函数中输入如下的代码:</P>
</FONT><FONT FACE="Courier New" SIZE=3><P>pdoc_>UpdateAllViews(this,0L,0);</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P>这行代码的作用就是通知本视窗所在的文档的所有其他的视窗,文档中的数据已经更新,这些视窗应该重新从文档中取回数据用来显示,这样就维持了同一文档的所有视窗的数据的一致性。这一行是视窗类中对文档的数据作了修改以后需要加的一条典型语句。</P>
<P>接下来运行这个程序,在BUILD菜单中选择REBUILD ALL菜单项来编译连接应用程序,然后单击BUILD菜单的EXECUTE菜单项运行程序,从键盘上输入一些字符,可以发现这些字符显示在视窗也就是主窗口的客户区当中。</P>
<P> </P>
<P>而这些字符的实际位置是存放在文档对象的成员变量MYSTRING这个字符串中。改变一下窗口的大小,可以发现显示的数据都没有了,这是因为我们在窗口尺寸改变的时候没有把数据重新输出到窗口的客户区中。关闭应用程序,找到CMyView类的成员函数ONDRAW,在其中添加如下的代码:</P>
</FONT><FONT FACE="Courier New" SIZE=3><P>void CMyView::OnDraw(CDC* pDC)</P>
<P>{</P>
<P>	CMyDoc* pDoc = GetDocument();</P>
<P>	ASSERT_VALID(pDoc);</P>
<P>	// TODO: add draw code for native data here</P>
<P>	pDC_>TextOut(0,0,pDoc_>mystring);</P>
<P>}</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P>当窗口的大小改变的时候,应用程序会调用ONDRAW这个函数,我们添加的这行代码的作用就是把字符串对象MYSTRING重新显示在窗口的客户区当中,这样在窗口大小改变的时候,数据依然显示在窗口客户区中。</P>
<P>再次编译运行这个程序,可以发现窗口大小的改变不再影响数据的显示了。</P>
<P>在前面的内容当中,我们已经介绍了使用MFC编制程序的基本结构。MFC的内容非常丰富,下面我们将针对软件的基本任务:接受用户输入、处理程序输出、进行文件处理以及数据库访问技术,向您介绍如何使用MFC编写程序,实现这些基本的功能。</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=6><P ALIGN="JUSTIFY"><A NAME="_Toc419740446"><A NAME="_Toc419881628">三 深入MFC类库</A></A></P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=5><P ALIGN="JUSTIFY"><A NAME="_Toc419740447"><A NAME="_Toc419881629">1 处理用户输入</A></A></P>
</B></FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P>程序从用户那里得到数据,经过自己的处理,再把计算的结果输出到屏幕、打印机或者其他的输出设备上,这是软件工作的基本模型。消息和键盘消息是最基本的输入信息,除此之外,</FONT><FONT SIZE=3>MFC</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>封装了一系列的使用户可以进行可视化的输入的界面对象,比方说对话框以及可以布置在上面的编辑框、按钮、列表控件、树形控件等等。使程序支持用户输入的手段更加丰富。</P>
<P ALIGN="CENTER"> </P>
<P ALIGN="CENTER"><IMG SRC="Image24.gif" WIDTH=292 HEIGHT=278>图3.1</P>
</FONT><FONT FACE="宋体" LAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -