《Windows程序的内部运行原理》由会员分享,可在线阅读,更多相关《Windows程序的内部运行原理(34页珍藏版)》请在金锄头文库上搜索。
1、WindowsWindows程序的程序的内部运行原理内部运行原理Windows程程序序设设计计是是完完全全不不同同于于Dos环环境境下下的的程程序序设设计计,是是一一种种事事件件驱驱动动的的程程序序设设计计方方法法。主主要要是是基基于于消消息息的的。当当用用户户需需要要完完成成某某种种功功能能时时,会会调调用用OS的的某某种种支支持持,OS将将用用户户的的需需要要包包装装成成某某种种消消息息,并并投投递递到到消消息息队队列列当当中中。然然后后利利用用应应用用程程序序从从消消息息队队列中取走消息并进行响应。列中取走消息并进行响应。操作系统操作系统输入输出设备输入输出设备应用程序应用程序消息队列消
2、息队列操作系统能操作系统能操纵输入输操纵输入输出设备,以出设备,以执行特定的执行特定的功能功能操作系统能操作系统能感知输入输感知输入输出设备的状出设备的状态变化态变化 应用程序可应用程序可以通知操作以通知操作系统执行某系统执行某个具体的动个具体的动作作 操作系统能操作系统能够将输入设够将输入设备的变化上备的变化上传给应用程传给应用程序序 在应用程序中要完成某个功能,都是以函数调用的形式实现的,在应用程序中要完成某个功能,都是以函数调用的形式实现的,同样,应用程序也是以函数调用的方式来通知操作系统执行相同样,应用程序也是以函数调用的方式来通知操作系统执行相应的功能的。操作系统所能完成的每一个特殊
3、功能通常都有一应的功能的。操作系统所能完成的每一个特殊功能通常都有一个函数与其对应。也就是说,操作系统把它能完成的功能以函个函数与其对应。也就是说,操作系统把它能完成的功能以函数的形式提供给应用程序使用,应用程序对这些函数的调用就数的形式提供给应用程序使用,应用程序对这些函数的调用就叫做系统调用。这些函数的集合就是叫做系统调用。这些函数的集合就是windows操作系统提供给操作系统提供给应用程序的编程接口,即应用程序的编程接口,即API。如。如CreateWindow就是一个就是一个API函数,应用程序中调用这个函数,操作系统就会按照该函数提函数,应用程序中调用这个函数,操作系统就会按照该函数
4、提供的参数信息产生一个相应的窗口。供的参数信息产生一个相应的窗口。 应用程序如何通知操作系统应用程序如何通知操作系统执行某个功能执行某个功能比如用户在某个程序活动时按下一个键,操作系统马上能够感比如用户在某个程序活动时按下一个键,操作系统马上能够感知到这一事件,并且能知道用户按下的是哪个键,操作系统并知到这一事件,并且能知道用户按下的是哪个键,操作系统并不决定对这个事件如何做出反应,而是将这一事件转交给应用不决定对这个事件如何做出反应,而是将这一事件转交给应用程序,由应用程序决定如何对这一事件做出反应。程序,由应用程序决定如何对这一事件做出反应。好比有只蚊子叮了我们一口,我们的神经末梢(相当于
5、操作系好比有只蚊子叮了我们一口,我们的神经末梢(相当于操作系统)马上感知到这一事件,并传递给我们的大脑(相当于应用统)马上感知到这一事件,并传递给我们的大脑(相当于应用程序)。我们的大脑最终决定如何对这一事件做出反应,如将程序)。我们的大脑最终决定如何对这一事件做出反应,如将蚊子赶走,或是将蚊子拍死。对事件做出反应的过程就是消息蚊子赶走,或是将蚊子拍死。对事件做出反应的过程就是消息响应。响应。操作系统能够将输入设备的变化操作系统能够将输入设备的变化上传给应用程序上传给应用程序操作系统是怎样将感知到的事件传递给应用程序的呢?操作系统是怎样将感知到的事件传递给应用程序的呢?这是通过消息机制(这是通
6、过消息机制(Message)来实现的。操作系统将每个事)来实现的。操作系统将每个事件都包装成一个称为消息的结构体件都包装成一个称为消息的结构体MSG来传递给应用程序。来传递给应用程序。typedef struct tagMSG HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; MSG; 关于消息和消息队列关于消息和消息队列窗口句柄消息的名字消息的附加参数窗口是屏幕上的一个矩形区域,应用程序窗口是屏幕上的一个矩形区域,应用程序在该区域中显示数据并等待鼠标点击。在该区域中显示数据并等待鼠标点击。
7、WindowsWindows应用程序的用户界面可以包含许多应用程序的用户界面可以包含许多窗口,当然要对这些窗口进行标识。窗口,当然要对这些窗口进行标识。窗窗 口口操作系统要管理和操作这些资源,都是通过句柄来找到对应操作系统要管理和操作这些资源,都是通过句柄来找到对应的资源。按资源的类型,又可将句柄细分成的资源。按资源的类型,又可将句柄细分成图标句柄(图标句柄(HICON)、光标句柄()、光标句柄(HCURSOR),),窗口句柄(窗口句柄(HWND),应用程序实例句柄(),应用程序实例句柄(HINSTANCE)等各种类型的句柄。等各种类型的句柄。操作系统给每一个窗口指定的一个唯一的标识号即窗口句
8、柄。操作系统给每一个窗口指定的一个唯一的标识号即窗口句柄。句柄就是资源的标识,就象指针一样,我们要索引这样一个句柄就是资源的标识,就象指针一样,我们要索引这样一个资源,就需要通过句柄去索引它。资源,就需要通过句柄去索引它。句柄:句柄: 资源的标识资源的标识int x,y; x=30,y=40;/x和和y既可以用来表示坐标点,也可以用来表示宽度和既可以用来表示坐标点,也可以用来表示宽度和高度,还可以用来表示身高和体重。高度,还可以用来表示身高和体重。typedef int WIDTH;typedef int HEIGHT;WIDTH x;HEIGHT y;/好处:我们从变量的类型就可以知道好处:
9、我们从变量的类型就可以知道x和和y是用来表示是用来表示宽度和高度。宽度和高度。从变量的类型区分变量的用途从变量的类型区分变量的用途操操作作系系统统会会为为每每个个应应用用程程序序建建立立一一个个消消息息队队列列。这这个个队队列列是是个个先先进进先先出出的的缓缓冲冲区区。消消息息队队列列中中的的每每个个元元素素都都是是一一条条消消息息。操操作作系系统统将将生生成成的的消消息息放放在在消消息息队队列列里里。第第一一条条消消息息放放入入第第一一格格,第第二二条条消消息息放放入入第第二二格格,依依次次类类推推。应应用用程程序序总总是是取取走走消消息息队队列列中中的的第第一一条条消消息息。第第一一条条消
10、消息息取取走走后后,第第二二条条消消息息往往前前移移,成成为为第第一一条条,剩剩余余的的消消息息依依次次前前移移。应应用用程程序序取取得得消消息息后后,便便能知道用户的操作以及应用程序的状态的变化。能知道用户的操作以及应用程序的状态的变化。当当收收到到消消息息的的时时候候,会会编编写写针针对对这这个个消消息息的的处处理理代代码码,这这个个过过程程就就叫叫消消息息响响应应。消消息息响响应应是是通通过过程程序序实实现现的的,这这就就是是WindowsWindows应用程序的主要代码区。应用程序的主要代码区。消息队列消息队列消息队列消息队列PostMessageSendMessage在在消消息息响响
11、应应过过程程中中,我我们们可可能能要要调调用用操操作作系系统统提提供供的的其其他他APIAPI函函数数以以便便完完成成特特定定的的功功能能。例例如如收收到到窗窗口口关关闭闭的的消消息息,我我们们就就可可以以调调用用一一个个销销毁毁窗窗口口的的APIAPI函函数数DestroyWindowsDestroyWindows去去关关闭闭该该窗窗口口,或者弹出一个消息框提示用户是否真的要关闭该窗口。或者弹出一个消息框提示用户是否真的要关闭该窗口。消息队列消息队列Windows程序的入口函数程序的入口函数int APIENTRY _tWinMain ( HINSTANCE hInstance, HINST
12、ANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);WinMain函数函数实例句柄:当运行一个程序的时候,这个运行的程序就叫实例。先前应用程序实例句柄命令行参数显示的状态(1)设计一个窗口类)设计一个窗口类(2)注册窗口类)注册窗口类(3)创建窗口)创建窗口(4)显示及更新窗口)显示及更新窗口窗口的创建窗口的创建设计窗口类设计窗口类窗口类的类型Typedef struct tagWNDCLASSEXW UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndE
13、xtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; HICON hIconSm; WNDCLASSEXW#ifdef UNICODEtypedef WNDCLASSEXW WNDCLASSEX;在我们的程序中经常要用到一类变量,这个变量里的在我们的程序中经常要用到一类变量,这个变量里的每一位每一位(bit)都对应某一特性。当该变量的某位为都对应某一特性。当该变量的某位为1时,时,表示有该位对应的哪种特
14、性,当该位为表示有该位对应的哪种特性,当该位为0时,即没有该时,即没有该位所对应的特性。当变量中的某几位同时为位所对应的特性。当变量中的某几位同时为1时,就表时,就表示同时具有几种特性的组合。一个变量中的哪一位代示同时具有几种特性的组合。一个变量中的哪一位代表哪种意义,不容易记忆,所以根据特征的英文拼写表哪种意义,不容易记忆,所以根据特征的英文拼写的大写去定义一些宏,该宏所对应的数值中仅有与该的大写去定义一些宏,该宏所对应的数值中仅有与该特征相对应的那一位为特征相对应的那一位为1,其余的位都为,其余的位都为0。CS_VREDRAW=0X0001, CS_HREDRAW=0X0002, CS_D
15、BLCKS=0X0008, CS_NOCLOSE=0X0200。它。它们的共同点就是只有一位为们的共同点就是只有一位为1,其余位都为,其余位都为0.窗口类的类型窗口类的类型如果希望某一变量的数值既有如果希望某一变量的数值既有CS_VREDRAW特性,特性,又有又有CS_HREDRAW特性,只需使用二进制特性,只需使用二进制OR操作操作符符将它们进行或运算相组合。将它们进行或运算相组合。如如style=CS_VREDRAW| CS_HREDRAW| CS_NOCLOSE。如果希望在某一变量原有的几个特征上去掉其中一个如果希望在某一变量原有的几个特征上去掉其中一个特征,用取反之后再进行与运算就能够
16、实现。特征,用取反之后再进行与运算就能够实现。如如styl& CS_NOCLOSE。窗口类的类型窗口类的类型设计窗口类设计窗口类窗口过程函数typedef struct tagWNDCLASSEXW UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; HICO
17、N hIconSm; WNDCLASSEXW回调函数的原理回调函数的原理:当应用程序收到给某一窗口的消息时:当应用程序收到给某一窗口的消息时(消息通常与窗口相关),就应该调用某一函数来处理这(消息通常与窗口相关),就应该调用某一函数来处理这条消息。这一调用过程不用应用程序自己来实施,而由操条消息。这一调用过程不用应用程序自己来实施,而由操作系统来完成,但是,回调函数本身的代码必须由应用程作系统来完成,但是,回调函数本身的代码必须由应用程序自己完成。对于一条消息,操作系统到底调用应用程序序自己完成。对于一条消息,操作系统到底调用应用程序中的哪个函数(回调函数)来处理呢?操作系统调用的就中的哪个函
18、数(回调函数)来处理呢?操作系统调用的就是接受消息的窗口所属的类型中的是接受消息的窗口所属的类型中的lpfnWndProc成员指成员指定的函数。每一种不同类型的窗口都有自己专用的回调函定的函数。每一种不同类型的窗口都有自己专用的回调函数,该函数是通过数,该函数是通过lpfnWndProc成员指定的。成员指定的。 窗口过程函数窗口过程函数汽车厂家生产汽车好比应用程序创建窗口,用户使用汽车厂家生产汽车好比应用程序创建窗口,用户使用汽车好比操作系统管理窗口,某种汽车在销售前就指汽车好比操作系统管理窗口,某种汽车在销售前就指定好了修理站(类似回调函数),当用户的汽车出现定好了修理站(类似回调函数),当
19、用户的汽车出现故障后(类似窗口接受到消息),汽车用户(类似操故障后(类似窗口接受到消息),汽车用户(类似操作系统)自己直接找到修理站去修理,不用厂家(类作系统)自己直接找到修理站去修理,不用厂家(类似应用程序)亲自将车送到修理站去修理,但修理站似应用程序)亲自将车送到修理站去修理,但修理站还得由厂家事先建造好。还得由厂家事先建造好。窗口过程函数窗口过程函数typedef struct tagWNDCLASSEXW UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hIn
20、stance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBac kground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; HICON hIconSm; WNDCLASSEXW设计窗口类设计窗口类类的额外参数窗口的实例句柄光标的句柄画刷的句柄菜单的名字类的名字图标的句柄小图标的句柄创建窗口创建窗口HWND CreateWindow( HWND CreateWindow( LPCTSTRLPCTSTR lpClassName, , /已注册的窗口类的名字LPCTSTRLPCTSTR lpWindowName,
21、 , / 窗口的名字,即标题栏上显示的文字 DWORDDWORD dwStyle, , / 窗口的类型 intint x, , / 窗口显示时左上角的x坐标intint y, , /窗口显示时左上角的y坐标intint nWidth, , / 窗口宽度 intint nHeight, , / 窗口高度 HWNDHWND hWndParent, , / 父窗口的句柄 HMENUHMENU hMenu, , / 菜单的句柄 HINSTANCEHINSTANCE hInstance, , / 实例的句柄 LPVOIDLPVOID lpParam / 与窗口相关的附加参数 ););消息循环消息循环hA
22、ccelTable =LoadAccelerators(hInstance,MAKEINTRESOURCE(IDC_WINMAIN2); 装载指定的加速键表。(加速键就是比如你按Ctrl+N会新建文档,Ctrl+S会保存文档,这些组合键就是加速键。使用加速键首先要建立加速键的资源,然后在程序初始化的时候LoadAccelerators,然后在WinMain主消息循环中调用TranslateAccelerator)GetMessage是从消息队列中取消息,操作系统会为是从消息队列中取消息,操作系统会为每个应用程序建立一个消息队列。每个应用程序建立一个消息队列。BOOL GetMessage( L
23、PMSG lpMsg, / 消息消息 HWND hWnd, / 窗口句柄,表明从哪个窗口的消息队列中取消息。窗口句柄,表明从哪个窗口的消息队列中取消息。 UINT wMsgFilterMin, / 消息的最小值消息的最小值 UINT wMsgFilterMax / 消息的最大值消息的最大值 );消息循环消息循环通过指定消息的通过指定消息的范围来过滤消息。范围来过滤消息。如果都为如果都为0,则,则没有消息的过滤没有消息的过滤消息循环消息循环TranslateAccelerator(msg.hwnd, hAccelTable, &msg);(当你定义的组合键出现时,该函数会把这个组合键消息翻译成h
24、wnd对应的窗口的WM_COMMAND消息,并直接Send到窗口过程,得到处理后该函数才返回)该函数翻译成功时返回非0值,如果失败,则返回0值即成功时就不需再调用TranslateMessage和DispatchMessage函数BOOL TranslateMessage( const MSG *lpMsg );/翻译消息翻译消息就是对取到的消息对进行转换。就是对取到的消息对进行转换。当当我我们们按按下下键键盘盘上上的的某某一一个个按按键键时时,系系统统会会产产生生WM_KEYDOWN和和WM_KEYUP两两个个消消息息,并并且且参参数数中中提提供供这这个个键键的的虚虚拟拟扫扫描描码码。但但用
25、用户户按按下下某某个个键键,可可能能需需要要知知道道具具体体按按下下的的是是哪哪个个字字符符,在在消息的附加参数中提供该键的消息的附加参数中提供该键的ASCII码。码。TranslateMessage会会将将WM_KEYDOWN和和WM_KEYUP两两个个消消息息转转换换成成WM_CHAR消消息息,并并且且将将转转换换好好的的消消息息投投递递到到消消息息队队列列中中。这这个个转转换换过过程程不不会会影影响响原原来来的的消消息息,只只会会产产生生一一个个新新消消息息。如如果我们不用这个函数,则收不到果我们不用这个函数,则收不到WM_CHAR消息。消息。消息循环消息循环DispatchMessag
26、e函函数数的的作作用用是是将将收收到到的的消消息息传传给给窗窗口口的的回回调调函函数数,即即窗窗口口过过程程函函数数去去处处理理。可可以以这这样样理理解解,该该函函数数将将消消息息路路由由给给了了操操作作系系统统,操操作作系系统统通通过过调调用用窗窗口口过过程程函函数数去去处处理理消消息息。这这个个窗窗口口过过程程函函数数就是在就是在设计窗口类时设计窗口类时指定的。指定的。每每当当从从消消息息队队列列中中取取到到一一条条消消息息时时,都都会会调调用用窗窗口口过过程程函函数数。因因此此在在该该函函数数中中我我们们要要判判读读是是哪哪个个消消息息。用用的是的是SWITCH语句。语句。消息循环消息循
27、环设计窗口类设计窗口类窗口过程函数typedef struct tagWNDCLASSEXW UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBac kground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; HICON hIconSm; WNDCLASSEXW是是调调用用的的约约定定。vc+中中有有2种种调调用用约约定
28、定。一一种种是是标标准准的的调调用用约约定定,一一种种是是C语语言言的的调调用用约约定定。标标准准的的调调用用约约定定就就是是PASCAL的的调调用用。主主要要是是参参数数传传递递的的顺顺序序以以及及堆堆栈栈的的清清除除有有些些差差异异。除除了了可可变变参参数数的的函函数数外外,其其余余的的函函数数都都是是STDCALL的的调调用用习习惯惯,但但是是c+的的编编译译环环境境,缺缺省省下下是是cdecl的的调调用用约约定定。所所以以在在vc+中中要要调调用用stdcall这这样样调调用用约约定定的的API函函数数的的话话,就就要要在函数原型前说明在函数原型前说明stdcall,回调函数也应该是。
29、,回调函数也应该是。CALLBACK操作系统会在多个不同的时机发送操作系统会在多个不同的时机发送WM_PAINT消息:消息:(1)当第一次创建一个窗口时)当第一次创建一个窗口时(2)当改变窗口的大小时)当改变窗口的大小时(3)当把窗口从另一个窗口背后移出时)当把窗口从另一个窗口背后移出时(4)当最大化或最小化窗口时等等)当最大化或最小化窗口时等等这这些些动动作作都都是是由由系系统统管管理理的的,应应用用只只是是被被动动地地接接收收该该消消息,在消息响应中进行绘制操作;息,在消息响应中进行绘制操作; WM_PAINT消消 息息Windows程序的生与死程序的生与死(1)程序初始化过程中调用)程序
30、初始化过程中调用CreateWindow,为程序,为程序建立一个窗口。建立一个窗口。CreateWindow产生窗口之后会发送产生窗口之后会发送WM_CREATE消息给窗口函数。消息给窗口函数。(2)在程序运行的过程中,不断用)在程序运行的过程中,不断用GetMessage函数函数从消息队列中抓取消息。如果该消息是从消息队列中抓取消息。如果该消息是WM_QUIT,GetMessage会传回会传回0而结束而结束while循环,进而结束整个循环,进而结束整个程序。程序。(3)DispatchMessag把消息派送到窗口函数。消息把消息派送到窗口函数。消息将在窗口函数中被判读并处理。将在窗口函数中被
31、判读并处理。(4)程序不断进行()程序不断进行(2)和()和(3)的操作。)的操作。Windows程序的生与死程序的生与死(5)当按下系统菜单中的)当按下系统菜单中的Close命令时,系统发送命令时,系统发送WM_CLOSE消息。一般程序的窗口函数不需要处理该消息,消息。一般程序的窗口函数不需要处理该消息,于是于是DefWindowProc处理它。处理它。(6)DefWindowProc收到收到WM_CLOSE后,调用后,调用DestroyWindow把窗口清除。把窗口清除。DestroyWindow本身又会发本身又会发送送WM_DESTROY消息。消息。(7)程序对)程序对WM_DESTRO
32、Y消息的反应是调用消息的反应是调用PostQuitMessage。(8)PostQuitMessage没什么其它操作,只是送出没什么其它操作,只是送出WM_QUIT消息,准备让消息循环中的消息,准备让消息循环中的GetMessage取得,如取得,如(2)所示,结束消息循环。)所示,结束消息循环。WNDCLASSEX wcex;wcex.cbSize= sizeof(WNDCLASSEX); wcex.style= CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc= (WNDPROC)WndProc;wcex.cbClsExtra= 0;wcex.cbWndExt
33、ra= 0;wcex.hInstance= hInstance;wcex.hIcon= LoadIcon(hInstance, (LPCTSTR)IDI_HELLO);wcex.hCursor= LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName= (LPCSTR)IDC_HELLO;wcex.lpszClassName= szWindowClass;wcex.hIconSm= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL)
34、;return RegisterClassEx(&wcex);hWnd = CreateWindow(szWindowClass,szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);LRESULT CALLBACK WndProc( )窗口函数IDI_HELLO ICON DISCARDABLE Hello.ICOIDI_SMALL ICON DISCARDABLE SMALL.ICOIDC_HELLO MENU DISCARDABLEBEGIN POPUP
35、 &File . POPUP &HelpEND菜单图标小图标窗口窗口类类名称名称菜单窗口标题.rcIDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 179, 43STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENUCAPTION AboutFONT 8, SystemBEGINICON IDI_HELLO,IDC_MYICON,14,9,20,20LTEXT ,IDC_STATIC,49,10,77,8 LTEXT Copyright (C) 2004,IDC_STATIC,49,20,73,8 DEFPUSHBUTTON O
36、K,IDOK,135,13,30,11,WS_GROUP对话对话框模板(在框模板(在.RC文件中)文件中)(1)DialogBox打开一个打开一个对话对话框框DialogBox ( hInst, (LPCTSTR)IDD_ABOUTBOX, /对话框模板名称hWnd, /父窗口 (DLGPROC)About /对话框函数名称);LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)switch (message) case WM_INITDIALOG: return TRUE; case WM_COMMAND:if (LOWORD(wParam) = IDOK | LOWORD(wParam) = IDCANCEL) EndDialog(hDlg, LOWORD(wParam);return TRUE;break; return FALSE;(2)控制)控制权权交交给对话给对话框函数框函数(3)对话框内部有一个循环,由系统维护