M
Micro Whaight
Unregistered / Unconfirmed
GUEST, unregistred user!
我希望在程序实现下述目的:<br><br>1.打开一个计算器供用户使用;<br>2.但只打开一次,如果没有关闭,下次再用按钮打开计算器时,把<br>上次打开的调到前面;<br>3.程序关闭时,同时关闭可能打开的计算器;<br><br>说白了,就是如何调用一个外部程序,同时获得这个程序窗口的句柄?<br><br>从以前讨论中,抄得部分代码,"组装"成下面的样子:用CreateProcess<br>打开计算器,用EnumThreadWindows查找打开的计算器窗口句柄,<br>用ShowWindows显示计算器,用TerminateProcess<br>或者TerminateThread关闭可能已经打开的计算器.<br><br>但是EnumThreadWindows部分的代码被说成是画蛇添足,因为<br>CreateProcess中已经有了窗口句柄?或者说是线程句柄?那么如何<br>用这个线程句柄得到窗口句柄呢?因为ShowWindows要使用一个窗口<br>句柄?EnumWindows好象又没办法找到这个特定的计算器窗口?不用<br>CreateProcess,有其他API可以即打开外部程序,又同时获得这个程序<br>的窗口句柄的好办法吗?或者直接用GetTopWindow? 实在想不通...<br><br>还有,用EnumThreadWindows时,会产生一个延时?外面要加个While,<br>不然会打开五六个计算器后,才能找到计算器窗口? why?<br><br>最后,千万别说"...都不知道?!",因为我确实不知道,代码都是抄的. <br><br>unit...<br><br>interface<br><br>uses...<br><br>type<br> EnumThreadWndProc = function(hWnd:HWND; lParam:LPARAM): Boolean;<br><br> TfrmCreateAndRestore = class(TForm)<br> ...<br> end;<br><br> function Enum(hWnd:HWND; lParam:LPARAM): Boolean;stdcall;<br><br>var<br> frmCreateAndRestore: TfrmCreateAndRestore;<br> CalledWinHandle: THandle;<br> ProcessInfo: TProcessInformation;<br> temp: THandle;<br><br>implementation<br><br>{$R *.DFM}<br><br>function Enum(hWnd:HWND; lParam:LPARAM): Boolean;<br>{回调函数}<br>begin<br> if GetTopWindow(hWnd) <> 0 then<br> CalledWinHandle := hWnd;<br> Result:=True;<br>end;<br><br>procedure TfrmCreateAndRestore.btnOpenCalcClick(Sender: TObject);<br>{打开计算器,同时获得窗口句柄}<br>var<br> StartInfo: TStartupInfo;<br> CallBackProc: EnumThreadWndProc;<br> ExitCode: Cardinal;<br>begin<br> if CalledWinHandle <> 0 then<br> begin<br> if GetExitCodeProcess(ProcessInfo.hProcess, ExitCode) then<br> begin<br> if ExitCode = 0 then<br> begin<br> ShowMessage('Calc have exited'); //测试用的<br> CalledWinHandle := 0;<br> end;<br> end<br> else begin<br> ShowMessage('Can''t retrive Calc window'); //测试用的<br> CalledWinHandle := 0;<br> end;<br> end;<br> if CalledWinHandle = 0 then<br> begin<br> //创建进程,打开计算器<br> FillChar(StartInfo, SizeOf(StartInfo), #0);<br> with StartInfo do<br> begin<br> cb := SizeOf(StartInfo);<br> dwFlags := StartF_UseShowWindow;<br> wShowWindow := SW_NORMAL;<br> end;<br> if CreateProcess(nil, PChar('Calc'), nil, nil, True,<br> CREATE_DEFAULT_ERROR_MODE, nil, nil, StartInfo, ProcessInfo) then<br> begin<br> //获得窗口句柄<br> CallBackProc := @Enum;<br> while CalledWinHandle = 0 do<br> //如果不做这个While,就会要打开五六个计算器才能找到,why?<br> EnumThreadWindows(ProcessInfo.dwThreadId, @CallBackProc, 0);<br> end<br> else begin<br> ShowMessage('Create fail'); //测试用的<br> Exit;<br> end;<br> end;<br> //显示计算器<br> if IsWindowVisible(CalledWinHandle) then<br> begin<br> SetForeGroundWindow(CalledWinHandle);<br> ShowWindow(CalledWinHandle, SW_RESTORE);<br> end<br> else<br> ShowWindow(CalledWinHandle, SW_SHOW);<br>end;<br><br>procedure TfrmCreateAndRestore.FormClose(Sender: TObject;<br> var Action: TCloseAction);<br>//窗口关闭时,同时关闭可能已经打开的计算器<br>var<br> ProcessHandle: THandle;<br>begin<br> if ProcessInfo.dwProcessId <> 0 then<br> begin<br> ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessInfo.dwProcessId);<br> if not TerminateProcess(ProcessHandle, 0) then<br>//或者直接用 TerminateThread(ProcessInfo.hThread, 0)也行<br> ShowMessage('Close Calc error'); //测试用的<br> end;<br>end;<br>