Programming Field - プログラミング Tips

ダイアログ: メモリ上にテンプレートを作成する例 (2)

ここでは、DLGTEMPLATE、DLGITEMTEMPLATE 構造体を使った例を示します。

元のページに戻る

作成例 2

    HGLOBAL hgbl;
    LPDLGTEMPLATE lpdt;
    LPDLGITEMTEMPLATE lpdit;
    LPWORD lpw;
    LPBYTE lpb;
    LPWSTR lpwsz;
    int nChar;

    // 実際は、サイズはデータが収まりきるように
    // あらかじめ計算しておく必要があります。
    // 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;

    // 次のメンバの設定に移ります。
    lpw = (LPWORD) (lpdt + 1);

    // <Menu ID>
    //   *lpw++ = の文は、その位置に値を設定した後 ++ を行います。
    //   (つまり *lpw = 0; lpw++; と同じ)
    //   正式には lpw++ がインクリメントする前のアドレスを返し、
    //   そのアドレスに対して *XXX = 0 を行っています。
    *lpw++ = 0;

    // <Window Class>
    *lpw++ = 0;

    // <Dialog Title>
    lpwsz = (LPWSTR) lpw;

    // MultiByteToWideChar 関数で ANSI 文字列を Unicode 文字列に変換します。
    // 戻り値 (書き込んだ文字列の長さ) に NULL 文字が含まれているので + 1 しません。
    nChar = MultiByteToWideChar(CP_ACP, 0, "ダイアログ テスト", -1, lpwsz, 50);

    // lpw = (LPWORD) lpwsz は必要ありません (アドレスが同じであるため)。
    lpw += nChar;

    // WORD fontSize
    // ※ DS_SETFONT を指定しなかった場合、コントロールの設定に
    //   移るまでのデータ設定は行いません。
    *lpw++ = 9;

    // WCHAR fontName[]
    lpwsz = (LPWSTR) lpw;
    nChar = MultiByteToWideChar(CP_ACP, 0, "MS P明朝", -1, lpwsz, 50);
    lpw += nChar;

    // コントロールの設定に移ります。
    //   移る前に DWORD 境界に揃えます。
    lpw = (LPWORD) (((DWORD_PTR) lpw + 3) & ~((DWORD_PTR) 3));
    lpdit = (LPDLGITEMTEMPLATE) lpw;

    // 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;

    // 次のメンバの設定に移ります。
    lpw = (LPWORD) (lpdit + 1);

    // <Window Class>
    //   これでも構いません。
    //     lpwsz = (LPWSTR) lpw;
    //     nChar = MultiByteToWideChar(CP_ACP, 0, "Button", -1, lpwsz, 50);
    //     lpw += nChar;
    *lpw++ = 0xFFFF;  // 数値指定に必要
    *lpw++ = 0x0080;  // ボタンのウィンドウクラスを指定します。

    // <Control Text>
    lpwsz = (LPWSTR) lpw;
    nChar = MultiByteToWideChar(CP_ACP, 0, "OK", -1, lpwsz, 50);
    lpw += nChar;

    // WORD SizeOfCreationData
    //   特にデータは無いため、0 で終わります。
    //   ※ データがある場合、データのサイズ + sizeof(WORD) (= 2) を設定します。
    *lpw++ = 0;

    // 次のコントロールの設定に移ります。
    lpw = (LPWORD) (((DWORD_PTR) lpw + 3) & ~((DWORD_PTR) 3));
    lpdit = (LPDLGITEMTEMPLATE) lpw;

    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;

    lpw = (LPWORD) (lpdit + 1);

    // <Window Class>
    //   これでも構いません。
    //     lpwsz = (LPWSTR) lpw;
    //     nChar = MultiByteToWideChar(CP_ACP, 0, "Static", -1, lpwsz, 50);
    //     lpw += nChar;
    *lpw++ = 0xFFFF;
    *lpw++ = 0x0082;  // スタティックコントロールのウィンドウクラスを指定します。

    // <Control Text>
    lpwsz = (LPWSTR) lpw;
    nChar = MultiByteToWideChar(CP_ACP, 0, "メッセージ", -1, lpwsz, 50);
    lpw += nChar;

    // WORD SizeOfCreationData
    //   特にデータは無いため、0 で終わります。
    *lpw++ = 0;

    // データ設定は終了しました。ロックを解除します。
    GlobalUnlock(hgbl);

    // DialogBoxIndirect を呼び出して作成します。GMEM_FIXED なので
    // LPDLGTEMPLATE の引数には hgbl をそのまま指定します。
    // (hInst、hWndOwner、DialogProc は既に定義されているものとします。)
    DialogBoxIndirect(hInst, (LPDLGTEMPLATE) hgbl, hWndOwner, (DLGPROC) DialogProc);

    // メモリを解放します。
    GlobalFree(hgbl);

最終更新日: 2005/04/17