Core Frmaework Components
The high DPI scaling solution revolves around three key components:
- DPI Change Detection Interface (ICallDPIChanged)
- DPI Management System (IDPIHelper)
- Floating Widget Controller
DPI Change Detection Interface
struct DPIChangeHandler {
virtual void handleScaleChange(float newScale) = 0;
virtual WindowID getWindowID() const = 0;
virtual void updateScale(float scale) = 0;
};
DPI Management System
const float BASE_DPI = 96.0f;
struct DPIManager {
virtual bool handleDPIChange(unsigned short dpi, WindowID window) = 0;
virtual void removeWindowRecord(WindowID window) = 0;
virtual float getCurrentScale(WindowID window) const = 0;
virtual float getPreviousScale(WindowID window) const = 0;
virtual QString getStyleContent(WindowID window) const = 0;
virtual float getScaledValue(float value, WindowID window) const = 0;
};
Implementation Strategy
Window Size Adaptation
class ScaledWidget : public QWidget, public DPIChangeHandler {
Q_OBJECT
public:
void resize(int width, int height) override {
sizeFlags |= SizeAction::Resize;
baseSize = QSize(width, height);
QWidget::resize(baseSize * currentScale);
}
// Other size-related overrides...
};
Font Scaling
QString scaleStyleSheet(const QString& original, float scale) {
if (qFuzzyCompare(scale, 1.0f)) return original;
QString scaled = original;
QRegularExpression sizePattern("\\d+px");
auto match = sizePattern.match(scaled);
while (match.hasMatch()) {
int pxValue = match.captured().replace("px", "").toInt();
int scaledValue = qRound(pxValue * scale);
scaled.replace(match.capturedStart(), match.capturedLength(),
QString::number(scaledValue) + "px");
match = sizePattern.match(scaled, match.capturedEnd());
}
return scaled;
}
Icon Handling
float calculateImageScaleFactor(float dpiScale) {
if (dpiScale < 1.5f) return dpiScale;
if (dpiScale < 2.5f) return dpiScale / 2;
if (dpiScale < 3.5f) return dpiScale / 3;
return dpiScale / 3; // Default to 3x scaling
}
Floating Widget Management
class FloatingWidgetController : public QObject {
Q_OBJECT
public:
static FloatingWidgetController* instance();
void registerWidget(QWidget* widget);
void notifyDPIChange(WindowID window, float newScale);
private:
QSet<DPIChangeHandler*> managedWidgets;
};