Every window has a procedure associated with it that receives 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
appears or behaves.
The handle of the procedure associated with the window can be obtained 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:
type
TForm1=class(TForm)
private
hproc:TFarproc;
protected
procedure WndProc(var msg:TMessage);
end;
Here, the procedure WndProc will replace the original window procedure.
To replace the original procedure with WndProc, you must first call
MakeObjectInstance, which converts a member procedure (here WndProc is member of TForm1 class) to a standard procedure.
This is because WndProc 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. (Remember 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 MakeObjectInstance as shown here:
fproc:TFarProc;
fproc:=MakeObjectInstance(WndProc);
Then call SetWindowlong to replace the procedure
of the window:
SetWindowlong(hwnd,GWL_WNDPROC,longword(fcurProc));
Now all messages that are sent to the window will be intercepted by your WndProc procedure.
The messages that are not handled by WndProc can be sent to the original procedure by using CallWindowProc. Here is how to call the function:
procedure TForm1.DlgProc(var msg:Tmessage);
begin
case msg.msg of
WM_SIZE:
begin
//user defined code
end;
WM_PAINT:
begin
//user defined code
end;
end;
//all unhandled messages are sent to original procedure. Here,
//hproc is the handle to the original window procedure.
msg.result := CallWindowProc(hproc, hwnd, msg.msg, msg.wparam, msg.lparam);
end;
Once you have finished you have to destroy the handle created by the MakeObjectInstance(WndProc) function by calling FreeObjectInstance, which is also defined in the forms unit. You usually call this function when the form is closed. Here is how it's done:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeObjectInstance(fproc);
end;
私達とつながりましょう