使用运行时创建的模板的对话框在 XP 32 位上不起作用

Dialog using runtime-created template doesn't work on XP 32 bit

本文关键字:XP 不起作用 运行时 创建 对话框      更新时间:2023-10-16

我编写了一个运行时创建的对话框类,该类不使用任何基于此示例的资源文件: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版本还是CPU部分才是罪魁祸首。

一些有趣但奇怪的事情:

  • 同一程序中使用普通资源的对话框在Win7和WinXP中都能正常工作
  • 当逐字节比较运行时创建的对话框模板时,我看不出与资源构建的对话框有什么不同
  • 只要我不在对话框中添加任何控件,它就会在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);
}

哇,如果代码按制表符缩进,粘贴到这里会非常烦人:-/

代码看起来大致正确,但它没有显示生成的模板,该模板无法实例化。

我注意到一件奇怪的事:

m_data.Write<DWORD>(dwType);    // control type (as DWORD)

这听起来不对,如果是,你需要0xFFFF在前面

如果第一个元素是0xFFFF,则该数组具有一个附加元素其指定预定义系统类的序数值。这个序数可以是以下原子值之一。

在Win32下,我认为对话框模板结构需要字节对齐。