0

実行されたアプリケーションのハンドルを返す winexec(...):Hwnd のようなカスタム関数を作成するために使用します。

findwindow() を使用しましたが、ウィンドウのキャプションを変更すると問題が発生します。

4

3 に答える 3

8

どのプログラムにも 1 つのウィンドウ ハンドルがあるという保証はないため、アプリケーションの "the" ウィンドウ ハンドルを取得する一般的な方法はありません。プログラムには、多数のトップレベル ハンドル (つまり、各ドキュメントに 1 つずつある Microsoft Word) がある場合や、ウィンドウがまったくない場合があります。ウィンドウ ハンドルが本当に必要な理由を疑問に思うかもしれません。特定のウィンドウハンドルを必要としない、あなたがやろうとしていることを何でもするためのより良い方法があるかもしれません.

WinExec(これは 15 年近く非推奨になっているため、もう使用しないことを真剣に検討する必要があります) ShellExecute。実際にプログラムを起動したとしても、起動したプログラムに関する情報はまったく返されません。( ShellExecuteDDE を使用して、アプリケーションの既に実行中のインスタンスにコマンドを送信する場合があります。) また、アプリケーションを開始すると、プログラムが実行されなくなる前に実行が終了する可能性があります。

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を教えてくれます; プロセスハンドルのみを返すため、その上で使用します。ウィンドウ列挙関数には、次のシグネチャに一致するコールバック関数が必要です。TProcessInformationShellExecuteExGetProcessID

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 がプロセスの簿記情報をクリーンアップできるようにします。

于 2010-06-15T14:56:50.483 に答える
2

EnumWindows という関数があります。お役に立てると思います。

詳細については、次のリンクを確認してください

http://delphi.about.com/od/windowsshellapi/l/aa080304a.htm

http://www.swissdelphicenter.ch/torry/showcode.php?id=327

于 2010-06-15T06:58:27.780 に答える
0

このページ ( 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() をスローするためにこれに嫌がらせメールをドロップすることは承知していますが、大量の処理を実行して待機しているときに、その実行が完了するまでウィンドウをロックしたくありません。

于 2016-07-26T22:28:35.243 に答える