Trapping Messages Sent to an Application
http://www.delphicorner.f9.co.uk/articles/apps7.htm
Trapping Messages Sent to an Application
I wrote code for the OnMessage event handler of Application object
to trap all Windows messages sent to my application,
but it doesn't seem to fire on all messages.
Is there a way to trap all messages sent to my application?
There sure is. And the answer to this "problem" is amazingly simple.
But before I go into trapping messages at the application level,
I should probably discuss some mechanics.
TApplication's "Hidden" Window
It's not a commonly known fact that the default Application object creates a hidden window
when your application is started.
But you can seen evidence of this by creating a new application saving it,
then running it (make sure you don't rename anything -
just keep the main form as "Form1" and the project as "Project1).
When you run the application, you'll notice that the caption bar for your main form says,
"Form1" while the icon displayed on the task bar says "Project1."
That icon represents the application's hidden window,
and it affects your program in many ways,
especially when you're trying to handle messages sent to your application.
Delphi surfaces the OnMessage event for the Application object.
The OnMessage event handler is "supposed" to allow you trap every message sent to your application.
But there's a problem with this:
OnMessage will only fire when there's something in the Application object's message queue.
These messages are typically window management messages such as WM_PAINT
or messages sent to the application from Windows through PostMessage,
Broadcast or SystemMessage .
However, messages sent directly to a window using SendMessage
bypass the Application object's message queue,
so OnMessage doesn't fire for those types of situations.
Some of you more familiar with handling windows messages
might think that a solution to the problem above
might be to override the WndProc method for the Application object.
Unfortunately, that's not possible because TApplication's WndProc method is not only private,
it's also declared as a static method which means it's not overrideable.
So it's not only invisible, you can't create a TApplication subclass
to override WndProc (not that you'd want either).
But that doesn't mean that you can't get to the WndProc method using alternative means.
"Hooking" All Messages
Even though WndProc is all but closed to direct subclassing,
TApplication does include a method called HookMainWindow
that allows you to insert your own message handler
at the top of WndProc to intercept messages sent to your application
before they're handled by the Application object.
This is convenient for all developers, and solves the problem
of trapping any message sent to your application.
HookMainWindow is declared under TApplication as follows:
procedure HookMainWindow(Hook : TWindowHook);
Notice that HookMainWindow takes one parameter,
Hook of type TWindowHook.
TWindowHook is a method pointer type that's defined like so:
type
TWindowHook = function(var Message : TMessage) : Boolean of object;
Since TWindowHook is a method pointer, you can define your own method as the hook function
as long as it follows the nomenclature defined for TWindowHook.
Notice that the return value of the function is of type Boolean.
This is the equivalent of the "Handled" parameter of OnMessage.
If your function handles a particular message, you'd return true.
This will be passed back to the Application's WndProc and
message processing for that message will be terminated.
Otherwise, you'd return False. Here's an example method:
function TForm1.AppHookFunc(var Message : TMessage) : Boolean;
begin
Result := False; //I just do this by default
if Message.Msg = WM_<SomethingOrOther> then begin
...DoSomething...
Result := True;
end;
end;
Okay, now that we've set up everything,
we need to make the application hook the messages.
This can be done in the main form's OnCreate method:
function TForm1.FormCreate(Sender : TObject);
begin
HookMainWindow(AppHookFunc);
end;
I should mention that you need to clear the hook using,
you guessed it, UnHookMainWindow,
after you're done using it, and this can be done
in the OnDestroy for the main form:
function TForm1.FormDestroy(Sender : TObject);
begin
UnHookMainWindow(AppHookFunc);
end;
Okay, disgustingly simple.
But I feel the best things in life are those that give maximum satisfaction
for the least amount of cost (please don't read ANYTHING into that <G>).
So, now you've got the tools to create your own message "hooker" (sorry, had to do that at least once).
Until next time...
Trapping Messages Sent to an Application的更多相关文章
- Sending messages to non-windowed applications -- AllocateHWnd, DeallocateHWnd
http://delphi.about.com/od/windowsshellapi/l/aa093003a.htm Page 1: How Delphi dispatches messages in ...
- Application.HookMainWindow完全替代了原来的窗口过程(但是好像也会继续传递)
unit HookMain; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialo ...
- 对发给Application.Handle消息的三次执行(拦截)消息的过程
unit Main; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms ...
- VCL -- Understanding the Message-Handling System
Understanding the Message-Handling System http://docwiki.embarcadero.com/RADStudio/XE7/en/Understand ...
- windows消息机制详解(转载)
消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按下键盘上的一个键都会使Windows发送一个消息给应用程序.消息本身是作为一个记录传递给应用程序的 ...
- 将asp.net core站点发布到IIS上遇到的问题
今天第一次将整个 asp.net core 站点发布到 IIS 上,以前都是发布到 Linux 服务器上. 开始使用 dotnet publish -c release 命令发布,用浏览器访问站点时出 ...
- Competing Consumers Pattern (竞争消费者模式)
Enable multiple concurrent consumers to process messages received on the same messaging channel. Thi ...
- Logging configuration
The Play logger is built on Log4j. Since most Java libraries use Log4j or a wrapper able to use Log4 ...
- django+nginx+xshell简易日志查询,接上<关于《rsyslog+mysql+loganalyzer搭建日志服务器<个人笔记>》的反思>
纠正一下之前在<关于<rsyslog+mysql+loganalyzer搭建日志服务器<个人笔记>>的反思>中说到的PHP+MySQL太慢,这里只是说我技术不好,没 ...
随机推荐
- 创建Web API
引言 在公司中用到的都是webAPI的应用程序,这个东西之前没有接触过.但是这个并不是什么新鲜的东西,因我们 之前有mvc的基础,所以说学习这个东西还是比较容易的,在开始的时候自己可能突然蒙圈了.因为 ...
- Jquery 设置style:display 通过ID隐藏区域
$("#id").css('display','none'); $("#id").css('display','block'); 或 $("#id&q ...
- mybatis Java API
既然你已经知道如何配置 MyBatis 和创建映射文件,你就已经准备好来提升技能了. MyBatis 的 Java API 就是你收获你所做的努力的地方.正如你即将看到的,和 JDBC 相比, MyB ...
- Windows Server 2012 R2 设置 smtp 服务器
Windows Server 2012/2012 R2:安装和配置 SMTP 服务器 安装 SMTP 服务器 以下是安装 SMTP 服务器功能的步骤: 打开“服务器管理器”:单击键盘上的 Window ...
- Delphi 注册文件类型 设置文件图标
{------------------------------------------------------------------------------- @过程名: slpert -& ...
- bjfu1262 优先队列
比较典型的应用优先队列的题.题目是在一个长为n的数组中,依次问m个数中的最小值.那么把值和下标做成一个结构体,放进优先队列里,每次移动窗口就把该T的T掉,剩下的最小值就是答案,复杂度nlogn,轻松a ...
- 关于COUNT STOPKEY的工作机制(转载)
SQL> select rownum rn ,a.* from cnmir.ew_auctions a where rownum<50000; Execution Plan-------- ...
- 【LeetCode 239】Sliding Window Maximum
Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...
- 【Unity入门】场景、游戏物体和组件的概念
版权声明:本文为博主原创文章,转载请注明出处. 游戏和电影一样,是通过每一个镜头的串联来实现的,而这样的镜头我们称之为“场景”.一个游戏一般包含一个到多个场景,这些场景里面实现了不同的功能,把它们组合 ...
- 说说Python 中的文件操作 和 目录操作
我们知道,文件名.目录名和链接名都是用一个字符串作为其标识符的,但是给我们一个标识符,我们该如何确定它所指的到底是常规文件文件名.目录名还是链接名呢?这时,我们可以使用os.path模块提供的isfi ...