タスクバーのアイコンの列挙方法は?

解決


ぴょぴょ  2007-11-18 03:04:38  No: 66913

環境は Windows XP SP2 Home、VC++2003(SDK) です。

タスクバーの最小化されるアイコンを取得したいです。
ここのアイコンボタンはウインドウハンドルになるのでしょうか?
それともアイコンハンドルですか?

あとタスクトレイのアイコン(ハンドル)も取得したいです。
分かる方がいましたら教えて下さい。
お願い致します。


シャノン  2007-11-20 00:39:11  No: 66914

確実な方法はありません。

Windows XP のタスクバーは、実態はツールバーのようなので、ツールバーボタンを列挙すればできるでしょう。
が、タスクバーの実装は OS によって変わり得るので、ツールバーだと決め打ちにすることは避けたほうがいいでしょう。

ITaskBarList という COM インターフェイスもありますが、名前に反して、タスクバーボタンの列挙はしてくれません。とんだ期待はずれ。

あとは、タスクバーにボタンが表示される条件を満たすウィンドウを列挙するといった間接的な方法になりますが、確かな条件は知りません。

タスクトレイも、XP ではツールバーですが、他の OS ではわかりません。

http://qwerty.s2.xrea.com/XC2CCCAB82FA5BFA5B9A5AFA5C8A5ECA5A4A4CEA5A2A5A4A5B3A5F3CEF3B5F3CAFDCBA1X.xhtml


ぴょぴょ  2007-11-20 20:20:08  No: 66915

シャノンさん。
ヒントをありがとう。

> Windows XP のタスクバーは、実態はツールバーのようなので、ツールバーボタンを列挙すればできるでしょう。
僕もウインドウを列挙して調べてみました。
確かにツールバーのようです。
下に結果を載せておく。

000500AC[Shell_TrayWnd]
├00040118[Button]スタート
├00040138[TrayNotifyWnd]
│├00050064[TrayClockWClass]17:59
│├000500DE[SysPager]
││└0009005C[ToolbarWindow32]通知領域
││
│└0005003E[Button]

├00020072[ReBarWindow32]
│├0005007A[CiceroUIWndFrame]TF_FloatingLangBar_WndTitle
│└000400AE[MSTaskSwWClass]実行中のアプリケーション
│  └000400A2[ToolbarWindow32]実行中のアプリケーション

├0002006E[tooltips_class32]
├000600A0[DV2ControlHost]スタート メニュー
│├000800F2[Desktop User Pane]
││└000900EE[Static]******
││
│├000700E2[DesktopSFTBarHost]
││└00060090[SysListView32]
││  └000500CE[SysHeader32]
││
│├00060042[Desktop More Programs Pane]
││└000500CC[Button]すべてのプログラム(&P)
││
│├00060142[DesktopSFTBarHost]
││└00090030[SysListView32]
││  └00040074[SysHeader32]
││
│└00060044[DesktopLogoffPane]
│  └00050104[ToolbarWindow32]

├000400B0[tooltips_class32]
├00020070[tooltips_class32]
├0004009A[CiceroUIWndFrame]CiceroUIWndFrame
├0008011C[tooltips_class32]
├00040046[tooltips_class32]
└000300DA[IME]Default IME
※表示は左から順にウインドウハンドル値、クラス名、タイトル名となります。
※「******」はユーザ名が入ります。

タスクバーを簡略化すると
[Shell_TrayWnd]
└[ReBarWindow32]
  ├[CiceroUIWndFrame]TF_FloatingLangBar_WndTitle
  └[MSTaskSwWClass]実行中のアプリケーション
    └[ToolbarWindow32]実行中のアプリケーション
こうなるようです。

タスクトレイを簡略化すると
[Shell_TrayWnd]
└[TrayNotifyWnd]
  ├[Button]
  ├[SysPager]
  │└[ToolbarWindow32]通知領域
  └[TrayClockWClass]17:59
こうなるようです。

ついでにスタートボタンを簡略化すると
[Shell_TrayWnd]
└[DV2ControlHost]スタート メニュー
  ├[Desktop User Pane]
  │└[Static]******
  ├[DesktopSFTBarHost]
  │└[SysListView32]
  │  └[SysHeader32]
  ├[Desktop More Programs Pane]
  │└[Button]すべてのプログラム(&P)
  ├[DesktopSFTBarHost]
  │└[SysListView32]
  │  └[SysHeader32]
  └[DesktopLogoffPane]
    └[ToolbarWindow32]
となるようです。
全部 Windows XP Home SP2 です。

> タスクバーの実装は OS によって変わり得るので、ツールバーだと決め打ちにすることは避けたほうがいいでしょう。
http://homepage1.nifty.com/kazubon/progdoc/tclock/taskbarhistory.html
のリンクに詳しく書いてあるようですね。
XP 以外は試せないので参考になるページです。

