2016-03-16 2 views
2

У меня возникли проблемы с некоторыми из моих владельцев, нарисованными списками на мониторах с высоким разрешением DPI в Windows 10 в диалоговом окне. Текст отрублен внизу. Мы видели проблему в Windows 7 и смогли ее исправить. Это не обязательно высокий DPI, но когда пользователь устанавливает другое масштабирование текста. Я решил проблему, поэтому я подумал (!), Используя CClientDC (обертка вокруг GetDC()) и вызывая GetTextMetrics(), чтобы определить высоту текста. Раньше наши значки всегда были выше нашего текста, поэтому это не проблема. С более крупными мониторами DPI мы видели, как некоторые клиенты сообщали о проблемах при масштабировании текста.Различия между GetDC() и BeginPaint()?

Теперь мы получаем новые отчеты под Windows 10. Первая проблема хорошо под Windows 7, но Windows 7 только масштабируется до 100, 125 и 150 процентов. Windows 10 (и, возможно, 8? - но без отчетов клиентов) позволяет определять масштабирование пользователя.

Итак, я несколько раз обнаружил проблему ... Я знал, что такое высота шрифта, когда я вызывал GetTextMetrics() во время WM_MEASUREITEM. Я пошел и добавил код для отладки того, что GetTextMetrics() было во время моего WM_DRAWITEM. Ну, они были разные - 20 пикселей в высоту во время WM_MEASUREITEM и 25 пикселей в высоту во время WM_DRAWITEM. Очевидно, что это проблема. Я хочу, чтобы GetTextMetrics() имел одинаковые результаты в обоих местах.

Я думал, что единственная реальная разница, о которой я мог думать, заключалась в том, что во время WM_MEASUREITEM я вызываю GetDC() через конструктор CClientDC, а во время WM_DRAWITEM я использую уже построенный HDC (который, вероятно, был из возврата GetPaint() внутри GDI32.dll или другой DLL системы).

Я думал, что, может быть, BeginPaint() делает что-то, как выбрать окна HFONT в HDC ...

Итак, в моем WM_MEASUREITEM после получения DC, я выбираю шрифт ListBox в HDC, и то я вызываю GetTextMetrics(). И вот, числа теперь совпадают в WM_MEASUREITEM и WM_DRAWITEM.

Однако, я не знаю, удался ли мне просто. На данный момент это всего лишь догадки.

Does BeginPaint() выбирает шрифт окна в DC, тогда как GetDC() не работает? Использует ли обработчик по умолчанию WM_PAINT для владельца, нарисованный LISTBOX или COMBOBOX, что-то вроде выбора шрифта окна в краску DC?

BOOL DpiAwareMeasureGraphItem(LPMEASUREITEMSTRUCT lpM, CWnd* pWnd) 
{ 
    int iItemHeight = INTERG_BITMAP_HEIGHT + 4; 

    if (pWnd) 
    { 
     CClientDC dc(pWnd); 
     if (dc.GetSafeHdc()) 
     { 
     CFont* pOldFont = dc.SelectObject(pWnd->GetFont()); // seems to fix it on Windows 10, but is it luck? 

     TEXTMETRIC tm; 
     memset(&tm, 0, sizeof(tm)); 
     dc.GetTextMetrics(&tm); 
     LONG tmHeight = tm.tmHeight + 4; //pad 

     iItemHeight = max(iItemHeight, tmHeight); 

     dc.SelectObject(pOldFont); 
     } 
    } 

    lpM->itemHeight = iItemHeight; 

    return (TRUE); 
} 
+1

Windows 7, даже Vista, позволяет определять размер шрифта, заданного пользователем –

+0

Спасибо. Я пошел в настройки, чтобы «доказать, что вы ошибаетесь», потому что я никогда его не видел. Затем я посмотрел на левую панель и увидел обстановку, которую я никогда раньше не видел. –

ответ

3

Ни GetDC() или BeginPaint() Инициализируем DC они возвращаются ни с чем системного шрифта по умолчанию в. Но WM_DRAWITEM отличается - он дает вам уже инициализированный DC для рисования.

Метод, которым вы наткнулись, является правильным. WM_MEASUREITEM не содержит DC, поэтому, если вам нужен один для расчета размера, вы несете ответственность за его получение и настройку соответствующего шрифта.

Смежные вопросы