Version 5.24
ウィンドウスタイルいろいろ
「前回はエクスプローラーのウィンドウについて見てきたけど、今回は
FileTest ダイアログについて見ていきます」
『ダイアログもウィンドウなんだよね』
「そう、でも普通のウィンドウといくらか違う部分もあるからね。とりあえ
ず実行して、 Spy++ で照準合わせてみて」
『ほいっと。ウィンドウハンドル 00000B38 、キャプション "てすと" 、
ウィンドウクラス "#32770 (ダイアログ)" ってなにこのウィンドウクラス』
「ダイアログもウィンドウのひとつなんだけど、違う部分のひとつは、ダイ
アログはウィンドウクラスの登録をしなくていいってとこ」
『この前の長ったらしいのしなくていいんだ』
「そう。で、代わりにこういう #32770 ってウィンドウクラスが登録されて
ます。ダイアログは全部このウィンドウクラスだから」
『え、全部?』
「一応ね。ダイアログっぽく見えるものの中には、普通にウィンドウとして
作って、スタイルを変更してダイアログっぽく見せてるものもあるから」
『そんなことできんの?』
「もちろん。ウィンドウは、ダイアログもコントロールも、基本のウィンド
ウを元に作られてるんだから」
『そーゆーもんなんだ』
「じゃ、そのスタイルを見てみると」
『 94C800C4 だって』
「この数字を実際に見てみようか。例によって CFileTestDlg::OnBtnShow()
の最初で」
void CFileTestDlg::OnBtnShow()
{
TRACE( "%X\n", GetStyle() );
return;
// あとは残しておきましょう。
『あ、ちゃんと 94C800C4 って出た!』
「 CWnd::GetStyle() はウィンドウスタイルの値を取得します。この値は
ビットフラグになってるから」
『たとえばこの前見た……えっと、 OK して【スタイル】ページっと、
WS_POPUPWINDOW とかがこの中に含まれてるのか調べるんなら、 & すればい
いんだよね』
「そういうこと。 WS_POPUPWINDOW は 0x80880000 だから」
『だと、 10000000100010000000000000000000 ってビットになるんだよね』
「リトルエンディアンだから 00000000000000001000100010000000 だよ」
『あ、そういえば。なんかバイトオーダーなんて懐かしい……。でさ、
WS_POPUPWINDOW が 0x80880000 ってどうやって分かったの?』
「見てみたから。 WS_POPUPWINDOW で【ファイルから検索】してみ」
『ほい。あ、 Winuser.h ってとこにあった』
#define WS_POPUPWINDOW (WS_POPUP | \
WS_BORDER | \
WS_SYSMENU)
『??』
「 #define は分かるでしょ」
『うん、定数値作るときに使うヤツ。1番目のを、2番目のに置き換えるん
だよね。でも……』
「 #define 使った Ver 4.09 ( No.059 ) でこういう例を見せたでしょ」
#define DEF_FLAG_OK 1
『これだと DEF_FLAG_OK を 1 に置き換えるんだよね』
「最後にセミコロンが付いてないでしょ」
『ホントだ!』
「最初に # がついてるのは、最後にセミコロンが要りません。つまり改行
すればOKってこと」
『うん、そだね。でもそれだと、改行して続き書きたいときはどーすんの?』
「そういうときは \ を付けます」
『あ! それが上の \ なんだ』
「だから、上のは」
#define WS_POPUPWINDOW ( WS_POPUP | WS_BORDER | WS_SYSMENU )
「と同じ」
『ほー。で、 WS_POPUP とかは……あ、すぐ上にあるね』
#define WS_POPUP 0x80000000L
『そっか、こういうののビット和で 0x80880000 が出てくるのね』
「そゆこと」
『質問! 最後の L はなに?』
「この数字は32ビットサイズですよって意味。 MSDN の 【C++ 整数定数】
ってページに書いてあるから」
『 unsigned にする u なんてのもあるんだ』
「ま、わざわざ付ける必要はないんだろうけどね」
『質問2! ( WS_POPUP | WS_BORDER | WS_SYSMENU ) ってカッコでくくっ
てるのはなんで?』
「たとえば!」
WS_POPUPWINDOW * 3
「ってしたとき。カッコ付きだと」
( WS_POPUP | WS_BORDER | WS_SYSMENU ) * 3
「でいいんだけど、カッコがないと」
WS_POPUP | WS_BORDER | WS_SYSMENU * 3
「で、先に WS_SYSMENU * 3 が計算されちゃうから」
『そっか、優先順位が * の方が上だからなんだ』
「これは #define が〈単に置き換えしかしない〉っていうのが原因。他に
定数値作る方法があったでしょ」
『 const int とか enum とかだよね』
「そうそう。そういうのは置き換えじゃないから、こういう問題はおきない
わけ」
『だから #define よりもこういうの使った方がいいってことね。最後の質
問! WS_POPUP とかのフラグって左の方から、しかも 8 からビット使っ
てくけど、なんで?』
「たぶんバイトオーダーの関係だろうね」
『でもさ、 8 からだと、1バイトの中じゃ左からになるよね』
「そういえばそうだね……ま、それはいいとして」
『あっ逃げた』
「たぶん分かってると思うけど、このウィンドウスタイルは、ウィンドウズ
の機能だからね」
『それって API の機能ってことでしょ? うん分かってたよ、 Winuser.h
って MFC のファイルじゃないじゃん』
「そう、だからたとえば〈 WS_POPUPWINDOW ってどういうスタイル?〉とか
は API のリファレンスに載ってます。 MSDN で CreateWindow() 見てみて」
『ほいっと。なんかかなり長いページだね』
「下の方に」
『あった! WS_BORDER とか WS_CAPTION とか、 WS_POPUPWINDOW もちゃん
とあるね。あ!』
「どしたの?」
『この前 CWnd::Create() でこういうの渡してたから、それと関係ある?』
「ってゆーかそのまま。 CWnd::Create() は CreateWindow() 呼んでるから
ね」
『ってことは、ホントはウィンドウスタイルって、ウィンドウ作るときに決
めるもんなんだ』
「そゆこと。ダイアログの場合は簡単にできるんだけどね」
『どやって?』
「ダイアログエディタ開いて、ダイアログのプロパティ見てみ」
『右クリックからプロパティ……あ、スタイルってある!! もしかしてこ
れ全部、スタイルなの?』
「そう、スタイル。ここでダイアログのスタイルを決められるから、わざわ
ざ指定しなくていいわけ」
『ほー』
「ついでに、 FileTest.rc をテキスト形式で開いて」
『 FileTest プロジェクトの中にそういうファイルがあるのね……ダイアロ
グエディタ閉じちゃえって』
「閉じていいよ」
『ほい。あ、自分で探してみるから……ここ?』
IDD_FILETEST_DIALOG DIALOGEX 0, 0, 206, 159
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
「そう! さっきの【ダイアログ プロパティ】での設定がここに書き込ま
れて、ダイアログを表示するときに使用されます」
『だからプログラムとして書かなくてよかったんだ』
「そゆこと」
『あれ、 DS_MODALFRAME ってなんだろ。そういえば Spy++ のスタイルにも
あるね』
「これはダイアログ専用のスタイル。さっきの CreateWindow() のを見ると」
『あったあった、 DS_3DLOOK とかが! DS_MODALFRAME もあるね』
「この辺はダイアログ専用のスタイル。こういうのもウィンドウスタイルの
中に含まれるから」
『へー。このページ見ると、ボタンのスタイルとかもあるんだね』
「ボタンとかのダイアログコントロールも」
『ウィンドウの一種、だよね。 Spy++ の照準合わせてっと、 BS_PUSHBUTTON
とかあるね』
「これも」
『プロパティで決められるの? ダイアログエ……の前に、もう一度開き直
すのめんどいから FileTest.rc の中から探しとこっと』
「あ、意味ないよ」
『ええ〜? あ、あった』
PUSHBUTTON "表示(&S)",IDC_BTN_SHOW,149,23,50,14
『ううっ、スタイルらしきものがない〜』
「でしょ、別にスタイル付いてないんだもの。一度閉じてダイアログエディ
タ開いて」
『ほい。んで【表示】ボタンのプロパティっと』
「【平面】にしてみて」
『ほい平面。あ、これするとボタンが真っ平らになるんだね』
「そしたら保存して」
『 FileTest.rc をテキスト形式で開くっと』
PUSHBUTTON "表示(&S)",IDC_BTN_SHOW,149,23,50,14,BS_FLAT
『おおお、ボタンのスタイルが付いた!』
「こんなふうに、ボタンもウィンドウの一種だから」
『スタイル付けられるんだ。……ふと思ったんだけど、もしかしてボタンと
かも CreateWindow() で作れるの?』
「作れるよ? だから同じページに書いてあるんじゃない」
『そりゃそうだけど、でもボタンとかリストボックスとか、普通のウィンド
ウと見た目全然ちがうでしょ。そういうのもプログラムで』
「しなくても大丈夫。〈ウィンドウの原型〉ってあったでしょ」
『ウィンドウクラス!』
「同じ CreateWindow() のリファレンスに……」
『 BUTTON とか COMBOBOX あるね、そっか、ウィンドウクラスをこーゆーの
にすれば、ボタンとかができるんだ!』
「そゆこと」
『ってことは…… Spy++ で見てもちゃんとウィンドウクラスが Button と
か ListBox とかになってる! 大文字小文字は違うけど』
「その辺も含めて次回に続く!」
/*
Preview Next Story!
*/
『なんかちょっと複雑。でも……』
「でも?」
『ちょっと中身分かってくると、なんか面白いかも』
「そう、そうなんだよ火美ちゃん!」
『な、なに?』
「色々分かってくるとプログラミングが楽しくてしょうがなくなるんだよ!」
『というわけで次回』
< Version 5.25 ボタンを作ろう! >
「につづく!」
『ま、自分で色々できるようになるってのは楽しいけどね』
「……でも作業中のウィンドウを最小化するのはやめて……」