> ITaskBarList という COM インターフェイスもありますが、名前に反して、
> タスクバーボタンの列挙はしてくれません。とんだ期待はずれ。
ネットで調べたら次のリンクを見つけた。
http://www.runan.net/program/tips/sdk_10_ITaskbarList.shtml
追加と削除か。何かに使えそうな気が…。

> あとは、タスクバーにボタンが表示される条件を満たすウィンドウを列挙するといった
> 間接的な方法になりますが、確かな条件は知りません。
ウインドウの列挙と階層構造で表示するプログラムで確認しましたが
タスクバーのボタン(ハンドル)は列挙できなかったです。

つまり「ToolbarWindow32」は子のウインドウを持っていないというわけ。
ツールバーのボタンは「ウインドウハンドル」を持たないのでしょうかね。
でも SendMessage などで取得すれば何か帰ってきた気が…。
ツールバーはあまり詳しくないや〜。

> タスクトレイも、XP ではツールバーですが、他の OS ではわかりません。
http://homepage1.nifty.com/kazubon/progdoc/tclock/taskbarhistory.html
このリンクをまとめると
Windows 95、NT    SysTabControl32  (不明)
Windows 98        SysTabControl32  (不明)
Windows Me、2000  SysTabControl32  ToolbarWindow32
Windows XP        ToolbarWindow32  ToolbarWindow32
となるようです。ちなみに左側から OS、タスクバー、タスクトレイ(通知領域)の順です。

Windows 95、98、NT はタスクトレイ部が「TrayNotifyWnd」となっています。
これはただのウインドウですか?
そしてこのウインドウに単にアイコンを表示して
「タスクトレイ」部分と呼んでいるのでしょうか?
どう思います?

いろいろと調べたらまた書き込みます。


洋子  2007-11-20 20:45:37  No: 66916

ていうかリンク先が十分まとまってるので、個人的なメモはいらないかと…


ぴょぴょ  2007-11-20 21:57:49  No: 66917

> ていうかリンク先が十分まとまってるので、個人的なメモはいらないかと…
そうでしたか。
次からはメモ書きはひかえます。

それで洋子さんは
> Windows 95、98、NT はタスクトレイ部が「TrayNotifyWnd」となっています。
> これはただのウインドウですか?
> そしてこのウインドウに単にアイコンを表示して
> 「タスクトレイ」部分と呼んでいるのでしょうか?

これはどう思いますかね?
何かあればまた。


シャノン  2007-11-20 22:30:32  No: 66918

>> あとは、タスクバーにボタンが表示される条件を満たすウィンドウを列挙するといった
>> 間接的な方法になりますが、確かな条件は知りません。
> ウインドウの列挙と階層構造で表示するプログラムで確認しましたが
> タスクバーのボタン(ハンドル)は列挙できなかったです。

そうではなくて。
タスクバーボタンに対応する、デスクトップ上のトップレベルウィンドウを列挙するということです。
非表示でない、タイトルバーを持っている、WS_EX_APPWINDOWスタイルを持っている、etc…といった条件を満たすウィンドウを EnumWindows で列挙すれば、タスクバーボタンを列挙したのと同じことになるかな、と。
ただし、タスクバーボタンが表示されるウィンドウの確かな条件が何なのか、その条件は OS に依存しないかということは知りません。


ぴょぴょ  2007-11-21 01:10:46  No: 66919

> そうではなくて。
> タスクバーボタンに対応する、デスクトップ上のトップレベルウィンドウを列挙するということです。
この方法なら以前に成功しています。
でも左から順番に取得できませんよね。
EnumWindows はZオーダー順でしたっけ。

最初のリンク先にソースがあったのでダウンロードして試してみました。
http://qwerty.s2.xrea.com/data/te_core.lzh
このソースは「タスクトレイ」のアイコン情報を取得するサンプルです。
これを利用して「タスクバー」のアイコン情報も取得は出来ました。

// タスクバーの場合
hTrayWnd = FindWindow( "Shell_TrayWnd", NULL );
hTrayWnd = FindWindowEx( hTrayWnd, NULL, "ReBarWindow32", NULL );
hTrayWnd = FindWindowEx( hTrayWnd, NULL, "MSTaskSwWClass", NULL );
hTrayWnd = FindWindowEx( hTrayWnd, NULL, "ToolbarWindow32", NULL );
と変更しました。その結果は
No.                      Title name                       hIcon     hWnd       uID    uCallbackMessage
--- ---------------------------------------------------- -------- -------- ---------- ----------------
  1 [Internet Explorer                                 ] 000FF840 00000000          0          0
  2 [タスクバーのアイコンの列挙方法は? - Microsoft In ] 00000000 001100C4          0     870328
  3 [Windows Command Processor                         ] 0387B2E8 00000000         64          0
  4 [C:\WINDOWS\system32\cmd.exe - GetTaskbar          ] 00000000 00190196         64   59748744
  5 [TeraPad                                           ] 038AA4F8 00000000          0          0
  6 [質問.txt - TeraPad                                ] 00000000 004801F2          0   59136936
