実行されたアプリケーションのハンドルを返す winexec(...):Hwnd のようなカスタム関数を作成するために使用します。
findwindow() を使用しましたが、ウィンドウのキャプションを変更すると問題が発生します。
実行されたアプリケーションのハンドルを返す winexec(...):Hwnd のようなカスタム関数を作成するために使用します。
findwindow() を使用しましたが、ウィンドウのキャプションを変更すると問題が発生します。
どのプログラムにも 1 つのウィンドウ ハンドルがあるという保証はないため、アプリケーションの "the" ウィンドウ ハンドルを取得する一般的な方法はありません。プログラムには、多数のトップレベル ハンドル (つまり、各ドキュメントに 1 つずつある Microsoft Word) がある場合や、ウィンドウがまったくない場合があります。ウィンドウ ハンドルが本当に必要な理由を疑問に思うかもしれません。特定のウィンドウハンドルを必要としない、あなたがやろうとしていることを何でもするためのより良い方法があるかもしれません.
WinExec
(これは 15 年近く非推奨になっているため、もう使用しないことを真剣に検討する必要があります) ShellExecute
。実際にプログラムを起動したとしても、起動したプログラムに関する情報はまったく返されません。( ShellExecute
DDE を使用して、アプリケーションの既に実行中のインスタンスにコマンドを送信する場合があります。) また、アプリケーションを開始すると、プログラムが実行されなくなる前に実行が終了する可能性があります。
CreateProcess
代わりにorを使用できますShellExecuteEx
。プログラムを開始すると、開始したプログラムを表すプロセス ハンドルが提供されます。これを使用して、ウィンドウのリストなど、プログラムに関する追加情報を取得できます。気にしないでくださいFindWindow
。キャプションとウィンドウ クラスが一意であるとは限りません。プログラムは多くの異なるウィンドウに同じクラス名を使用する可能性があり、プログラムの複数のインスタンスが同じクラス名を使用するため、本当に必要なものを選択する方法はほとんどありません。
EnumWindows
候補ウィンドウ ハンドルのリストを取得するために使用できる関数です。関数ポインタを指定すると、デスクトップの最上位ウィンドウごとにその関数が 1 回呼び出されます。どのプロセスに関心があるかを伝える方法と、結果のリストを返す方法が必要です。この関数は 1 つのパラメーターのみを受け入れるため、パラメーターは、より多くの情報を保持する構造体へのポインターである必要があります。
type
PWindowSearch = ^TWindowSearch;
TWindowSearch = record
TargetProcessID: DWord;
ResultList: TWndList;
end;
TWndList
値のリストを保持するために作成した型HWnd
です。Delphi 2009 以降を使用している場合は、TList<HWnd>
;を使用できます。以前のバージョンでは、TList
子孫または選択したものを使用できました。
CreateProcess
それが埋めるレコードのdwProcessID
メンバーの新しいプロセスIDを教えてくれます; プロセスハンドルのみを返すため、その上で使用します。ウィンドウ列挙関数には、次のシグネチャに一致するコールバック関数が必要です。TProcessInformation
ShellExecuteEx
GetProcessID
function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall;
EnumWindows
次のようなハンドル リストを取得するために使用できます。
function GetWindowListByProcessID(pid: DWord): TWndList;
var
SearchRec: TWindowSearch;
begin
Result := TWndList.Create;
try
SearchRec.TargetProcessID := pid;
SearchRec.ResultList := Result;
Win32Check(EnumWindows(SelectWindowByProcessID, LParam(@SearchRec)));
except
Result.Free;
raise;
end;
end;
次のようにコールバック関数を実装します。
function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall;
var
SearchRec: PWindowSearch;
WindowPid: DWord;
begin
SearchRec := PWindowSearch(Param);
Assert(Assigned(SearchRec));
GetWindowThreadProcessID(Wnd, WindowPid);
if WindowPid = SearchRec.TargetProcessID then
SearchRec.ResultList.Add(Wnd);
Result := True;
end;
リストを取得したら、ウィンドウの他の属性を調べて、実際に必要なものを判断できます。ウィンドウのタイトルまたはクラス名によって、またはそのウィンドウの 1 つである他のコントロールによって決定することができます。
プロセス ハンドルの使用が終了したら、必ずそれを呼び出しCloseHandle
て、OS がプロセスの簿記情報をクリーンアップできるようにします。
EnumWindows という関数があります。お役に立てると思います。
詳細については、次のリンクを確認してください
このページ ( http://delphidabbler.com/tips/134 ) の例 6 を試して、少しだけ変更してください。それが私がしたことです。
チェックする場所と結果を確認する場所を分割したい場合は、次のようなことができます
var
//...
runNext : Boolean;
//...
begin
{ startup code from other sample here }
// but instead of if
runNext := ShellExecuteEx(@SEInfo);
{ some more code here }
// need delay before running next process
// run loop until window with Handle is closed
if runNext then
with SEInfo do
repeat
GetExitCodeProcess(SEInfo.hProcess, ExitCode);
Sleep(20);
Application.ProcessMessages;
CheckSynchronize();
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
{ next process code here }
end;
一部の人が Sleep() をスローするためにこれに嫌がらせメールをドロップすることは承知していますが、大量の処理を実行して待機しているときに、その実行が完了するまでウィンドウをロックしたくありません。