好文档 - 专业文书写作范文服务资料分享网站

第1章 Windows系统的消息机制 - 图文

天下 分享 时间: 加入收藏 我要投稿 点赞

第1章 Windows系统的消息机制

对诸如PowerBuilder(后文简写为PB)、Visual Basic和Dephi等大多数可视化程序设计语言来讲,程序设计的核心是对象的事件、属性和方法,但对Windows系统本身而言,却是以消息处理为其控制机制。Windows把系统中的对象都作为窗口来对待,每个窗口都有一个用来标识其身份的句柄。Windows通过向窗口发送消息,在开发语言中转化为对象的事件,然后驱动对象,响应用户的动作。在许多面向对象的可视化程序设计语言中,Windows的众多消息已经演变成了对象的属性或方法。本章内容包括Windows系统的消息机制、消息的发送、消息的应用实例等。

1.1 Windows的工作机制

1.1.1 Windows 的工作方式——窗口、事件和消息

全面地讨论Windows的内部工作机制需要很大的篇幅,对于一般的PB用户当然没有必要深入了解所有的技术细节。Windows系统的工作机制,简单地说就是3个关键的概念:窗口、事件和消息。

不妨简单地将窗口看做带有边界的矩形区域。读者也许已经了解多种不同类型的窗口,如Windows系统的“资源管理器”窗口、文字处理程序中的文档窗口或者弹出提示有约会信息的消息对话框窗口等。除了这些最普通的窗口外,实际上还有许多其他类型的窗口。命令按钮是一个窗口,图标、文本框、选项按钮和菜单条也都是窗口。

Windows 操作系统通过给每一个窗口指定一个惟一的标识号(窗口句柄,常用hWnd表示)来管理所有的窗口。操作系统连续地监视每一个窗口的活动或事件的信号。事件可以通过诸如单击鼠标或按下按键的操作而产生,也可以通过程序的控制而产生,甚至可以由另一个窗口的操作而产生。

每发生一次事件,将引发一条消息发送至操作系统。操作系统处理该消息并广播给其他窗口。然后,每一个窗口才能根据自身处理该条消息的指令而采取适当的操作(例如,当窗口解除了其他窗口的覆盖时,重新绘制自身窗口)。

可以想象,处理各种窗口、事件和消息的所有可能的组合将有惊人的工作量。幸运的是,PB使用户摆脱了所有的低层消息处理。许多消息由PB自动处理了,其他的作为事件过程由编程者自行处理,这样可以快速创建强大的应用程序,而毋需涉及不必要的细节。

1.1.2 句柄的概念

在解释消息之前,首先了解系统如何准确地将消息发送到指定的窗口。当一个应用或多

个应用运行后,会同时创建许多个窗口,Windows作为系统的“大总管”,那么它又是如何识别每一个窗口呢?在程序设计时,通过窗口的名称属性,为每个窗口命名,然后在程序其他部分把窗口名作为识别窗口的标识。这种通过为窗口命名来识别不同窗口的方法,对Windows系统来讲显然是不现实的。Windows系统是通过称之为句柄的标识符来识别每一个窗口。

句柄是系统动态分配给窗口的32位整型数标识值,常用hWnd表示,即英文handle to a window的缩写。大量API函数都需要窗口句柄作参数,或返回一个窗口或设备场境的句柄。句柄可以通俗地理解为Windows为系统中所有存在的窗口动态分配的身份识别号码。

在PB中,可以通过handle函数来取得窗口和控件的句柄,当声明API函数时,常把保存句柄的变量声明为Long或Ulong长整型数据类型。Windows为窗口和控件分配句柄标识是动态,同样的程序每次运行时和在不同计算机上运行时所分配的窗口句柄标识可能是完全不一样的。

窗口的句柄属性仅能在运行时访问,该属性对窗口的外观并没有任何影响,它仅作为API函数调用的参数或返回值,或其他需识别窗口或对象的地方。在后面章节中,读者将会看到几乎所有涉及窗口的API函数都需要传递hWnd参数,以便函数准确获得用户要处理的窗口或对象。

句柄作为由操作系统定义的惟一的长整型值,可以用它来引用窗体和控件等对象。在Windows系统中,API函数的调用常用的句柄包括窗口句柄,菜单句柄、设备对象句柄、设备场景句柄,等等。如果函数需要用句柄作为参数,则应该把参数声明为传值,对于返回句柄的API函数,应将返回的句柄值声明为Long或Ulong类型数据类型。句柄是一种标识符(ID)编号,而不是指针或者数值,不要试图对它们进行任何数学运算。

