Visual C++ 基本原理.docx
- 文档编号:18394657
- 上传时间:2023-08-16
- 格式:DOCX
- 页数:50
- 大小:52.60KB
Visual C++ 基本原理.docx
《Visual C++ 基本原理.docx》由会员分享,可在线阅读,更多相关《Visual C++ 基本原理.docx(50页珍藏版)》请在冰点文库上搜索。
VisualC++基本原理
VisualC++基本原理
FAQ
问:
阅读以下文章需要具备哪些知识?
答:
只要会开机就行了,如果大家有C++和面向对象(Object-Oriented)的基础知识,会有事半功倍的效果。
问:
必须具备哪些软件?
答:
Windows98,WindowsNT,Windows2000中的任意一种,另外再加上VisualC++5.0或6.0。
由于我没有测试过Windows95和VisualC++5.0以下的版本,所以不知道他们可不可用。
问:
为什么用VisualC++?
答:
因为VC功能强而多。
基本概念
心情随笔:
其实这一章是最枯燥的,概念又多,本来我不想写这一章的,但为了照顾初学者,我觉得还是有必要讲一下。
由于这一章是属于”入门篇”的,所以大家只需要了解以下内容就行了,不需要深入研究其原理,到了”高级篇”时,我们还会重新仔细分析其原理的,希望大家不会被这一章的内容吓跑,有问题就去本站的留言本留言吧。
首先我们要了解以下概念:
应用程序(Application),他就是由指令(Instruction)组成的可以运行的文件。
进程(Process),有时和应用程序的意思一样,但在通常的情况下,进程是指一个正在运行的应用程序,正因为这样,进程由以下部分组成:
1、一个可以执行的程序
2、位于内存(Memory)中的私有地址空间
3、系统资源(SystemResource),例如文件(File),管道(Pipe),通讯端口(CommunicationsPort),信号(Semaphore)
4、至少还要有1个线程(Thread),线程是最基本的执行单位。
因为多个进程是可以同时存在时,所以Windows操作系统(OperatingSystem)必须给进程提供保护,以防止他们冲突。
物理内存(PhysicalMemory),即你的计算机的实际内存,例如我现在用的电脑的内存是128M,物理内存的容量是达不到程序的要求的,于是就产生了虚拟内存(VirtualMemory)。
虚拟内存(VirtualMemory),不是真正的内存,它通过映射(Map)的方法,使可用的虚拟地址(VirtualAddress)达到4G(2的32次方),每个应用程序可以被分配2G的虚拟地址,剩下的2G留给操作系统自己用。
在WindowsNT中,应用程序可以有3G的虚拟地址。
简单的说,虚拟内存的实现方法和过程是:
1、当一个应用程序被启动时,操作系统就创建一个新进程,并给每个进程分配了2G的虚拟地址(不是内存,只是地址);
2、虚拟内存管理器(VirtualMemoryManager)将应用程序的代码(Code)映射到那个应用程序的虚拟地址中的某个位置,并把当前所需要的代码读取到物理地址中。
注意,虚拟地址和应用程序代码在物理内存中的位置是没有关的;
3、如果你有使用动态链接库(Dynamic-LinkLibrary,即DLL)的话,DLL也被映射到进程的虚拟地址空间,在有需要的时候才被读入物理内存;
4、其他项目(例如数据,堆栈等)的空间是从物理内存分配的,并被映射到虚拟地址空间中;
5、应用程序通过使用它的虚拟地址空间中的地址开始执行,然后虚拟内存管理器把每次的内存访问映射到物理位置。
如果大家看不明白上面的步骤也不要紧(似乎超出了入门篇的范围),但大家要明白以下两点:
1、应用程序是不会直接访问物理地址的;
2、虚拟内存管理器通过虚拟地址的访问请求,控制所有的物理地址访问;
使用虚拟内存的好处是:
简化了内存的管理,并可以弥补物理内存的不足;可以防止在多任务(Multitasking)环境下的各个应用程序之间的冲突。
线程(Thread),是最基本的执行单位,CPU时间就是分配给每个线程的。
每个进程一开始时只有一个线程,但每个线程都可以产生出其他线程,前者叫做父线程(ParentThread),后者叫做子线程(ChildThread)。
每个执行的线程都有自己的虚拟输入队列(VirtualInputQueue),用来处理来自硬件、处理器(Processor)或操作系统的消息(Message)。
这些队列都是异步的,也就是说,当处理器发送一个消息给另外一个线程的队列时,发送函数不用等待其他线程处理该消息就可返回,而接收消息的线程可以等到该线程准备好时再访问并处理接收到的消息。
多线程(Multithread),如果一个进程中有多个线程同时存在,就叫做多线程了。
多任务(Multitasking),即多个程序看起来好像是在同时执行,其实并不是同时的,只不过因为时间太短,人类感觉不出来而已。
其原理是操作系统分配给每个线程一个非常短(大约百分之秒)的时间片,每个线程轮流切换执行,这个过程叫做场境转换(ContextSwitching)。
场境转换(ContextSwitching),是指:
1、运行一个线程直到该线程的时间片用完,或者这个线程必须等待其他的资源;
2、保存这个线程的场境;
3、取出其他线程的场境;
4、只要有线程在等待执行,就会不停的重复以上过程。
RawInputThread(RIT),是指用来接收所有由键盘和鼠标产生的事件(Event)的线程,它是一个特殊的系统线程,每当RIT接收到处理器发出的硬件(Hardware)事件,它就把那些事件放到相应线程的虚拟输入队列中。
因此,应用程序的线程通常是不用等待它的硬件事件的。
事件驱动(Event-Driven)编程,Windows-based的应用程序运行后,就会一直等待,直到有用户发布命令(例如:
按一个按钮或选中一个菜单)之类的事件发生,这就叫做事件驱动编程(Event-DrivenProgramming)。
它同DOS下的应用程序的最大区别就是:
DOS下的应用程序是通过命令行加参数的方法来控制应用程序的执行,而Windows-based的应用程序是通过图形用户界面(GUI)来控制应用程序的执行。
用户所产生的事件,在程序里就会转化为消息,不同的事件产生不同的消息,从而可以产生不同的响应。
终于讲完这一节了,大家看得明白吗?
如果不明白的话,那就一字一句的从头到尾再看一遍吧。
如果还不明白,那就请跳过这一节吧,我在后面的章节中还会逐步解释这些概念的。
在本章的最后一节我将会举一个具体的程序来说明Windows-based应用程序的结构和组成元素。
以下是本节出现的专业名词
应用程序=Application
指令=Instruction
进程=Process
内存=Memory
系统资源=SystemResource
文件=File
管道=Pipe
通讯端口=CommunicationsPort
信号=Semaphore
线程=Thread
物理内存=PhysicalMemory
虚拟内存=VirtualMemory
映射=Map
虚拟地址=VirtualAddress
虚拟内存管理器=VirtualMemoryManager
代码=Code
动态链接库=Dynamic-LinkLibrary,即DLL
数据=Data
堆栈=Stack
多任务=Multitasking
父线程=ParentThread
子线程=ChildThread
多线程=Multithread
场境转换=ContextSwitching
虚拟输入队列=VirtualInputQueue
处理器=Processor
操作系统=OperatingSystem
消息=Message
队列=Queue
RawInputThread=RIT
事件=Event
硬件=Hardware
事件驱动=Event-Driven
事件驱动编程=Event-DrivenProgramming
图形用户界面=GUI
Windows下的程序的结构和组成元素
Windows下的程序的基本组成元素是代码,用户界面资源(UserInterfaceResource)和动态链接的库模块(LibraryModule)。
代码,是应用程序的主要内容,Windows下的应用程序必须要有两个函数:
1、WinMain,它为操作系统提供了进入点(EntryPoint),是所有Windows-Based应用程序都必须要有的函数。
它也用来创建初始Window和启动Message检索;
2、WindowProcedure,它用于处理所有从操作系统发送到Window的Message,每一个Window都有一个相关联的WindowProcedure。
WindowProcedure用来决定Window的ClientArea(即客户窗口,例如Notepad中用来写字的空白部分)显示什么以及如何响应用户的输入。
WindowProcedure处理Message时,既可以用专门添加的代码来处理Message,也可以直接把Message传递给默认的WindowProcedure——DefWindowProc。
一个Windows-Based应用程序可以包含多个不同名的WindowProcedure。
用户界面资源,菜单(Menu),对话框(Dialogbox)等图形用户界面的元素,就叫做资源。
它们被当成模板(Template)储存在相应的可执行文件或DLL文件的只读(Read-Only)区域,当有需要时,Windows就调用这个资源区域并动态创建所需要的GUI元素。
主要有以下几种资源:
Accelerator(快捷键表),储存快捷键和相应的命令
Bitmap(位图),一种图形格式
DiabloBox,包含对话框的控件(Control),布局和属性的细节
Icon(图标),一种特殊的位图
Menu(菜单),包含菜单及其选项的文本和布局
StringTable(字符串表),储存字符串及其ID
Toolbar(工具栏),包含工具栏的布局和按钮的位图
Version(版本),储存程序的状态信息,例如程序名,作者,版权,版本号等
Cursor(光标),包含用于绘制光标的特殊的位图
库模块,主要是指在运行时可以被动态链接的二进制文件,即DLL。
默认的WindowProcedure——DefWindowProc,是Windows系统提供的一个函数,用于处理某些通用的Win32-based应用程序的Messages(例如最大化、最小话窗口,显示目录等)。
如果DefWindowProc不能处理该Message,那么它就被忽略。
当一个应用程序被启动时,将会按顺序发生下列事件(上一节也提到过这个问题)
1、操作系统创建一个新进程和一个起始线程;
2、应用程序的代码被载入内存;
3、DLL也被载入内存(如果有的话);
4、从物理内存分配其他项目(例如数据,堆栈等)的空间,并被映射到虚拟地址空间中;
5、应用程序开始执行。
在Windows-Based应用程序中,Windows是应用程序和用户之间传递信息的主要方法。
Windows-Based的应用程序为了接收从系统队列传来的Message,是通过以下方法实现的:
1、当Windows-Based的应用程序启动后,操作系统和这个应用程序就通过进入点(WinMain函数)联系起来。
2、应用程序创建一个或多个Windows,每个Window都包含有一个WindowProcedure函数,用来决定Window显示什么以及Window如何响应用户的输入。
3、有专门的代码将Message队列中的Message循环检索出来,并传递给相应的WindowProcedure,而不是直接传给Window。
这样就可以使应用程序在Message被送到Window之前预先处理它。
到了下一节,我们将会用一个简单的源程序说明以上元素和步骤。
以下是本节新出现的专业名词
用户界面资源=UserInterfaceResource
库模块=LibraryModule
进入点=EntryPoint
客户窗口=ClientArea(例如Notepad中用来写字的空白部分)
菜单=Menu
对话框=Dialogbox
模板=Template
只读=Read-Only
控件=Control
快捷键表=Accelerator
位图=Bitmap
图标=Icon
字符串表=StringTable
工具栏=Toolbar
版本=Version
光标=Cursor
动态链接=DynamicLinking
源程序示例
本节列出了一个简单的源程序,来说明上两节的内容。
请大家结合上两节的内容来看看下面的源程序,不需要完全看懂,只用理解大概的框架和流程就行了,注意黑体字部分。
源程序如下:
//摘自
//包含头文件windows.h
#include
//预先声明MessageHandler,可以叫做任何名字,这里是MyWindowProcedure
LRESULTCALLBACKMyWindowProcedure(HWND,UINT,WPARAM,LPARAM);
//以下是所有Windows程序都需要的WinMain函数
//WinMain主要用来实现三个功能:
//1.注册WindowClass;
//2.在内存中创建Window并初始化Window的属性;
//3.创建一个MessageLoop来检查MessageQueue中有没有该Window的Message。
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpszCmdLine,intnCmdShow)
{
staticcharszAppName[]=“WinHello”;//定义一个字符串
HWNDhwnd;//定义一个WindowHandle变量
MSGmsg;//定义一个Message结构的变量,用来储存Message的信息
WNDCLASSwc;//定义一个WindowClass数据结构,用来储存WindowClass的属性
//下面这段代码用来定义Window的属性,例如MessageHandler的地址、窗口背景、光标和图标等
wc.style=CS_HREDRAW|CS_VREDRAW;//设置style:
当窗口改变大小时就重新绘制窗口
wc.lpfnWndProc=(WNDPROC)MyWindowProcedure;//设定WindowProcedure
wc.cbClsExtra=0;//用来储存ClassStructure后的额外的数据,这里不需要
wc.cbWndExtra=0;//用来储存WindowInstance后的额外的数据,这里不需要
wc.hInstance=hInstance;//WindowProcedure所在的Instance
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);//class的图标
wc.hCursor=LoadCursor(NULL,IDC_ARROW);//class的光标
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);//背景刷
wc.lpszMenuName=NULL;//菜单资源的名字,这里没有
wc.lpszClassName=szAppName;//应用程序的名字
//注册Window,通过调用API函数RegisterClass来实现
//注册WindowClass的一个目的就是将Window和WindowProcedure关联起来
RegisterClass(&wc);
//注册WindowClass后,WinMain就调用CreateWindow函数来创建应用程序的Window
hwnd=CreateWindow(
szAppName,//已注册的Class名字
“Hello,World–Windows_98Style”,//Window名字
WS_OVERLAPPEDWINDOW,//Window风格
CW_USEDEFAULT,//Window起点的X坐标
CW_USEDEFAULT,//Window起点的Y坐标
CW_USEDEFAULT,//Window的宽度
CW_USEDEFAULT,//Window的高度
HWND_DESKTOP,//父窗口的handle
NULL,//菜单的handle
hInstance,//应用程序instance的handle
NULL//window-creation数据的指针
);
//以下两条语句用来显示Window
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//用while循环语句来检索并发送Messages
//从MessageQueue中检索Message,并将它放到变量msg中。
//当收到”WM_QUIT”这个Message时,GetMessage函数就返回0,循环结束。
而且WinMain函数也结束,程序终止。
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);//将Virtual-KeyMessages转化为CharacterMessages
DispatchMessage(&msg);//将Message发送到WindowProcedure
}
returnmsg.wParam;
}
//MyWindowProcedure函数处理WM_PAINT和WM_DESTROY这两个Message,然后必须调用DefWindowProc去处理其他Message
LRESULTCALLBACKMyWindowProcedure(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAMlParam)
{
PAINTSTRUCTps;//定义一个PAINTSTRUCT结构的变量,用来储存绘制Window的ClientArea的信息
HDChdc;//定义一个HDC变量
LPCTSTRtext=”Welcome!
”;//定义一个LPCTSTR类型的字符串指针
//用switch语句来处理WM_PAINT和WM_DESTROY这两个Message
switch(message)
{
caseWM_PAINT:
//下面5条语句是用来在屏幕上输出文字的,我们在后面的章节会详细讨论这个问题的,这里就不多说了
hdc=BeginPaint(hwnd,&ps);
RECTrect;
GetClientRect(hwnd,&rect);
TextOut(hdc,(rect.right-rect.left)/2,(rect.bottom-rect.top)/2,text,strlen(text));
EndPaint(hwnd,&ps);
return0;
//处理退出消息
caseWM_DESTROY:
PostQuitMessage(0);
return0;
}
//调用默认的WindowProcedure,使所有Message都可以被处理
returnDefWindowProc(hwnd,message,wParam,lParam);
}
运行上面程序的步骤:
1、选菜单File–>New…–>Projects–>Win32Application
2、在ProjectName中输入vchack_01_002_003(其它名字也行)
3、其他地方就保留默认值就行了,然后按”OK”
4、选中”Anemptyproject”,然后按”Finish”
5、再按次”OK”
6、按Toolbar上的按钮”NewTextFile”新建一个空白文件
7、将以上源程序复制到那个空白文件中,然后按Toolbar上的按钮”Save”来储存文件,文件名为vchack_01_002_003.cpp
8、按左下角的”FileView”,然后按”vchack_01_002_003files”旁边的”+”号展开这个目录
9、在”SourceFiles”上按鼠标右键,选”AddFilestoFolder…”
10、选中vchack_01_002_003.cpp这个文件,然后按”OK”
11、选”Build”菜单中的”Buildvchack_01_002_003.exe”
12、选”Build”菜单中的”Executevchack_01_002_003.exe”来运行这个程序
以下是本节新出现的专业名词
类=Class
窗口类=WindowClass
数据结构=DataStructure
消息处理器=MessageHandler
实例=Instance
句柄=Handle
工程=Project
MFC简介
微软基础类库(MicrosofFoundationClassLibrary)和VisualC++提供了一个创建各种各样应用程序的环境,并简化了其中部分工作。
MFCLibrary是Class的集合,大约有250个Class,在很大程度上扩展了C++语言;MFCLibrary也是一个应用程序框架(ApplicationFramework),它定义了应用程序的结构(当然你也可以用源程序一行一行地写出自己的应用程序结构,不过这样比较麻烦),并可以处理应用程序的一些常规任务。
如果你想用MFC进行程序开发,首先你必须熟悉MFC所包含的Class以及各个Class之间的关系。
MFCClass是有层次的(MFC的层次图请看Class)一般不直接使用。
为了学习的方便,一般将MFCClass划分为以下几个种类:
CObject-DerivedClasses
ApplicationArchitectureClasses
User-InterfaceClasses
General-PurposeClasses
ActiveXClasses
DatabaseClasses
InternetClasses
GlobalAfxFunctions
以上划分的种类之间决不是相互独立的,大多数的MFCClasses是直接或间接从CObjectClass派生的,CObje
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Visual C+ 基本原理