Top > Programming > @Diary
Table of Contents

クラシックなスタートメニューのクローンプログラムを作っています

Windows95からVistaまでの間のWindowsで使うことができた、クラシック・スタートメニューを模倣するプログラムを作っています。私はVistaまでずっとこのクラシックなスタートメニューを使ってきましたが、先ごろWindows7の動作するPCを購入しそのスタートメニューの使いにくさから、このようなプログラムの作成を始めてしまった次第です。

世にはWindowsスタートメニューの代替を謳うプログラムは幾つかあるようですが、私が今まで知り得たそれらはどれも使用感がクラシック・スタートメニューと違うため、まったく私の気には入りませんでした。私はクラシック・スタートメニューを主にキーボードから使っていたので、いま作っているプログラムもキーボードからの使用感がオリジナルのクラシック・スタートメニューと全く同じようになることを目指しています。

そのためには、Windowsのスタートボタンを横取りしなければいけないので、同種のプログラムに倣って、Windowsエクスプローラをフッキングしスタートボタンをサブクラス化するという技法を使います。これについては、かずぼんさんのプログラミングTClockが非常に参考になっています。というかほとんどTClock Lightのソースを引き写す形で作成をしています。良いソースとよいドキュメントを残してくださったかずぼんさんには頭の下がる思いです。

これが私のはじめてのWindowsプログラムですので、時間はかかるかもしれませんが、αバージョンぐらいになったらgithubでソースを公開するつもりです。(2010-04-24)

スタートボタンがShell_TrayWndの直下にない!

Windowsのスタートボタンをいじくるプログラムを書いています。ネットを検索すると、次のようなコードが、スタートボタンのウィンドウハンドルを取得する場合の定石として出てきます。

HWND hTaskBar; // タスクバー用
HWND hStart; // スタートボタン用
hTaskBar = FindWindow( TEXT("Shell_TrayWnd"), NULL );
hStart = FindWindowEx( hTaskBar, NULL, TEXT("Button"), NULL );

しかしWindows7では、上記のhStartにはNULLが返ります。

Platform SDK 2003 に入っているUISpyで表示させると、スタートボタンがShell_TrayWndの子供として表示されるので、これはおかしいと思い、GetWindow(hTaskBar, GW_CHILD)や、EnumChildWindows(hTaskBar, ...) で、子ウィンドウを列挙させるルーチンを書いてみましたが、Shell_TrayWndの子孫ウィンドウのなかにはスタートボタンは見当たりませんでした。

結果的には、次のようにしたらスタートボタンのウィンドウハンドルが取得できました。

hStart2 = FindWindowEx(NULL, NULL, TEXT("Button"), TEXT("スタート"));

すなわち、スタートボタンはデスクトップの子ウィンドウになっていたのです。

では、UISpyで表示された親子関係は何なのか。それは、次のようにすると分かりました。

hParent = GetAncestor(hStart2, GA_PARENT); // 親の取得
hParentOrOwner = GetParent(g_hwndStartButton); // 親かそれがなければオーナーの取得

これの結果は、hParentがデスクトップウィンドウのハンドル、hParentOrOwnerがShell_TrayWndウィンドウのハンドル、というものでした。つまり、UISpyはウィンドウの親子関係ではなく、owner-owned関係を表示していたのです。

上記の現象はWindows7でAeroをオフにしても全く同じように再現されました。(2010-04-22)

VC++ 2008 Expressで.defファイルを使ったDLL作成

次の点がどうしても分からなかった。

__declspec(dllexport)で宣言された関数がソースファイルにひとつもない場合、リンクは正常に終了するが、.dll(と.lib)ファイルが生成されない。生成されるようにするには:

コマンドラインの場合
リンカに/DEF:nameオプションで.defファイルのファイル名nameを指定する。
統合環境の場合
DLLのプロジェクトを右クリック > プロパティ > リンカ > 入力 > モジュール定義ファイル に.defファイルのファイル名を指定する。これがリンカへの/DEF:オプションと等価。(2010-03-xx)

プログラミング日記を創設

創設しました(^_^;) (2010-04-24)

Tag: Programming Diary