unit UnitFrmInstance;
{
    Purpose:
        Recieve data from a previous instance;

    Notes:
        This form is conditionally created for only the first instance
        of this program.        
}

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;


const MYMESSAGE = WM_USER + 5;
const MYCLASS = 'ArsClip.FrmDummyInstance';
type InstanceCommand = (INST_INIT, INST_POPUP, INST_PARAM, INST_CONFIG, INST_DEFAULT);
type
  TFrmDummyInstance = class(TForm)
  private




    { Private declarations }

    command : InstanceCommand;

  public
    procedure CreateParams(var Params: TCreateParams); override;
    { Public declarations }
    procedure GetDataMessage(var Msg: TWMCopyData); message WM_COPYDATA;

  end;




var
  FrmDummyInstance: TFrmDummyInstance;

procedure FrmInstance_SendData(data : string);
procedure FrmInstance_Init(ic : InstanceCommand);  overload;
procedure FrmInstance_Init(p : string);  overload;
procedure FrmInstance_DeInit;
function FrmInstance_IsFirst : boolean;

implementation

uses  StrUtils, UnitFrmMainPopup, UnitPopupGenerate, UnitFrmJumpList, TypInfo,
  UnitMisc, UnitFocusManager;


{$R *.dfm}
var mutex : THandle;
    First : Boolean;
    param : string;
{ TFrmDummyInstance }

function FrmInstance_IsFirst : boolean;
begin
    result := First;
end;

procedure FrmInstance_Init(p : string);
begin
    param := p;
    FrmInstance_init(INST_PARAM);
end;

procedure FrmInstance_Init(ic : InstanceCommand);
var TA : TTaskArg;

    function AC(arg : TTaskArg) : string;
    begin
        result := TypInfo.GetEnumName(TypeInfo(TTaskArg), Integer(arg));
    end;
begin
    mutex := Windows.CreateMutex(nil, true, pchar(ExtractFileName(Application.exename)));
    first := (Windows.GetLastError = 0);

    case ic of
        INST_INIT: if First then Application.CreateForm(TFrmDummyInstance, FrmDummyInstance);
        INST_POPUP:
            begin
                Application.Terminate;
                Application.ProcessMessages;
                UnitFrmInstance.FrmInstance_SendData(IntToStr(Integer(ic)));
                Application.ProcessMessages;
            end;
        INST_PARAM:
            begin
                Application.Terminate;
                Application.ProcessMessages;
                UnitFrmInstance.FrmInstance_SendData(param);
                Application.ProcessMessages;
            end;
        INST_CONFIG:
            begin
                Application.Terminate;
                Application.ProcessMessages;
                ta := ARG_CONFIG;
                UnitFrmInstance.FrmInstance_SendData(AC(ta));
                Application.ProcessMessages;
            end;
        INST_DEFAULT:
            begin
                TFocusManager.ForceForeground(Application.Handle);
                // Without this, the original instance can't correctly
                // find the Next Window

                Application.Terminate;
                Application.ProcessMessages;
                ta := ARG_CONFIG;
                UnitFrmInstance.FrmInstance_SendData(IntToStr(Integer(ic)));
                Application.ProcessMessages;
            end;
    end;
end;

procedure FrmInstance_DeInit;
begin
    if mutex <> 0 then begin
        Windows.CloseHandle(mutex);
    end;
end;

procedure FrmInstance_SendData(data : string);
var
  cd : TCopyDataStruct;
  s : string;
  h : THandle;

begin
    s := data + #0;

    try

        ParamCount;
        cd.dwData := 0;
        cd.cbData := strsize(s);
        cd.lpData := StrAlloc(cd.cbData);
        StrPCopy(PChar(cd.lpData), s);

        // Send copy data message
        // set result according to result returned from other instance
        h := FindWindow(MYCLASS, nil);


        if (h <> 0) then begin
            SendMessage(
                h,
                WM_COPYDATA,
                0,
                integer(@cd)
            );
        end;

    finally
    end;
end;


procedure TFrmDummyInstance.GetDataMessage(var Msg: TWMCopyData);
var s : string;
begin
    s := PChar(MSg.CopyDataStruct.lpData);
    command := INST_PARAM;
    try
        command := InstanceCommand(StrToInt(s));
    except
        // the PARAM isn't an integer and will cause an exception
    end;

    case command of
    INST_INIT: ;
    INST_POPUP:
        begin
            FrmMainPopup.FakePopupHotkey;
        end;
    INST_PARAM:
        begin
            FrmJumpList.HandleTaskArgument(s);
        end;
    INST_DEFAULT:
        begin
            FrmMainPopup.JumplistDefault;
        end;
    end;
end;

procedure TFrmDummyInstance.CreateParams(var Params: TCreateParams);
begin
    inherited CreateParams(params);
{
    Params.Style := WS_POPUP ;
    Params.ExStyle := WS_EX_TOOLWINDOW or WS_EX_TOPMOST ;

    ParentWindow := GetDesktopWindow;
}
    StrCopy(Params.WinClassName, MYCLASS);
end;


end.
