Version 3.5
ウィンドウハンドルとAPI
「この前は〈ウィンドウハンドル〉ってものについて見てみました」
『ウィンドウの出席番号よねー』
「今回はこれをもっと突き詰めて見てみるね。この前使った……」
void CCalcDlg::OnBEqual()
{
SetWindowText( "あいうえお" );
}
『あ、これこの前使った〈ウィンドウタイトルを変える関数〉だね』
「Ver 3.2( No.27 )の時に使ったね。まずはこの CWnd::SetWindowText()
のAPI版を使ってみましょう」
『API版、ねぇ。えっと、とりあえずMSDNだよね』
SetWindowText() をダブルクリック、F1キーが押される。MSDNが開
き、ダイアログが表示される。
『APIのだから、【プラットフォームSDK】ってのなんだよね』
「そうそう、API=SDKで大丈夫でしょ」
【SetWindowText() プラットフォームSDK】をダブルクリックすると、
SetWindowText についての情報が表示される。
(以下、MSDNからの引用)
BOOL SetWindowText(
HWND hWnd, // handle to window or control
LPCTSTR lpString // address of string
);
(引用、ここまで))
『あ、この前使ったのと引数が違う……あ、もしかして!』
「もしかして?」
『この1番目の HWND ってのが、ウィンドウハンドルなんじゃない?』
「そう! この第1引数に渡すのがウィンドウハンドル。で、 HWND が、
ウィンドウのハンドルの型」
『えっちうぃんど?』
「う”、僕はそう発音してるけど……」
『私、番号って言うから int 型だと思ってた』
「そしたらウィンドウもアイコンも全部同じになっちゃうでしょ」
『あ、そっか』
「ウィンドウを操作するためのハンドルが、ウィンドウハンドル、HWND な
のです」
『これ、わざわざウィンドウハンドル渡さなきゃなんないの?』
「APIのを使う時には〈タイトルを変えるウィンドウ〉を指定しなきゃい
けないからね」
『MFCの時にはいいの?』
「これは今度見るけど、 CWnd は中にウィンドウハンドルを持ってて、自動
的に渡してくれるから省略できるわけ」
『そっか、そういうのが便利ってことなんだ』
「ま、そうなるかな。さて、実際にこのAPIを使ってみましょう」
『げ、なんか難しそう……』
「全然難しくないよ。まず第1引数は空欄にしておいて、その他のとこを
APIのに書き換えてみて」
『んっと……APIの時には最初に :: を付けるんだから……』
void CCalcDlg::OnBEqual()
{
::SetWindowText( , "あいうえお" );
}
『かな?』
「そうそう。で、あとはなんか適当にウィンドウハンドルを渡せればいいわ
けだ。そうだね…… SetWindowText() を呼び出す前に、HWND 型の変数を作っ
てみて」
『はーい』
void CCalcDlg::OnBEqual()
{
HWND windowhandle;
::SetWindowText( , "あいうえお" );
}
『変数名、よく分かんなかったから適当付けちゃったけど……』
「僕はこんなふうにしてるかな」
HWND hWnd;
「最初の h がハンドルって意味、その次の Wnd がウィンドウって意味」
『ってただ大文字小文字変えただけじゃない』
「そうとも言う。さて次に、この前使った Spy++ を起動して」
『あ、それでウィンドウハンドルを見るんだ。【ツール】−【Spy++】っと』
Spy++ が起動し、ウィンドウ一覧が表示される。
「こんなかからMSDNを探してみて」
『はーい……って、もしかしてMSDNのタイトル変えるってゆーの!?』
「そ、こういうのも簡単にできるってことでね」
00000758 "MSDN ライブラリ Visual Studio 6.0" HH Parent
「ウィンドウハンドルは実行するたびに変わるから、注意してください」
『で、この最初の 00000758 っての入れればいいんだよね』
「っと、ちょっと待って。これにはちょっとコツがあって、こんなふうにし
ないとダメなんだよね」
hWnd = reinterpret_cast< HWND >( 0x00000758 );
『?? なんかチンプンカンプン……』
「まず【 0x 】から」
『そのあとのはウィンドウハンドルだよね』
「そう。ウィンドウハンドルは16進数で書かれてるって言ったよね」
『うん、言ってた。ってことは……』
「16進数で書かれた数字の前に【 0x 】を付けると、10進数に自動的に
変換します」
『変数の中じゃ10進数なんだもんね』
「そ。ま、16進数の前には 0x でいいかな」
『じゃあ reinterpret_cast< HWND >() は? HWND って型なんだから、な
んか変数作ってるの? でもなんか関数っぽいし、これ』
「関数って考えた方がいいかな」
reinterpret_cast< 変換先の型 >( 変換する値 )
「って感じで呼び出すと、【変換先の型】に変換してくれます」
『変換? なんでそんなことする必要あるの?』
「ほら、今回の最初の方で言ったでしょ、 int 型をハンドルにしたら、ウィ
ンドウのかアイコンのか分かんないって」
『あ』
「HWND は【ウィンドウハンドル】だから、普通の数字とは区別されてるわ
け」
『確かに全然区別なく使えちゃったらやばそうよねー』
「その区別を取っ払うために reinterpret_cast<>() ってものを使うわけ」
『確かに、面倒だけどこの方が安全そうねー』
「というわけでまとめれば、16進数の数字をまず 0x で10進数に変換し
て、さらに〈普通の数字〉から reinterpret_cast<>() で〈ウィンドウハン
ドルの数字〉に変換して、最後に HWND 型の変数 hWnd に入れてる、ってこ
とになるかな」
『2度変換するってことね』
「で、まとめると……」
void CCalcDlg::OnBEqual()
{
HWND hWnd;
hWnd = reinterpret_cast< HWND >( 0x00000758 );
::SetWindowText( hWnd, "あいうえお" );
}
『あ、SetWindowText() に hWnd を渡してる』
「こうやって、操作するウィンドウを指定するわけだね。で……」
『ビルドして実行……』
MSDNのウィンドウタイトルが「あいうえお」に変わる。
『あははははは!! ホントに変わったぁ!』
「こんなふうに、API経由だとどんなウィンドウでも操作できる、ってこ
だね」
『なーんか面白い! こーゆーことできるんだ』
「んじゃ真面目に戻って、Calc ダイアログのタイトルを変えるの、同じよ
うにAPIでしてみて」
『えっと、Spy++ で……ってその前に実行しないと……って、ビルドすると
きには一度終了しなきゃいけないんだから、そしたらウィンドウハンドル変
わっちゃうわけで……結論、無理!』
「なんでやねん! Calc ダイアログのウィンドウハンドル、この前見方教
えたでしょ!」
『あ、そういえば Calc ダイアログのウィンドウハンドル、表示したよね。
このとき使ったのは…… GetSafeHwnd() だ!』
「そう、CWnd::GetSafeHwnd() は、操作対象のウィンドウハンドルを返すメ
ンバ関数。つまりここで使えば CCalcDlg が持ってるウィンドウのハンドル
が返ってくるってわけだね」
『えっと、確認確認』
MSDNの【キーワード欄】に GetSafeHwnd と書き込み、下の欄から選び
ダブルクリックする。右側の欄に情報が表示される。
HWND GetSafeHwnd( ) const;
『ホントだ、戻り値が HWND になってる!』
「これを使えばいいんだから?」
『さっきのプログラムを書き換えると……』
void CCalcDlg::OnBEqual()
{
HWND hWnd;
hWnd = reinterpret_cast< HWND >( GetSafeHwnd() );
::SetWindowText( hWnd, "あいうえお" );
}
『こう?』
「いや、CWnd::GetSafeHwnd() は直接 HWND を返すんだから、変換する必要
はないでしょ?」
『あ、そっか』
void CCalcDlg::OnBEqual()
{
HWND hWnd;
hWnd = GetSafeHwnd();
::SetWindowText( hWnd, "あいうえお" );
}
『ま、そう考えると hWnd 変数とかもいらないんだろうけどねー』
「最初は複数行に分けて書いたほうが分かりやすいと思うよ?」
『かもねー。ビルドして実行、うん、この前と同じ結果!』
/*
Preview Next Story!
*/
『それにしても、ウィンドウタイトルってこんな簡単に変えられるんだ』
「火美ちゃんのウィンドウを〈ぱっつんあたま〉に変えてあげましょう」
『げ! じゃ、じゃあ水希ちゃんのを〈むっつりすけべ〉に』
「人にウィンドウタイトルはありません」
『ふ、不覚!!』
「というわけで次回」
< Version 3.6 アイコンのハンドル >
『につづく!!』
「あれ、ファイルがコピーできない……」
『……』
「なにい、いつの間にかファイルがごみ箱にぃ!?」
『……(にやり)』