--- ---------------------------------------------------- -------- -------- ---------- ----------------
となりました。この一覧は IE、コマンドプロンプト、TeraPadエディタの3つです。

これで一応は「タスクバー」のボタンに対応するウインドウのハンドルが取得できました。
最初に実行したときはもっと多くの残骸らしき情報が表示されていました。
そこでいろいろと試行錯誤して気づきました。

フリーソフトでタスクバーのボタンを並び替えできるものを使うとプログラムを終了しても
タスクバーの管理情報が残骸として残るようです。ここに気づかず一覧の意味が分からずいました。

上手くツールバーから情報を取得できたので解決です。
最初のリンクが大いに役に立ちました。
有り難うございました。


シャノン  2007-11-21 01:23:19  No: 66920

解決されたようで何よりです。

ところで、最初のリンク先の最後の言葉をぎゅっと噛み締めてください。
味がなくなるまで何回でも噛んでください。

OS のバージョンによって場合分けするなんていうのは下策です。

> なんでトレイアイコンの列挙や他人のアプリのトレイアイコン操作なんてしたいの?
> 本当にする必要があるの?
> ちゃんと仕様は検討した


ぴょぴょ  2007-11-21 03:01:16  No: 66921

> OS のバージョンによって場合分けするなんていうのは下策です。
ごもっともなご意見です。確かに。そうですね。

> > なんでトレイアイコンの列挙や他人のアプリのトレイアイコン操作なんてしたいの?
> > 本当にする必要があるの?
> > ちゃんと仕様は検討した
これは巷でよくある「仮想デスクトップ」を僕も実現させるためです。
最近 Vector さんで「仮想かな?」というソフトが紹介されていました。
http://www.vector.co.jp/magazine/softnews/071106/n0711064.html

前は「仮想デスクトップ」の意味が分からなかったのでスルーしていました。
それで今回ダウンロードして使ってみたら便利に感じました。

でも、いくつかの不満と不具合が発生してしまった。
それで最近プロセスとかの一覧などを作っていたので「情報表示ツール」の
一環として先に「タスクバー」「タスクトレイ」のウインドウハンドルを
取得しようと思ったのです。

その後に僕も似たようなのを作ってみようと思っています。自分専用かな。
あと普段利用しているタスクバーのアイコンを入れ替えるソフトも自作できたら
メモリが節約できると思って。

単純ですがこれが「タスクバーのアイコンの列挙方法」を知りたかった理由です。
一番安全な(と思われる)タスクバーの列挙やタスクバーのボタン入れ替えは
EnumWindows で列挙してウインドウの非表示と表示を行えば出来そうです。
問題は列挙の条件がちょっと複雑ですし OS バージョンの違いもあるかも。
(でもタスクバーのツールバーなどから情報を取得するよりは安全かと思う)

こんな感じです。
シャノンさん。
良い助言をありがとうございました。


シャノン  2007-11-21 20:01:49  No: 66922

SwitchDesktop とか使ったら面白いかも?


ぴょぴょ  2007-11-22 01:10:37  No: 66923

> SwitchDesktop とか使ったら面白いかも?
このAPIを調べてみました。

すると次のリンクを見つけました。
http://www.yuboo.net/~ybsystem/sys_build/win_client/dsk_create.html
その後に「公開ソフト」ページで「マルチデスクトップ管理ツール」を見つけました。
http://www.yuboo.net/~ybsystem/soft/YBDesktop/index.html

SwitchDesktop って複数のデスクトップを切り替えるんですね。
この関数を調べたら巷で存在している「仮想デスクトップ」は邪道(擬似的)ですね。

CreateDesktop で本物のデスクトップを作れるようで驚きです。
作ろうとしていた「仮想デスクトップ」にはタスクバー、タスクトレイ、壁紙も
切り替えられるようにするために無理やり「タスクバーのアイコンの列挙方法は?」を
質問してしまった。(恥)

最初のリンクの最後を思い出します。
> なんでトレイアイコンの列挙や他人のアプリのトレイアイコン操作なんてしたいの?
> 本当にする必要があるの?
> ちゃんと仕様は検討した?

あとシャノンさんの言葉も…。
> ところで、最初のリンク先の最後の言葉をぎゅっと噛み締めてください。
> 味がなくなるまで何回でも噛んでください。

仕様の検討とは、無理やり仮想デスクトップを作るのではないようですね。
今回は SwitchDesktop などの機能で同等の仕組みが API に既に存在した。
これからは MSDN とかいろいろと調べる癖を付けたいと思います。

「仮想デスクトップ」の仕様をよく検討したと思います。
また名前も「仮想」はつける必要はないですね。(笑)


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加