Interesante cuestión
El problema aquí es que ese botón realmente no pertenece al Frame. Cualquier derivado de TWinControl tiene la capacidad de arrastrarse fuera de su contenedor; lo mismo que haces con el Frame, puedes hacerlo con un Panel, por ejemplo, o ¡incluso con un Button! Al hacerlo con este último queda más clara la situación: al arrastar el control fuera del formulario, lo que sucede es que la VCL crea un formulario
en caliente, de tipo TCustomDockForm e inserta en él el control.
Así pues, es con este último formulario con quien tenemos que lidiar.
Para ello, hay que capturar el mensaje CM_FLOAT del control (el Frame) que se le manda cuando -justamente- se pone a flotar y se crea el CutomDockForm.
El mensaje manda como parámetro dicho formulario y lo que podemos hacer es reemplazar su WindowProc por uno nuestro para interceptar el mensaje WM_CLOSE.
Aquí más o menos la idea:
Código Delphi
[-]
type
TFrame2 = class(TFrame)
private
OldHostWndProc: TWndMethod;
procedure CMFloat(var Msg: TCMFloat); message CM_FLOAT;
procedure HostWndProc(var Message: TMessage);
end;
implementation
procedure TFrame2.CMFloat(var Msg: TCMFloat);
begin
inherited;
if (TObject(Msg.DockSource.DragTarget) is TCustomDockForm) then
begin
OldHostWndProc := TCustomDockForm(Msg.DockSource.DragTarget).WindowProc;
TCustomDockForm(Msg.DockSource.DragTarget).WindowProc := HostWndProc;
end;
end;
procedure TFrame2.HostWndProc(var Message: TMessage);
begin
if Message.Msg = WM_CLOSE then
ShowMessage('Frame Closed!');
OldHostWndProc(Message);
end;
// Saludos