program dsplnk; { 2011-05-10:Ver 0.0.2.0 ・TScreenのMonitorプロパティがモニター情報の変更に追随しない不具合を回避。 2011-02-15:Ver 0.0.1.0 ・二重起動防止を実装。 2011-02-14:作成。 } uses // FastMM4, // myDebug, my_safedll, Windows, Forms, Messages, PsAPI, SysUtils, main in 'main.pas' {App_TOOLDspLnk}; {$R *.res} function gfnsExeNameGet(hHandle: HWND): WideString; {ウィンドウハンドルから実行ファイル名を返す http://m--takahashi.com/bbs/pastlog/02500/02414.html http://www.geocities.jp/fjtkt/problems/2003_0004.html http://www2.big.or.jp/~osamu/Delphi/tips.cgi?index=0182.txt http://homepage1.nifty.com/MADIA/delphi/Win32API/Process.htm } var li_PID : DWORD; lh_Process : THandle; lp_Buff : PWideChar; begin Result := ''; GetWindowThreadProcessId(hHandle, @li_PID); lh_Process := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, li_PID); try lp_Buff := AllocMem((MAX_PATH + 1) * SizeOf(lp_Buff)); try //プロセスハンドルを渡すだけで実行ファイル名を得られた。インスタンスハンドルはいらないようだ。 if (GetModuleFileNameExW(lh_Process, 0, lp_Buff, MAX_PATH) <> 0) then begin Result := WideString(lp_Buff); end; finally FreeMem(lp_Buff); end; finally CloseHandle(lh_Process); end; end; function EnumWindowProc(hHandle: HWND; iLParam: LPARAM): BOOL; stdcall; var lh_Owner : HWND; begin Result := True; // if (gfnsExeNameGet(hHandle) = gfnsExeNameGet(Application.Handle)) then begin if (gfnsExeNameGet(hHandle) = WideString(PWideChar(iLParam))) then begin //実行ファイルの名前が同じだった。 //ただし自分自身である可能性がある。 lh_Owner := GetWindow(hHandle, GW_OWNER); if (lh_Owner <> Application.Handle) and (hHandle <> Application.Handle) then begin Beep; //hHandleのオーナーウィンドウが自身のオーナーウィンドウのハンドルではなかった。 //このhHndleが目的のプログラムのウィンドウハンドル。 if (IsIconic(lh_Owner)) then begin //最小化されていたら元に戻す。 SendMessage(lh_Owner, WM_SYSCOMMAND, WPARAM(SC_RESTORE and $FFF0), 0); end; //前面に移動させる SetForegroundWindow(lh_Owner); //必要な処理を終えたので以降の処理(トップレベルウィンドウの列挙)を続行しない。 Result := False; end; end; end; var ls_AppExe : WideString; begin //二重起動チェック。 if (CreateMutex(nil, False, 'DispLnkapbi203dap') <> 0) //関数が成功して、 and (GetLastError = ERROR_ALREADY_EXISTS) //既に同名のミューテックスオブジェクトがあれば、 then begin //二重起動である。 //メッセージを出す。 //Application.MessageBox('二重起動は許可されていません', 'メッセージ'); //先に起動しているプログラムを探して前面に表示する処理を行う。 ls_AppExe := gfnsExeNameGet(Application.Handle); EnumWindows(@EnumWindowProc, Integer(PWideChar(ls_AppExe))); //プロラム終了。 Exit; end; Application.Initialize; Application.Title := 'DispLnk'; Application.CreateForm(TApp_TOOLDspLnk, App_TOOLDspLnk); Application.Run; end.