(Assuming VCL) The frame must somehow intercept the parent form, activate / deactivate events. There are many possible ways to do this (setting the parent form of the OnActivate / OnDeactivate events, subclasses of SetWindowLong (GWL_WNDPROC) or WindowProc ), but you will need to ensure that if multiple instances of the frame do this in the same instance of the form, the hook removal order must be insert reversed hook. In addition, you will have the problem of properly handling cases when window handlers are restored.
A simpler approach would be to use something like this as the ancestor of all your forms in a project:
TMyForm = class(TForm) procedure Activate; override; procedure Deactivate; override; end; procedure TMyForm.Activate; begin inherited Activate; NotifyControls(CM_ACTIVATE); end; procedure TMyForm.Deactivate; begin inherited Deactivate; NotifyControls(CM_DEACTIVATE); end;
and something like this as the ancestor of all your frames in the project:
TMyFrame = class(TFrame) procedure CMActivate(var Msg: TCMActivate); message CM_ACTIVATE; procedure CMDeactivate(var Msg: TCMDeactivate); message CM_DEACTIVATE; end; procedure TMyFrame.CMActivate(var Msg: TCMActivate); begin // parent form activated end; procedure TMyFrame.CMDeactivate(var Msg: TCMDeactivate); begin // parent form deactivated end;
Thus, the relationship is fairly loose, and it still allows you to override the default behavior of TMyFrame by overriding the CM_ACTIVATE or CM_DEACTIVATE message handler in descendants that require special handling.
Cautions:
- This has not been tested - it is just a quick suggestion, as a starting point. You can also declare and use your own custom messages instead of
CM_ACTIVATE / CM_DEACTIVATE to avoid any interference with the rest of the VCL. NotifyControls notifies all controls - not just frames - but regular controls ignore / do not process CM_ACTIVATE / CM_DEACTIVATE by default, so this should not be a problem. You can also implement your own NotifyFrames method.
source share