1.1.3 消息的概念

Windows系统是以消息处理为其控制机制,系统通过消息为窗口过程(windows procedure)传递输入。系统和应用两者都可以产生消息。对于每个输入事件,例如用户按下了键盘上的某个键、移动了鼠标、单击了一个控件上的滚动条,等等,系统都将产生一系列消息。此外,对于应用带给系统的变化,如字体资源的改变、应用本身窗口的改变,系统都将通过消息以响应这种变化。应用通过产生消息指示应用的窗口完成特定的任务,或与其他应用的窗口进行通信。

每个窗口都有一个处理Windows系统发送消息的处理程序,称为窗口程序。它是隐含在窗口背后的一段程序脚本,其中包含对事件进行处理的代码。

Windows系统为每条消息指定了一个消息编号,例如当一个窗口变为活动窗口时,它事实上是收到一条来自Windows系统的WM_ACTIVATE消息,该消息的编号为6,它对应于PB窗口的Activate事件。对于窗口来说,诸如Open、Activate、MouseDown、Resize等事件,实际上对应的是窗口内部的消息处理程序,这些程序对于用户来讲是不可见的。类似地,命令按钮也有消息处理程序,它的处理程序响应诸如WM_LBUTTONDOWN和WM_RBUTTONDOWN之类的消息,即激活命令按钮的MouseDown事件。

系统向窗口发送的消息通常包含3个参数,分别是:

(1)窗口句柄(a window handle):窗口句柄用来标识消息将要发送到的窗口对象,系统使用窗口句柄来确定哪一个窗口句柄应该接收该消息。

(2)消息标识符(a message identifier):消息标识符是用来区分不同消息的命名常量,当窗口过程接收到一个消息时,它使用消息标识符来确定如何处理该消息。例如,消息标识符WM_PAINT告诉窗口过程“窗口的客户区已经发生变化,窗口必须进行重新绘制”。

(3)消息参数(message parameters):消息参数用来表述窗口过程处理消息时所使用的数据或数据的位置,通常用一对参数表示。消息参数的意义和取值取决于消息。消息参数取值可以是整型数、Bit位标识、指向结构的指针,等等,当不需要使用消息参数时,通常将其设置为NULL。窗口过程必须通过检查消息标识符来确定如何对消息参数进行解释。

有关消息标识符、消息参数的具体使用,将在后面介绍Sendmessage函数时给予进一步 解释。

1.1.4 消息的类型

1.系统定义的消息

当系统与应用进行通信时,系统将发送或邮寄消息。系统通过这些消息控制应用的运行,并为应用的进程提供输入或其他信息。应用内部也可发送或邮寄系统定义的消息,应用通常使用这些消息控制由预先注册的窗口类创建的窗口的操作。

每一个系统定义的消息都有一个惟一的消息标识符(值),并用一个表明消息用途标识符常量表示(这些在SDK的头文件中定义)。如WM_PAINT消息标识符表示要求窗口进行重绘的消息。

消息标识符常量前缀表示消息所属的消息类别,如WM_表示窗口类消息,BM_表示按钮类消息,表1-1给出了不同类别消息的前缀。

在PB中,消息标识符常量通常声明为窗口或对象的实例常量,例如:

CONSTANT long WM_MOUSEMOVE CONSTANT long WM_LBUTTONDOWN CONSTANT long WM_LBUTTONUP CONSTANT long WM_LBUTTONDBLCLK CONSTANT long WM_RBUTTONDOWN CONSTANT long WM_RBUTTONUP CONSTANT long WM_RBUTTONDBLCLK

= 512 = 513 = 514 = 515 = 516 = 517 = 518

表1-1 Windows系统定义的消息类别

消息标识符前缀 ABM BM CB CBEM CDM DBT DL DM DTM 消息分类 应用桌面工具栏消息 按钮控件消息 组合框控件消息 扩展组合框控件消息 通用对话框消息 设备消息 拖曳列表框控件消息 默认按钮控件消息 日期时间选取控件消息 续表 消息标识符前缀 EM HDM HKM IPM LB LVM MCM PBM PGM PSM RB SB SBM STM TB TBM TCM TTM TVM UDM WM 消息分类 编辑控件消息 头控件消息 热键控件消息 IP地址控件消息 列表框控件消息 列表视图控件消息 月历控件消息 进度条控件消息 Pager控件消息 属性页面消息 Rebar 控件消息 状态栏窗口消息 滚动条控件消息 静态控件消息 工具栏消息 跟踪条控件消息 Tab 控件消息 Tooltip控件消息 树形控件消息 Up-down 控件消息 普通窗口消息

