[BlueLeaf1336]> PROBLEMS> ClickThereItIs!>

ClickThereItIs! > IShellWindows

historyTOP

2006/01/19:作成

overviewTOP

最近、マウスでクリックしたエクスプローラのフォルダパスの取得方法について、ある方からメールを受けましてわかる範囲のヘナチョコ回答をしているうちに、少しだけ試してみたくなってためしてみました。

オリジナルではかなり情けない方法をとっていたせいで、遅いコンピュータだと何ミリ秒か待たなければうまくいかなかったり、フォルダオプションで「アドレスバーにフルパスを表示」にしておかないと駄目、などもう一つでした。

そこで、メールの返事にも書いたんですが、このサイトで触れられている方法を試してみることにしました。方法は、異常に長い引用になってしまいますが、こんな感じです。

で、いざエクスプローラで選択されているファイル名を取得しようとして、はたと行き詰まってしまった。ファイル名はリストビューから取ればよいんだろう。じゃぁフォルダ名はどうするの。アドレスバーにあるじゃない。んー、でもフォルダオプション変更すると、ここフルパスじゃなくなってしまうんだよなぁ。

それからWEBで検索をしてみたが、あんまりいい情報がない。DelphiMLで、どなたかが、「ShellWindowsとInternetExplorerを使えばいけるのではないか」というアイデアを書いていらっしゃるのを見つけたが、具体的なコードはない。ShellWindowsで調べても、あんまり情報がないのだよなぁ。で、もう一度DelphiのVCLに戻って、ShellWindowsを調べると、TShellWindowsというのがあった。どうやら、エクスプローラとインターネットエクスプローラを列挙してくれるActiveX系のオブジェクトのようだ。使い方が全くわからん。(略)

var
    SW: IShellWindows;
begin
    SW := CoShellWindows.Create;
    for I := 0 to SW.Count - 1 do
    begin
        (SW.Item(I) as InternetExplorer).LocationURL;
    end;
end;

と書く必要がありました。うーん、この辺に関しては絶対的な知識不足だー。こんなコードをすらすら書けるようになるのか。やはりCOM関連は一度ちゃんと勉強しないといけない。でも、関連ドキュメントが少なすぎるよー。

これが全てです。ただテストとしては、自分のプログラムじゃなくて、エクスプローラ上のクリックを判定しないといけないので、以前から使っているフックのDLLを、マウスフック専用に単純化して使っています。ですので、調子悪くなったりしないと思いますが、ご注意ください。

で、クリックした時の直下にあるウィンドウのハンドルをテスト用のプログラムに送りつけています。受けとった後は、そのウィンドウハンドルと、IShellWindowsインターフェースのHWNDプロパティを順番に比較していって一致したウィンドウについて、LocationURL他を表示しています。

コードTOP

一部しか乗せられないので変なことになってますが、DLLからPostMessageで「クリックされたよ」メッセージが飛んでくるので、フォームのウィンドウプロシージャの中で受けとってます。で、DoTargetHackっていう変な名前の関数に渡して処理しています。

とりあえず、InternetExplorer(==IWebBrowser)インターフェースの公開しているプロパティを何も考えずに列挙するようにしてみました。

//-----------------------------------------------------------------------------
//  メッセージハンドラ
procedure TForm1.WndProc(var Msg: TMessage);
begin
    case Msg.Msg - WM_APP of
        //  マウスの左ボタン上げ
        WM_LBUTTONUP: DoTargetHack(Msg.WParam);
    end;

    //  残りは丸投げ
    inherited WndProc(Msg);
end;

//-----------------------------------------------------------------------------
//  マウス操作の対象となったエクスプローラの示すフォルダパスを表示する
//-----------------------------------------------------------------------------
//  K2雑記帳
//  http://k2top.jpn.org/k2soft/doc/diary2002-12.html
procedure TForm1.DoTargetHack(const WindowHandle: HWND);
var
    TopHandle: HWND;
    SW: IShellWindows;
    IE: InternetExplorer;
    i: Integer;
begin
    Memo1.Lines.Clear();

    //  エクスプローラへのインターフェース準備
    SW := CoShellWindows.Create;

    //  指定のハンドルを持つウィンドウのてっぺんのハンドル取得
    TopHandle := GetMostTopLevelWindow(WindowHandle);

    //  ハンドルの一致するものを検索
    for i := 0 to SW.Count - 1 do
    begin
        //  型を明示して取り出し
        IE := SW.Item(I) as InternetExplorer;

        try
            //  ハンドルを比較
            if (TopHandle = IE.HWND) then
            begin
                Memo1.Lines.Add('タイトル :' + IE.Name);
                Memo1.Lines.Add('パス   :' + IE.FullName);
                Memo1.Lines.Add('作業パス :' + IE.Path);
                Memo1.Lines.Add('ステータス:' + IE.StatusText);
                Memo1.Lines.Add('フルパス :' + IE.LocationURL);
                Memo1.Lines.Add('名称   :' + IE.LocationName);
                Memo1.Lines.Add('フルパス2:' + GetWindowTextStr(IE.HWND));
                Memo1.Lines.Add('クラス名 :' + GetClassNameStr(IE.HWND));

                //  たかだか1個
                Break;
            end;
        except
            //  フォルダを閉じると例外発生
            Caption := '(>_<) 急に閉じちゃイヤ';
        end;
    end;
end;

実行結果TOP

アクティブな時の画面をキャプチャできないという弱点発見(そういうウィンドウを発見できなかったら表示をクリックしているせいですが)。

マイネットワークもちゃんと表示できています。びっくりしました。

20060119IShellWindows.zip(229,228bytes)

EOFTOP