Finally, I got a working solution (Windows 7 and Windows 10 tested OK).
If one looks at the documenations for the SetForegroundWindow in Microsft MSDN, there is a "Remarks" section with a list of restrictions, when the command would work, and when it would not. There is a note that SetForegroundWindow would work, if "The process received the last input event." So I send my own process a dummy input, and gee, now everything works like expected, when OnOtherInstance fires, my application will either restore itself from the Taskbar, and/or come to the foreground and grab the input focus.
Here is the code:
procedure TForm1.Form1_OnCreate(Sender: TObject);
begin
// Application.restore hack #1
Self.formstyle := fsStayOnTop;
end;
procedure TForm1.UniqueInstance1_OnOtherInstance(Sender: TObject;
ParamCount: Integer; Parameters: array of String);
var
I: LPInput;
begin
// Revert Application.restore hack #1
Self.formstyle := fsNormal;
// Restore and bring to front
Application.Restore;
Application.BringToFront;
// Grab focus
I := nil;
try
// Hack #2: send myself some dummy input
GetMem(I,SizeOf(Input));
FillChar(I^, SizeOf(Input),$00); // empty input structure
SendInput(1, I, SizeOf(Input));
SetForegroundWindow(Application.MainForm.Handle);
finally
if I <> nil then FreeMem(I,SizeOf(Input));
end;
end;
Summary: Windows does not honor the formstyle attribute, so at first glance it is pointless to set it to any value. Application.Restore will just flash the application icon but not restore it, and Application.BringToFront and SetForegroundWindow (grab Focus) won't work at all either.
Hack #1: If the formstyle attribute is set to fsStayOnTop initally, the Window won't stay on top, but if the attribute is set to fsNormal later, Application.Restore and Application.BringToFront work like expected.
Hack #2: the "dummy input" hack entitles my App to call SetForegroundWindow to grab the focus.
Tested and found working with Windows 10 x86 and Windows 7 x64, Lazarus 1.6.
Armin.