掉坑日志: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的字体,字体偏大,我们通过上面的方法,把字体缩小回正常的尺寸

 

转载于:https://www.cnblogs.com/Philip-Tell-Truth/p/7290545.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值