unit ScreenDispatch;

interface

uses
  SysUtils, Types, Classes, Forms, Generics.Collections;

type
  TScreenDispatcher = class
  strict private
    class var FActiveFormChangeFcns: TDictionary<string, TProc>;
    class procedure ActiveFormChange(Sender: TObject);
    class constructor ClassCreate;
    class destructor ClassDestroy;
  public
    class procedure RegisterFormChangeProc(const AIdentifier: string; AProc: TProc); static;
    class procedure RemoveFormChangeProc(const AIdentifier: string); static;
  end;

implementation

{ TScreenDispatcher }

class procedure TScreenDispatcher.ActiveFormChange(Sender: TObject);
begin
  if not Application.Terminated then
    if Assigned(FActiveFormChangeFcns) then
      for var p in FActiveFormChangeFcns do
        if Assigned(p.Value) then
          p.Value();
end;

class constructor TScreenDispatcher.ClassCreate;
begin
  FActiveFormChangeFcns := TDictionary<string, TProc>.Create;
end;

class destructor TScreenDispatcher.ClassDestroy;
begin
  FreeAndNil(FActiveFormChangeFcns);
end;

class procedure TScreenDispatcher.RegisterFormChangeProc(const AIdentifier: string;
  AProc: TProc);
begin
  if Assigned(FActiveFormChangeFcns) then
    FActiveFormChangeFcns.AddOrSetValue(AIdentifier, AProc);
  if Assigned(Screen) then
    Screen.OnActiveFormChange := ActiveFormChange;
end;

class procedure TScreenDispatcher.RemoveFormChangeProc(const AIdentifier: string);
begin
  if Assigned(FActiveFormChangeFcns) then
    FActiveFormChangeFcns.Remove(AIdentifier);
end;

end.
