Windows: Fix font metrics of Vista style wizards.

QVistaHelper::drawTitleBar() used the font returned by
QApplication::font("QMdiSubWindowTitleBar")
(typically "MS Shell Dlg 2",16) to calculate the
bounding rectangle of the title text. However, if the window
is a toplevel QVistaHelper::drawTitleText() uses the theme font
obtained for WIZ_TMT_CAPTIONFONT (typically "Segoe UI",11.25)
to draw the title (since it is a window title). This causes the
font to be cropped when changing the application font or spurious
black rectangles to occur.

Fix this by exposing QWindowsFontDatabase::LOGFONT_to_QFont() via
QWindowsNativeInterface, and creating a QFont from the LOGFONT
obtained for WIZ_TMT_CAPTIONFONT and using that for the
bounding rectangle in the case of toplevel windows.

Split up the HFONT QVistaHelper::getCaptionFont(HANDLE hTheme)
into static LOGFONT getCaptionLogFont(HANDLE hTheme) and use
that to obtain the HFONT in drawTitleText() or QFont in
static QFont getCaptionQFont(), respectively.

Task-number: QTBUG-46360
Change-Id: I9069b403f7f948b6738eec452cb7584be45b8a29
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
bb10
Friedemann Kleint 2015-05-28 10:00:45 +02:00
parent a47dbb010f
commit 0a7fcfd612
4 changed files with 43 additions and 16 deletions

View File

@ -34,6 +34,7 @@
#include "qwindowsnativeinterface.h"
#include "qwindowswindow.h"
#include "qwindowscontext.h"
#include "qwindowsfontdatabase.h"
#include "qwindowsopenglcontext.h"
#include "qwindowsopengltester.h"
#include "qwindowsintegration.h"
@ -222,6 +223,11 @@ int QWindowsNativeInterface::registerMimeType(const QString &mimeType)
return QWindowsMime::registerMimeType(mimeType);
}
QFont QWindowsNativeInterface::logFontToQFont(const void *logFont, int verticalDpi)
{
return QWindowsFontDatabase::LOGFONT_to_QFont(*reinterpret_cast<const LOGFONT *>(logFont), verticalDpi);
}
QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &function) const
{
if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())

View File

@ -34,6 +34,7 @@
#ifndef QWINDOWSNATIVEINTERFACE_H
#define QWINDOWSNATIVEINTERFACE_H
#include <QtGui/qfont.h>
#include <QtGui/qpa/qplatformnativeinterface.h>
QT_BEGIN_NAMESPACE
@ -77,6 +78,7 @@ public:
Q_INVOKABLE void registerWindowsMime(void *mimeIn);
Q_INVOKABLE void unregisterWindowsMime(void *mime);
Q_INVOKABLE int registerMimeType(const QString &mimeType);
Q_INVOKABLE QFont logFontToQFont(const void *logFont, int verticalDpi);
bool asyncExpose() const;
void setAsyncExpose(bool value);

View File

@ -361,6 +361,36 @@ bool QVistaHelper::setDWMTitleBar(TitleBarChangeType type)
Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
static LOGFONT getCaptionLogFont(HANDLE hTheme)
{
LOGFONT result = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } };
if (!hTheme || FAILED(pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &result))) {
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);
result = ncm.lfMessageFont;
}
return result;
}
static bool getCaptionQFont(int dpi, QFont *result)
{
if (!pOpenThemeData)
return false;
const HANDLE hTheme =
pOpenThemeData(QApplicationPrivate::getHWNDForWidget(QApplication::desktop()), L"WINDOW");
if (!hTheme)
return false;
// Call into QWindowsNativeInterface to convert the LOGFONT into a QFont.
const LOGFONT logFont = getCaptionLogFont(hTheme);
QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
return ni && QMetaObject::invokeMethod(ni, "logFontToQFont", Qt::DirectConnection,
Q_RETURN_ARG(QFont, *result),
Q_ARG(const void *, &logFont),
Q_ARG(int, dpi));
}
void QVistaHelper::drawTitleBar(QPainter *painter)
{
Q_ASSERT(backButton_);
@ -378,7 +408,9 @@ void QVistaHelper::drawTitleBar(QPainter *painter)
const int verticalCenter = (btnTop + btnHeight / 2) - 1;
const QString text = wizard->window()->windowTitle();
const QFont font = QApplication::font("QMdiSubWindowTitleBar");
QFont font;
if (!isWindow || !getCaptionQFont(wizard->logicalDpiY() * wizard->devicePixelRatio(), &font))
font = QApplication::font("QMdiSubWindowTitleBar");
const QFontMetrics fontMetrics(font);
const QRect brect = fontMetrics.boundingRect(text);
int textHeight = brect.height();
@ -649,19 +681,6 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event)
return false;
}
HFONT QVistaHelper::getCaptionFont(HANDLE hTheme)
{
LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } };
if (!hTheme || FAILED(pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &lf))) {
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);
lf = ncm.lfMessageFont;
}
return CreateFontIndirect(&lf);
}
// Return a HDC for the wizard along with the transformation if the
// wizard is a child window.
HDC QVistaHelper::backingStoreDC(const QWidget *wizard, QPoint *offset)
@ -713,7 +732,8 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q
bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
// Set up the DC
HFONT hCaptionFont = getCaptionFont(hTheme);
const LOGFONT captionLogFont = getCaptionLogFont(hTheme);
const HFONT hCaptionFont = CreateFontIndirect(&captionLogFont);
HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
HFONT hOldFont = (HFONT)SelectObject(dcMem, (HGDIOBJ) hCaptionFont);

View File

@ -105,7 +105,6 @@ public:
static HDC backingStoreDC(const QWidget *wizard, QPoint *offset);
private:
static HFONT getCaptionFont(HANDLE hTheme);
HWND wizardHWND() const;
bool drawTitleText(QPainter *painter, const QString &text, const QRect &rect, HDC hdc);
static bool drawBlackRect(const QRect &rect, HDC hdc);