ダイアログを作るときにリソースをいちいちつくるのが面倒なときがある。また、他のアプリケーションに移植するためにリソースIDなどの固有値を作るのが嫌な時がある。そん時に使えるVisual C++ MFCのTips。
CreateIndirect
モーダレス系のダイアログを作成する場合に使えるCDialogメソッド。追っていくと::CreateDialogIndirectで作っているのがわかる。MSDNによると、
CreateWindowEx 関数を使ってダイアログボックスを作成します。
とのことなので結局はCreateWindowExで作っているようだ。
コードとしては、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
struct { DLGTEMPLATE dtp; WORD param[ 4 ]; } dtp; dtp.dtp.cdit = 0; dtp.dtp.cx = width; dtp.dtp.cy = height; dtp.dtp.x = 0; dtp.dtp.y = 0; dtp.dtp.style = style; dtp.dtp.dwExtendedStyle = 0; memset( dtp.param, 0, sizeof( WORD ) * 4 ); CreateIndirect( &dtp, parent ); |
こんな感じになる。どうやら、DLGTEMPLATEだけでは足りないようで4つWORDをさらに後ろにつける必要がある。なぜなら、DLGTEMPLATEEXを本来は指定なくてはならないのだが、このDLGTEMPLATEEXの定義が探しても見つからない。かろうじて探しているとatlwin.hの中にこの定義を発見。しかし、わざわざインクルードするのあれなので今回はその方法は取っていない。また、ウォッチでsizeof( DLGTEMPLATEEX )をとると26になりsizeof( DLGTEMPLATE )が18なので8バイト(WORD*4)足りないこともよくわかる。
出来たダイアログはモードレスなので、RunModalLoopなどしてあげるとモーダルとして動作してくれる。
InitModalIndirect
モーダル系のダイアログを作成する場合に使えるCDialogメソッド。これ自体は、単に値(ポインタ)をセットするだけのもの。なので、引数に使うLPDLGTEMPLATEはどこかに保存しておく必要がある。なおここも上とどうように、
1 2 3 4 5 |
struct { DLGTEMPLATE dtp; WORD param[ 4 ]; } dtp; |
これを使って行う。こちらの方式で作る場合もDoModalの中で結局CreateDlgIndirectがよばれることになり上と同様な仕組みであることがわかる。
WTLやATLの場合CDialogImplのCreateの方で簡単に作れる。こちらの場合、CreateWindowExを使っているようだ。