下载
第13章 核 心 技 术
本章内容: ? 高级消息处理 ? 防止同时出现多个应用程序实例 ? 使用Delhpi的BASM ? 使用挂钩 ? 使用C/C++的OBJ文件 ? 使用C++类 ? 替换 ? 获得包的信息 本章将介绍一些在 Delphi中的高级编程技术。在这一章里,你将更直接地接触到 Win32 API,并且 要介绍一些 VCL没有提供的功能。稍后,你将学习到这些概念:窗口过程、多实例、窗口挂钩以及在 Delphi与C++之间共享代码。
13.1 高级消息处理
在第5章“理解 Wi n d o w s消息”中,我们曾讲过窗口过程是一种函数,当一个窗口收到消息时由 Windows来调用它。在每个应用程序对象中都包含一个窗口过程,应用程序对象利用它来接收所有被 发送到应用程序的消息。 TApplication类利用OnMessage()事件通知消息的到来。 TApplication.OnMessage只在应用程序的消息队列接收到一个消息时才被触发 (在第5章中有关于消 息的讨论)。一般应用程序接收到的消息是与窗口管理有关的消息 (例如WM_PAINT和WM_SIZE),或由 PostMessage()、PostAppMessage()或BroadcastSystemMessage()等API函数发送出的消息。但是,由于 Wi n d o w s或S e n d M e s s a g e ( )有可能会绕过消息队列直接将消息发送给窗口过程。当发生这种情况时, TApplication.OnMessage就不会被触发。 13.1.1 子类化 为了知道什么时候一个消息被发送到应用程序,必须用自己的窗口过程代替 Application的窗口过 程。当在自己的窗口过程中对消息处理完后,要把消息再传递给原窗口过程。这样的过程就叫做子类 化窗口。 可以传递一个常量 G W L _ W N D P R O C给Win32 API函数S e t Wi n d o w L o n g ( )来指定一个新的窗口过 程。窗口过程可以是以下两种格式 :一是利用API定义;二是利用Delphi使窗口方法作为窗口过程。 注意 当子类化一个VCL窗口的窗口过程时,可能由于窗口的句柄被重复创建而导致应用程序 失败。使用子类化技术一定要小心。一种更为安全的使用方法是使用 Application.HookMainWindow()。我们将在后面讨论它。 1. 一个Win32 API 的窗口过程 一个API的窗口过程必须像这样声明:
下载
第13章 核 心 技 术
393
声明中,Handle参数用于标识目标窗口; Msg是一个消息; wParam、lpParam参数含有消息的附加 信息。函数的返回值要依靠收到的消息确定。需要特别注意,此函数必须用 stdcall作为调用约定。 可以这样使用SetWindowLong()函数给应用程序的窗口指定窗口过程:
在此调用后,返回一个指针类型的 W P r o c指向旧的窗口过程。对这个值的保留是很必要的,因为 有些消息可能需要传递给旧的窗口过程。下面是一个窗口过程的实现示例:
清单1 3 - 1列出了 S c W n d P r c . p a s单元的代码,程序中利
用自己的窗口过程代替了 A p p l i c a t i o n对象的 窗口过程来处理自定义的消息 DDGM_FOOMSG。 清单13-1 ScWndPrc.pas
394
第二部分 高 级 技 术
下载
警告 一定要把SetWindowLong()函数值保存起来。如果你在自定义的窗口过程中不把该值返 还给旧窗口过程,有可能导致应用程序甚至操作系统的崩溃。 2. Delphi的窗口方法 利用 D e l p h i提供的函数 M a k e O b j e c t I n s t a n c e ( )可以把一个 A P I窗口过程与一个 D e l p h i方法关联。 M a k e O b j e c t I n s t a n c e ( )能够创建一个 T W n d M e t h o d类型的方法,该方法可以当作窗口过程使用。 MakeObjectInstance()在Forms单元中声明如下: TWndMethod在Forms单元中定义如下:
MakeObjectInstance()的返回值为一个指针即 Pointer,它指向新创建的窗口过 程。这是 S e t Wi n d o w L o n g ( ) 需要的最后一个参数的值。最后,你要利用 FreeObjectInstance()函数释放用MakeObjectInstance()创建的窗口方法。 作为一个示范程序, Wi n P r o c . d p r演示了子类化应用程序的窗口过程和如 何利用Application.OnMe-ssage的方法。这个项目的主窗体如图 13-1所示。 清单13-2显示WinProc项目