当前位置: 首页 > news >正文

获取DPI、设置进程DPI感知(C++源码)

1、概述

本文实现如下功能:
1、设置进程 DPI 感知(告诉系统,程序自己处理dpi变化,不要拉伸我的界面)
2、获取系统或窗口所在显示器的 DPI
3、查询其他进程的 DPI 感知状态

2、源码

2.1、调用示例

    // 调用示例// 获取dpidpiUtil::InitDpiAPIFunc();dpiUtil::SetProcessDpiAware();UINT dpi = dpiUtil::GetDpiFromSystem();std::cout << "dpi:" << dpi << std::endl;HWND hwWxWork = FindWindowW(L"WeWorkWindow", L"企业微信");dpi = dpiUtil::GetDpiFromWindow(hwWxWork);std::cout << "dpi:" << dpi << std::endl;

2.2、源码

#ifndef dpi_util_h_
#define dpi_util_h_#include <windows.h>
#include <shellscalingapi.h>class dpiUtil
{
public:// 初始化dpistatic void InitDpiAPIFunc();// 获取系统dpistatic UINT GetDpiFromSystem();// 获取窗口对应显示器的dpistatic UINT GetDpiFromWindow(HWND hWnd);// 设置进程DPI感知(告诉系统,程序自己处理dpi变化,不要拉伸我的界面)// 在程序的入口处调用, DPI感知设置必须在创建第一个窗口前完成static bool SetProcessDpiAware();// 获取进程是否DPI感知static bool GetProcessDpiAwareness(DWORD pid, PROCESS_DPI_AWARENESS& awareness);
};#endif
#include "dpiUtil.h"
#include <memory>
#include "WinVerUtil.h"using funGetDpiForSystem = UINT(WINAPI*)(VOID);
using funGetDpiForWindow = UINT(WINAPI*)(HWND hwnd);
using funGetDpiForMonitor = HRESULT(__stdcall *)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*);
using funSetProcessDpiAwarenessContext = BOOL(__stdcall *)(DPI_AWARENESS_CONTEXT);
using funSetProcessDpiAwareness = HRESULT(__stdcall *)(PROCESS_DPI_AWARENESS);
using funSetProcessDPIAware = BOOL(__stdcall *)();
using funGetProcessDpiAwareness = HRESULT(__stdcall*)(HANDLE, PROCESS_DPI_AWARENESS*);funGetDpiForSystem g_fnGetDpiForSystem = nullptr;
funGetDpiForWindow g_fnGetDpiForWindow = nullptr;
funGetDpiForMonitor g_fnGetDpiForMonitor = nullptr;
funSetProcessDpiAwarenessContext g_fnSetProcessDpiAwarenessContext = nullptr;
funSetProcessDpiAwareness g_fnSetProcessDpiAwareness = nullptr;
funSetProcessDPIAware g_fnSetProcessDPIAware = nullptr;
funGetProcessDpiAwareness g_fnGetProcessDpiAwareness = nullptr;template <typename T>
bool GetFuncPtr(HMODULE h, T& ptr, const char* funcName)
{auto funcPtr = reinterpret_cast<T>(::GetProcAddress(h, funcName));if (funcPtr){ptr = funcPtr;return true;}return false;
}void dpiUtil::InitDpiAPIFunc()
{if (WinVerUtil::IsWindows10OrGreater()){HMODULE hUser32 = ::GetModuleHandle(L"user32.dll");if (hUser32 != nullptr){GetFuncPtr(hUser32, g_fnGetDpiForSystem, "GetDpiForSystem");GetFuncPtr(hUser32, g_fnGetDpiForWindow, "GetDpiForWindow");GetFuncPtr(hUser32, g_fnSetProcessDpiAwarenessContext, "SetProcessDpiAwarenessContext");GetFuncPtr(hUser32, g_fnSetProcessDPIAware, "SetProcessDPIAware");}}HMODULE hShcore = ::GetModuleHandle(L"shcore.dll");if (hShcore == nullptr){hShcore = ::LoadLibrary(L"shcore.dll");}if (hShcore != nullptr){GetFuncPtr(hShcore, g_fnGetDpiForMonitor, "GetDpiForMonitor");GetFuncPtr(hShcore, g_fnSetProcessDpiAwareness, "SetProcessDpiAwareness");GetFuncPtr(hShcore, g_fnGetProcessDpiAwareness, "GetProcessDpiAwareness");}
}UINT dpiUtil::GetDpiFromSystem()
{// win10 version 1703支持的api,返回主显示器的dpi// GetDpiForSystem() 返回主显示器的逻辑 DPI,但其值受进程 DPI Awareness 模式影响// 若进程未声明高 DPI 感知(默认为 Unaware),Windows 会启用 DPI 虚拟化,// 强制所有 DPI API 返回 96(即使系统缩放设为 125%),并由系统拉伸界面(导致模糊)// 要获取真实 DPI,必须通过SetProcessDpiAwarenessContext 声明 DPI 感知if (g_fnGetDpiForSystem != nullptr){return g_fnGetDpiForSystem();}// 降级方案:用GDI的GetDeviceCapsUINT dpi = 96;// 返回整个屏幕(桌面窗口) 的DCHDC hdc = ::GetDC(nullptr);if (hdc != nullptr){dpi = ::GetDeviceCaps(hdc, LOGPIXELSX);::ReleaseDC(nullptr, hdc);}return dpi;
}UINT dpiUtil::GetDpiFromWindow(HWND hWnd)
{if (!::IsWindow(hWnd)){return GetDpiFromSystem();}// GetDpiForWindow() 返回主显示器的逻辑 DPI,但其值受进程 DPI Awareness 模式影响// 若进程未声明高 DPI 感知(默认为 Unaware),Windows 会启用 DPI 虚拟化,// 强制所有 DPI API 返回 96(即使系统缩放设为 125%),并由系统拉伸界面(导致模糊)// 要获取真实 DPI,必须通过SetProcessDpiAwarenessContext 声明 DPI 感知if (g_fnGetDpiForWindow != nullptr){auto dpi = g_fnGetDpiForWindow(hWnd);if (dpi > 0){return dpi;}}if (g_fnGetDpiForMonitor != nullptr){UINT dpiX = 0;UINT dpiY = 0;if (SUCCEEDED(g_fnGetDpiForMonitor(::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), MDT_EFFECTIVE_DPI, &dpiX, &dpiY)) && dpiX != 0 && dpiY != 0){return dpiX;}}return GetDpiFromSystem();
}bool dpiUtil::SetProcessDpiAware()
{// win10if (g_fnSetProcessDpiAwarenessContext != nullptr){if (g_fnSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)){return true;}if (g_fnSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)){return true;}}// win8.1if (g_fnSetProcessDpiAwareness != nullptr){if (SUCCEEDED(g_fnSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE))){return true;}}// vista+if (g_fnSetProcessDPIAware != nullptr){if (g_fnSetProcessDPIAware()){return true;}}return false;
}bool dpiUtil::GetProcessDpiAwareness(DWORD pid, PROCESS_DPI_AWARENESS& awareness)
{if (g_fnGetProcessDpiAwareness == nullptr){return false;}HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);if (!hProcess) {return false;}bool success = SUCCEEDED(g_fnGetProcessDpiAwareness(hProcess, &awareness));::CloseHandle(hProcess);return success;
}

