6.30.5 - Создание шаблона в памяти

Прикладные программы время от времени изменяют или модифицируют содержимое диалоговых окон, в зависимости от текущего состояния обрабатываемых данных. В подобных случаях не практично давать все возможные шаблоны диалогового окна как ресурсы в исполняемом файле прикладной программы. Однако создание шаблонов в памяти дает прикладной программе больше гибкости для адаптации к любым обстоятельствам.

В примере ниже прикладная программа создает шаблон в памяти для модального диалогового окна, которое содержит сообщение и кнопки ОК и Справка (Help).

В шаблоне блока диалога все символьные строки, такие как названия диалоговых окон и кнопок, должны быть строками Уникода. Этот пример использует функцию MultiByteToWideChar для создания этих строчек Уникода, поскольку и Windows NT и Windows 95 поддерживают MultiByteToWideChar.

Структуры DLGITEMTEMPLATE в шаблоне диалогового окна должны быть выровнены по границам ДВОЙНОГО СЛОВА (DWORD). Чтобы выровнять эти структуры, этот пример использует подпрограмму - помощника, которая получает введенный указатель, а возвращает самый близкий указатель, который выравнен по границе ДВОЙНОГО СЛОВА - DWORD (4 байта).

#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);
 
	// Определение диалогового окна.
 
	lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
		| DS_MODALFRAME | WS_CAPTION;
	lpdt->cdit = 3;	// число элементов управления
	lpdt->x  = 10;  lpdt->y  = 10;
	lpdt->cx = 100; lpdt->cy = 100;

	lpw = (LPWORD) (lpdt + 1);
	*lpw++ = 0;	// меню нет
	*lpw++ = 0;	// класс предопределенного диалогового окна (по умолчанию)

	lpwsz = (LPWSTR) lpw;

	nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "My Dialog",  -1, lpwsz, 50);
	lpw   += nchar;

	//-----------------------
	// Определение кнопки OK.
	//-----------------------
	lpw = lpwAlign (lpw); 	// выравнивание DLGITEMTEMPLATE по границе DWORD
	lpdit = (LPDLGITEMTEMPLATE) lpw;
	lpdit->x  = 10; lpdit->y  = 70;
	lpdit->cx = 80; lpdit->cy = 20;
	lpdit->id = IDOK;  	// идентификатор кнопки OK
	lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;

	lpw = (LPWORD) (lpdit + 1);
	*lpw++ = 0xFFFF;
	*lpw++ = 0x0080;	// класс кнопки

	lpwsz = (LPWSTR) lpw;
	nchar = 1+MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
	lpw   += nchar;
	lpw = lpwAlign (lpw);	// выравнивание созданных данных по границе DWORD 
	*lpw++ = 0;		// созданных данных нет

	//-----------------------
	// Определение кнопки Help.
	//-----------------------
	lpw = lpwAlign (lpw); 	// выравнивание DLGITEMTEMPLATE по границе DWORD

	lpdit = (LPDLGITEMTEMPLATE) lpw;
	lpdit->x  = 55; lpdit->y  = 10;
	lpdit->cx = 40; lpdit->cy = 20;
	lpdit->id = ID_HELP;    // идентификатор кнопки Help
	lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;

	lpw = (LPWORD) (lpdit + 1);
	*lpw++ = 0xFFFF;
	*lpw++ = 0x0080;	// атом класса кнопки
	lpwsz = (LPWSTR) lpw;
	nchar = 1+MultiByteToWideChar (CP_ACP, 0, "Help", -1, lpwsz, 50);
	lpw += nchar;
	lpw = lpwAlign (lpw); 	// выравнивание созданных данных по границе DWORD

	*lpw++ = 0;		// созданных данных нет

	//-----------------------
	// Определение статического текста в элементе управления.
	//-----------------------
	lpw = lpwAlign (lpw); 		// выравнивание DLGITEMTEMPLATE по границе DWORD
	lpdit = (LPDLGITEMTEMPLATE) lpw;
	lpdit->x  = 10; lpdit->y  = 10;
	lpdit->cx = 40; lpdit->cy = 20;
	lpdit->id = ID_TEXT;  // идентификатор текста
	lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;

	lpw = (LPWORD) (lpdit + 1);
	*lpw++ = 0xFFFF;
	*lpw++ = 0x0082;	// класс статического элемента

	for (lpwsz = (LPWSTR)lpw;
		*lpwsz++ = (WCHAR) *lpszMessage++;
	);
	lpw = (LPWORD)lpwsz;
	lpw = lpwAlign (lpw);	// выравнивание созданных данных по границе DWORD
	*lpw++ = 0;		// созданных данных нет 

	GlobalUnlock(hgbl); 
	ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl, 
		hwndOwner, (DLGPROC) DialogProc); 
	GlobalFree(hgbl); 
	return ret; 
}

Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Владимир Соковиков - 09.05.2002