開いているフォルダウィンドウのアドレスの取得について

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
ゲスト

開いているフォルダウィンドウのアドレスの取得について

#1 投稿記事 by ゲスト »

はじめまして。ActiveBasicでWIN32APIプログラミングを勉強させてもらっています。
件名の件について頭を悩ませているのですが、
開いているフォルダウィンドウから、そのURL(フォルダパス)を取得することは可能でしょうか?
私はよく、デスクトップにウィンドウを大量に開いて作業するので、
Explorerが落ちたときや一旦別の作業に取りかかるときに
簡単に以前のウィンドウを復旧できるような機能を求めています。
それには、
「現在のウィンドウ状態を保存する」
「記憶したウィンドウ状態を再現する(要するにフォルダを順に開く)」機能があれば実現できる訳です。
WSHではシェルの機能を利用して、WindowsオブジェクトのLocationURLとハンドルを取得できたのですが、
タスクバーボタンを入れ替えるソフトを利用している為か
タスクバーでの順番通りに取得できず(左から順に取得したいのだが、フォルダを開いた順になってしまう)、限界を感じています。
THEREMIN
記事: 36
登録日時: 2007年2月11日(日) 01:52
お住まい: HYOGO pref.

ログインし忘れました

#2 投稿記事 by THEREMIN »

間違えてゲストで投稿してしまいました。
上の投稿は私(THEREMIN)です。すみません。
ゲスト

#3 投稿記事 by ゲスト »

フォルダウインドウというのがエクスプローラーのウインドウでしたら
タイトルバーにフォルダのパスが全て表示されるのでエクスプローラーのウインドウハンドルを
取得後、そのウインドウハンドルを使ってタイトルバーの文字列を取得すれば
一応出来る気はしますが、根本的ではないですね
THEREMIN
記事: 36
登録日時: 2007年2月11日(日) 01:52
お住まい: HYOGO pref.

#4 投稿記事 by THEREMIN »

>ゲスト様
その場合では、フォルダ名しか取得できないんですよね・・・
フォルダオプションで「タイトルバーにフォルダのパス名を表示する」設定にしていれば
確かに取得はできるんですが、設定に依存するからいい方法ではない。

何かいい方法は無いんでしょうか?
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#5 投稿記事 by イグトランス »

ABでやるとしても結局WindowsオブジェクトのLocationURLを読み取ることに変わりはありません。
ただしWSHでやるよりもかなり低水準になるので結構書くのが大変になると思います。

まず,タスクバーの内容を読み取る正式な方法はありません。
しかし,タスクバーのあのアプリケーションのボタンの部分はタブコントロールで出来ているため,
適切なメッセージを送ることにより,タスクバーのボタンの文字列を読み取ることまでは可能だと思います。
参考:タスクバーとスタートメニューの歴史
その文字列を元にFindWindowを行えば対象となるウィンドウハンドルがわかります。

単純にウィンドウハンドルを取得したければ,ほかにもEnumWindows関数を使う手などがありますが,
タスクバーのボタンの並んでいる順にウィンドウハンドルが得られる保証はないと思います。

エクスプローラのフォルダ表示のウィンドウハンドルを元に,いくつか手順を踏むことでIWebBrowser2へのポインタを得られます。
これでWSH版に追いつきました。IWebBrowser2にはLocationURLがあり,これでようやくパスを得られます。

勿論WSHの手順を忠実に真似ていく方法もありますが,それではWSHから替える必要性がありませんね。
THEREMIN
記事: 36
登録日時: 2007年2月11日(日) 01:52
お住まい: HYOGO pref.

#6 投稿記事 by THEREMIN »

>>イグトランス様
返答が遅くなってすみません。
助言通りに作ってある程度感じが掴めてからレスしようかと思ってたもので・・・

>結局WindowsオブジェクトのLocationURLを読み取ること
要するにShellの機能を使うしか無い訳ですか
私の環境はWindowsXPなので、
Shell_TrayWnd> ReBarWindow32> MSTaskSwWClass> ToolbarWindow32クラスの
ウィンドウのハンドルを取得して、とりあえずそこにSendMessageを試しています。
コマンドがTB_系なので定数値が分からず、困ってますが。

>エクスプローラのフォルダ表示のウィンドウハンドル
これってCabinetWClassのことでしょうか?
それなら自分のやってることは間違ってるのかな・・・
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#7 投稿記事 by イグトランス »

