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

Winforms: 为什么Graphics.DpiX/DpiY总是返回96

一、问题描述

Windows中缺省的DPI值为96。在Vista中,我们把DPI设为150%,也就是144。可如果此时我们去获取属性System.Drawing.Graphics.DpiX或者System.Drawing.Graphics.DpiY的值,我们发现得到的仍然是96,而不是144

二、原因分析

修改WindowsDPI值,所有窗口的字体会变大,因此窗口的布局(Layout)也有可能不同。Windows程序员可以根据WindowsDPI设置去定义窗口的布局,但我们发现很多程序员在根据DPI定义窗口布局的时候遇到了很多问题。所以Windows的解决办法就是不建议程序员根据DPI设置调整窗口布局,Windows会根据系统设置自动按比例放大窗口的所有元素(包括文字和控件)。这样虽然降低了程序员的灵活性和自主性,但至少保证了窗口布局在所有DPI设置时都是正确的。

于是从Vista开始,Windows添加了一个叫SetProcessDPIAwareAPI。缺省的情况下,该函数不被调用,因此我们的进程不知道DPI已经修改,那我们得到的DPI也总是其缺省值96了。

三、建议

如前所述,我们不建议程序员试图去获取DPI设置值,并根据该值去调整窗口布局。如果确实需要得到系统的DPI的设置值,我们必须调用API SetProcessDPIAware。下面是一个例子:

public class Utility

{

private const int LOGPIXELSX = 88;

private const int LOGPIXELSY = 90;

public static int DpiX

{

get

{

if (Environment.OSVersion.Version.Major >= 6)

SetProcessDPIAware();

IntPtr hDC = GetDC(new HandleRef(null, IntPtr.Zero));

return GetDeviceCaps(hDC, LOGPIXELSX);

}

}

public static int DpiY

{

get

{

if (Environment.OSVersion.Version.Major >= 6)

SetProcessDPIAware();

IntPtr hDC = GetDC(new HandleRef(null, IntPtr.Zero));

return GetDeviceCaps(hDC, LOGPIXELSY);

}

}

[DllImport("user32.dll")]

private extern static bool SetProcessDPIAware();

[DllImport("user32.dll")]

private extern static IntPtr GetDC(HandleRef hWnd);

[DllImport("gdi32.dll")]

private extern static int GetDeviceCaps(IntPtr hdc, int nIndex);

}

上述代码先得到显示器的DC,然后得到该DCX方向和Y方向的DPI值。另外值得注意的是,由于API SetProcessDPIAwareVista才被引入,所以在调用该API之前,我们需要判断Windows的版本号。Vista的主版本号是6

相关文章:

  • Swift 无操作时自动登出
  • SQL 死锁进程查看与处理
  • SQL Server进程阻塞的检查和解决办法
  • Azure 软件架构选择
  • Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)
  • 简单说说什么是Restful
  • Flex与.NET互操作(十三):FluorineFx.Net实现视频录制与视频回放
  • Swift中的本地化实现
  • Azure .Net应用架构原型
  • Nebula3中的委托(Delegate)
  • 使用微软T4 template进行代码生成
  • ora-12537教训
  • Asp.Net MVC webAPI Token based authentication
  • Asp.Net 2.0 TreeView的Checkbox级联操作
  • azure最佳实践系列1-自我修复的设计
  • java中具有继承关系的类及其对象初始化顺序
  • jquery ajax学习笔记
  • js面向对象
  • MySQL的数据类型
  • React-redux的原理以及使用
  • redis学习笔记(三):列表、集合、有序集合
  • Twitter赢在开放,三年创造奇迹
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 基于axios的vue插件,让http请求更简单
  • 前端
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • 一个完整Java Web项目背后的密码
  • 智能合约开发环境搭建及Hello World合约
  • 进程与线程(三)——进程/线程间通信
  • #单片机(TB6600驱动42步进电机)
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (十六)串口UART
  • (一)u-boot-nand.bin的下载
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET委托:一个关于C#的睡前故事
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • @ResponseBody
  • [AIGC] MySQL存储引擎详解
  • [Android]RecyclerView添加HeaderView出现宽度问题
  • [Android]一个简单使用Handler做Timer的例子
  • [BUUCTF NewStarCTF 2023 公开赛道] week4 crypto/pwn
  • [C#]C#学习笔记-CIL和动态程序集
  • [C++随笔录] 红黑树
  • [codevs 2822] 爱在心中 【tarjan 算法】