Creating a Template in Memory

Applications sometimes adapt or modify the content of dialog boxes depending on the current state of the data being processed. In such cases, it is not practical to provide all possible dialog box templates as resources in the application's executable file. But creating templates in memory gives the application more flexibility to adapt to any circumstances.

In the following example, the application creates a template in memory for a modal dialog box that contains a message and OK and Help buttons.

In a dialog template, all character strings, such as the dialog box and button titles, must be Unicode strings. This example uses the MultiByteToWideChar function to generate these Unicode strings, because both Windows NT and Windows 95 support MultiByteToWideChar

The DLGITEMTEMPLATE structures in a dialog template must be aligned on DWORD boundaries. To align these structures, this example uses a helper routine that takes an input pointer and returns the closest pointer that is aligned on a DWORD (4 byte) boundary.

#define ID_HELP 150

#define ID_TEXT 200

LPWORD lpwAlign ( LPWORD lpIn)

{

ULONG ul;

ul = (ULONG) lpIn;

ul +=3;

ul >>=2;

ul <<=2;

return (LPWORD) ul;

}

LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner,

LPSTR lpszMessage)

{

HGLOBAL hgbl;

LPDLGTEMPLATE lpdt;

LPDLGITEMTEMPLATE lpdit;

LPWORD lpw;

LPWSTR lpwsz;

LRESULT ret;

int nchar;

hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);

if (!hgbl)

return -1;

lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);

// Define a dialog box.

lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU

| DS_MODALFRAME | WS_CAPTION;

lpdt->cdit = 3; // number of controls

lpdt->x = 10; lpdt->y = 10;

lpdt->cx = 100; lpdt->cy = 100;

lpw = (LPWORD) (lpdt + 1);

*lpw++ = 0; // no menu

*lpw++ = 0; // predefined dialog box class (by default)

lpwsz = (LPWSTR) lpw;

nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "My Dialog",

-1, lpwsz, 50);

lpw += nchar;

//-----------------------

// Define an OK button.

//-----------------------

lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary

lpdit = (LPDLGITEMTEMPLATE) lpw;

lpdit->x = 10; lpdit->y = 70;

lpdit->cx = 80; lpdit->cy = 20;

lpdit->id = IDOK; // OK button identifier

lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;

lpw = (LPWORD) (lpdit + 1);

*lpw++ = 0xFFFF;

*lpw++ = 0x0080; // button class

lpwsz = (LPWSTR) lpw;

nchar = 1+MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);

lpw += nchar;

lpw = lpwAlign (lpw); // align creation data on DWORD boundary

*lpw++ = 0; // no creation data

//-----------------------

// Define a Help button.

//-----------------------

lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary

lpdit = (LPDLGITEMTEMPLATE) lpw;

lpdit->x = 55; lpdit->y = 10;

lpdit->cx = 40; lpdit->cy = 20;

lpdit->id = ID_HELP; // Help button identifier

lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;

lpw = (LPWORD) (lpdit + 1);

*lpw++ = 0xFFFF;

*lpw++ = 0x0080; // button class atom

lpwsz = (LPWSTR) lpw;

nchar = 1+MultiByteToWideChar (CP_ACP, 0, "Help", -1, lpwsz, 50);

lpw += nchar;

lpw = lpwAlign (lpw); // align creation data on DWORD boundary

*lpw++ = 0; // no creation data

//-----------------------

// Define a static text control.

//-----------------------

lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary

lpdit = (LPDLGITEMTEMPLATE) lpw;

lpdit->x = 10; lpdit->y = 10;

lpdit->cx = 40; lpdit->cy = 20;

lpdit->id = ID_TEXT; // text identifier

lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;

lpw = (LPWORD) (lpdit + 1);

*lpw++ = 0xFFFF;

*lpw++ = 0x0082; // static class

for (lpwsz = (LPWSTR)lpw;

*lpwsz++ = (WCHAR) *lpszMessage++;

);

lpw = (LPWORD)lpwsz;

lpw = lpwAlign (lpw); // align creation data on DWORD boundary

*lpw++ = 0; // no creation data

GlobalUnlock(hgbl);

ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,

hwndOwner, (DLGPROC) DialogProc);

GlobalFree(hgbl);

return ret;

}