ダイアログ: Win16 でメモリ上にテンプレートを作成
ここでは、Win16 版のダイアログ テンプレートを使って、メモリ上にダイアログ テンプレートを作成し、表示する例を示しています。リソースを読み込むプログラムを作る時などにも参考になると思います。
Win32 版のものは「メモリ上にテンプレートを作成」をご覧下さい。
Win16 のダイアログ テンプレート
Win32 との大きな違いは、
- 拡張スタイル (dwExtendedStyle) が無い
- コントロールの最大数が 255 (cdit が BYTE なため)
- 文字列はすべて ANSI 文字列 (Unicode が無いため)
です。ただ、ほとんどの構造は変わり無いので、Win32 の時の方法ができるようであれば、これもそれほど難しくはありません。
以下は DLGTEMPLATE、DLGITEMTEMPLATE 構造体の定義です。
DLGTEMPLATE、DLGITEMTEMPLATE という定義はありません。よって、自分でヘッダーファイルに記述する必要があります。
typedef struct { DWORD style; BYTE cdit; short x; short y; short cx; short cy; // <Menu ID>; // <Window Class>; // <Dialog Title>; // WORD fontSize; // CHAR fontName[]; // DLGITEMTEMPLATE controls[cdit]; } DLGTEMPLATE, FAR* LPDLGITEMPLATE;
typedef struct { // Win32 のものとは順番が違います short x; short y; short cx; short cy; WORD id; DWORD style; // <Window Class>; // <Control Text>; // BYTE SizeOfCreationData; // BYTE CreationData[SizeOfCreationData]; } DLGITEMTEMPLATE, FAR* LPDLGITEMTEMPLATE;
※ 上記の定義でコメントアウトしている部分は、実際には設定する内容によって型やサイズ・メモリ上での位置が変わってしまうため、明確な定義をすることが出来ません。
構造体のメンバ
- style
- ダイアログ、またはコントロールのスタイルです。(WS_ 、DS_ など)
- cdit
- ダイアログが持つコントロールの数です。(Count of DLGITEMTEMPLATE の略)
- x, y, cx, cy
- ダイアログ、またはコントロールのサイズです。このサイズはダイアログベース単位で指定する必要があります。ピクセルからこの単位に変換するには、GetDialogBaseUnits 関数を使う方法がありますが、本来はフォントのサイズを計算に含める必要があり、おすすめできません。
- id
- コントロールの ID です。なお、IDOK (= 1) を指定し、スタイルに BS_DEFPUSHBUTTON を指定すると既定のボタン (エディットコントロールで Enter をしたときに自動的に押されるボタン) に、IDCANCEL (= 2) を指定するとキャンセルボタン (ESC キーを押すと自動的に押されるボタン) になります。
- <Menu ID>
- メニューリソースの ID を指定します。整数値で指定する場合は、このメンバは BYTE + WORDとなり、最初 (BYTE) に 0xFF、2 番目 (WORD) に ID を指定します。
ID を文字列で指定する場合は、このメンバは NULL で終わる ANSI 文字列となります。NULL 文字の次の位置が、次のメンバの始点となります。
指定しない場合 (メニュー無し) は、BYTE サイズで 0 を指定します。(空の文字列と同じ) - <Window Class>
- ウィンドウのクラスを指定します。指定方法は <Menu ID> と同じです。
ここでも整数値が指定できます。最初に 0x80 以上の値を指定します。この値は以下の通りで、クラス名の文字列を入れなくてもそのクラスで作成できます。
値 コントロール 0x80 ボタン (Button) 0x81 エディットコントロール (Edit) 0x82 スタティックコントロール (Static) 0x83 リストボックス (ListBox) 0x84 スクロールバー (ScrollBar) 0x85 コンボボックス (ComboBox) - <Dialog Title>、<Control Text>
- ダイアログのタイトル、コントロールのテキストを指定します。指定方法は <Menu ID> と同じです。
ダイアログのタイトルの場合は文字列のみですが、コントロールのテキストの場合、最初が 0xFF なら、このメンバは BYTE + WORD となり、次に来る WORD 値 (最初の BYTE 値は左の通り 0xFF) は ID です。この ID はスタティック コントロールなどで、画像を表示する際にリソースから読み込む時のリソース ID となります。 - fontSize
- フォントのサイズをポイント単位で指定します。ただし、DS_SETFONT スタイルが無い場合、このメンバを指定することは出来ません。
- fontName
- フォントの名前を、NULL で終わる ANSI 文字列で指定します。ただし、DS_SETFONT スタイルが無い場合、このメンバを指定することは出来ません。
- SizeOfCreationData, CreationData
- WM_CREATE メッセージの lParam のデータで渡される任意のデータを指定します。SizeOfCreationData はそのサイズで、0 を指定した場合は CreationData は存在しません。なお、SizeOfCreationData には SizeOfCreationData 分のサイズ (sizeof(BYTE)) は含みません。
※ DWORD 境界に揃える、といった動作はありません。
作成例
ここでは、Win16 版の DLGTEMPLATE、DLGITEMTEMPLATE 構造体を使った例を示します。
// ※ DLGTEMPLATE、DLGITEMTEMPLATE は元々定義されていません。 // 上記の定義をヘッダーなどに含めてください。 typedef BYTE FAR* LPBYTE; HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPBYTE lpb; LPSTR lpsz; // 実際は、サイズはデータが収まりきるように // あらかじめ計算しておく必要があります。 // GMEM_ZEROINIT であらかじめデータを 0 に設定しておきます。 // (省略されているメンバは 0 になります) hgbl = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, 1024); if (!hgbl) ErrorAndExit(); // ダイアログボックスの初期値を設定します。 // ※ hgbl と lpdt のアドレスは同じになります (GMEM_FIXED のため)。 lpdt = (LPDLGTEMPLATE) GlobalLock(hgbl); lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT; // フォント付き lpdt->cdit = 2; // コントロールの数 lpdt->x = 10; lpdt->y = 10; lpdt->cx = 100; lpdt->cy = 100; // 次のメンバの設定に移ります。 lpb = (LPBYTE) (lpdt + 1); // <Menu ID> // ID を指定する場合は以下の通りです。 // *lpb++ = 0xFF; // *((LPWORD&) lpb)++ = id; *lpb++ = 0; // <Window Class> *lpb++ = 0; // <Dialog Title> lpsz = (LPSTR) lpb; // 文字列をコピーします。 strcpy(lpsz, "ダイアログ テスト"); // strlen 関数の戻り値は NULL 文字を含みません。 lpb += strlen(lpsz) + 1; // WORD fontSize // ※ DS_SETFONT を指定しなかった場合、コントロールの設定に // 移るまでのデータ設定は行いません。 *((LPWORD&) lpb)++ = 9; // CHAR fontName[] lpsz = (LPSTR) lpb; strcpy(lpsz, "MS P明朝"); lpb += strlen(lpsz) + 1; // コントロールの設定に移ります。 // DWORD 境界に揃える必要はありません。 lpdit = (LPDLGITEMTEMPLATE) lpb; // OK ボタンを作ります。 lpdit->x = 10; lpdit->y = 70; lpdit->cx = 60; lpdit->cy = 14; lpdit->id = IDOK; // OK ボタンの ID lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; // 次のメンバの設定に移ります。 lpb = (LPBYTE) (lpdit + 1); // <Window Class> // これでも構いません。 // lpsz = (LPSTR) lpb; // strcpy(lpsz, "Button"); // lpb += strlen(lpsz) + 1; *lpb++ = 0x80; // ボタンのウィンドウクラスを指定します。 // <Control Text> // ID を指定する場合は以下の通りです。 // *lpb++ = 0xFF; // *((LPWORD&) lpb)++ = id; lpsz = (LPSTR) lpb; strcpy(lpsz, "OK"); lpb += strlen(lpsz) + 1; // BYTE SizeOfCreationData // 特にデータは無いため、0 で終わります。 *lpb++ = 0; // 次のコントロールの設定に移ります。 lpdit = (LPDLGITEMTEMPLATE) lpb; lpdit->x = 10; lpdit->y = 10; lpdit->cx = 40; lpdit->cy = 9; lpdit->id = IDC_STATIC; // スタティックコントロールによくある ID (IDC_STATIC = -1) lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; lpb = (LPBYTE) (lpdit + 1); // <Window Class> // これでも構いません。 // lpsz = (LPSTR) lpb; // strcpy(lpsz, "Static"); // lpb += strlen(lpsz) + 1; *lpb++ = 0x82; // スタティックコントロールのウィンドウクラスを指定します。 // <Control Text> lpsz = (LPSTR) lpb; strcpy(lpsz, "メッセージ"); lpb += strlen(lpsz) + 1; // BYTE SizeOfCreationData // 特にデータは無いため、0 で終わります。 *lpb++ = 0; // データ設定は終了しました。ロックを解除します。 GlobalUnlock(hgbl); // DialogBoxIndirect を呼び出して作成します。GMEM_FIXED なので // 2 番目の引数は HGLOBAL なので hgbl をそのまま指定します。 // (hInst、hWndOwner、DialogProc は既に定義されているものとします。) DialogBoxIndirect(hInst, hgbl, hWndOwner, (DLGPROC) DialogProc); // メモリを解放します。 GlobalFree(hgbl);
最終更新日: 2005/08/10(推定)