> これってCabinetWClassのことでしょうか?
それです。これがタスクバーのボタンにあるウィンドウタイトルと同じ名前のテキストを持っているため,
先程の手順で,FindWindowで検索するとおそらくこのクラスのウィンドウが該当することになると思います。

試したことがないのでわかりませんが,ほかのウィンドウハンドルでもできるのかもしれません。
THEREMIN
記事: 36
登録日時: 2007年2月11日(日) 01:52
お住まい: HYOGO pref.

#8 投稿記事 by THEREMIN »

>>イグトランス様
こんなに早く返事が来るとは思っていませんでした。
自分のつまらない報告に答えていただき、ありがとうございます。

>ほかのウィンドウハンドルでもできるのかもしれません
そうなんです、今まさにそれを試しているところなんですが・・

ただ、ウィンドウタイトルだけでは同じフォルダ名のウィンドウが開いたときに
判別できないので、やはり別の方法が必要だと思います。
自分の考えている方法は、タスクバーのボタンにはIDがあるようなので
それを左から順に取得できれば、最悪WSHとの合わせ技で実現できるかも、という感じです。

そこらへんは、タスクバーアイコンを移動することができるソフトのソースでもあればはっきり理解できると思うんですけどね・・・
THEREMIN
記事: 36
登録日時: 2007年2月11日(日) 01:52
お住まい: HYOGO pref.

できました!

#9 投稿記事 by THEREMIN »

ここのアドバイスや他の掲示版での情報も参考にして、なんとか
フォルダウィンドウのハンドルと ウィンドウの並んでいる順は取得することができました。
結構前に取得自体はできていたのですが、Unicodeテキストファイルの扱いで悪戦苦闘していて返事が遅れてしまいました。

イグトランス様のアドバイスを参考に、ToolbarWindow32クラスのウィンドウハンドルを取得して
そこからタブボタンの情報をSendMessage()で取得していったところ、
うまくフォルダウィンドウのハンドルを取得することができました。一応ソースを示しておきます。
SendMessage()の他にも色々処理がいるようで、あんまり理解してはいないのですが、要するに
ToolBarコントロールは別プロセスなので、共有メモリをオープンし、
それを利用してメッセージの受け渡しをしなければならないようです。
http://techtips.belution.com/ja/vc/0001/
http://forums.belution.com/ja/vc/000/271/11s.shtml
http://hongliang.seesaa.net/article/7851680.html
http://www.atmarkit.co.jp/bbs/phpBB/vie ... forum=7&11
最後に編集したユーザー THEREMIN [ 2007年3月12日(月) 10:20 ], 累計 1 回
THEREMIN
記事: 36
登録日時: 2007年2月11日(日) 01:52
お住まい: HYOGO pref.

追記

#10 投稿記事 by THEREMIN »

*注記
上記のコードではウィンドウIDも取得していますが、ハンドル取得時にCabinetWClassのものを取得しているようなので
たぶん不要です。最初はウィンドウIDだけが一意なのかと思っていたので・・・

このように、ウィンドウの順番は取得できましたが、
フォルダウィンドウのアドレスだけはどうしてもCOMを使わないと取得できないようなので、
今の段階ではWSHとの合わせ技で、
ウィンドウの情報(LocationURLとウィンドウハンドル)を取得しファイルに保存する自作のWSHスクリプトを使って
ファイル経由でウィンドウの情報を受け取り、そのウィンドウハンドルと突き合わせながら
AB上で取得したフォルダウィンドウの順番を取得し、再度ファイルに書きこむという間接的なやり方で取得しています。

手順としては、
1. CreateProcess()でコマンドを渡すことでWSHスクリプトを起動
2. 終了するまで待って、終了コード(保存したファイル番号)を取得
3. 終了コードからファイルパスを作成してファイルを読み込む。読み込んだバッファからフォルダウィンドウの情報を取得する。
4. ABプログラム上で取得したタブボタンの情報を、取得したウィドウハンドル同士で突き合わせながらウィンドウの順番を設定する。
5. フォルダウィンドウの情報をウィンドウの並んでいる順にファイルに再書き込みする
このような感じでやっています。

ここまで作る上で副産物として、ユニコードテキストを読み込んで処理する関数ができました。
元の関数は、るっとパパ 様のLineInput #エミュレート ライブラリ「RPLineInput.sbp」を改変しています。
(上手く汎用化できたら、皆様に感謝の意も込めて実践コードモジュールに投稿したいと考えています。)
返信する