If you've written code for the OnMessage event handler of Application object to trap all Windows messages sent to your application, it may not fire on all messages. This is because OnMessage will only fire when there's something in the Application object's message queue. Messages sent directly to a window using SendMessage bypass the Application object's message queue, and as a result OnMessage doesn't fire in those situations. An amazingly simple way to trap all messages sent to the Application object's window is to use a method called HookMainWindow, which is included in TApplication. HookMainWindow 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 solution is convenient for all developers, and solves the problem of trapping any message sent to your application. Before I go into trapping messages at the application level, I'll discuss some mechanics.
TApplication's "Hidden" Window
It's not commonly known that the default Application object creates a hidden window when your application is started. But you can see evidence of this behavior by creating a new application, saving it, and 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 that are more familiar with handling windows messages might think that a solution to the problem could be to override the WndProc method for the Application object. Unfortunately, that solution is 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 the WndProc method is not only invisible, but you also can't create a TApplication subclass to override WndProc (not that you'd want to 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. 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: