Trap Windows Messages by Subclassing your Form

It is easy to subclass your form to hook into the stream of messages Windows sends to your form. This lets you customize your form by reacting to or ignoring events that Visual Basic does not normally give you control over. Be forewarned, however, that subclassing removes much of the stability and robustness built into Visual Basic.

Subclassing can be accomplished through the use of the SetWindowLong and CallWindowProc API calls. These functions are described in detail in the source code.

Subclass a Form to Intercept Windows Messages
Download Source Code


First off, forms are really windows. Any time you click a form, move it, size it, or do anything at all to it, Windows generates one or more messages and sends them to the target window. Associated with every window is a message handling procedure, called a window procedure, that runs whenever a message is sent to it.

To subclass a form you must replace the standard window procedure with your own custom procedure. This causes Windows to call your procedure instead of the standard one. That is why your procedure is referred to as a Callback procedure. Windows passes the message and its associated parameters to your callback procedure. You can then watch for certain messages and handle them in a fashion that suites your needs. Any messages that you are not interested in must be passed to the original window procedure.

To replace the standard window procedure with your own you use the SetWindowLong API function with the GWL_WNDPROC flag. This creates a subclass of the window class used to create your form. SetWindowLong returns a value which is the address of the original window procedure. Looking at the sample program, the click event for the SubClass button calls the fSubClass function. fSubClass then calls SetWindowLong and uses Visual Basic's AddressOf operator to pass the address of our new window procedure which I have called pMyWindowProc.

pMyWindowProc is the callback procedure used when a message is received by the form. The desired message, based on the option selected, is processed and all others are passed back to the original window procedure. This step is very important. To pass a message to the original window procedure CallWindowProc is issued with the address of the original procedure. Recall that this address was returned by the SetWindowLong API and was stored in the glPrevWndProc variable.

Before your application terminates, you must remove any subclassing. Failure to do so will bring Visual Basic crashing down horribly. To remove the subclassing issue SetWindowLong using the original window procedure's address which was stored in the glPrevWndProc variable.

Whenever you employ subclassing, you should always start your application with a full compile. Stepping through the code while subclassed can sometimes prove impossible. Try to work out as many bug as possible first then use a full compile to start.

Subclassing lets you watch for messages sent to any object. In this case it was the form. It could have been a textbox, toolbar, etc. Although the two are very similar, do not confuse subclassing with using hooks. Briefly, a hook allows you to see all messages sent to an entire thread, regardless of the active window. When using hooks, you do not replace the window procedure with your own. Instead, you add your procedure to the top of a chain of procedures. Each hook procedure is responsible for calling the next procedure in the chain. Failure to do so does not cancel the message but merely prevents the other procedures in the chain from seeing the message. To see how to use a hook, see my Owner Drawn Controls program.


Download the source code and press Ctl-F5 to run the program. Make sure the Immediate window is open so you can see the displayed messages. Pick a Window's message to trap then click the SubClass button and perform the indicated action.

About TheScarms
About TheScarms

Sample code
version info

If you use this code, please mention ""

Email this page

© Copyright 2024 TheScarms
Goto top of page