友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
C语言实例教程(PDF格式)-第14部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
16位版本相兼容。但是,从16位分段内存模式到32位虚拟内存模式的
转变将使得一些函数和一些选项变得不必要甚至没有意义。比如说,
现在不再和近指针和远指针的区别,因为无论在本地还是在全局进行
分配都将返回32位虚拟地址。
函数GlobalAlloc和LocalAlloc都可以分配固定或可移动的内存对
象。可移动对象也可以被标记为可丢弃的(discardable)。在早期的
Windows版本中,可移动的内存对象对于内存管理非常之重要,它们
允许系统在必要时压缩堆以为其它内存分配提供可用空间。通过使用
虚拟内存,系统能够通过移动物理内存页来管理内存,而不影响使用
这些页的进程的虚拟地址。当系统移动一个物理内存页时,它简单的
将进程的虚拟页映射到新的物理页的位置。可移动内存在分配可丢弃
内存仍然有用。当系统需要额外的物理存储时,它使用一种称作 “最
近最少使用”的算法来释放非锁定的可丢弃内存。可丢弃内存可以用
于那些不是经常需要和易于重新创建的数据。
当分配固定内存对象时,GlobalAlloc和LocalAlloc返回32位指针,
调用线程可以立即使用该指针来进行内存存取。对于可移动内存,返
回值为一个句柄。为了得到一个指向可移动内存的指针,调用线程可
…………………………………………………………Page 155……………………………………………………………
以使用GlobalLock和LocalLock函数。这些函数锁定内存使得它不能
够被移动或丢弃,除非使用函数GlobalReAlloc或LocalReAlloc对内
存对象进行重新分配。已锁定内存对象的内存块保持锁定状态,直至
锁定计数减到0,这时该内存块可以被移动或丢弃。
由GlobalAlloc和LocalAlloc所分配的内存的实际大小可能大于所要
求的大小。为了得到已分配的实际内存数,可以使用函数GlobalSize
和LocalSize。如果总分配量大于所要求的量,进程则可以使用所有
的这些量。'
函数GlobalReAlloc和LocalReAlloc以字节为单位改变由GlobalAlloc
和LocalAlloc函数分配内存对象的大小或其属性。内存对象的大小可
以增大,也可以减小。
函数GlobalFree和LocalFree用于释放由GlobalAlloc、LocalAlloc、
GlobalReAlloc或LocalReAlloc分配的内存。
其它的全局和本地函数包括GlobalDiscard、LocalDiscard、
GlobalFlags、LocalFlags、GlobalHandle和LocalHandle。
GlobalDiscard和LocalDiscard用于丢弃指定的可丢弃内存对象,但
不使其句柄无效。该句柄可能通过函数GlobalReAlloc或
LocalReAlloc与新分配的内存块相关联。函数GlobalFlags或
LocalFlags返回关于指定内存对象的信息。这些住处包括对象的锁定
计数以及对象是否可丢弃或是否已被丢弃。函数GlobalHandle或
LocalHandle返回与指定指针相关联的内存对象的句柄。
Win32进程可以完全的使用标准的C库函数malloc、free等来操作内
存。在Windows的早期版本中使用这些函数,将可能带来问题隐患,
但是使用Win32 API的应用程序中则不会。举例来说,使用malloc分
配固定指针将不能使用可移动内存的优点。由于系统可以通过移动物
理内存页来自由的管理内存,而不影响虚拟地址,因此内存管理将不
再成为问题。类似的,远指针和近指针之间不再有差别。因此,除非
你希望使用可丢弃内存,否则完全可以将标准的C库函数用于内存管
理。
Win32 API提供了一系列的虚拟内存函数来操作或决定虚拟地址空间
中的页的状态。许多应用程序使用标准的分配函数GlobalAlloc、
LocalAlloc、malloc等就可以满足其需要。然而,虚拟内存函数提供
了一些这些标准分配函数所不具有的功能,它们可以进行下面的这些
操作:
…………………………………………………………Page 156……………………………………………………………
l 保留进程虚拟地址空间中的一段 保留地址空间并不为它们分配物
理存储,而只是防止其它分配操作使用这段空间。它并不影响其
它进程的虚拟地址空间。保留页防止了对物理存储的不必要的浪
费,然而它允许进程为可能增长的动态数据结构保留一段地址空
间,进程可以在需要的时候为这些空间分配物理存储。
l 占用进程虚拟地址空间中的保留页的一部分,以使得物理存储 (无
论是RAM还是磁盘空间)只对正在进行分配的进程可用。
l 指定允许读写存取、只读存取或不允许存取的占用页区域。这和
标准的分配函数总是分配允许读写存取的页不同。
l 释放一段保留页,使得调用线程在随后的分配操作中可以使用这
段虚拟地址。
l 取消对一段页的占用,释放它们的物理存储,使它们可以其它进
程在随后的分配中使用。
l 在物理内存RAM中锁定一个或多个占用页,以免系统将这些页交换
到页面文件中。
l 获得关于调用线程或指定线程的虚拟地址空间中的一段页的信
息。
l 改变调用线程或指定线程的虚拟地址空间中指定占用页段的存取
保护。
虚拟内存函数对内存页进行操作。函数使用当前计算机的页大小来对
指定的大小和地址进行舍入。
可以使用函数GetSystemInfo来获得当前计算机的页大小。
函数VirtualAlloc完成以下操作:
l 保留一个或多个自由页。
l 占用一个或多个保留页。
l 保留并占用一个或多个自由页。
你可以指针所保留或占用的页的起始地址,或者让系统来决定。函数
将指定的地址舍入到合适的页边界。保留页是不可访问的,但占用页
可以使用标志位PAGE_READWRITE、PAGE_READONLY和PAGE_NOACCESS来
…………………………………………………………Page 157……………………………………………………………
分配。当页被占用时,从页面文件中分配存储空间,每个页仅在第一
次试图对其进行读写操作时被初始化并加载到物理内存中。可以用一
般的指针引用来访问由VirtualAlloc函数 占用的页。
函数VirtualFree完成下面的操作:
l 解除对一个或多个页的占用,改变其状态为保留。解除对页的战
胜释放与之相关的物理存储,使其为其它进程可用。任何占用页
块都可以被解除占用。
l 释放一个或多个保留页块,改变其状态为 自由。释放页块使这段
保留空间可以为进程分配空间使用。保留页只能通过释放由函数
VirtualAlloc最初保留的整个块来释放。
l 同时解除对一个或多个占用页的占用并释放它们,将其状态改变
为自由。指定的块必须包括由VirtualAlloc最初保留的整个块,
而且这些页的当前状态必须为占用。
函数VirtualLock允许进程将一个或多个占用页锁定在物理内存RAM
中,防止系统将它们交换到页面文件中。这保证了一些要求苛刻的数
据可以不通过磁盘访问来存取。将一个页锁定入内存是很危险的,因
为它限制了系统管理内存的能力。由于可能会将可执行代码交换到页
面文件中,可执行程序使用VirtualLock将有可能降低系统性能。函
数VirtualUnlock解除VirtualLock对内存的锁定。
函数VirtualQuery和VirtualQueryEx返回关于以进程地址空间中某一
指定地址开始的一段连续内存区域的信息。VirtualQuery返回关于调
用线程内存的信息。VirtualQueryEx返回指定进程内存的信息,这通
常用来支持调试程序,这些程序常常需要知道关于被调试进程的信
息。页区域以相对于指定地址最接近的页边界为界。一般来说,它通
过具有下述属性的后续页来进行扩展:
所有页具有相同的状态,或为占用,或为保留,或为自由。
如果初始页不为自由,区域中的所有页都属于通过调用VirtualAlloc
保留的同一个最初页分配。
所有页的存取保护相同,或为PAGE_READONLY,或为
PAGE_READWRITE,或为PAGE_NOACCESS。
函数VirtualProtect允许进程修改进程地址空间中任意占用页的存取
保护。举例来说,一个进程可以分配读写页来保存易受影响的数据,
…………………………………………………………Page 158……………………………………………………………
然后将存取改变为只读或禁止访问,以避免无意中被重写。典型的,
VirtualProtect用于使用VirtualAlloc分配的页,但事实下,它也可
以用于通过其它分配函数占用的页。然而,VirtualProtect改变整个
页的保护状态,而由其它函数返回的指针并非总是指向页边界。函数
VirtualProtectEx类似于VirtualProtect,但函数VirtualProtectEx
可以改变指定进程的内存的保护状态。改变这些内存的保护状态在调
试程序访问被调试进程的内存的非常有用。
…………………………………………………………Page 159……………………………………………………………
第四章 基于对话框的应用程序
从本章我们将学习如何使用Visual C++进行真正意义上的Windows应
用程序设计。对于编程者来说,最简单的实用程序应该是本章所要讲
述的基于对话框的应用程序。当然,我们已在前面的章节中介绍了基
于包括用户区的一般窗口的最简单的Windows程序,相比本章将要讲
述的程序来说,它们还要更简单一些。但是要记住,在前面讲述的这
些应用程序中,我们没有实现任何实际的功能。事实上,在这些应用
程序中,实现一些哪怕是很简单的功能也需要很多的代码量。举一个
例子,如果我们需要在用户区绘制图形或文本的话,就需要为
Windows消息WM_PAINT编写消息处理函数。一个实用的Windows应用程
序的WM_PAINT 的消息处理过程常常会很庞大和很复杂。而对于在这章
将要讲述的基于对话框的应用程序来说,整个应用程序都是由一个或
多个对话框 (dialog box)组成,对话框只是作为其它一些行为标准化
了的窗口(我们叫它们控件 (control))的容器,其行为也是标准化了
的。这样,Windows就可以为这些行为标准化了的窗口实现很多默认
的操作,而不需要我们进行更多的干预。比如对于一个文本框,我们
只需要预先设定文本框的文字及其它一些属性,Windows就可以知道
在不同的情况下这个文本框应该进行什么样的操作,因为它的行为,
如编辑和选定文本等,都已经是标准化了的。虽然各种各样的控件各
有各的特点,但是,对于一类控件来说,它们的行为在某种意义是一
致的。(从这个意义上来说,这是面向对象程序设计的很大程度上的
优点所在。)
使用MFC编写的对话框应用程序和使用SDK编写的对话框应用程序在结
构上有着很大的不同。对于使用Visual C++的程序员来说,我们有充
分的理由使用MFC来编写这些应用程序,因此,我们在这里将不讲述
如何使用SDK编写的基于对话框的应用程序。
本章涉及的内容包括:
l 使用AppWizard生成基于对话框的框架应用程序
l 由CWinApp派生的应用程序类
l MFC的消息映射机制及其实现
l 对话框及由CDialog派生的对话框类
第一节 使用AppWizard生成应用程序框架
…………………………………………………………Page 160……………………………………………………………
在编写MFC应用程序时,我们通常使用AppWizard来生成应用程序框
架,然后再在此框架的基础上来添加特定于应用程序的功能的实现。
在计算机术语中,Wizard通常被译作向导 (AppWizard即应用程序向
导),它是这样的一种程序:你只需要回答一系列的与你所需完成的
操作有关的问题,Wizard就会 自动的完成其余的步骤,而这些步骤如
果通过手工来完成的话,将可能会耗费相当长的时间和精力 (但同时
我们也要向你指出,AppWizard所能够帮助你完成的,也只是一个应
用程序的框架。它所建立的,在绝大部分是我们在Windows 下程序设
计中所需要完成的例行化的工作)。在Visual C++中,一种被称作
AppWizard的向导,通过向你询问一些关于所需编写的应用程序各项
特性的问题,即可按照程序员的要求生成相应的框架文件,这些框架
文件本身就构成了一个完整的Windows应用程序,它实现了绝大多数
同类型的Windows所共有的一些特性和功能。
l 注意:
l 我们还想说明的一点是:AppWizard能够帮助我们建立起一个应用
程序的框架,但绝大多数的应用程序的代码还需要我们亲 自编
写。我们还从来没有看到仅仅通过AppWizard的代码就生成了一个
成功的程序。明白这一点是很重要的:AppWizard所做的,只不过
是我们在程序设计过程中所需要的最没有创意的那一部分事情。
真正应该 引起我们更多的重视的,是Visual C++的可视化的
界面生成。要知道,在可视化编程出现以前,为了一个简单
的框架,程序 员不得不重复干一些相当烦琐的工作:仅仅是
为了安排好一个对话框中的控件的位置,他们就不得不先在
稿纸上试着画布局图,写入程序,运行,再修改,再运
行。。。。你可以想见,这是一件多么烦琐乏味的工作 !
最后我们想提醒你,如果你不需要一个标准的Windows 程序
界面或者不需要AppWizard所提供的文档/视结构,使用
AppWizard并不一定是一个明智的选择。
…………………………………………………………Page 161……………………………………………………………
图4。 1 新建工程
使用AppWizard是一件简单和愉快的事情,并且,明白AppWizard所能
完成的和所不能完成的内容会在编程时少走很多的弯路,因此,我们
将在下面的过程中详细的讲述如何使用AppWizard创建基于对话框的
应用程序:
1。 选择文件菜单下的New命令 (出于排版方面的一些考虑,我们将参
考图形进行了一定程度的处理),如图4。1所示。
2。 从New对话框中选择Project选项卡。在Project name处输入工程
名,一般来说,工程的命名在一定程度上是任意的,这里我们假定工
程名为DialogDemo,在Location处输入保存工程的文件夹。然后在左
边的列表中确信选择了MFC AppWizard (exe),在Platform列表中确
信选择了Win32。完成之后单击OK进入下一步。
3。 随后弹出如图4。2所示的对话框。在该对话框中选择应用程序类型
为Dialog based,即基于对话框的应用程序。还可以在下面的下拉列
表框中选择应用程序资源所使用的语言。这里我们选择了简体中文,
即 “中文'中国'(APPWZCHS。DLL)”。这样,AppWizard为应用程序自
动创建的所有资源都将是中文的。单击Next进入下一步。
…………………………………………………………Page 162……………………………………………………………
图4。 2 使用AppWizard创建基于对话框的应用程序:第一步
l 注意:
l 在默认情况下,安装Visual C++时并没有安装支持远东语言的动
态链接库,这些语言包括简体中文、繁体中文、 日文和韩文等,
对这些语言的支持需要相应的双字节的操作系统。因此,在如 图
4。2所示的MFC AppWizard对话框中将不会看到这些语言的选择
项。为了添加对这些语言的支持,我们必须手动的将它们添加
Visual C++的安装 目录下。这些语言的支持文件在Visual C++安
装光盘上的DevStudioSharedIDEBinIDE 目录下,不同的语言
所对应的动态链接库的。DLL文件名如表4。1所示。
表4。 1 不同的远东语言所对应的支持文件
语言 支持该语言的动态
链接库
中文(简 APPWZCHS。DLL
体)
中文(繁 APPWZCHT。DLL
体)
日文 APPWZJPN。DLL
韩文 APPWZKOR。DLL
…………………………………………………………Page 163……………………………………………………………
如果在你的AppWizard中还没有添加对上面的这些语言的支持
文件,可以将它们从光盘上的
DevStudioSharedIDEBinIDE 目录中将它们复制到对应的
Visual C++安装 目录下,举个例子说,如果你的Visual C++
被安装到D:Program FilesDevStudio 目录下,对应的目录
将是D:Program FilesDevstudioSharedIDE BinIDE。然
后再在操作系统中安装对应的代码页。在很多情况下,我们
还需要重新启动Developer Studio或操作系统。
l 如果应用程序使用MFC的动态链接,还必须有相对应的MFC资源动
态链接库的本地化版本,它们位于Windows 系统 目录下,且具有
MFC40LOC。DLL的文件名。可以将Visual C++安装光盘上的
MFCincludeL。XXXMFC40XXX。DLL 目录下的对应DLL文件复制到
Windows的系统 目录下,然后将其改名为MFC40LOC。DLL。详细的内
容可以参考帮助中的Microsoft Foundation Class
ReferenceMFC Technical Notes节点下的文章TN056和TN057。
l 如果你使用的是Visual C++的专业版或企业版,还可以在应用程
序中使用MFC的静态链接。这时,需要在MFC'src|include'
L。XXX*。rc 目录下有正确的本地化的MFC资源文件。这些文件可
以在Visual Studio的第一章安装光盘上的对应 目录中找到。
4。 在如图4。3所示的对话框中为应用程序选择合适的特性。该对话框
中各选项的含义如下:
About box: 如果选择了该选项,AppWizard将为一个
被称为 “关于”对话框的消息框生成代
码,该消息框用来显示应用程序的版本
号和版权信息等。绝大多数的Windows应
用程序都具有一个关于对话框,图4。4是
Microsoft Word 95 的 “关于”对话框。
在默认情况下,使用AppWizard创建的应
用程序,都具有一个 “关于”对话框。
Context 该选项决定是否让AppWizard为应用程序
sensitive 创建上下文相关的帮助文件。需要注意
help: 的是,对帮助的支持需要帮助编译器
(help piler),如果在你的Visual
C++中没有安装帮助编译器的话,可以重
新运行Setup程序来安装它。
…………………………………………………………Page 164……………………………………………………………
3D 决定是否在应用程序中使用具有三维阴
controls: 影的用户界面。使用了三维外观的应用
程序界面看起来象那些在Windows的早期
版本 (如Windows 3。x)下运行的程序的外
观。默认情况下,使
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!