2013-03-02 3 views
1

뮤텍스를 작성하여 응용 프로그램의 다른 인스턴스가 이미 실행중인 경우 기본 양식의 OnCreate 중에 확인하는 응용 프로그램이 있습니다. 그럴 경우 두 번째 인스턴스는 첫 번째 인스턴스로 메시지를 전달한 다음 자신을 닫습니다. 두 번째 응용 프로그램의 작은 중괄호가 닫히기 전에 화면에 잠시 동안 기본 양식을 깜박임을 제외하고는 정상적으로 작동합니다.두 번째 응용 프로그램 인스턴스를 거의 즉시 닫을 때 양식이 잠깐 깜박임 중지

기본 폼 WindowState를 wsMinimize로 설정하여 응용 프로그램을 시작한 다음 폼을 최대화하기 위해 1ms 지연 타이머를 사용하는 것이 좋습니다. 그러나 이것은 끔찍한 해킹처럼 보입니다.

더 좋은 아이디어가 있습니까?

procedure TMyAwesomeForm.FormCreate(Sender: TObject); 
var 
    h: HWND; 
begin 
    // Try to create mutex 
    if CreateMutex(nil, True, '6EACD0BF-F3E0-44D9-91E7-47467B5A2B6A') = 0 then 
    RaiseLastOSError; 

    // If application already running 
    if GetLastError = ERROR_ALREADY_EXISTS then 
    begin 
    // Prevent this instance from being the receipient of it's own message by changing form name 
    MyAwesomeForm.Name := 'KillMe'; 

    // If this instance was started with parameters: 
    if ParamCount > 0 then 
    begin 
     h := FindWindow(nil, 'MyAwesomeForm'); 

     //Pass the parameter to original application 
     SendMessage(h, WM_MY_MESSAGE, strtoint(ParamStr(1)),0); 
    end; 

    // Shut this instance down - there can be only one 
    Application.Terminate; 
    end; 

    // Create Jump Lists  
    JumpList := TJumpList.Create; 
    JumpList.ApplicationId := 'TaskbarDemo.Unique.Id'; 
    JumpList.DeleteList; 
    CreateJList(); 
end; 
+3

은 * .DPR 파일에서 호출됩니다. – TLama

+0

이것은 [이 질문] (http://stackoverflow.com/q/15136960/62576)과 매우 유사합니다. 아마도 거기에 대한 대답이 도움이 될 수 있습니다. (당신이 너무 늦게 체크하고있다 - FormCreate를 치기 전에 너무 늦어서 막을 수 없으며,'Application.Terminate'는 주 윈도우에 단순히'WM_QUIT' 메시지를 게시한다. 이전 인스턴스를 체크 할 필요가있다. 'Application.Initialize'가 호출되기 전에'.dpr' 파일에.) –

답변

4

양식이 생성되어 나타나기 때문에 양식 클래스 내에서 검사를 수행하지 마십시오.

IMHO 자신이 선택한 것과 같은 검사를하는 것이 .dpr 파일 자체입니다. 예를 들어

:

program Project3; 

uses 
    Forms, 
    Windows, //<--- new citizens here 
    SysUtils, 
    Messages, 
    Unit1 in 'Unit1.pas' {Form1}; 

{$R *.res} 

function IsAlreadyRunning: Boolean; 
var 
    h: HWND; 
begin 
    //no comments, sorry, but I don't use comments to explain what the 
    //code explains by itself. 
    Result := False; 

    if CreateMutex(nil, True, '6EACD0BF-F3E0-44D9-91E7-47467B5A2B6A') = 0 then 
    RaiseLastOSError; 

    if GetLastError = ERROR_ALREADY_EXISTS then 
    begin 
    if ParamCount > 0 then 
    begin 
     h := FindWindow(nil, 'MyAwesomeForm'); 
     if h <> 0 then 
     PostMessage(h, WM_MY_MESSAGE, strtoint(ParamStr(1)),0); 
     Result := True; 
    end; 
    end; 
end; 

begin 
    if not IsAlreadyRunning then 
    begin 
    Application.Initialize; 
    Application.MainFormOnTaskbar := True; 
    Application.CreateForm(TForm1, Form1); 
    Application.Run; 
    end; 
end. 
는`Application.CreateForm` 전에 양식을 실제로 만들어 어딘가에 전에 코드를 이동
+0

메시지를 보내지 않고 보내는 대신 메시지 수신자가 진행 중에 멈춘다면이 초기화를 막을 수 있습니다. 또한'wParam' 매개 변수를 적절한'WPARAM' 유형으로 변환하십시오. 그리고 마지막으로, 'IsAlreadyRunning'은 윈도우가 발견되었는지 검사조차하지 않는 함수의 좋은 이름이 아니며, FindWindow가 0 (NULL)을 반환하더라도 메시지를 보냅니다. – TLama

+0

@traama 폼의 표시를 피하기 위해 질문에서 코드를 옮겼습니다.하지만 당신이 옳았습니다. 나는 게으르다. 그래서 검사를 추가하고'SendMessage' 대신'PostMessage'로 변경했습니다. WPAREM에 대한 캐스트 당, IMHO 컴파일러가 항상 당신을 위해 그것을하기 때문에 필요하지 않습니다. – jachguate

+0

대단히 고마워. 그것은 그것을 분류했다. 나는 dpr 파일에 코드를 넣을 수도 있다는 것을 몰랐다. 자신을 가르치려는 즐거움! 나는 당신의 해결책을 upvote하려고했지만 슬프게도 나의 평판은 충분하지 않습니다. – user2125574

관련 문제