1.1 Windows 程序运行原理(消息循环和响应)

更新时间:2023-06-05 04:31:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1.1 Windows 程序运行原理(消息循环和响应) *************************************************

* 本文由小鸟飞飞整理发表 <samboy@> *

* 首发网站:蓝丽网 *

* 其他网站转载请保留以上信息,谢谢! *

*************************************************

Windows 的工作方式:

全面地讨论 Windows 的内部工作机制将需要整整一本书的容量,没有必要深入了解所有的技术细节。但是对于windows程序运行的一些根本性的概念,是一个Visual C++程序员所必须掌握的知识。

一,Windows应用程序,操作系统,计算机硬件之间的相互关系。

(原稿这里是一张 图,蓝丽不能贴图,改为文字叙述,也不知道能不能说明白)

输入设备->产生事件->操作系统->发生消息->应 用程序->调用API->输出设备

操作者控制输入设备(如键盘、鼠标)时,操作系统能够感知输入设备状态的变化,然后通 知输出设备执行特定的功能。Windows程序主要是由消息和事件进行驱动,所以做好Windows程序必须要清楚消息和事件的运行,这一点在以后的文章 中会详细介绍。

操作系统和计算机硬件直接进行交互,应用程序开发者通常不需知道其具体实现细节。当应用程序需要和硬件进行交互时只需使用操作 系统提供的API即可。

1.关于API

这里提到一个非常重要的概念:API

应用程序可以通知操作系统执 行某个具体的动作,如操作系统能够控制声卡发出声音,但其并不知道何时发出何种声音,得由应用程序告诉操作系统该发出什么样的声音。在应用程序中要完成某个功能,都是以函数调用的形式实现的,应用程序也是以函数调用的方式来通知操作系统执行相应功能的,操作系统所能够完成的每一个特殊功能通常都有一个函数 与其对应,也就是说,操作系统把它所能完成的功能以函数的形式提供给应用程序使用,应用程序对这些函数的调用叫系统调用,这些函数的集合是Windows 操作系统提供给应用程序编程的接口(Application Programming Interface),简称Windows API。如

CreateWindow就是一个API函数,应用程序中调用这个函数,操作系统就会按照该函数提供的参数信息产生一个相应的窗口。关于这个函 数的详细解释,请参阅MSDN(微软开发编程的开发系统)。

顺便提一下,对于一个真正的程序员来说,不可能死记硬背每一个API函数 及其各参数的详细信息。通常都是只记住其英文拼写,有时甚至是凭着语意拼读出来的,如显示窗口用ShowWindow,退出Windows操作系统用 ExitWindows等等,API函数的正确拼写格式及各参数的详尽信息都是在MSDN迅速检索到的,没必要刻意去死记这些信息,等用的次数多了,这些 信息也就在不知不觉中掌握了,但一定要具备在需要的时候能够从帮助系统中检索想要的信息的能力,这样就能做到事半功倍。学习VC++,一定要有一套真实的 练习环境,学会查阅帮助系统,决不能纸上谈兵,照着书本亦步亦趋,否则就真的是没有一两年的时间,

是学不好VC++的了。

注意:请不 要将这里的API与java API以及其他API混淆。API正如其语义一样,已成为一种被广泛使用的专业术语。如果某个系统或某个设备提供给某种应用程序对其进行编程操作的函数, 类,组件等的集合,就称作该系统的API。

2.关于消息和事件

Windows程序是事件驱动的,所谓事件就是应用程 序做了什么事情或是程序用户通过输入设备做了哪些事情(比如移动鼠标)。

操作系统能够将输入设备的变化上传给应用程序。如用户在某个程序活动 时按了一下键盘,操作系统马上能够感知到这一事件,并且能够知道用户按下的是哪一个键,操作系统并不决定对这一事件如何做出反应,而是将这一事件转交给应 用程序,由应用程序决定如何对这一事件做出反应。对事件做出反应的过程就是消息响应。

操作系统是怎样将感知到的事件传递给应用程序的 呢?这是通过消息机制来实现的。操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序的,参看MSDN,MSG结构定义如下:

typedef struct tagMSG { // msg

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

} MSG;

看不懂这种定义的读者,请赶快复习C语言,其基本意义是定义一个struct tagMSG的结构体,并在以后的应用中用MSG来代替struct tagMsg。该结构体中各成员变量的作用如下:

第一个成员变 量hwnd即代表消息所属的窗口,一个消息一般都是与某个窗口相联系的,如在某个活动窗口中按下键盘,该键盘消息就是发给该窗口的,在VC中,用HWND 变量类型来标识窗口。有关窗口的知识,在稍后有详细解释。

第二个成员变量message代表消息代号,无论是键盘按下,还是鼠标移 动,都是用一个数字来表示的,不同的数值对应不同的消息。由于数值不便于记忆,在VC中将消息对应的数值定义为WM_xxx宏的形式,xxx对应某种消息 的英文拼写的大写,如鼠标移动消息为WM_MOUSEMOVE,键盘按下消息为WM_KEYDOWN,输入一个字符消息为WM_CHAR等等。我们在程序 中一般以WM_xxx宏的形式来使用消息。

提示:如果想知道WM_xxx消息对应的具体数值,请在程序中选中WM_xxx,单击右 键,在弹出菜单中选择goto definition即可看到该宏的具体定义。跟踪,查看某个变量的定义,使用此方法非常有效。

第三个,四个成员变量分别为wParam,lParam,用于对消息进行补充说明,如message成员表示字符消息,但没有说明输入的是哪个字符,这就需要 用其他变量对其进行补充说明。wParam,lParam代表的意义,

随消息的不同而异。读者可用goto definition功能查看WPARAM,LPARAM的定义,发现它们分别为unsigned int和long,并不是什么神秘莫测的变量类型。VC++中之所以要这样做,是希望从变量定义的类型上,就能区分出变量的用途。对于同一种变量类型,可 按其用途细分定义成多种其他的形式。这种概念在VC++中被广泛使用,也是导致初学者困惑的一个因素。

最后两个变量分别代表发出消息 的时间和鼠标的当前位置,这里没有什么需要特殊解释的。

明白了消息,我们再来看看消息队列。如上面的图例所示,每个Windows程 序都有一个消息队列。队列是一个先进先出的缓冲区,通常是一个某种变量类型的数组。消息队列里的每一个元素即一条消息,操作系统将生成的每个消息按先后顺 序放进消息队列,第一条消息放入第一格,第二条消息放入第二格,依次类推...。应用程序总是取走队列里的第一条消息,消息取走后,第二条消息成为第一 条,剩余的消息依次前移。应用程序取得消息后,便能够知道用户的操作和程序状态的变化。例如,应用程序从队列里取到了一条WM_CHAR消息,那一定是用 户输入了一个字符,并且能够知道输入的是哪个字符。应用程序得到消息后,就要对消息进行处理,这即我们通常说的消息响应,消息响应是我们通过编码实现的, 这也是Windows程序的主要代码区。在消息响应代码中,我们很可能又要调用操作系统提供的API函数,以便完成特定的功能。如果我们收到窗口的 WM_CLOSE消息,我们可以调用DestroyWindow这个API函数来关闭该窗口,或是用MessageBox这个API函数来提示用户是否真 的要关闭窗口。

通过上面的分析,我们可以想象到,要用VC++编写Windows程序,除了要具备良好的C语言功底外,还要求掌握掌 握两点知识:1.不同的消息所代表的用户操作和程序状态,2.要让操作系统执行某个功能所对应的API函数。

本文来源:https://www.bwwdw.com/article/k7q1.html

Top