프로그램의 중복실행을 방지하는 방법으로는 CreateMutex가 많이 쓰이는 것 같습니다.
저는 조금 고전적이지만 이해하기 쉬운 Global Atom Table을 이용한 방법을 소개합니다.
실은 10년전쯤에 컴포넌트로 만든 것을 컴포넌트 설치과정 없이 바로 이용할 수 있도록 단순한 유니트로
바꾼 것입니다. 
이용법은 프로그램 소스 내용 중 상수로 정의된 Author와 RunProgram 값을 올바르게 고친 후 프로젝트가 위치한 
폴더에 복사해 두고, 아래와 같이 프로젝트 소스화일(*.dpr)의 uses절에 제일 먼저 RunOne을 등록만 하면 됩니다. 
  uses RunOne, 
            Forms, . . .  .

그리고 RunOne은 실행하고자 하는 프로그램이 이미 실행중일 경우 최소화 상태이면 원래 크기로, 최상위
윈도우가 아니면 최상위 윈도우로 변경하여 사용자가 이전에 이미 실행 중이었다는 것을 바로 인식할 수 
있도록 해 줍니다.
아래는 RunOne.pas 소스입니다.

unit RunOne;

interface

uses WinTypes, SysUtils, Forms;

const
  Author = 'Silhwan Hyun';  // 저자명 : 실행여부를 검사하기 위한 검색어를 구성함.
  RunProgram = 'TClock';    // 프로그램명 :             "

implementation

var
  AtomText: array[0..63] of Char;
  AtomSaved : boolean = false;

  MyClassName    : array[0..255] of Char;
  FoundPrevInst  : boolean = false;
  PrevInstHandle : HWnd = 0;
  FoundAtom      : TAtom;

  NewAtom : TAtom;
  MyPopup : HWnd;

function LookAtAllWindows(Handle: HWnd; Temp: Longint): BOOL; stdcall;
var
  ClassName : array[0..255] of Char;
begin
  LookAtAllWindows := true;

  if GetClassName(Handle, ClassName, SizeOf(ClassName)) > 0 then
  begin
    if StrComp(ClassName, MyClassName) = 0 then // 동일 window class ?
    begin
    // 중복실행여부를 조사하기 위한 검색어 생성
       StrPCopy(AtomText, Author + RunProgram + IntToStr(Handle));
    // 검색어가 Global Atom Table에 등록되어 있는지 확인
       FoundAtom := GlobalFindAtom(AtomText);
       if FoundAtom <> 0 then  // Global Atom Table에 등록되어 있으면
       begin
          FoundPrevInst  := true;    // 이미 실행 중인 것으로 표시
          PrevInstHandle := Handle;  // 실행 중인 어플리케이션 윈도우 핸들
          LookAtAllWindows := false; // enumeration 함수를 종료시킨다
       end;
    end;
  end;
end;

initialization
 // 프로그램의 클래스명을 알아낸다.   
  GetClassName(Application.Handle, MyClassName, SizeOf(MyClassName));
 // 윈도우를 검색하여 중복실행이 아닌지 확인한다
  EnumWindows(@LookAtAllWindows, 0);
  if FoundPrevInst then   // 이미 실행 중이면
  begin
     MyPopup := GetLastActivePopup(PrevInstHandle);
     BringWindowToTop(PrevInstHandle);
     if IsIconic(MyPopup) then
     begin
        ShowWindow(MyPopup, SW_RESTORE);  // 최소화 상태이면 원래 크기로
     end else
        BringWindowToTop(MyPopup);        // 최상위 윈도우로
     SetForegroundWindow(MyPopup);      // 포커스를 준다.    *** Added ***

     Halt(0);  // 새로 실행한 프로그램은 강제로 종료시킨다
  end else
  begin
   // 실행중이 아니면 검색어를 Global Atom Table에 등록한다
     StrPCopy(AtomText, Author + RunProgram + IntToStr(Application.Handle));
     NewAtom := GlobalAddAtom(AtomText);
     if NewAtom <> 0 then   // Global Atom Table에 등록성공이면
        AtomSaved := true;
  end;

finalization
  // 프로그램 종료시는 Global Atom Table에 등록해 둔 검색어를 해제한다.
  if AtomSaved then
  begin
     FoundAtom := GlobalFindAtom(AtomText);
     if FoundAtom <> 0 then
        GlobalDeleteAtom(FoundAtom);
  end;

end.



댓글 중~ 


단지...
BringWindowToTop 다음에

     SetForegroundWindow(MyPopup);

이것을 추가하는것이 더 편할것 같습니다.
어차피 실행할려고 한것이니 최상위 및 원복 후 포커스를 주는것이 좋을듯 합니다. ^^  



원본 링크 : http://www.delmadang.com/community/bbs_print.asp?bbsNo=3&bbsCat=0&indx=412497

+ Recent posts