如何获得调用的外部程序窗口句柄及EnumThreadWindows延时问题(100分)

  • 主题发起人 主题发起人 Micro Whaight
  • 开始时间 开始时间
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>&nbsp; EnumThreadWndProc = function(hWnd:HWND; lParam:LPARAM): Boolean;<br><br>&nbsp; TfrmCreateAndRestore = class(TForm)<br>&nbsp; ...<br>&nbsp; end;<br><br>&nbsp; function Enum(hWnd:HWND; lParam:LPARAM): Boolean;stdcall;<br><br>var<br>&nbsp; frmCreateAndRestore: TfrmCreateAndRestore;<br>&nbsp; CalledWinHandle: THandle;<br>&nbsp; ProcessInfo: TProcessInformation;<br>&nbsp; temp: THandle;<br><br>implementation<br><br>{$R *.DFM}<br><br>function Enum(hWnd:HWND; lParam:LPARAM): Boolean;<br>{回调函数}<br>begin<br>&nbsp; if GetTopWindow(hWnd) &lt;&gt; 0 then<br>&nbsp; &nbsp; CalledWinHandle := hWnd;<br>&nbsp; Result:=True;<br>end;<br><br>procedure TfrmCreateAndRestore.btnOpenCalcClick(Sender: TObject);<br>{打开计算器,同时获得窗口句柄}<br>var<br>&nbsp; StartInfo: TStartupInfo;<br>&nbsp; CallBackProc: EnumThreadWndProc;<br>&nbsp; ExitCode: Cardinal;<br>begin<br>&nbsp; if CalledWinHandle &lt;&gt; 0 then<br>&nbsp; begin<br>&nbsp; &nbsp; if GetExitCodeProcess(ProcessInfo.hProcess, ExitCode) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; if ExitCode = 0 then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; ShowMessage('Calc have exited'); &nbsp;//测试用的<br>&nbsp; &nbsp; &nbsp; &nbsp; CalledWinHandle := 0;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else begin<br>&nbsp; &nbsp; &nbsp; ShowMessage('Can''t retrive Calc window'); &nbsp;//测试用的<br>&nbsp; &nbsp; &nbsp; CalledWinHandle := 0;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; if CalledWinHandle = 0 then<br>&nbsp; begin<br>&nbsp; &nbsp; //创建进程,打开计算器<br>&nbsp; &nbsp; FillChar(StartInfo, SizeOf(StartInfo), #0);<br>&nbsp; &nbsp; with StartInfo do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; cb := SizeOf(StartInfo);<br>&nbsp; &nbsp; &nbsp; dwFlags := StartF_UseShowWindow;<br>&nbsp; &nbsp; &nbsp; wShowWindow := SW_NORMAL;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; if CreateProcess(nil, PChar('Calc'), nil, nil, True,<br>&nbsp; &nbsp; &nbsp; CREATE_DEFAULT_ERROR_MODE, nil, nil, StartInfo, ProcessInfo) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; //获得窗口句柄<br>&nbsp; &nbsp; &nbsp; CallBackProc := @Enum;<br>&nbsp; &nbsp; &nbsp; while CalledWinHandle = 0 do<br>&nbsp; &nbsp; &nbsp; //如果不做这个While,就会要打开五六个计算器才能找到,why?<br>&nbsp; &nbsp; &nbsp; &nbsp; EnumThreadWindows(ProcessInfo.dwThreadId, @CallBackProc, 0);<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else begin<br>&nbsp; &nbsp; &nbsp; ShowMessage('Create fail'); &nbsp;//测试用的<br>&nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; //显示计算器<br>&nbsp; if IsWindowVisible(CalledWinHandle) then<br>&nbsp; begin<br>&nbsp; &nbsp; SetForeGroundWindow(CalledWinHandle);<br>&nbsp; &nbsp; ShowWindow(CalledWinHandle, SW_RESTORE);<br>&nbsp; end<br>&nbsp; else<br>&nbsp; &nbsp; ShowWindow(CalledWinHandle, SW_SHOW);<br>end;<br><br>procedure TfrmCreateAndRestore.FormClose(Sender: TObject;<br>&nbsp; var Action: TCloseAction);<br>//窗口关闭时,同时关闭可能已经打开的计算器<br>var<br>&nbsp; ProcessHandle: THandle;<br>begin<br>&nbsp; if ProcessInfo.dwProcessId &lt;&gt; 0 then<br>&nbsp; begin<br>&nbsp; &nbsp; ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessInfo.dwProcessId);<br>&nbsp; &nbsp; if not TerminateProcess(ProcessHandle, 0) then<br>//或者直接用 TerminateThread(ProcessInfo.hThread, 0)也行<br>&nbsp; &nbsp; &nbsp; ShowMessage('Close Calc error'); &nbsp; //测试用的<br>&nbsp; end;<br>end;<br>
 
&nbsp; &nbsp; &nbsp; &nbsp;HANDLE HWndCalculator ;<br>&nbsp; &nbsp; &nbsp; &nbsp; HWndCalculator = FindWindow(NULL, "计算器"); // close the exist Calculator<br>&nbsp; &nbsp; &nbsp; &nbsp; if (HWndCalculator !=0 )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(HWndCalculator, WM_CLOSE, 0, 0);<br>&nbsp; &nbsp; &nbsp; &nbsp; HWndCalculator = FindWindow(NULL, "计算器"); // close the exist Calculator<br>
 
FindWindow会把所有找到的窗口关了,而不是程序中打开的那个。还有什么好建议吗?
 
拉一把。不成,加分? &nbsp;:)
 
如果用findwindow找到hndl后,可以使用setwindowpos将其调到最前端。
 
我想在NT下列举系统中所有的执行程序,结果发现Findwindow是找所有的窗体而不是程序的<br>句柄。
 
如果没有好的解决办法,是不是说我的方法已经是正确的了?(怀疑)如果是这样,也请<br>各位肯定一下呀?谢谢了!!!
 
结束吧。<br><br>我只好认为自己是对的了…… &nbsp;:)
 
真的没有啦吗
 
后退
顶部