[delphi-users:4266] プロセスIDからウィンドウハンドルを取得するには

2,132 views
Skip to first unread message

OE

unread,
Oct 14, 2015, 5:20:54 AM10/14/15
to delphi...@freeml.com
[開発環境 XE7 Windows7(64)]
[クライアント環境 Windows10(64)]

こんばんは、OEです。

プロセスIDからウィンドウハンドルを取得するには
どの様にしたら良いでしょうか。


例えば...
メモ帳(notepad.exe)で hogehoge.txt を開くと、
アプリケーションのタイトルは
「hogehoge.txt - メモ帳」となります。

起動中のnotepad.exeのプロセスIDの取得は
見よう見まねで何とかできました。
しかし、そのアプリケーションのタイトルの
取得方法がわかりません。


>プロセスIDからウィンドウハンドルを取得する
>http://d.hatena.ne.jp/yu-hr/20100323/1269355469
というC++の記事を見つけたのですが、これをDelphiに
することもできない状況です。


どなたかアドバイス頂けると助かります。
よろしくお願いいたします。


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
キレイになりたい美女子には植物性乳酸菌!
オシャレに腸活☆毎日お腹すっきり~
http://ad.freeml.com/cgi-bin/sa.cgi?id=nvJuf
------------------------------------------------------[freeml byGMO]--

dacho

unread,
Oct 14, 2015, 6:03:54 AM10/14/15
to delphi...@freeml.com
こんにちは。Dachoです。

>>プロセスIDからウィンドウハンドルを取得する
>>http://d.hatena.ne.jp/yu-hr/20100323/1269355469
>というC++の記事を見つけたのですが、これをDelphiに
>することもできない状況です。

Windows APIについてはググればすぐ出てきます。

http://www.geocities.jp/asumaroyuumaro/program/winapi/window/gettopwindow.html
http://www.geocities.jp/asumaroyuumaro/program/winapi/window/getnextwindow.html
http://www.geocities.jp/asumaroyuumaro/program/winapi/window/getwindowlong.html
http://www.geocities.jp/asumaroyuumaro/program/winapi/window/iswindowvisible.html
http://drang.s4.xrea.com/program/tips/window/exename_get.html

あとはこのCの処理をDelphiの文法で書き直すだけですよね。
特別高度な知識は必要なさそうに見えますが・・・もしかしてCの文法
が分からないのでしょうか?



MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
「スマホ一台」あれば「誰でも稼げる!?
モニター様の多くが、稼ぐことに
成功してます^^
※まずは、あなたも見てみて下さい。↓コチラ↓
http://ad.freeml.com/cgi-bin/sa.cgi?id=nvJXL
------------------------------------------------------[freeml byGMO]--

umez

unread,
Oct 14, 2015, 6:20:35 AM10/14/15
to delphi...@freeml.com
こんにちは、梅澤@プロキャストです。

Mr.XRAYさんの「Delphiサンプルプログラム集」の

■ 06_EXE のフルパスからウィンドウハンドルを取得
http://mrxray.on.coocan.jp/Delphi/plSamples/330_AppProcessList.htm#06

が参考になるのではないでしょうか。


OE <delphi...@freeml.com> さんは書きました。<2015/10/14>
----------
Tomomi Umezawa um...@procast.co.jp


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
キレイになりたい美女子には植物性乳酸菌!
オシャレに腸活☆毎日お腹すっきり~
http://ad.freeml.com/cgi-bin/sa.cgi?id=nvKlD
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Oct 14, 2015, 5:38:39 PM10/14/15
to delphi...@freeml.com
[delphi-users:4268] Re: プロセスIDからウィンドウハンドルを取得するには
へのレスです.

こんにちは.Mr.XRAYです.

>■ 06_EXE のフルパスからウィンドウハンドルを取得
>http://mrxray.on.coocan.jp/Delphi/plSamples/330_AppProcessList.htm#06

ちょっとしたテクニックというか,ノウハウ的に,こんな手もあります.
コールバック関数の引数を利用して,ウィンドハンドルを取得します.

