DialogBoxIndirect создает диалог больше, чем требуется - PullRequest
5 голосов
/ 09 февраля 2012

Для моего приложения мне нужно создать диалоговое окно без использования ресурса. Я пытаюсь сделать это с помощью функции DialogBoxInderect . Код невероятно уродливый, но каким-то образом мне удалось это сделать.

Проблема в том, что диалог по некоторым причинам гораздо больше, чем я просил, с гораздо большими шрифтами.

Вот как выглядит диалоговое окно, если я загружаю его из ресурса: enter image description here

А вот и диалог того же размера, который указан, когда я вызываю DialogBoxInderect . enter image description here

Вот как это определено в коде:

HGLOBAL             hGlobal;
LPDLGTEMPLATE       wlsDialogTemplate;
LPDLGITEMTEMPLATE   wlsDialogItemTemplate;
LPWORD              nextItem;
LPWSTR              itemString;
int32_t             itemStringLength;

// Check for memory allocation errors
hGlobal = GlobalAlloc(GMEM_ZEROINIT, 1024);
if (!hGlobal) 
    return -1;

wlsDialogTemplate = (LPDLGTEMPLATE)GlobalLock(hGlobal);

// Define a dialog box.
wlsDialogTemplate->style    = WS_CAPTION;
wlsDialogTemplate->x        = 0;
wlsDialogTemplate->y        = 0;
wlsDialogTemplate->cx       = 320;
wlsDialogTemplate->cy       = 115;

GlobalUnlock(hGlobal);
retCode = DialogBoxIndirect(0, (LPDLGTEMPLATE)hGlobal, 0, ActivateWlsMsgDialog);

А вот как это определено в файле RC:

IDD_WLS_SMALL_MESSAGE_DLG DIALOGEX 0, 0, 320, 115
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    DEFPUSHBUTTON   "OK",ID_CUSTOM_OK,175,95,120,15
    PUSHBUTTON      "Cancel",ID_CUSTOM_CANCEL,45,95,120,15
    CTEXT           "Static",IDC_HEADER_TEXT,120,10,170,70
    CONTROL         "",IDC_LOGO,"Static",SS_BITMAP,16,10,83,70
END

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

Помогите ли вы с этим? Спасибо!

Ответы [ 3 ]

6 голосов
/ 09 февраля 2012

Больший размер легко объяснить. Windows автоматически изменяет размер диалога в соответствии со своим шрифтом, а в более крупном диалоге используется другой шрифт. Фактически, он использует системный шрифт по умолчанию (более подробную информацию о запутанной проблеме шрифтов диалогов Windows можно найти в моем ответе здесь ).

Таким образом, реальная проблема, на которой следует сосредоточиться, - это использование другого шрифта и исправление, которое решит проблему с размером.

В файле ресурсов диалогового окна вы указываете флаг DS_SETFONT в качестве одного из стилей диалогового окна. Согласно документации этот флаг

[i] указывает, что заголовок шаблона диалогового окна (стандартный или расширенный) содержит дополнительные данные, указывающие шрифт для текста в клиентской области и элементы управления диалогового окна. Если возможно, система выбирает шрифт в соответствии с указанными данными шрифта. Система передает дескриптор шрифта в диалоговое окно и каждому элементу управления, отправляя им сообщение WM_SETFONT.

Это объясняет, почему отображается с ожидаемым шрифтом.

Следующий логический вопрос: чем отличается динамически созданный шаблон диалога, показанный с помощью функции DialogBoxIndirect. Преступник, опять же, флаг DS_SETFONT, но в этом случае флаг отсутствует. Это означает, что диалоговое окно не содержит никакой информации о том, какой шрифт использовать для отображения своих элементов управления, и система по умолчанию использует системный шрифт по умолчанию (который является уродливым шрифтом эпохи Windows 2.0, который вы видите на втором снимке экрана).

Как только мы придем к этому пониманию, решение должно стать очевидным: вам нужно указать диалогу, какой шрифт вы хотите использовать. Есть два возможных способа сделать это:

  1. Вы можете установить флаг DS_SETFONT и предоставить информацию о шрифте в заголовке шаблона диалогового окна, как описано в приведенной выше документации.
  2. Или вы можете просто создать и установить шрифт диалога в ответ на сообщение WM_INITDIALOG.

Последнее, вероятно, то, что вы действительно хотите сделать, поскольку оно позволяет вам использовать фактический системный шрифт (который, как ни странно, отличается от того, что я называю "по умолчанию) " системный шрифт), который является Segoe UI в Windows Vista и более поздних версиях. Обратите внимание, что даже на первом скриншоте он использует MS Sans Serif и поэтому торчит, как больной большой палец в интерфейсе Aero. Опять же, смотрите этот ответ , чтобы узнать больше о шрифтах, чем вы когда-либо хотели знать, и пример кода для выполнения этой работы. Вам нужно убедиться, что вы установили шрифт для самого диалога и всех его дочерних элементов управления.

0 голосов
/ 02 июля 2015

Эту проблему можно решить в обработчике диалогов, найдя сообщение WM_INITDIALOG, а затем установив шрифт для всех элементов управления в диалоговом окне.

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

Я играл с DialogBoxIndirect (фактически с DialogBoxIndirectParam), и вот часть кода, которая устанавливает шрифт.Обратите внимание на параметр DS_SHELLFONT.

LPWORD lpwAlign(LPWORD lpIn, int nAlignment)
{
    return (LPWORD)(((ULONG_PTR)lpIn + nAlignment - 1) & -nAlignment);
}

LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, LPMYMESSAGEPARAMS pParams)
{
    WORD mem[1024];           // Buffer for dialog resource
    LPDLGTEMPLATEW lpdt;      // Pointer to heading resource structure
    LPDLGITEMTEMPLATEW lpdit; // Pointer to current control
    LPWORD lpw;               // Cursor to resource buffer
    LPWSTR lpwsz;             // Cursor to resource buffer (of type WCHAR)
    LPCWSTR lpwszCaption;     // Aux pointer for text copying
    LRESULT ret;              // Function's return value

    lpdt = (LPDLGTEMPLATEW)lpwAlign( mem, 4 );

    //-----------------------
    // Define a dialog box.
    //-----------------------
    lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION |
        DS_MODALFRAME | DS_CENTER | DS_SHELLFONT;
    lpdt->dwExtendedStyle = 0;
    lpdt->cdit = 3;  // number of controls
    lpdt->x  = 0;   lpdt->y  = 0;
    lpdt->cx = 164; lpdt->cy = 49;

    lpw = (LPWORD)(lpdt + 1);
    // Dialog menu
    *lpw++ = 0;
    // Dialog class
    *lpw++ = 0;
    // Dialog title
    for (lpwsz = (LPWSTR)lpw, lpwszCaption = L"Choose language";
        *lpwsz++ = *lpwszCaption++;
        );
    lpw = (LPWORD)lpwsz;
    // Dialog font
    if ( lpdt->style & (DS_SETFONT | DS_SHELLFONT) )
    {
        // Size
        *lpw++ = 8;
        // Typeface name
        for (lpwsz = (LPWSTR)lpw, lpwszCaption = L"MS Shell Dlg";
            *lpwsz++ = *lpwszCaption++;
            );
        lpw = (LPWORD)lpwsz;
    }


    // Define the rest of the controls
    ...

    ret = DialogBoxIndirectParamW( hinst, lpdt, 
        hwndOwner, MyMessageProc, (LPARAM)pParams );

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