Я написал класс диалогов, созданный во время выполнения, который не использует файлы ресурсов на основе этого примера: http://blogs.msdn.com/b/oldnewthing/archive/2005/04/29/412577.aspx
Он скомпилирован на компьютере с Windows 7 x64, но как приложение x86. Диалог является частью более крупной программы, которая в других местах использует обычные диалоги с файлами ресурсов (MFC).
Диалог запускается DialogBoxIndirectParam следующим образом:
DialogBoxIndirectParam(NULL, m_template.GetTemplate(), NULL, DlgProc, reinterpret_cast<LPARAM>(this));
Диалоговое окно хорошо отображается на всех машинах с Windows 7 x64, которые я пробовал, но на машинах с Windows XP x86 оно не работает. Я не знаю, виновна ли версия Windows или битовая часть процессора.
Некоторые интересные, но странные вещи:
- Диалоги в одной программе с использованием обычных ресурсов прекрасно работают как в Win 7, так и в Win XP.
- При сравнении побайтовых шаблонов диалоговых окон, создаваемых во время выполнения, я не вижу отличий от диалогов, построенных из ресурсов.
- Пока я не добавлю какие-либо элементы управления в диалог, он будет отображаться в XP, но если я добавлю столько же, сколько один статический, он не будет.
- Я наблюдал за функцией обратного вызова и при ее запуске отправляет WM_SETFONT, WM_DESTROY, WM_NCDESTROY, а затем умирает. Как будто он сдается где-то между WM_SETFONT и WM_CREATE.
Я нашел других с похожими проблемами, но ни одна из них не была похожа на мою: http://social.msdn.microsoft.com/Forums/zh/vcgeneral/thread/45989a10-2785-486d-94ae-4f1f3e1ca651, http://cboard.cprogramming.com/windows-programming/39218-createdialog-failure.html
Я должен сказать, что я в своем уме, я просто недостаточно хорош в программировании на win32, чтобы точно понять, что здесь может быть не так.
Вот как выглядит код шаблона:
DialogTemplate::DialogTemplate(const std::wstring& title, WORD width, WORD height) :
m_numControls(0)
{
AddHeader(title, width, height);
AddFont();
}
DialogTemplate::~DialogTemplate(void)
{
}
void DialogTemplate::AddHeader(const std::wstring& title, WORD width, WORD height)
{
// Write out the extended dialog template header
m_data.Write<WORD>(1); // dialog version
m_data.Write<WORD>(0xFFFF); // extended dialog template
m_data.Write<DWORD>(0); // help ID
m_data.Write<DWORD>(0); // extended style
m_data.Write<DWORD>(WS_CAPTION | WS_SYSMENU | DS_SETFONT | DS_MODALFRAME);
m_data.Write<WORD>(0); // number of controls (placeholder)
m_data.Write<WORD>(32); // X
m_data.Write<WORD>(32); // Y
m_data.Write<WORD>(width); // width
m_data.Write<WORD>(height); // height
m_data.WriteString(L""); // no menu
m_data.WriteString(L""); // default dialog class
m_data.WriteString(title.c_str()); // title
}
bool DialogTemplate::AddFont()
{
// Write out font
HDC hdc = GetDC(NULL);
if (!hdc)
return false;
NONCLIENTMETRICSW ncm = { sizeof(ncm) };
if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
return false;
if (ncm.lfMessageFont.lfHeight < 0)
ncm.lfMessageFont.lfHeight = -MulDiv(ncm.lfMessageFont.lfHeight, 72, GetDeviceCaps(hdc, LOGPIXELSY));
m_data.Write<WORD>((WORD)ncm.lfMessageFont.lfHeight); // point
m_data.Write<WORD>((WORD)ncm.lfMessageFont.lfWeight); // weight
m_data.Write<BYTE>(ncm.lfMessageFont.lfItalic); // Italic
m_data.Write<BYTE>(ncm.lfMessageFont.lfCharSet); // CharSet
m_data.WriteString(ncm.lfMessageFont.lfFaceName);
return true;
}
void DialogTemplate::AddControl(LPCWSTR pszType, WORD x, WORD y, WORD width, WORD height, const std::wstring& text, DWORD controlId, DWORD style)
{
m_data.AlignToDword();
m_data.Write<DWORD>(0); // help id
m_data.Write<DWORD>(0); // window extended style
m_data.Write<DWORD>(WS_CHILD | style); // style
m_data.Write<WORD>(x); // x
m_data.Write<WORD>(y); // y
m_data.Write<WORD>(width); // width
m_data.Write<WORD>(height); // height
m_data.Write<DWORD>(controlId); // control ID
m_data.WriteString(pszType); // control type (as string)
m_data.WriteString(text.c_str()); // text
m_data.Write<WORD>(0); // no extra data
++m_numControls;
m_data.Overwrite<WORD>(m_numControls, NUM_CTRL_OFFS);
}
void DialogTemplate::AddControl(DWORD dwType, WORD x, WORD y, WORD width, WORD height, const std::wstring& text, DWORD controlId, DWORD style)
{
m_data.AlignToDword();
m_data.Write<DWORD>(0); // help id
m_data.Write<DWORD>(0); // window extended style
m_data.Write<DWORD>(WS_CHILD | style); // style
m_data.Write<WORD>(x); // x
m_data.Write<WORD>(y); // y
m_data.Write<WORD>(width); // width
m_data.Write<WORD>(height); // height
m_data.Write<DWORD>(controlId); // control ID
m_data.Write<DWORD>(dwType); // control type (as DWORD)
m_data.WriteString(text.c_str()); // text
m_data.Write<WORD>(0); // no extra data
++m_numControls;
m_data.Overwrite<WORD>(m_numControls, NUM_CTRL_OFFS);
}
Ничего себе, вставлять код здесь очень неприятно, если он имеет отступы: - /