INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

How To

How to ensure only one instance of application runs at once? by roo0047
Posted: 5 Jul 08 (Edited 6 Jul 08)

This is the final of several incarnations.  I can not take credit for all the code.  It once had more comments than code and in an overzealous clean-up, all the credits were removed.  I will search my archives and edit later to give credit where it is due.

First the unit, followed by how it is used:

CODE

unit PrevInst;

interface

Uses
  Windows, SysUtils, Messages;

function ActivatePrevInstance(const MainFormClass, ATitle: string): Boolean;

(*
Usage:
  if ActivatePrevInstance(TMainForm.ClassName, '') then
    Exit;
*)

implementation

function StrPAlloc(const S: string): PChar;
begin
  Result := StrPCopy(StrAlloc(Length(S) + 1), S);
end;

function GetWindowParent(Wnd: HWND): HWND;
begin
  Result := GetWindowLong(Wnd, GWL_HWNDPARENT);
end;

function WindowClassName(Wnd: HWND): string;
var Buffer: array [0..255] of Char;
begin
  SetString(Result, Buffer, GetClassName(Wnd, Buffer, SizeOf(Buffer) - 1));
end;

function WindowsEnum(Handle: HWND; Param: Longint): BOOL; export; stdcall;
begin
  if WindowClassName(Handle) = 'TAppBuilder' then
  begin
    Result := False;
    PLongint(Param)^ := 1;
  end
  else
    Result := True;
end;

procedure ActivateWindow(Wnd: HWND);
begin
  if Wnd <> 0 then
  begin
    ShowWindow(Wnd, SW_SHOWNOACTIVATE);   //ShowWinNoAnimate(Wnd, SW_SHOW);
    SetForegroundWindow(Wnd);
  end;
end;

function FindPrevInstance(const MainFormClass, ATitle: string): HWnd;
var
  BufClass, BufTitle: PChar;
begin
  Result := 0;
  if (MainFormClass = '') and (ATitle = '') then Exit;
  BufClass := nil; BufTitle := nil;
  if (MainFormClass <> '') then
    BufClass := StrPAlloc(MainFormClass);
  if (ATitle <> '') then
    BufTitle := StrPAlloc(ATitle);
  try
    Result := FindWindow(BufClass, BufTitle);
  finally
    StrDispose(BufTitle);
    StrDispose(BufClass);
  end;
end; //FindPrevInstance

function ActivatePrevInstance(const MainFormClass, ATitle: string): Boolean;
var
  PrevWnd, PopupWnd, ParentWnd: HWnd;
  IsDelphi: Longint;
begin
  Result := False;
  PrevWnd := FindPrevInstance(MainFormClass, ATitle);
  if PrevWnd <> 0 then begin
    ParentWnd := GetWindowParent(PrevWnd);
    while (ParentWnd <> GetDesktopWindow) and (ParentWnd <> 0) do begin
      PrevWnd := ParentWnd;
      ParentWnd := GetWindowParent(PrevWnd);
    end;
    if WindowClassName(PrevWnd) = 'TApplication' then begin
      IsDelphi := 0;
      EnumThreadWindows(GetWindowTask(PrevWnd), @WindowsEnum, LPARAM(@IsDelphi));
      if Boolean(IsDelphi) then
        Exit;
      if IsIconic(PrevWnd) then  { application is minimized }
      begin
        SendMessage(PrevWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
        Result := True;
        Exit;
      end
      else
        ShowWindow(PrevWnd, SW_SHOWNOACTIVATE); {ShowWinNoAnimate(PrevWnd, SW_SHOWNOACTIVATE);}
    end
    else
      ActivateWindow(PrevWnd);
    PopupWnd := GetLastActivePopup(PrevWnd);
    if (PrevWnd <> PopupWnd) and IsWindowVisible(PopupWnd) and IsWindowEnabled(PopupWnd) then
      SetForegroundWindow(PopupWnd)
    else
      ActivateWindow(PopupWnd);
    Result := True;
  end;
end; //ActivatePrevInstance

end.
The following DPR (project1.exe) will only launch once outside the IDE:

IMPORTANT NOTE: This function works ONLY if the Delphi IDE is NOT running.  There is a line of code in ActivatePrevInstance "if Boolean(IsDelphi) then exit;" to allow debugging.  It returns "false" if the IDE is running.

CODE

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  PrevInst in 'PrevInst.pas';

{$R *.res}

begin
  if ActivatePrevInstance(TForm1.ClassName, '') then
    Exit;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Back to Embarcadero: Delphi FAQ Index
Back to Embarcadero: Delphi Forum

My Archive

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close