Version 3.6
アイコンのハンドル
「さて今回は、ダイアログのアイコンを変えてみましょう」
『タイトルの次はアイコンねー』
「んでもアイコンを変えるだけだと簡単すぎるんで、今回はAPIやMFC
を使う上でのいろんな注意をしてきます」
『ふーん、なんかめんどそー』
「でもこーゆーのが役立つんだよ?」
『まぁそうかもねー』
「じゃ、まずこれから」
void CCalcDlg::OnBEqual()
{
HICON hIcon;
hIcon = ::LoadIcon( reinterpret_cast< HINSTANCE >( 0 )
, MAKEINTRESOURCE( IDI_QUESTION ) );
SetIcon( hIcon, FALSE );
}
『ビルドして実行。あ、ダイアログのアイコンがはてなマークになった!』
「こんなふうに、アイコンも簡単に変えられるから」
『でもこのはてなマーク、どっかで見たような……』
「 MessageBox() を使ったときに見たでしょ、Ver 2.11( No.22 )で」
『そうそう! MessageBox() に MB_ICONQUESTION ってゆーの渡したら、は
てなマークが出たんだよね。……ってことは』
「ん?」
『もしかして IDI_QUESTION を変えれば、他のアイコンになるってこと?』
「それはあとのお楽しみ。とりあえず関数の中身見ていこうか」
『はーい。でもなんかよく分かんないけど』
「そう?」
『んっとねー……あ、HICON って、アイコンハンドルってこと!?』
「そ。別に難しくないでしょ」
『ってゆーか安直』
「まぁそうかも……」
『えっと、 HICON 型の変数 hIcon を作ってるんだよね、1行目。 2行目
は……? :: がついてるからAPIだとは思うけど』
「はい分からなくなったら?」
『MSDN! LoadIcon をダブルクリック、F1っと、:: が付いてるから
プラットフォームSDK……ん?? 相変わらず分かりにくい文章〜』
「ま、それはいつものこと。このAPIは〈アイコンを取得する関数〉。な
んかのアイコンを使いたいときに、このAPIを呼び出します」
『HINSTANCE ってなに? 一応ハンドルみたいだけど』
「これは〈インスタンスハンドル〉。インスタンス=アプリケーションって
考えていいかな」
『つまりアプリのハンドルってこと?』
「そういうことだね。この LoadIcon() は特定のアプリからもアイコンを取
得できるんだけど、今回はウィンドウズシステムから取得します」
『はてなマークアイコンがウィンドウズのものってことね』
「で、特定のアプリを指定しないって言う意味でゼロを渡すわけ」
『〈先生の出席番号〉って感じ?』
「そんな感じ」
『その次の行は』
「っと、セミコロンで区切ってないから、まだ LoadIcon() の引数が続いて
るんだよ?」
『あ、そっか。じゃー2番目の引数、は、はてなマークをってことでしょ?』
「そう。今見た LoadIcon() のリファレンスの下の方を見てみて」
『あ、IDI_APPLICATION とか色々あるんだねー』
「これを変えればびっくりマークのアイコンとかも付けられるよ」
『あと……まけいんとれそう……って?』
「〈メーク・イント・リソース〉ね。これはただの変換。 LoadIcon() のリ
ファレンスを見るとそんなこと書いてあるでしょ」
『まーそんな感じのこと書いてあるねー』
「ちなみにこれはただの変換だから、 reinterpret_cast<>() を使うことも
できます」
, reinterpret_cast< LPTSTR >( IDI_QUESTION ) );
『こっちの方が良くない? 新しいこと憶えなくていいし』
「LPTSTR って何か分かる?」
『う”……』
「ま、どっちも同じってことでいいかな。それにホントは、どっちも要らな
かったり……」
『何か言った?』
「イヤなんでもないです。で次の行は?」
『4行目よねー、 SetIcon() はやっぱアイコンをセットするの?』
「そういうこと。 CWnd::SetIcon() は、第1引数に渡されたアイコンハン
ドルをウィンドウにセットします」
『これも CWnd のメンバ関数なんだ。ホント、CWnd のっていっぱい……と
ころで2番目の FALSE って?』
「MSDNを見ましょう」
『ケチぃ。んっと、32ドットアイコンなら TRUE 、16ドットなら FALSE、
だって。でも16ドットとかって?』
「アイコンの大きさ。32ドットだったら、横32ドット、高さ32ドット
のアイコンってことだね」
『大と小ね』
「試しにこれ、TRUE に変えてみたら?」
『んっと、TRUE に書き換えて、ビルド、実行。……なんも変わんないよ?』
「そう、ウィンドウ左上のアイコンは、小さいアイコンしか使わないから、
ここのを変えたいときには FALSE を渡さなきゃダメってことだね」
『……って、じゃあ32ドットのってどこで使うの? 大きいアイコンなん
て、どこでも使ってないんじゃない?』
「ではALTキーを押しながらTABキーを押してみましょう」
『ん? なんか機能あったっけ……あ!』
横長のダイアログが表示され、そこに大きいアイコンがならんでいる。そ
のうちのひとつに〈吹き出しにはてなマーク〉のアイコンがある。
『これってタスクマネージャってヤツだよね。そっかー、ここで大きいアイ
コンを使うんだー』
「そういうこと」
『……もしかして、ここだけ?』
「ここだけ」
『変なのー』
「変なのって言えば、 CWnd::SetIcon() みたいに〈TRUE で大、 FALSE で
小〉みたいなのは悪い例だからね」
『そりゃそうよねー、ぱっと見で全然判んないもの』
「というわけで真似しないようにね。さて、ここまでをまとめてみると?」
『まず HICON 型の変数、 hIcon を作って』
「うん」
『次にAPIの LoadIcon() で、ウィンドウズからはてなマークのアイコン
のハンドルをもらって、hIcon に入れて』
「うんうん」
『最後にMFCの CWnd::SetIcon() でアイコンをダイアログにセット!』
「そういうこと」
『そういえば、LoadIcon() のMFC版ってないの?』
「あるけど……」
hIcon = AfxGetApp()->LoadStandardIcon( IDI_QUESTION );
『うお! なんかむつかしい……』
「ちなみに CWnd::SetIcon() をAPIですると……」
::SendMessage( GetSafeHwnd(), WM_SETICON
, ICON_SMALL, (LPARAM)hIcon );
『きゃー! さらに判んない〜!!』
「というわけで今はAPIとMFCを組み合わせてみたけど、ホントは統一
した方がミスしづらいからいいんだけどね」
『解るようになるまでちょっと我慢ってことねー』
「さて、今度は自分で作ったアイコンを表示してみましょう」
『それしたい!』
「まずワークスペースを開いて、そしたら下のタブから【ResourceView】を
選んで」
『ワークスペースってファイル開いたりクラス見たりしたときのよね。その
中のりそーすびゅーっと』
【Calc リソース】を元にツリーが表示されている。
「ツリーの中から【Icon】を選んで、右クリックメニューから【Icon の挿
入】を選んで」
『挿入?』
「ってゆーか新規作成ってとこだね」
『んじゃアイコンを作っちゃおう!』
【Icon】の下に【IDI_ICON1】が加わり、メインウィンドウに緑色の四角
が表示される。
『これ好きに描いちゃっていい!?』
「まぁ、今は他に教えることあるから簡単にね」
『またぁ!?』
「ってゆーかそーゆーことは他の時間にしましょー。別にわざわざこの時に
する必要はないんだから」
『そうだけどさー』
「じゃーさっさと終わらせて、それ描いたら次のようにプログラムを書き換
えてね」
『鬼〜悪魔〜人でなし〜』
「人じゃないのは火美ちゃんでしょうが」
『う”』
void CCalcDlg::OnBEqual()
{
HICON hIcon;
hIcon = ::LoadIcon( AfxGetInstanceHandle()
, MAKEINTRESOURCE( IDI_ICON1 ) );
SetIcon( hIcon, FALSE );
}
『ま、とりあえずビルドして実行っと。あ! ダイアログのアイコンがさっ
き描いたのになった!』
「さっきはウィンドウズシステムからアイコンを取得したけど、今度は今の
アプリから取得したわけだね」
『そのための AfxGetInstanceHandle() ってこと?』
「そう。さっきはゼロを渡したところに、今度は AfxGetInstanceHandle()
の戻り値を返してます」
『つまりこの戻り値が、今実行したアプリの……えっと、インスタンス、ハ
ンドル、ってことなのね』
「そういうこと。ちなみにこの関数はMFCの関数だから」
『CWnd のメンバ関数?』
「ううん、::LoadIcon() とかと同じ、どのクラスにも属さない関数」
『へー、MFCにもそういうのがあるんだ』
「ま、要するにこの関数を呼び出せば、関数を呼びだしてるプログラムを実
行してるアプリのハンドルが取得できるってことだね」
『……なんかこんがらがりそう。で、それを LoadIcon() に渡して、アプリ
からアイコンってことね』
「さて、これをもっと簡単に書くと、こうなります」
void CCalcDlg::OnBEqual()
{
HICON hIcon;
hIcon = AfxGetApp()->LoadIcon( IDI_ICON1 );
SetIcon( hIcon, FALSE );
}
『あ、これさっき見たのに似てる!』
「そう、これがMFCを使った方法」
『なんかよくわかんない〜』
「でも、余分なのなくてすっきりしてるでしょ」
『確かに』
「LoadIcon() のリファレンスって、APIのの他にあったでしょ」
『そういえば……』
LoadIcon をダブルクリックしてF1キーを押す。【該当するトピック】
ダイアログが表示される。
『あ、 CWinApp::LoadIcon() ってある!』
「上の例はこれを呼んでるってことだね」
『ふーん……』
「よく分かってないでしょー」
『もちろん!』
「じゃあ思い出してみて、今の Calc プロジェクトにあるクラスは?」
『今使ってる CCalcDlg と、あと CCalcApp っての』
「CCalcApp はなんてクラスから派生してた?」
『…… CWinApp クラスだ!』
「 CCalcDlg がウィンドウハンドルを管理しているのと同じで、 CCalcApp
はインスタンスハンドルを管理してます」
『それぞれ CDialog と CWinApp から派生してるわけよね』
「というわけで、 CCalcDlg のメンバ関数を呼ぶと、APIを呼ぶときに渡
したウィンドウハンドルを省略できる、代わりに渡してくれる、ってことが
CCalcApp にもあてはまるってこと」
『 CWinApp::LoadIcon() を呼び出せば、APIの LoadIcon() を呼び出し
たときに渡すインスタンスハンドルを代わりに渡してくれるってこと、かな』
「で、CCalcDlg のメンバ関数を呼び出すときに必要なのが AfxGetApp()->
って感じに憶えてもらえればいいかな」
『ってことは、やっぱ色々奥深いんだ』
「そういうことだねー」
/*
Preview Next Story!
*/
『今日はむつかしかったなー』
「……全部MFCが悪いんだ……」
『え?』
「MFCがもっと普通でシンプルだったら、こんな苦労しなくても……」
『というわけで次回』
< Version 3.7 ハンドルとメンバ変数 >
「につづく!!」
『……私プログラマーなるのやめよっかなー』
「じゃー何になる?」
『カリスマ美容師!!』
「みーはー」
『むっ』