mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
130 lines
3.9 KiB
C++
130 lines
3.9 KiB
C++
#include "dpi_utils.h"
|
|
|
|
namespace flutter {
|
|
|
|
namespace {
|
|
|
|
constexpr UINT kDefaultDpi = 96;
|
|
|
|
// This is the MDT_EFFECTIVE_DPI value from MONITOR_DPI_TYPE, an enum declared
|
|
// in ShellScalingApi.h. Replicating here to avoid importing the library
|
|
// directly.
|
|
constexpr UINT kEffectiveDpiMonitorType = 0;
|
|
|
|
template <typename T>
|
|
|
|
/// Retrieves a function |name| from a given |comBaseModule| into |outProc|.
|
|
/// Returns a bool indicating whether the function was found.
|
|
bool AssignProcAddress(HMODULE comBaseModule, const char* name, T*& outProc) {
|
|
outProc = reinterpret_cast<T*>(GetProcAddress(comBaseModule, name));
|
|
return *outProc != nullptr;
|
|
}
|
|
|
|
/// A helper class for abstracting various Windows DPI related functions across
|
|
/// Windows OS versions.
|
|
class Win32DpiHelper {
|
|
public:
|
|
Win32DpiHelper();
|
|
|
|
~Win32DpiHelper();
|
|
|
|
/// Returns the DPI for |hwnd|. Supports all DPI awareness modes, and is
|
|
/// backward compatible down to Windows Vista. If |hwnd| is nullptr, returns
|
|
/// the DPI for the primary monitor. If Per-Monitor DPI awareness is not
|
|
/// available, returns the system's DPI.
|
|
UINT GetDpiForWindow(HWND);
|
|
|
|
/// Returns the DPI of a given monitor. Defaults to 96 if the API is not
|
|
/// available.
|
|
UINT GetDpiForMonitor(HMONITOR);
|
|
|
|
private:
|
|
using GetDpiForWindow_ = UINT __stdcall(HWND);
|
|
using GetDpiForMonitor_ = HRESULT __stdcall(HMONITOR hmonitor,
|
|
UINT dpiType,
|
|
UINT* dpiX,
|
|
UINT* dpiY);
|
|
using EnableNonClientDpiScaling_ = BOOL __stdcall(HWND hwnd);
|
|
|
|
GetDpiForWindow_* get_dpi_for_window_ = nullptr;
|
|
GetDpiForMonitor_* get_dpi_for_monitor_ = nullptr;
|
|
EnableNonClientDpiScaling_* enable_non_client_dpi_scaling_ = nullptr;
|
|
|
|
HMODULE user32_module_ = nullptr;
|
|
HMODULE shlib_module_ = nullptr;
|
|
bool dpi_for_window_supported_ = false;
|
|
bool dpi_for_monitor_supported_ = false;
|
|
};
|
|
|
|
Win32DpiHelper::Win32DpiHelper() {
|
|
if ((user32_module_ = LoadLibraryA("User32.dll")) != nullptr) {
|
|
dpi_for_window_supported_ = (AssignProcAddress(
|
|
user32_module_, "GetDpiForWindow", get_dpi_for_window_));
|
|
}
|
|
if ((shlib_module_ = LoadLibraryA("Shcore.dll")) != nullptr) {
|
|
dpi_for_monitor_supported_ = AssignProcAddress(
|
|
shlib_module_, "GetDpiForMonitor", get_dpi_for_monitor_);
|
|
}
|
|
}
|
|
|
|
Win32DpiHelper::~Win32DpiHelper() {
|
|
if (user32_module_ != nullptr) {
|
|
FreeLibrary(user32_module_);
|
|
}
|
|
if (shlib_module_ != nullptr) {
|
|
FreeLibrary(shlib_module_);
|
|
}
|
|
}
|
|
|
|
UINT Win32DpiHelper::GetDpiForWindow(HWND hwnd) {
|
|
// GetDpiForWindow returns the DPI for any awareness mode. If not available,
|
|
// or no |hwnd| is provided, fallback to a per monitor, system, or default
|
|
// DPI.
|
|
if (dpi_for_window_supported_ && hwnd != nullptr) {
|
|
return get_dpi_for_window_(hwnd);
|
|
}
|
|
|
|
if (dpi_for_monitor_supported_) {
|
|
HMONITOR monitor = nullptr;
|
|
if (hwnd != nullptr) {
|
|
monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
|
|
}
|
|
return GetDpiForMonitor(monitor);
|
|
}
|
|
HDC hdc = GetDC(hwnd);
|
|
UINT dpi = GetDeviceCaps(hdc, LOGPIXELSX);
|
|
ReleaseDC(hwnd, hdc);
|
|
return dpi;
|
|
}
|
|
|
|
UINT Win32DpiHelper::GetDpiForMonitor(HMONITOR monitor) {
|
|
if (dpi_for_monitor_supported_) {
|
|
if (monitor == nullptr) {
|
|
const POINT target_point = {0, 0};
|
|
monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTOPRIMARY);
|
|
}
|
|
UINT dpi_x = 0, dpi_y = 0;
|
|
HRESULT result =
|
|
get_dpi_for_monitor_(monitor, kEffectiveDpiMonitorType, &dpi_x, &dpi_y);
|
|
if (SUCCEEDED(result)) {
|
|
return dpi_x;
|
|
}
|
|
}
|
|
return kDefaultDpi;
|
|
} // namespace
|
|
|
|
Win32DpiHelper* GetHelper() {
|
|
static Win32DpiHelper* dpi_helper = new Win32DpiHelper();
|
|
return dpi_helper;
|
|
}
|
|
} // namespace
|
|
|
|
UINT GetDpiForHWND(HWND hwnd) {
|
|
return GetHelper()->GetDpiForWindow(hwnd);
|
|
}
|
|
|
|
UINT GetDpiForMonitor(HMONITOR monitor) {
|
|
return GetHelper()->GetDpiForMonitor(monitor);
|
|
}
|
|
} // namespace flutter
|