MFC: динамически изменять размер управляющего шрифта?

#mfc #fonts

#mfc #шрифты

Вопрос:

У меня есть класс CListCtrl, который я хотел бы иметь возможность легко изменять размер шрифта. Я подкласс CListCtrl как MyListControl. Я могу успешно установить шрифт, используя этот код в обработчике событий PreSubclassWindow:

 void MyListControl::PreSubclassWindow()
{
    CListCtrl::PreSubclassWindow();

    // from http://support.microsoft.com/kb/85518
    LOGFONT lf;                        // Used to create the CFont.

    memset(amp;lf, 0, sizeof(LOGFONT));   // Clear out structure.
    lf.lfHeight = 20;                  // Request a 20-pixel-high font
    strcpy(lf.lfFaceName, "Arial");    //    with face name "Arial".
    font_.CreateFontIndirect(amp;lf);    // Create the font.
    // Use the font to paint a control.
    SetFont(amp;font_);
}
  

Это работает. Однако то, что я хотел бы сделать, это создать метод с именем SetFontSize(int size), который просто изменит существующий размер шрифта (оставив лицо и другие характеристики как есть). Поэтому я считаю, что для этого метода потребуется получить существующий шрифт, а затем изменить размер шрифта, но мои попытки сделать это не увенчались успехом (это убивает мою программу):

 void MyListControl::SetFontSize(int pixelHeight)
{
    LOGFONT lf;                        // Used to create the CFont.

    CFont *currentFont = GetFont();
    currentFont->GetLogFont(amp;lf);
    LOGFONT lfNew = lf;
    lfNew.lfHeight = pixelHeight;                  // Request a 20-pixel-high font
    font_.CreateFontIndirect(amp;lf);    // Create the font.

    // Use the font to paint a control.
    SetFont(amp;font_);

}
  

Как я могу создать этот метод?

Комментарии:

1. Каким образом это «убивает» вашу программу?

2. Существует ошибка mfc ASSERT, которая завершается с ошибкой.

Ответ №1:

Я нашел рабочее решение. Я открыт для предложений по улучшению:

 void MyListControl::SetFontSize(int pixelHeight)
{
    // from http://support.microsoft.com/kb/85518
    LOGFONT lf;                        // Used to create the CFont.

    CFont *currentFont = GetFont();
    currentFont->GetLogFont(amp;lf);
    lf.lfHeight = pixelHeight;
    font_.DeleteObject();
    font_.CreateFontIndirect(amp;lf);    // Create the font.

    // Use the font to paint a control.
    SetFont(amp;font_);
}
  

Два ключа к тому, чтобы заставить это работать, были:

  1. Удаление копии шрифта журнала, lfNew.
  2. Вызов font_.DeleteObject(); перед созданием нового шрифта. По-видимому, уже не может быть существующего объекта шрифта. В коде MFC есть некоторое УТВЕРЖДЕНИЕ, которое проверяет наличие существующего указателя. Это УТВЕРЖДЕНИЕ является причиной сбоя моего кода.

Комментарии:

1. Что такое font_ ? Это не объявлено.

2. font_ имеет тип CFont и является переменной-членом моего класса MyListControl .

3. font_. DeleteObject() — это реальная экономия времени. В wingdi.cpp примерно в строке 1113, которая проверяет наличие существующего прикрепленного объекта.