http://www.dtcms.com/a/582428.html

相关文章:

  • 时间序列图的“性能陷阱”:Highcharts “金融级”优化方案
  • 网站开发的方法和步骤网站构成的作用是什么
  • 6、prometheus资源规划
  • 淄博哪有做网站的wordpress无头像
  • 在 DigitalOcean GPU 云服务上使用 LangChain 构建Serverless AI 应用
  • 【生活技术分享】基于“稀释-增香”原理的波特酒风味优化方案
  • 如何做国外假发网站优秀的图片设计网站
  • C++笔记-23-类和对象-多态
  • 网站开发有哪些方向微信小程序开通要钱吗
  • 网站开发技术架构南京网站设计平台
  • CSS 导航栏
  • html5 网站正在建设中网页设计 html
  • 拓扑排序深入
  • docker部署kafka
  • 【镜中异客:AI与人类的禁忌之舞】
  • 微信网站模版下载新闻类网站源码
  • 手机网站滑动效果深圳一公司今年成立16家核检机构
  • 面向强化学习的状态空间建模:RSSM和PyTorch(3)
  • #Prometheus 权威指南:云原生监控的技术架构与实践精髓
  • Android11-Launcher3 定制-去除副屏幕-可以滑动效果
  • 通风管道部件-图形识别更快捷
  • 黄浦网站制作那个网站可以做雪花特效
  • 万网站底部添加备案号wordpress如何更换主机
  • MongoDB 与 Java 实体类型 LocalTime 时区转换问题解决方案
  • Linux 文件软硬链接详解
  • 青海城乡和住房建设厅网站后台更改公司网站背景图片
  • 烟台营销型网站建设怎么做网站的学校的大图
  • 随笔-随便写了
  • IEC61850 标准分析(第三部分)
  • Zabbix7添加监控主机