// Copyright (C) 2015 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "qaxutils_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "qbstr_p.h" QT_BEGIN_NAMESPACE static inline QWindow *windowForWidget(QWidget *widget) { if (QWindow *window = widget->windowHandle()) return window; if (QWidget *nativeParent = widget->nativeParentWidget()) return nativeParent->windowHandle(); return nullptr; } HWND hwndForWidget(QWidget *widget) { if (QWindow *window = windowForWidget(widget)) return static_cast (QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", window)); return nullptr; } // Code courtesy of QWindowsXPStyle static void addRectToHrgn(HRGN &winRegion, const QRect &r) { HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); if (rgn) { HRGN dest = CreateRectRgn(0,0,0,0); int result = CombineRgn(dest, winRegion, rgn, RGN_OR); if (result) { DeleteObject(winRegion); winRegion = dest; } DeleteObject(rgn); } } HRGN qaxHrgnFromQRegion(const QRegion ®ion, const QWindow *window) { HRGN hRegion = CreateRectRgn(0, 0, 0, 0); for (const QRect &rect : QHighDpi::toNativeLocalRegion(region, window)) addRectToHrgn(hRegion, rect); return hRegion; } // HIMETRICS scaling static const qreal himetricsPerInch = 2540; static inline long qaxMapPixToLogHiMetrics(int x, qreal logicalDpi, qreal factor) { return qRound((qreal(x) * himetricsPerInch * factor) / logicalDpi); } static inline int qaxMapLogHiMetricsToPix(long x, qreal logicalDpi, qreal factor) { return qRound(logicalDpi * qreal(x) / (himetricsPerInch * factor)); } SIZEL qaxMapPixToLogHiMetrics(const QSize &s, const QDpi &d, const QWindow *w) { const qreal factor = QHighDpiScaling::factor(w); const SIZEL result = { qaxMapPixToLogHiMetrics(s.width(), d.first, factor), qaxMapPixToLogHiMetrics(s.height(), d.second, factor) }; return result; } QSize qaxMapLogHiMetricsToPix(const SIZEL &s, const QDpi &d, const QWindow *w) { const qreal factor = QHighDpiScaling::factor(w); const QSize result(qaxMapLogHiMetricsToPix(s.cx, d.first, factor), qaxMapLogHiMetricsToPix(s.cy, d.second, factor)); return result; } // Cache logical DPI in case High DPI scaling is active (which case // the fake logical DPI it calculates is not suitable). static QDpi cachedSystemLogicalDpi(-1, -1); void qaxClearCachedSystemLogicalDpi() // Call from WM_DISPLAYCHANGE { cachedSystemLogicalDpi = QDpi(-1, -1); } static inline QDpi systemLogicalDpi() { if (cachedSystemLogicalDpi.first < 0) { const HDC displayDC = GetDC(nullptr); cachedSystemLogicalDpi = QDpi(GetDeviceCaps(displayDC, LOGPIXELSX), GetDeviceCaps(displayDC, LOGPIXELSY)); ReleaseDC(nullptr, displayDC); } return cachedSystemLogicalDpi; } static inline QDpi paintDeviceLogicalDpi(const QPaintDevice *d) { return QDpi(d->logicalDpiX(), d->logicalDpiY()); } #ifdef QT_WIDGETS_LIB SIZEL qaxMapPixToLogHiMetrics(const QSize &s, const QWidget *widget) { return qaxMapPixToLogHiMetrics(s, QHighDpiScaling::isActive() ? systemLogicalDpi() : paintDeviceLogicalDpi(widget), widget->windowHandle()); } QSize qaxMapLogHiMetricsToPix(const SIZEL &s, const QWidget *widget) { return qaxMapLogHiMetricsToPix(s, QHighDpiScaling::isActive() ? systemLogicalDpi() : paintDeviceLogicalDpi(widget), widget->windowHandle()); } QPoint qaxFromNativePosition(const QWidget *w, const QPoint &nativePos) { const qreal factor = QHighDpiScaling::factor(w->windowHandle()); return qFuzzyCompare(factor, 1) ? nativePos : (QPointF(nativePos) / factor).toPoint(); } QPoint qaxNativeWidgetPosition(const QWidget *w) { return qaxFromNativePosition(w, w->geometry().topLeft()); } QSize qaxToNativeSize(const QWidget *w, const QSize &size) { const qreal factor = QHighDpiScaling::factor(w->windowHandle()); return qFuzzyCompare(factor, 1) ? size : (QSizeF(size) * factor).toSize(); } QSize qaxNativeWidgetSize(const QWidget *w) { return qaxToNativeSize(w, w->size()); } QSize qaxFromNativeSize(const QWidget *w, const QSize &size) { const qreal factor = QHighDpiScaling::factor(w->windowHandle()); return qFuzzyCompare(factor, 1) ? size : (QSizeF(size) / factor).toSize(); } RECT qaxNativeWidgetRect(const QWidget *w) { return QHighDpiScaling::isActive() ? qaxQRect2Rect(QRect(qaxNativeWidgetPosition(w), qaxNativeWidgetSize(w))) : qaxQRect2Rect(w->geometry()); } QRect qaxFromNativeRect(const RECT &r, const QWidget *w) { const QRect qr = qaxRect2QRect(r); const qreal factor = QHighDpiScaling::factor(w->windowHandle()); return qFuzzyCompare(factor, 1) ? qr : QRect((QPointF(qr.topLeft()) / factor).toPoint(), (QSizeF(qr.size()) / factor).toSize()); } HRGN qaxHrgnFromQRegion(const QRegion ®ion, const QWidget *widget) { return qaxHrgnFromQRegion(region, widget->windowHandle()); } #endif // QT_WIDGETS_LIB QByteArray qaxTypeInfoName(ITypeInfo *typeInfo, MEMBERID memId) { QByteArray result; QBStr names; UINT cNames = 0; typeInfo->GetNames(memId, &names, 1, &cNames); if (cNames && names) result = names.str().toLatin1(); return result; } QByteArrayList qaxTypeInfoNames(ITypeInfo *typeInfo, MEMBERID memId) { QByteArrayList result; QBStr bstrNames[256]; UINT maxNames = 255; UINT maxNamesOut = 0; typeInfo->GetNames(memId, reinterpret_cast(&bstrNames), maxNames, &maxNamesOut); result.reserve(maxNamesOut); for (UINT p = 0; p < maxNamesOut; ++p) result.append(bstrNames[p].str().toLatin1()); return result; } QT_END_NAMESPACE