//---------------------------------------------------------------------
// EnumWindowsのコールバック関数
// 以下の条件の時に終了とし,引数のlpにその時のウインドウハンドルを返す
// (1) hTopWndのプロセスIDが引数のlPと同じ
// (2) オーナーを持たないウィンドウ
// (3) 可視状態のウィンドウである
//---------------------------------------------------------------------
function EnumTopWindow(hTopWnd: HWND; lp: LPARAM): BOOL; stdcall;
var
p : LPDWORD;
ProcessId : DWORD;
begin
Result := True;

GetWindowThreadProcessId(hTopWnd, @ProcessId);
p := LPDWORD(lp);
if (ProcessId = p^) and (GetWindow(hTopWnd, GW_OWNER) = 0)
and IsWindowVisible(hTopWnd) then begin
p^ := hTopWnd;
Result := False;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
dwIDOrigin : DWORD; //プロセスID
dwIDHandle : DWORD; //EnumWindowsで取得したウィンドウハンドル
begin
....

//これがミソ
dwIDHandle := dwIDOrigin;
//ウィンドウの列挙
EnumWindows(@EnumTopWindow, LPARAM(@dwIDHandle));

//dwIDHandleが元のプロセスIDと同じなら取得できなかったことになる
if dwIDHandle <> dwIDOrigin then begin
...
end;
end;


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
キレイになりたい美女子には植物性乳酸菌!
オシャレに腸活☆毎日お腹すっきり~
http://ad.freeml.com/cgi-bin/sa.cgi?id=nvPWD
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Oct 14, 2015, 5:55:42 PM10/14/15
to delphi...@freeml.com
[delphi-users:4271] Re: プロセスIDからウィンドウハンドルを取得するには
へのレスです.

こんにちは,Mr.XRAYです.
レスはしたものの,ちょっと気になったので.

>プロセスIDからウィンドウハンドルを取得するには
>どの様にしたら良いでしょうか。

ではなく,

>しかし、そのアプリケーションのタイトルの
>取得方法がわかりません。

が主題であったとしたら,的はずれだったかも知れません.
具体的に何をどうしたいのかが分かれば,もう少しましな
レスができるかも知れません.


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
「スマホ一台」あれば「誰でも稼げる!?
モニター様の多くが、稼ぐことに
成功してます^^
※まずは、あなたも見てみて下さい。↓コチラ↓
http://ad.freeml.com/cgi-bin/sa.cgi?id=nvQbQ
------------------------------------------------------[freeml byGMO]--

OE

unread,
Oct 14, 2015, 8:13:24 PM10/14/15
to delphi...@freeml.com
皆様、おはようございます。
多くの返信ありがとうございます。

