The trick is to hook into message processing of the parent form (proof-of-concept code, tested with Delphi 2009, error and corner case handling need more work):
type
TFrame2 = class(TFrame)
strict private
fOnEnterSizeMove: TNotifyEvent;
fOnExitSizeMove: TNotifyEvent;
fSavedWndProc: TWndMethod;
procedure DoEnterSizeMove;
procedure DoExitSizeMove;
procedure ParentWindowProc(var AMessage: TMessage);
protected
procedure CreateWnd; override;
procedure DestroyWnd; override;
published
property OnEnterSizeMove: TNotifyEvent read fOnEnterSizeMove
write fOnEnterSizeMove;
property OnExitSizeMove: TNotifyEvent read fOnExitSizeMove
write fOnExitSizeMove;
end;
{ TFrame2 }
procedure TFrame2.CreateWnd;
var
ParentForm: TCustomForm;
begin
inherited;
ParentForm := GetParentForm(Self);
if ParentForm <> nil then begin
fSavedWndProc := ParentForm.WindowProc;
ParentForm.WindowProc := ParentWindowProc;
end;
end;
procedure TFrame2.DestroyWnd;
var
ParentForm: TCustomForm;
begin
ParentForm := GetParentForm(Self);
if ParentForm <> nil then
ParentForm.WindowProc := fSavedWndProc;
inherited;
end;
procedure TFrame2.DoEnterSizeMove;
begin
if Assigned(fOnEnterSizeMove) then
fOnEnterSizeMove(Self);
end;
procedure TFrame2.DoExitSizeMove;
begin
if Assigned(fOnExitSizeMove) then
fOnExitSizeMove(Self);
end;
procedure TFrame2.ParentWindowProc(var AMessage: TMessage);
begin
fSavedWndProc(AMessage);
if AMessage.Msg = WM_ENTERSIZEMOVE then
DoEnterSizeMove;
if AMessage.Msg = WM_EXITSIZEMOVE then
DoExitSizeMove;
end;
Note that the messages are sent whenever a secondary message loop for moving / sizing has been started or left - there is no way to distinguish between moving and sizing. If you need to make sure that you catch sizing only, you should compare old and new size of the frame in the handler.