Author: Vimil Saju
How to subclass non Delphi windows
Answer:
Every window has a procedure associated with it that recieves all the messages that
are sent to it. To subclass a window means to replace the procedure associated with
the window by another user defined procedure. The main use of subclassing windows
is to customize how a window works.
The handle of the procedure associated with the window can be got by calling the
GetWindowLong function.
hproc: TFarproc;
hproc := TFarProc(GetWindowLong(hwnd, GWL_WNDPROC));
if hwnd is the handle of the function then hproc is the handle of the procedure
associated with the window.
Now define a procedure that will replace the original procedure associated with the
window.
For example see the code below.
1 type2 TForm1 = class(TForm)
3 private4 hproc: TFarproc;
5 protected6 procedure WndProc(var msg: TMessage);
7 end;
Here the procedure WndProc will replace the original window procedure.
To replace the original procedure with the procedure WndProc you have to first call
the function 'MakeObjectInstance' defined in forms unit which converts a member
procedure(Here WndProc is member of TForm1 class) to a standard procedure.
This is because the WndProc procedure is a member function and Windows does not
understand class member functions. Class member functions have a "self" pointer as
a hidden first parameter which uniquely identifies a class object (keep in mind
that an object is a specific instantiation of a class). The API callback does not
know how to pass "self".
To convert the member procedure to a standard procedure call the MakeObjectInstance
function as shown below.
fproc: TFarProc;
fproc := MakeObjectInstance(WndProc);
after you have done this
call the SetWindowlong function to replace the procedure of the window as shown
below
SetWindowlong(hwnd, GWL_WNDPROC, longword(fcurProc));
Now all messages that are sent to the window will be intercepted by the WndProc
procedure
The messages that are not handled by the WndProc can be sent to the original
procedure by using the CallWindowProc function.
Here is how to call the function.
8 procedure TForm1.DlgProc(var msg: Tmessage);
9 begin10 case msg.msg of11 WM_SIZE:
12 begin13 //user defined code14 end;
15 WM_PAINT:
16 begin17 //user defined code18 end;
19 end;
20 //all unhandled messages are sent to original procedure. Here hproc is the 21 //handle to the original window procedure.22 msg.result := CallWindowProc(hproc, hwnd, msg.msg, msg.wparam, msg.lparam);
23 end;
once you have finshed you have to destroy the handle created by the
MakeObjectInstance(WndProc) function by calling the 'FreeObjectInstance' function
which is also defined in the forms unit. You usually call this function when the
form is closed. Example of how to call the function is shown below.
24 procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
25 begin26 FreeObjectInstance(fproc);
27 end;