Диалог с использованием созданного во время выполнения шаблона не работает в 32-разрядной версии XP - PullRequest
0 голосов
/ 08 февраля 2012

Я написал класс диалогов, созданный во время выполнения, который не использует файлы ресурсов на основе этого примера: 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);
}

Ничего себе, вставлять код здесь очень неприятно, если он имеет отступы: - /

Ответы [ 2 ]

0 голосов
/ 26 марта 2013

Под Win32 я считаю, что структура шаблона диалога должна быть выровнена по байту.

0 голосов
/ 08 февраля 2012

Код выглядит правильно, но он не показывает созданный шаблон, который не может быть создан.

Одна вещь, которую я заметил странно, это:

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

Это не звучитверно, вам нужно 0xFFFF впереди, если оно :

Если первый элемент 0xFFFF, массив имеет один дополнительный элемент, который задает порядковое значение предопределенного системного класса,Порядковый номер может быть одним из следующих значений атома.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...