Windows: Return high-DPI pixmaps from QWindowsTheme::standardPixmap

Most consumers feed the pixmaps into a QIcon, pulling out pixmaps
of sizes 32, 64, 128, 256, 512, so consumers of that QIcon will
not see low-resolution pixmaps for the common sizes like 64x64.

However if someone uses standardPixmap directly, or request an
icon with size 512x512, we won't have a high-DPI pixmap.

Unlike QStyle::standardPixmap we don't have a QWidget/QWindow
argument we can use to resolve the target DPR, so we have to
assume the pixmap can be used anywhere, and use the highest
DPR we've seen so far, via QGuiApplication::devicePixelRatio().

Pick-to: 6.9
Change-Id: Ib7fb08ab4932da1ca3f3325e25a7022c1cd17435
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Tor Arne Vestbø 2024-11-22 18:40:09 +01:00
parent 9b924a4907
commit 59bbfb17db

View File

@ -803,12 +803,12 @@ void QWindowsTheme::refreshIconPixmapSizes()
// Defined in qpixmap_win.cpp
Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon);
static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
static QPixmap loadIconFromShell32(int resourceId, QSize size)
{
if (const HMODULE hmod = QSystemLibrary::load(L"shell32")) {
auto iconHandle =
static_cast<HICON>(LoadImage(hmod, MAKEINTRESOURCE(resourceId),
IMAGE_ICON, int(size.width()), int(size.height()), 0));
IMAGE_ICON, size.width(), size.height(), 0));
if (iconHandle) {
QPixmap iconpixmap = qt_pixmapFromWinHICON(iconHandle);
DestroyIcon(iconHandle);
@ -818,7 +818,7 @@ static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
return QPixmap();
}
QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSize) const
QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
{
int resourceId = -1;
SHSTOCKICONID stockId = SIID_INVALID;
@ -907,16 +907,19 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
break;
}
const auto dpr = qGuiApp->devicePixelRatio(); // Highest in the system
if (stockId != SIID_INVALID) {
SHSTOCKICONINFO iconInfo;
memset(&iconInfo, 0, sizeof(iconInfo));
iconInfo.cbSize = sizeof(iconInfo);
stockFlags |= SHGSI_ICONLOCATION;
if (SHGetStockIconInfo(stockId, stockFlags, &iconInfo) == S_OK) {
const auto iconSize = pixmapSize.width();
const auto iconSize = size.width() * dpr;
HICON icon;
if (SHDefExtractIcon(iconInfo.szPath, iconInfo.iIcon, 0, &icon, nullptr, iconSize) == S_OK) {
QPixmap pixmap = qt_pixmapFromWinHICON(icon);
pixmap.setDevicePixelRatio(dpr);
DestroyIcon(icon);
return pixmap;
}
@ -924,13 +927,15 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
}
if (resourceId != -1) {
const QSize pixmapSize(size.width() * dpr, size.height() * dpr);
QPixmap pixmap = loadIconFromShell32(resourceId, pixmapSize);
if (!pixmap.isNull()) {
if (sp == FileLinkIcon || sp == DirLinkIcon || sp == DirLinkOpenIcon) {
QPainter painter(&pixmap);
QPixmap link = loadIconFromShell32(30, pixmapSize);
painter.drawPixmap(0, 0, int(pixmapSize.width()), int(pixmapSize.height()), link);
painter.drawPixmap(0, 0, pixmapSize.width(), pixmapSize.height(), link);
}
pixmap.setDevicePixelRatio(dpr);
return pixmap;
}
}
@ -943,7 +948,7 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
return pixmap;
}
return QPlatformTheme::standardPixmap(sp, pixmapSize);
return QPlatformTheme::standardPixmap(sp, size);
}
enum { // Shell image list ids