掉坑日志:Windows Native API与DPI缩放

高DPI显示器越来越普及,软件自然也要适应这个变化,最近实习的时候也遇到了一个关于DPI缩放的问题。因为内部框架的一个控件有BUG,会导致内容的显示出问题,后来实在没办法改成了用Windows Native API来自己定义字体,但是这一写就出问题了,本来在内部开发机100%放缩下好好的,一跑到我自己的WIN10,在2K屏放上缩放125%就字体就显示不正常了(字体变得过大)。

Window Vista以后的系统可以直接来个SetProcessDpiAwareness来控制程序的DPI问题,但是这个函数不是很好用,还是没有办法精确控制缩放,而且这个函数只有在Windows 8.1以上的系统才能用(SetProcessDPIAware也行,不过也必须是Windows Vista以上的系统),万一我们的程序需要在XP上运行呢?这就需要用另外一个办法了。

其实这个办法也很简单,就是用GetDeviceCaps来获取当前环境句柄的DPI就可以了,然后和默认的DPI(96)做运算,获得我们真正想要的DPI

case WM_PAINT:
{
      PAINTSTRUCT      ps;
      HDC hdc = BeginPaint(hwnd,&ps);

      auto curDPIX = GetDeviceCaps(hdc, LOGPIXELSX);
      auto curDPIY = GetDeviceCaps(hdc, LOGPIXELSY);

      std::wstring str(L"Hello World");

      LOGFONT lf;
      HGDIOBJ hObject;
      ZeroMemory(&lf, sizeof(LOGFONT));
      f.lfCharSet = GB2312_CHARSET;
      lf.lfWidth = MulDiv(20, 96, curDPIX);
      lf.lfHeight = MulDiv(55, 96, curDPIY);
      lf.lfPitchAndFamily = VARIABLE_PITCH;
      swprintf_s(lf.lfFaceName, _countof(lf.lfFaceName), L"微软雅黑");

      hObject = SelectObject(hdc, CreateFontIndirect(&lf));
      TextOut(hdc, 21, 100, str.data(), str.length());
      DeleteObject(SelectObject(hdc, hObject));

       lf.lfWidth = 20;
       lf.lfHeight = 55;

       hObject = SelectObject(hdc, CreateFontIndirect(&lf));
      TextOut(hdc, 21, 200, str.data(), str.length());
       DeleteObject(SelectObject(hdc, hObject));

       EndPaint(hwnd, &ps);
       return 0;
}

这里演示的是在屏幕上输出Hello Wolrd,现在假设我们的字体被放大了,但是假设我们其他控件没有被放大,那么字在控件里面就会显示不正常,这个时候就要缩小字的尺寸,要想和100%的时候类似,就需要MulDiv(尺寸, 96, curDPI);一下,字体被缩小了同理

这下我们可以看到,第二行是在120%放大下被放大的高度为55,宽度为22的字体,字体偏大,我们通过上面的方法,把字体缩小回正常的尺寸

时间: 2024-11-05 15:09:36

掉坑日志:Windows Native API与DPI缩放的相关文章

用Windows Native API枚举所有句柄及查找文件句柄对应文件名的方法

枚举所有句柄的方法 由于windows并没有给出枚举所有句柄所用到的API,和进程所拥有的句柄相关的只有GetProcessHandleCount这个函数,然而这个函数只能获取到和进程相关的句柄数,不能获取到实际的句柄,要获得句柄,我们必须使用未公开的Native API才可以. PS:网上有很多关于这类的方法,但几乎都是抄来抄去,很多连编译都过不了就直接放上去了(囧).我整理了一下方法,实测在win10和win7都可以用. NTSTATUS WINAPI NtQuerySystemInform

Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)

文章目录:                   1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Application 有何妙用: 5. MJ0011 关于 Native Application 的文章整理: 6. 互联网上其他关于 Native Application 的文章整理: 7. 小结: 1. 引子: 其实在好久以前就看了 MJ0011 翻译的那个<Native 应用程序详细>系列的文

使用Tcl脚本调用STC平台的Native API实现测试对象、Device、StreamBlock的创建和配置

环境配置如下: 在Windows的Conmand下操作 # # Configuration file(CommonConFig.tcl) # # Initializing the Script. # This script is used to set common configuration paramters used with the STC-300 class. #Step 1: Load Spirent TestCenter Automation API. # Type in the

不可或缺 Windows Native (22) - C++: 多重继承, 虚基类

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 多重继承 虚基类 示例1.基类 1CppBase1.h #pragma once #include <string> #include "CppBaseVirtual.h" using namespace std; namespace NativeDll { // virtual 代表 CppBaseVirtual 是 CppBase1 的虚基类(虚基类是在声明派生类时,指定继承方式

Windows录音API学习笔记--转

Windows录音API学习笔记 结构体和函数信息  结构体 WAVEINCAPS 该结构描述了一个波形音频输入设备的能力. typedef struct { WORD      wMid; 用于波形音频输入设备的设备驱动程序制造商标识符. WORD      wPid; 声音输入设备的产品识别码. MMVERSION vDriverVersion; 用于波形音频输入设备的设备驱动程序的版本号.高位字节是主版本号,低字节是次版本号. CHAR      szPname[MAXPNAMELEN];

windows内核Api的学习

windows内核api就是ntoskrnl.exe导出的函数.我们可以跟调用应用层的api一样,调用内核api.不过内核api需要注意的是,如果函数导出了,并且函数文档化(也就是可以直接在msdn上搜索到).ExFreePool函数导出,并且文档化,那么我们可以直接调用.导出了未文档化,那么我们就要声明.什么叫文档化和未文档化呢?大家来看一个函数: UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); 文档化:就是假设函数导出了,并且在

掉坑里了,小心

今天公司产品一个功能突然挂掉了...向客户演示之前出现了,手机端显示不能获取下载资源,可是急坏了一票人.. 通过手机端,调查服务器地址调用了http:/2342342.domain.hostname.cn/apis/stickydataurls/接口,服务器返回502和500错误,去查看服务器前端Nginx错误日志显示: 2014/08/13 16:11:00 [error] 23851#0: *10303771 connect() failed (111: Connection refused

Windows录音API学习笔记(转)

源:Windows录音API学习笔记 Windows录音API学习笔记 结构体和函数信息  结构体 WAVEINCAPS 该结构描述了一个波形音频输入设备的能力. typedef struct { WORD      wMid; 用于波形音频输入设备的设备驱动程序制造商标识符. WORD      wPid; 声音输入设备的产品识别码. MMVERSION vDriverVersion; 用于波形音频输入设备的设备驱动程序的版本号.高位字节是主版本号,低字节是次版本号. CHAR      sz

Unity在Android和iOS中如何调用Native API

本文主要是对unity中如何在Android和iOS中调用Native API进行介绍. 首先unity支持在C#中调用C++ dll,这样可以在Android和iOS中提供C++接口在unity中调用.利用这一特性,可以扩展unity的功能.例如集成和调用第三方库.同时为了满足对unity接口的一致性,可以考虑在android和iOS上提供相同的接口供C#调用. 这里列举以下两个例子. 1. 1. 以弹出一个覆盖部分屏幕的webview为例来说明如何从C#调用Native接口. 2. 2. 简