window窗口程序

窗口程序的运行过程

 

在屏幕上显示一个窗口的过程一般有以下步骤,这就是主程序

WinMain

的结构流程:

 

1

)得到应用程序的句柄(

GetModuleHandle

)。

 

2

)注册窗口类(

RegisterClassEx

)。在注册之前,要先填写

RegisterClassEx

的参数

WNDCLASSEX

结构。

 

3

)建立窗口(

CreateWindowEx

)。

 

4

)显示窗口(

ShowWindow

)。

 

5

)刷新窗口客户区(

UpdateWindow

)。

 

6

)进入无限的消息获取和处理的循环。首先获取消息(

GetMessage

),如果有消息到达,

则将消息分派到回调函数处理(

DispatchMessage

),如果消息是

WM_QUIT

,则退出循环。

 

程序的另一半

_ProcWinMain

子程序是用来处理消息的,

它就是窗口的回调函数

Callback

也叫做窗口过程,

之所以是回调函数是因为它是由

Windows

而不是我们自己调用的,

我们调

DispatchMessage

,而

DispatchMessage

在自己的内部回过来调用窗口过程。

 

所有的用户操作都是通过消息来传给应用程序的,

如用户按键、

鼠标移动、

选择了菜单和拖

动了窗口等,

应用程序中由窗口过程接收消息并处理,

在例子程序中就是

_ProcWinMain

于窗口过程构造了一个分支结构,

对应不同的消息执行不同的代码,

所以一个应用程序中几

乎所有的功能代码都集中在窗口过程里。

 

窗口程序运行中消息传输的流程可以由图

4.4

来表示。

 

先来看看

Windows

对消息的处理。

Windows

在系统内部有一个系统消息队列,当输入设备有

所动作的时候,如用户按动了键盘、移动了鼠标、按下或放开了鼠标等,

Windows

都会产生

相应的记录放在系统消息队列里,

如图

4.4

中的箭头

a

b

所示,

每个记录中包含消息的类

型、发生的位置(如鼠标在什么坐标移动)和发生的时间等信息。

 

 

 

  

 

同时,

Windows

为每个程序(严格地说是每个线程)维护一个消息队列,

Windows

检查系统

消息队列里消息的发生位置,

当位置位于某个应用程序的窗口范围内的时候,

就把这个消息

派送到应用程序的消息队列里,如图

4.4

中的箭头

c

所示。

 

当应用程序还没有来取消息的时候,

消息就暂时保留在消息队列里,

当程序中的消息循环执

行到

GetMessage

的时候,控制权转移到

GetMessage

所在的

USER32.DLL

中(箭头

1

),

USER32.DLL

从程序消息队列中取出一条消息(箭头

2

),然后把这条消息返回应用程序(箭

3

)。

 

应用程序可以对这条消息进行预处理,如可以用

TranslateMessage

把基于键盘扫描码的按

键消息转换成基于

ASCII

码的键盘消息,以后也会用到

TranslateAccelerator

把键盘快捷

键转换成命令消息,但这个步骤不是必需的。

 

然后应用程序将处理这条消息,但方法不是自己直接调用窗口过程来完成,而是通过

DispatchMessage

间接调用窗口过程,

Dispatch

的英文含义是

"

分派

"

之所以是

"

分派

"


 

 

因为一个程序可能建有不止一个窗口,

不同的窗口消息必须分派给相应的窗口过程。

当控制

权转移到

USER32.DLL

中的

DispatchMessage

时,

DispatchMessage

找出消息对应窗口的窗

口过程,然后把消息的具体信息当做参数来调用它(箭头

5

),窗口过程根据消息找到对应

的分支去处理,

然后返回

(箭头

6

这时控制权回到

DispatchMessage

最后

DispatchMessage

函数返回应用程序

(箭头

7

这样,

一个循环就结束了,

程序又开始新一轮的

GetMessage

 

有个很常见的问题:

为什么要由

Windows

来调用窗口过程,

程序取了消息以后自己处理不是

更简便吗?事实上并非如此,

如果程序自己处理消息的

"

分派

"

就必须自己维护本程序所属

窗口的列表,

当程序建立的窗口不止一个的时候,

这个工作就变得复杂起来;

另一个原因是:

别的程序也可能用

SendMessage

通过

Windows

直接调用你的窗口过程;

第三个原因:

Windows

并不是把所有的消息都放进消息队列,有的消息是直接调用窗口过程处理的,如

WM_SETCURSOR

等实时性很强的消息,所以窗口过程必须开放给

Windows

 

应用程序之间也可以互发消息,

PostMessage

是把一个消息放到其他程序的消息队列中,如

4.4

中箭头

d

所示,目标程序收到了这条消息就把它放入该程序的消息队列去处理;而

SendMessage

则越过消息队列直接调用目标程序的窗口过程(如图

4.4

中箭头

I

所示),窗

口过程返回以后才从

SendMessage

返回(如图

4.4

中箭头

II

所示)。

 

窗口过程是由

Windows

回调的,

Windows

又是怎么知道往哪里回调呢?答案是我们在调用

RegisterClassEx

函数的时候已经把窗口过程的地址告诉了

Windows

 



        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值