现在1920x1080以上分辨率的高分屏电脑渐渐普及了。我们会在Windows的显示设置里看到缩放比例的设置。在Windows桌面客户端的开发中,有时会想要精确计算窗口的面积或位置。然而在默认情况下,无论WinForms的Screen.Bounds.Width属性还是WPF中SystemParameters.PrimaryScreenWidth属性,以下图举例,将会返回除以150%的数值1280。而不是真实的物理分辨率1920。

接下来介绍如何获取Display resolution中显示的实际分辨率。通过如下Win32 API的调用:

        [DllImport("gdi32.dll", EntryPoint = "GetDeviceCaps", SetLastError = true)]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

该方法可以获取设备的硬件信息,可以通过第二个参数nIndex来指定要查询的具体信息。例如我们要用到的以像素为单位的桌面高度DESKTOPVERTRES。

        enum DeviceCap
{
VERTRES = 10,
PHYSICALWIDTH = 110,
SCALINGFACTORX = 114,
DESKTOPVERTRES = 117, // http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html
}

在获得物理像素高度后,通过计算不难得出屏幕的缩放比列。

        private static double GetScreenScalingFactor()
{
var g = Graphics.FromHwnd(IntPtr.Zero);
IntPtr desktop = g.GetHdc();
var physicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES); var screenScalingFactor =
(double)physicalScreenHeight / Screen.PrimaryScreen.Bounds.Height;
//SystemParameters.PrimaryScreenHeight; return screenScalingFactor;
}

在获取屏幕缩放比例后,诸如通过Graphics类的CopyFromScreen方法来截屏,或者精确控制窗口大小和位置才得以正确实现。
其实在WinForms程序中,我们还有更简单的方式来实现类似效果。即在工程中添加app.manifest文件,将<dipAware>节点的值设为true。这样修改后,Screen.PrimaryScreen.Bounds将获得实际的物理分辨率尺寸,同时你还会发现WinForms程序不糊了。这是因为Windows默认WinForms程序不支持DPI感知,在高分屏下就直接粗暴的把窗体放大。

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>

该设置对WPF无效,WPF默认支持DPI感知功能。而从UWP开始Windows客户端技术全面支持高分屏即高DPI缩放。老旧应用程序不肯升级,以至无法支持高分屏,这锅某软背着挺冤的……
所以同学们,现在开始全面转向WinUI 3吧,这货是这么些年某软兜兜转转,客户端技术集大成者。用Windows APP SDK创建Unpackged App时,恍惚间仿佛回到了在XP上装.NET Runtime的时光。
因为Github访问时常抽风,我将示例代码在Gitee上也同步了一份:

How to get Windows display scale using C#. (github.com)
How to get Windows display scale using C#. (gitee.com)

C#获取Windows10屏幕的缩放比例的更多相关文章

  1. android获取设备屏幕大小的方法

    // 通过WindowManager获取 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay( ...

  2. Android 修改toast的默认位置和获取当前屏幕的高度和宽度

    Toast toast; toast=Toast.makeText(this, "toast", Toast.LENGTH_LONG); toast.setGravity(grav ...

  3. WINFORM中几句程序获取整个屏幕的图片及当前窗口的图片快照

    /// <summary> /// 获取整个屏幕的图片        /// </summary>        /// <returns></returns ...

  4. Android编程心得-在任意类中获取当前屏幕宽高

    进行Android编程时,很多时候都需要获取当前屏幕的宽度与高度,但是当我们需要在别的类中调用屏幕宽高时,直接用原来的方法是不行的,下面我来介绍如何在任意类中调用宽度高度的两种方法. public v ...

  5. ios中获取当前屏幕尺寸的方法

    //获取当前屏幕尺寸 CGRect screenFrame = [UIScreen mainScreen].bounds; int screenWidth = screenFrame.size.wid ...

  6. Python + Appium 获取当前屏幕的截图方法的封装

    使用方法:get_screenshot_as_file(filename),来自于selenium\webdriver\remote\webdiver.py def take_screenShot(s ...

  7. C# 获取当前屏幕的宽高和位置

    上一篇博客<C# 获取当前屏幕DPI>,介绍了如何获取当前屏幕的DPI设置 本章主要介绍如何获取当前窗口所在屏幕的信息 当前屏幕信息 如果当前是单屏幕,可以直接获取主屏幕 var prim ...

  8. 获取系统屏幕尺寸参数的类WxHxD

    获取系统屏幕尺寸参数的类WxHxD 源码: // // WxHxD.h // PM2.5 // // Created by YouXianMing on 14/10/29. // Copyright ...

  9. C#获取显示器屏幕数量 控制winform显示到哪一个屏幕

    获取当前系统连接的屏幕数量: Screen.AllScreens.Count();获取当前屏幕的名称:string CurrentScreenName = Screen.FromControl(thi ...

随机推荐

  1. 【JAVA】笔记(5)--- final;抽象方法;抽象类;接口;解析继承,关联,与实现;

    final: 1.理解:凡是final修饰的东西都具有了不变的特性: 2.修饰对象: 1)final+类--->类无法被继承: 2)final+方法--->方法无法被覆盖: 3)final ...

  2. Eclipse使用JDBC方式连接SQLServer2008

    JDBC_连接数据库一.配置 (一)  通过SQL Server配置管理器配置相关部分: 右键点击,启动tcp/ip协议右键点击属性查看自己的TCP端口号,记住,后面会用到右键点击SQL Server ...

  3. Error filterStart

    一般原因为:1.xml配置失误filter应配置在servlet-mapping前面(应该都知道吧).看看class配的 别找不到.2.filter中某段代码未实例化(这个情况是出现最多的,要仔细检查 ...

  4. [cf1491I]Ruler Of The Zoo

    为了统一描述,下面给出题意-- 有$n$只动物,编号为$i$的动物有属性$a_{i,j}$($0\le i<n,0\le j\le 2$) 初始$n$只动物从左到右编号依次为$0,1,...,n ...

  5. 干掉if-else的方法

    策略模式+工厂方法消除if else 假设需求为,根据不同勋章类型,处理相对应的勋章服务,优化前有以下代码: String medalType = "guest"; if (&qu ...

  6. Electron快速入门

    node -v npm -v 安装node环境 my-electron-app/ ├── package.json ├── main.js └── index.html 为您的项目创建一个文件夹并安装 ...

  7. CF1553 部分题解

    CF1553D Backspace 题目传送门. 题意简述:给定 \(s,t\),现在要依次输入 \(s\) 中的字符.对于每个字符 \(s_i\),你可以选择输入 \(s_i\) 或者使用退格键,判 ...

  8. 【pheatmap热图scale报错】Error in hclust(d, method = method):NA/NaN/Inf in foreign function call (arg 11)

    初始数据类似如下: 填充下缺失值 data[data==0] <- NA data[is.na(data)] <- min(data,na.rm = T)*0.01 pheatmap(lo ...

  9. R语言与医学统计图形【4】直方图、金字塔图

    R语言基础绘图系统 基础图形--直方图.金字塔图 3.直方图 参数设置及比较. op <- par(mfrow=c(2,3)) data <- rnorm(100,10,5) hist(d ...

  10. R语言与医学统计图形-【23】ggplot2坐标系转换函数

    ggplot2绘图系统--坐标系转换函数 包括饼图.环状条图.玫瑰图.戒指图.坐标翻转. 笛卡尔坐标系(最常见). ArcGIS地理坐标系(地图). Cartesian坐标系. polar极坐标系. ...