Windows系统使用了成千上万条消息。从窗口到控件都有一组可接收和响应的消息。在Visual Basic的API浏览器中,以常量的方式列出了Windows的大部分消息。

据粗略统计,微软在MSDN中列出的消息约有数千种,全部弄清楚这么多种消息是不现实的,也是没有必要的。这是因为PB已经将很多消息封装为了对象的“属性”(例如窗口的Title和WindowState属性)和“方法(函数)”(例如关闭窗口函数Close)。可以发现,消息可能演变成PB对象的属性、方法(函数)和事件。既然PB已经对消息进行了封装,那么又何必使用消息来进行程序设计呢?这时因为,PB提供的事件、属性和方法并未完全涵盖所有消息,为了弥补PB在某些功能的不足,常使用系统消息或应用自定义的消息来强化PB的程序设计。

2.应用定义的消息

应用也可以创建自己的消息,并将消息应用于它的窗口或与其他窗口的进程进行通信。如果应用创建了自己的消息,接收消息的窗口过程必须解释消息,同时对消息进行恰当的处理。

系统保留的消息标识符的取值范围为0x0000~0x03FF(0~1023),专门用于系统定义的消息;应用定义的消息不能使用这些值,应用定义的消息取值范围为0x0400~0x7FFF(0~32767)。

RegisterWindowMessage函数提供了分配消息编号的功能,该函数用一个消息名称作为参

数,并为这个名称分配一个惟一的、尚未使用过的编号。

1.1.5 用于发送消息的API函数

Windows应用程序允许应用程序向自己或其他应用程序发送消息,甚至可以向Windows操作系统本身发送消息(比如要求关闭操作系统或重新启动操作系统)。Windows提供了2个专门用于发送消息的API函数SendMessage和PostMessage。

1.SendMessage函数

SendMessage函数发送指定的消息到窗口或Windows系统,然后函数调用窗口的处理消息的过程,并等待窗口过程处理完消息后返回。 C原型

LRESULT SendMessage(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam );

PB声明

FUNCTION Long SendMessage(Long hwnd, Long wMsg, Long wParam, Long lParam) LIBRARY \FOR \

参 数

hWnd 为接收消息窗口的句柄; wMsg 指定要发送的消息; wParam 依赖于消息wMsg的其他信息; lParam 依赖于消息wMsg的其他信息。 返回值

函数返回消息的处理结果,该值取决于消息的类型。

wParam和lParam两个参数的含义随消息wMsg参数不同而改变,因此每当向窗口传递某种消息时,除了要了解该消息的含义外,还要注意wParam和lParam的含义和设置。

SendMessage函数会返回一个Long值,由于这个函数是直接调用窗口程序,因此窗口程序可以返回一个值,把它作为SendMessage函数的返回值,这个返回值的具体含义由消息决定。不过,除非在MSDN明确列出了该消息的返回值,否则,返回值就没有具体意义,应该忽略。此外,在使用返回值时,通常调用SendMessageTimeOut函数检查是否超时,因为只有在消息完全处理完毕后,才能得到一个有效返回值。

前面曾提到默认的窗口过程函数DefWindowProc用来处理应用程序无法处理的消息,该函数确保所有消息都要处理,无论这些消息是否对窗口有用。调用DefWindowProc函数时,需要传入与窗口消息处理过程相同的参数。 C原型

LRESULT DefWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );

PB声明

FUNCTION Long DefWindowProc(Long hwnd,Long wMsg,Long wParam,Long lParam) LIBRARY \ALIAS FOR \

参 数

第1章 Windows系统的消息机制 - 图文

第1章Windows系统的消息机制对诸如PowerBuilder(后文简写为PB)、VisualBasic和Dephi等大多数可视化程序设计语言来讲,程序设计的核心是对象的事件、属性和方法,但对Windows系统本身而言,却是以消息处理为其控制机制。Windows把系统中的对象都作为窗口来对待,每个窗口都有一个用来标识其身份的句柄。Windows通过向窗口发送消息,在开
推荐度:
点击下载文档文档为doc格式
5pddr4abzq6d7jn4l8uv58u602x74s012me
领取福利

微信扫码领取福利

微信扫码分享