unit ftsubcls; {How to intercept messages that a form gets from one of it's components} interfaceuses SysUtils, WinTypes, WinProcs, Messages, Classes, Controls, Forms;type TFTSubclassWnd = class(TComponent) private FNewWndProcPtr : TFarProc; FOldWndProcPtr : TFarProc; FWindowHandle : HWnd; protected { Virtual methods for descendants } procedure NewWndProc(var Message: TMessage); virtual; abstract; procedure AssignHandle; virtual; { Component methods } procedure ReplaceWndProc; procedure RestoreWndProc; procedure CallOldWndProc(var Message: TMessage); { Protected properties } property NewWndProcPtr: TFarProc read FNewWndProcPtr; property OldWndProcPtr: TFarProc read FOldWndProcPtr; property WindowHandle: HWnd read FWindowHandle; public { Construction/destruction } constructor Create(AOwner: TComponent); override; destructor Destroy; override; end;implementation constructor TFTSubclassWnd.Create(AOwner: TComponent); begin inherited Create(AOwner); if not (AOwner is TForm) then raise Exception.Create('Owner must be form'); AssignHandle; ReplaceWndProc; end;destructor TFTSubclassWnd.Destroy; begin RestoreWndProc; inherited Destroy; end;procedure TFTSubclassWnd.CallOldWndProc(var Message: TMessage); begin with Message do Result := CallWindowProc(FOldWndProcPtr, FWindowHandle, Msg, wParam, lParam); end;procedure TFTSubclassWnd.AssignHandle; begin with (Owner as TForm) do begin { Ensure the window handle has been allocated } HandleNeeded; { Assign window handle (with special processing for MDI parent forms } if (FormStyle = fsMDIForm) then FWindowHandle := ClientHandle else FWindowHandle := Handle; end; end;procedure TFTSubclassWnd.ReplaceWndProc; begin { Save pointer to old WndProc } FOldWndProcPtr := Pointer(GetWindowLong(FWindowHandle, GWL_WNDPROC)); { Create pointer to NewWndProc } FNewWndProcPtr := MakeObjectInstance(NewWndProc); if (FNewWndProcPtr = nil) then raise EOutOfResources.Create('Cannot allocate WndProc handle'); { Subclass window by setting GWL_WNDPROC to NewWndProc } SetWindowLong(FWindowHandle, GWL_WNDPROC, LongInt(FNewWndProcPtr)); end;procedure TFTSubclassWnd.RestoreWndProc; begin SetWindowLong(FWindowHandle, GWL_WNDPROC, LongInt(FOldWndProcPtr)); if FNewWndProcPtr <> nil then FreeObjectInstance(FNewWndProcPtr); end;end.(* You'll need to descend any components which need to "listen" to the form's messages from the TSubclassWnd component. In your descendant component, you'll need to override the NewWndProc procedure, and provide a message handler that looks for messages of interest. For example, your procedure will look something like this: Procedure TMaleyComponent.NewWndProc(var Message: TMessage); begin if (Message.Msg = WM_SIZE) then { Do something }; end; *)这些就是代码了
{How to intercept messages that a form gets from one of it's components}
interfaceuses
SysUtils, WinTypes, WinProcs, Messages, Classes, Controls, Forms;type TFTSubclassWnd = class(TComponent)
private
FNewWndProcPtr : TFarProc;
FOldWndProcPtr : TFarProc;
FWindowHandle : HWnd;
protected
{ Virtual methods for descendants }
procedure NewWndProc(var Message: TMessage); virtual; abstract;
procedure AssignHandle; virtual;
{ Component methods }
procedure ReplaceWndProc;
procedure RestoreWndProc;
procedure CallOldWndProc(var Message: TMessage);
{ Protected properties }
property NewWndProcPtr: TFarProc read FNewWndProcPtr;
property OldWndProcPtr: TFarProc read FOldWndProcPtr;
property WindowHandle: HWnd read FWindowHandle;
public
{ Construction/destruction }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;implementation
constructor TFTSubclassWnd.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
if not (AOwner is TForm) then
raise Exception.Create('Owner must be form');
AssignHandle;
ReplaceWndProc;
end;destructor TFTSubclassWnd.Destroy;
begin
RestoreWndProc;
inherited Destroy;
end;procedure TFTSubclassWnd.CallOldWndProc(var Message: TMessage);
begin
with Message do
Result := CallWindowProc(FOldWndProcPtr, FWindowHandle, Msg, wParam, lParam);
end;procedure TFTSubclassWnd.AssignHandle;
begin
with (Owner as TForm) do begin
{ Ensure the window handle has been allocated }
HandleNeeded;
{ Assign window handle (with special processing for MDI parent forms }
if (FormStyle = fsMDIForm) then
FWindowHandle := ClientHandle
else
FWindowHandle := Handle;
end;
end;procedure TFTSubclassWnd.ReplaceWndProc;
begin
{ Save pointer to old WndProc }
FOldWndProcPtr := Pointer(GetWindowLong(FWindowHandle, GWL_WNDPROC));
{ Create pointer to NewWndProc }
FNewWndProcPtr := MakeObjectInstance(NewWndProc);
if (FNewWndProcPtr = nil) then
raise EOutOfResources.Create('Cannot allocate WndProc handle');
{ Subclass window by setting GWL_WNDPROC to NewWndProc }
SetWindowLong(FWindowHandle, GWL_WNDPROC, LongInt(FNewWndProcPtr));
end;procedure TFTSubclassWnd.RestoreWndProc;
begin
SetWindowLong(FWindowHandle, GWL_WNDPROC, LongInt(FOldWndProcPtr));
if FNewWndProcPtr <> nil then
FreeObjectInstance(FNewWndProcPtr);
end;end.(*
You'll need to descend any components which need to "listen" to the form's
messages from the TSubclassWnd component. In your descendant component, you'll
need to override the NewWndProc procedure, and provide a message handler that
looks for messages of interest. For example, your procedure will look something
like this:
Procedure TMaleyComponent.NewWndProc(var Message: TMessage);
begin
if (Message.Msg = WM_SIZE) then { Do something };
end;
*)这些就是代码了