Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
Member Area
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Become a Member
-Why sign up!
-Chat Online!
-Indexes NEW!!
-Build your resume
-Find a job
-Post a job
-Resume Search
-Link to us
Visit Embarcadero
Embarcadero Community
How to trap and process Windows messages before the applications' window procedu Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
Delphi 2.x
User Rating
No Votes
# Votes
DSP, Administrator
Reference URL:
			Author: Jonas Bilinkevicius 

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 

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:

1   type
2     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:
4   function TForm1.AppHookFunc(var message: TMessage): Boolean;
5   begin
6     Result := False; //I just do this by default
7     if message.Msg = WM_ < SomethingOrOther > then
8     begin
9       ...DoSomething...
10        Result := True;
11    end;
12  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:
14  function TForm1.FormCreate(Sender: TObject);
15  begin
16    HookMainWindow(AppHookFunc);
17  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:
19  function TForm1.FormDestroy(Sender: TObject);
20  begin
21    UnHookMainWindow(AppHookFunc);
22  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 ). So, now you've got the tools to create your own message "hooker" (sorry, had to do that at least once). Until next time...

Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10


Share this page
Download from Google

Copyright © Mendozi Enterprises LLC