function MakeModalState(H: HWND): Integer;
var
WindowList: Pointer;
ActiveWindow: HWnd;
ModalResult: Integer;
Visible, Enabled: Boolean;
begin
Visible:= IsWindowVisible(H);
Enabled:= IsWindowEnabled(H);
if Not Visible or not Enabled then
raise EInvalidOperation.Create(SCannotShowModal);
if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
ReleaseCapture;
Application.ModalStarted;
try
ActiveWindow := GetActiveWindow;
WindowList := DisableTaskWindows(0);
try
SendMessage(H, CM_ACTIVATE, 0, 0);
ModalResult := 0;
repeat
Application.HandleMessage;
if Application.Terminated then
ModalResult := mrCancel;
Sleep(1);
until Not IsWindow(H);
Result := ModalResult;
SendMessage(H, CM_DEACTIVATE, 0, 0);
if GetActiveWindow <> H then
ActiveWindow:= 0;
finally
EnableTaskWindows(WindowList);
if ActiveWindow <> 0 then
SetActiveWindow(ActiveWindow);
end;
finally
Application.ModalFinished;
end;
end;
function ForceSetForegroundWindow(AHandle: HWND): Boolean;
var
fromId, toId: DWORD;
begin
fromId:= GetCurrentThreadId();
toId:= GetWindowThreadProcessId(GetForegroundWindow, nil);
AttachThreadInput(fromId, toId, TRUE);
Result:= SetForegroundWindow(AHandle);
AttachThreadInput(fromId, toId, FALSE);
end;
procedure ShowFindWindow(WND: HWND);
var
Placement: TWindowPlacement;
begin
if IsWindow(WND) then
begin
Placement.length := SizeOf(TWindowPlacement);
GetWindowPlacement(WND, @Placement);
case Placement.showCmd of
SW_SHOWMINIMIZED:
ShowWindow(WND, SW_RESTORE)
else
ShowWindow(WND, SW_SHOW);
end;
if GetActiveWindow <> WND then
ForceSetForegroundWindow(WND);
end;
end;
function WaitUntilProcessTerminated(AppHandle: HWND; ExeFileName: TFileName;
ExeClass, ExeCaption: String): Boolean;
var
ExeHandle: HWND;
Count: Integer;
ValueNames: TStrings;
i: Integer;
dtsrunuifile: TFileName;
ec: PChar;
begin
Result:= False;
if Not FileExists(ExeFileName) then
Raise Exception.Create(Format('%s 파일이 존재하지 않습니다', [ExeFileName]));
if ExeCaption = '' then
ec:= nil
else
ec:= PChar(ExeCaption);
if FindWindow(PChar(ExeClass), ec) <> 0 then
begin
MessageDlg(Format('이미 %s 파일이 실행되어 있습니다', [ExtractFileName(ExeFileName)]), mtInformation, [mbYes], 0);
Exit;
end;
Screen.Cursor:= crHourGlass;
ShellExecute(AppHandle, 'Open', PChar(ExeFileName), nil, nil, SW_SHOW);
Count:= 0;
// 실행파일이 로딩 될 때 까지 기다리기
ExeHandle:= FindWindow(PChar(ExeClass), ec);
while (Count < 1000) and (ExeHandle = 0) do
begin
ExeHandle:= FindWindow(PChar(ExeClass), ec);
inc(Count);
Sleep(10);
end;
Screen.Cursor:= crDefault;
if ExeHandle = 0 then
Raise Exception.Create(Format('%s 실행파일의 윈도우를 찾을 수 없습니다', [ExtractFileName(ExeFileName)]));
SetForegroundWindow(ExeHandle);
if MakeModalState(ExeHandle) = 0 then
begin
ShowFindWindow(AppHandle);
Result:= True;
end;
end;
참고해서 코딩하시길...
uses
ShellAPI, Consts;
{$R *.dfm}
function MakeModalState(H: HWND): Integer;
var
WindowList: Pointer;
ActiveWindow: HWnd;
ModalResult: Integer;
Visible, Enabled: Boolean;
begin
Visible:= IsWindowVisible(H);
Enabled:= IsWindowEnabled(H);
if Not Visible or not Enabled then
raise EInvalidOperation.Create(SCannotShowModal);
if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
ReleaseCapture;
Application.ModalStarted;
try
ActiveWindow := GetActiveWindow;
WindowList := DisableTaskWindows(0);
try
SendMessage(H, CM_ACTIVATE, 0, 0);
ModalResult := 0;
repeat
Application.HandleMessage;
if Application.Terminated then
ModalResult := mrCancel;
Sleep(1);
until Not IsWindow(H);
Result := ModalResult;
SendMessage(H, CM_DEACTIVATE, 0, 0);
if GetActiveWindow <> H then
ActiveWindow:= 0;
finally
EnableTaskWindows(WindowList);
if ActiveWindow <> 0 then
SetActiveWindow(ActiveWindow);
end;
finally
Application.ModalFinished;
end;
end;
function ForceSetForegroundWindow(AHandle: HWND): Boolean;
var
fromId, toId: DWORD;
begin
fromId:= GetCurrentThreadId();
toId:= GetWindowThreadProcessId(GetForegroundWindow, nil);
AttachThreadInput(fromId, toId, TRUE);
Result:= SetForegroundWindow(AHandle);
AttachThreadInput(fromId, toId, FALSE);
end;
procedure ShowFindWindow(WND: HWND);
var
Placement: TWindowPlacement;
begin
if IsWindow(WND) then
begin
Placement.length := SizeOf(TWindowPlacement);
GetWindowPlacement(WND, @Placement);
case Placement.showCmd of
SW_SHOWMINIMIZED:
ShowWindow(WND, SW_RESTORE)
else
ShowWindow(WND, SW_SHOW);
end;
if GetActiveWindow <> WND then
ForceSetForegroundWindow(WND);
end;
end;
function WaitUntilProcessTerminated(AppHandle: HWND; ExeFileName: TFileName;
ExeClass, ExeCaption: String): Boolean;
var
ExeHandle: HWND;
Count: Integer;
ValueNames: TStrings;
i: Integer;
dtsrunuifile: TFileName;
ec: PChar;
begin
Result:= False;
if Not FileExists(ExeFileName) then
Raise Exception.Create(Format('%s 파일이 존재하지 않습니다', [ExeFileName]));
if ExeCaption = '' then
ec:= nil
else
ec:= PChar(ExeCaption);
if FindWindow(PChar(ExeClass), ec) <> 0 then
begin
MessageDlg(Format('이미 %s 파일이 실행되어 있습니다', [ExtractFileName(ExeFileName)]), mtInformation, [mbYes], 0);
Exit;
end;
Screen.Cursor:= crHourGlass;
ShellExecute(AppHandle, 'Open', PChar(ExeFileName), nil, nil, SW_SHOW);
Count:= 0;
// 실행파일이 로딩 될 때 까지 기다리기
ExeHandle:= FindWindow(PChar(ExeClass), ec);
while (Count < 1000) and (ExeHandle = 0) do
begin
ExeHandle:= FindWindow(PChar(ExeClass), ec);
inc(Count);
Sleep(10);
end;
Screen.Cursor:= crDefault;
if ExeHandle = 0 then
Raise Exception.Create(Format('%s 실행파일의 윈도우를 찾을 수 없습니다', [ExtractFileName(ExeFileName)]));
SetForegroundWindow(ExeHandle);
if MakeModalState(ExeHandle) = 0 then
begin
ShowFindWindow(AppHandle);
Result:= True;
end;
end;
ex)
WaitUntilProcessTerminated(Application.Handle, 'c:\windows\system32\notepad.exe', 'notepad', '');