ClickThereItIs! - Whose Window this is ?
history |
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html#page_top"
target=_blank>TOP |
2003/11/22:作成 2004/10/27:
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html#d20041027"
target=_blank>更新
最新版。
href="http://www.geocities.jp/fjtkt/problems/2003_0001/20041027ModuleView.zip"
target=_blank>
color=#0033cc>20041027ModuleView.zip(191,113bytes)
memo |
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html#page_top"
target=_blank>TOP |
とりあえずテストプログラム第1弾です。
あるタイミングにおいて(ってこのタイミングが非常に難しいんですが)、マウスの直下にあるウィンドウを捜します。これは大丈夫です。WindowFromPoint(うろ覚え)を使います。
でとりあえずテストなので、ボタンのMouseUpイベントをそのタイミングとします。ボタンの上でマウスの左ボタンをを押してそのままドラッグして別の場所で左ボタンを離すと、デスクトップの任意の場所にマウスがある状態で自作のアプリケーションがイベントを拾えます。で、このときのマウスの位置をそれなりにスクリーン座標に変換しその直下のウィンドウを見つけるというわけです。
それだけではなくて、今度はそのウィンドウを所有しているプログラム(アプリケーション)を捜します。たとえば自分の作ったアプリケーションなら"Project1.exe"とかデスクトップなら"Explorer.exe"とかフォルダを開いているのならやっぱり"Explorer.exe"とか。もちろんフルパスで。
本当の目的は開いているフォルダのフルパスをとりたいのですが、とりあえずそのウィンドウが何らかのアプリケーションなのかエクスプローラなのかを判断する必要があるかと。そしてもちろんエクスプローラなら、開いているフォルダのパスを取得したいと。ただこっちの方はさらに先の話になるかと思います。
とか書いてますが、実際には、マウスの下のウィンドウの持ち主は取得できています。以下にコードを示します。誰かの役にも自分の役にも立ちますように。
問題は、使用しているAPIが「psapi.dll」なんていう見たこともないDLLを使用していてこれがまたNT系でしか使用できないときた。嫌な感じだ。
screen shot |
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html#page_top"
target=_blank>TOP |
Button1を押したまま(左ボタンを離さずに)で、エクスプローラで開いたフォルダの上でマウスを離した状態です。1行目にその時のスクリーン座標、2行目にその場所にあったウィンドウを実行しているプロセス、で関連するモジュールが表示されています。モジュールの最初には大本のアプリケーションが表示されるようです。
src="http://www.geocities.jp/fjtkt/problems/2003_0001/ClickHereItIs_001.png"
width=448>
code |
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html#page_top"
target=_blank>TOP |
unit Main;
interface
uses
Windows, SysUtils, Classes, Controls, Forms, StdCtrls, Buttons, ExtCtrls;
type
TMainForm = class(TForm)
Panel1: TPanel;
Memo1: TMemo;
Button1: TButton;
procedure Button1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
public
end;
var
MainForm: TMainForm;
implementation
uses
psapi;
procedure PrintModules(AProcID: Cardinal; AResults: TStrings);
const
MAX_HMODULE = 1024;
var
DesiredAccess: Cardinal;
ModHandle : array[0..MAX_HMODULE-1] of HMODULE;
ProcHandle: THandle;
cbNeeded : DWORD;
i : integer;
p : PChar;
ModNameLen: integer;
ModName : string;
begin
AResults.Add(Format('Process ID: %d', [AProcID]));
DesiredAccess := PROCESS_QUERY_INFORMATION or PROCESS_VM_READ;
ProcHandle := OpenProcess(DesiredAccess, false, AProcID);
if (ProcHandle = INVALID_HANDLE_VALUE) then
begin
Exit;
end
else
begin
try
if (EnumProcessModules(ProcHandle, @ModHandle, MAX_HMODULE, cbNeeded)) then
begin
for i := 0 to (cbNeeded div sizeof(HMODULE)) - 1 do
begin
GetMem(p, MAX_PATH);
ModNameLen := GetModuleFileNameEx(ProcHandle, ModHandle[i], p, MAX_PATH);
SetString(ModName, p, ModNameLen);
FreeMem(p);
AResults.Add(Format('%s (%8d)', [ModName, ModHandle[i]]));
end;
end;
finally
CloseHandle(ProcHandle);
end;
end;
end;
procedure TMainForm.Button1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
Pnt : TPoint;
WH : HWND;
ProcessID: integer;
begin
Memo1.Lines.Clear;
Pnt := Point(X, Y);
Pnt := TControl(Sender).ClientToScreen(Pnt);
Memo1.Lines.Add(Format('Mouse X:%3.3d Y:%3.3d', [Pnt.X, Pnt.Y]));
WH := WindowFromPoint(Pnt);
if (WH <> 0) then
begin
GetWindowThreadProcessId(WH, @ProcessID);
PrintModules(ProcessID, Memo1.Lines);
end;
end;
end.
Delphi 6 Personal dpr/dfm/pas |
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html#page_top"
target=_blank>TOP |
href="http://www.geocities.jp/fjtkt/problems/2003_0001/20031122ClickHereItIs_001.zip"
target=_blank>
color=#0033cc>20031122ClickHereItIs_001.zip(2,918bytes)
2004/10/27 |
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html#page_top"
target=_blank>TOP |
ほんの少し変更しました。本当にどうでもよい変更ですが。
src="http://www.geocities.jp/fjtkt/problems/2003_0001/20041027ModuleView_001.png"
width=382>
白いパネルでマウスを押し、そのままマウスを移動させると調べようとするウィンドウを点滅させます。ただ、点滅はウィンドウなんですが、実際に調べるのはそのウィンドウの親をてっぺんまでさかのぼったウィンドウになります。出力するのは、そのウィンドウが使用しているDLL全て(のはず)です。
図は、自分自身を調べた状態です。ところで、変更箇所というのは、ウィンドウの点滅機能です。
実行ファイルとソースコード。
href="http://www.geocities.jp/fjtkt/problems/2003_0001/20041027ModuleView.zip"
target=_blank>
color=#0033cc>20041027ModuleView.zip(191,113bytes)
EOF |
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html#page_top"
target=_blank>TOP |
*01/11/2005 10:30:22 *
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html"
target=_blank>BlueLeaf1336-PROBLEMS-2003_0004 >
Whose Window this is ? :: ClickThereItIs! - Whose Window this is
? *<a target="link"
href="http://www.geocities.jp/fjtkt/problems/2003_0004.html">BlueLeaf1336-PROBLEMS-2003_0004
> Whose Window this is ? :: ClickThereItIs! - Whose Window this is
?</a>
:script --> |