>Dachoさん
そう、Cの文法を全く知らなくて書き直しする腕がないのです(^^;

>umezさん
今回別途「フルパスで指定した EXE を強制終了させる」ということも
やりたかったので、Mr.XRAYさんのそのページは大変参考にさせて頂きました。

>Mr.XRAYさん
そうですね、そもそも何がやりたいのか主題がぼやけてしまってました。
申し訳ありません。


今回の主題は...
「ある実行中のexeのウィンドウのタイトルの取得」です。


そこでMr.XRAYさんの330_AppProcessList.htm#06を見ていて、
プロセスID取得している所があったので、
ここに追記すればタイトルも取得できるのでは…と考えていました。


----
今ちょうど、ここのサイト
「デスクトップのウィンドウのタイトルとハンドルを取得する」を
見つけまして、
http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=8&refresh=1#0214.txt

しかし、これをXE7にて動かそうとしたところ、
if IsWindowVisible(hwnd) then
の閉じ括弧の部分でコンパイル時にエラー
「 '(' が必要な場所に ')' があります」が出てしまいます。

文法的なことが変わった時にそれを乗り越える手法がわからなくて、
泣けてきます。






MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
「発酵リラックスルーム」でカラダの中からキレイ!
さわやかな甘さでもっとハッピーになる健康効果5選
http://ad.freeml.com/cgi-bin/sa.cgi?id=nvRyK
------------------------------------------------------[freeml byGMO]--

Fukushi

unread,
Oct 14, 2015, 9:16:42 PM10/14/15
to delphi...@freeml.com
OEさん、こんにちは。福士と申します。

> 今ちょうど、ここのサイト
> 「デスクトップのウィンドウのタイトルとハンドルを取得する」を
> 見つけまして、
> http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=8&refresh=1#0214.txt
>
> しかし、これをXE7にて動かそうとしたところ、
> if IsWindowVisible(hwnd) then
> の閉じ括弧の部分でコンパイル時にエラー
> 「 '(' が必要な場所に ')' があります」が出てしまいます。

| if IsWindowVisible(hwnd) then



| if IsWindowVisible(WH) then

の間違いだと思います(Object Pascalでは大文字、小文字を区別しない
ので引数のhwndは型としてのHWNDとして解釈され、IsWindowVisibleの
引数の型はHWNDですから、HWND型にキャストするつもりなんじゃないの?
という意味で上記のエラーメッセージになったものと思われます)。


> 文法的なことが変わった時にそれを乗り越える手法がわからなくて、
> 泣けてきます。

コンパイラのエラーメッセージとその原因を結びつけて考えることが
大事だと思います。

---
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
カンタン夏のダメージケア!
トマトのリコピン効果を最大限に高める3つの方法とは?
http://ad.freeml.com/cgi-bin/sa.cgi?id=nvSpL
------------------------------------------------------[freeml byGMO]--

OE

unread,
Oct 15, 2015, 2:02:59 AM10/15/15
to delphi...@freeml.com
>福士さん

なるほどです。

各コードが具体的に何をしているのか理解できていないので、
エラー見ても分からないのがそもそも問題ですが…(^^;
よく見てみたら、function のパラメータ定義で「WH: HWND」としてるのに、
内部でWHがでてきてませんでした。

おかげさまで、今回やりたかったこともこのコードをもとに
改良すれば何とかなりそうです。
ありがとうございました。


修正したコードを載せておきます。

//--------------------------
// デスクトップのウィンドウのタイトルとハンドルを取得する
// ・フォーム上にButton/Label/ListBox
// ・確認:Windows7(64) DelphiXE7
//--------------------------
function CallBackTest(WH: HWND; LP: LParam): BOOL stdcall;
var
Buf: array [0..255] of Char;
begin
// スタイル ビットがセットされているもののみ
if IsWindowVisible(WH) then
begin
// タイトル バーのテキストをBufにコピー
if GetWindowText(WH, Buf, 255) <> 0 then
begin
TListBox(LP).Items.AddObject(Buf, Pointer(WH));
end;
end;
Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Clear;
EnumWindows(@CallBackTest, Longint(ListBox1));
Label1.Caption := IntToStr(ListBox1.Items.Count);
end;



MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
キレイになりたい美女子には植物性乳酸菌!
オシャレに腸活☆毎日お腹すっきり~
http://ad.freeml.com/cgi-bin/sa.cgi?id=nvVMG
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Oct 15, 2015, 9:05:56 PM10/15/15
to delphi...@freeml.com
[delphi-users:4277] 【解決】Re: ある実行中のexeのウィンドウのタイトルの
取得 へのレスです.

こんにちは,Mr.XRAY です.

>修正したコードを載せておきます。

別に強制ではないのですが,ローカル変数は初期化されません.
当サイトのような簡単なサンプルでは問題はないと思いますが,
業務アプリで,メモリを使いまわすようなプログラムではゴミが
入ることがあります.

初期化しておいた方が無難かと思われます.
そのためには,MAX_PATH 等の定数名を使用すると便利です.
蛇足ながら.

function CallBackTest(WH: HWND; LP: LParam): BOOL stdcall;
var
Buf: array [0..MAX_PATH-1] of Char;
begin
FillChar(Buf, Sizeof(Buf), #0); //追加


# 実を言うと,掲載しているサンプルで変な文字になる,という
# 問い合わせがあって,急きょ,そのサンプルだけ,FillChar を
# 追加したことがあります.


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
「スマホ一台」あれば「誰でも稼げる!?
モニター様の多くが、稼ぐことに
成功してます^^
※まずは、あなたも見てみて下さい。↓コチラ↓
http://ad.freeml.com/cgi-bin/sa.cgi?id=nwg95
------------------------------------------------------[freeml byGMO]--

OE

unread,
Oct 16, 2015, 12:58:12 AM10/16/15
to delphi...@freeml.com
Mr.XRAYさん

初期化って、コンパイル時に注意されるので、
何となく入れたり(時に気にせず入れなかったり)してたのですが、
使い回す時にゴミが混ざる(前回のカス)ことに気づいてませんでした。
今度から気をつけなければ。

助かりました。
ありがとうございました。

FillChar(Buf, Sizeof(Buf), #0);
という書き方、スマートで良いですね。
知らなくてFor文で回しちゃいそうです。


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
キレイになりたい美女子には植物性乳酸菌!
オシャレに腸活☆毎日お腹すっきり~
http://ad.freeml.com/cgi-bin/sa.cgi?id=nwjHc
------------------------------------------------------[freeml byGMO]--

Fukushi

unread,
Oct 16, 2015, 1:48:48 AM10/16/15
to delphi...@freeml.com
OEさん、Mr.XRAYさん、こんにちは。福士です。横から失礼します。

Win32APIのGetWindowTextで必要とされるバッファのサイズ(文字数)は
GetWindowTextLengthで取得することができます。これを利用して

var
Len: Integer;
Buf: String;
begin
if IsWindowVisible(WH) then
begin
Len := GetWindowTextLength(WH);
if Len > 0 then
begin
SetLength(Buf,Len + 1); // +1はNUL終端文字
SetLength(Buf,GetWindowText(WH,Buf,Len + 1));
...

のようにすることもできます。参考にしてください。

# 通常Win32APIでは、可変長のバッファを要求する場合はバッファの
# アドレスとしてNULL(nil)を渡すと必要なバッファサイズが返される
# ことが多いのですが、GetWindowTextの場合は特別で、別途
# GetWindowTextLengthが用意されています。

---
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
「発酵リラックスルーム」でカラダの中からキレイ!
さわやかな甘さでもっとハッピーになる健康効果5選
http://ad.freeml.com/cgi-bin/sa.cgi?id=nwkty
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Oct 16, 2015, 1:59:42 AM10/16/15
to delphi...@freeml.com
[delphi-users:4281] Re: 【解決】Re: ある実行中のexeのウィンドウのタイト
ルの取得 へのレスです.

こんにちは.Mr.XRAY です.

># GetWindowTextLengthが用意されています。

あっ,こんなのがあったんですね.
nil を渡すのはよくありますが...


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
カンタン夏のダメージケア!
トマトのリコピン効果を最大限に高める3つの方法とは?
http://ad.freeml.com/cgi-bin/sa.cgi?id=nwk1V
------------------------------------------------------[freeml byGMO]--

Fukushi

unread,
Oct 16, 2015, 2:13:50 AM10/16/15
to delphi...@freeml.com
Mr.XRAYさん、こんにちは。福士です。

> ># GetWindowTextLengthが用意されています。
>
> あっ,こんなのがあったんですね.
> nil を渡すのはよくありますが...

そう思ってMSDNでGetWindowTextを見てみたら記述がなくて、はて?
と思ったら別関数でした。たぶん古くからあるAPIだからでしょうけど。
あとGetWindowTextLengthの戻値はGetWindowTextで取得できる文字列の
長さとぴったり同じにはならないかもしれない(GetWindowTextLengthの
ほうが多めになるかも)という手抜き仕様なので注意が必要ですね。

---
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
キレイになりたい美女子には植物性乳酸菌!
オシャレに腸活☆毎日お腹すっきり~
http://ad.freeml.com/cgi-bin/sa.cgi?id=nwkE2
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Oct 16, 2015, 7:33:55 PM10/16/15
to delphi...@freeml.com
[delphi-users:4283] Re: 【解決】Re: ある実行中のexeのウィンドウのタイト
ルの取得 へのレスです.

福士さん,こんにちは.Mr.XRAY です.

>と思ったら別関数でした。たぶん古くからあるAPIだからでしょうけど。
>あとGetWindowTextLengthの戻値はGetWindowTextで取得できる文字列の
>長さとぴったり同じにはならないかもしれない(GetWindowTextLengthの
>ほうが多めになるかも)という手抜き仕様なので注意が必要ですね。

了解しました.
私も調べてみました.


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
キレイになりたい美女子には植物性乳酸菌!
オシャレに腸活☆毎日お腹すっきり~
http://ad.freeml.com/cgi-bin/sa.cgi?id=nwvxv
------------------------------------------------------[freeml byGMO]--

Reply all
Reply to author
Forward
0 new messages