C# 获取系统DPI缩放比例以及分辨率大小

一般方法

System.Windows.Forms.Screen

// 获取当前主屏幕分辨率
int screenWidth = Screen.PrimaryScreen.Bounds.Width;
int screenHeight = Screen.PrimaryScreen.Bounds.Height;

// 获取指定屏幕分辨率
Screen secondaryScreen = Screen.AllScreens[1];
int secondaryScreenWidth = secondaryScreen.Bounds.Width;
int secondaryScreenHeight = secondaryScreen.Bounds.Height;

System.Windows.SystemParameters

// 获取当前主屏幕分辨率
double screenWidth = SystemParameters.PrimaryScreenWidth;
double screenHeight = SystemParameters.PrimaryScreenHeight;

// 获取所有屏幕的分辨率
double virtualScreenWidth = SystemParameters.VirtualScreenWidth;
double virtualScreenHeight = SystemParameters.VirtualScreenHeight;

虚拟屏幕是指所有物理屏幕组合成的逻辑屏幕,可以用于跨越多个物理屏幕显示应用程序。

这两个方法都可以在正常情况下获取到屏幕的分辨率 - 当桌面缩放比例不是 100% 的时候获取到的分辨率就是“真实”的分辨率了,而是按缩放比例调整以后屏幕显示的内容的宽度和高度。

Windows API

一开始写了个只获取 DPI 缩放比例的,然后自己手动乘一下,但是调用System.Windows.Interop的时候在同事电脑上找不到这个命名空间,不知道什么原因,后来找到了一篇类似功能的文章,微调了一下:

using System;
using System.Drawing;
using System.Runtime.InteropServices;

namespace ScreenDPIHelper
{
    public class ScreenDPIHelper
    {
        #region Win32 API

        [DllImport("user32.dll")]
        static extern IntPtr GetDC(IntPtr ptr);
        [DllImport("gdi32.dll")]
        static extern int GetDeviceCaps(
        IntPtr hdc, // handle to DC
        int nIndex // index of capability
        );
        [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
        static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);

        #endregion

        #region DeviceCaps - 设备属性 常量

        const int HORZRES = 8;
        const int VERTRES = 10;
        const int LOGPIXELSX = 88;
        const int LOGPIXELSY = 90;
        const int DESKTOPVERTRES = 117;
        const int DESKTOPHORZRES = 118;

        #endregion

        #region 属性

        // 获取屏幕分辨率当前物理大小
        public static Size WorkingArea
        {
            get
            {
                IntPtr hdc = GetDC(IntPtr.Zero);
                Size size = new Size();
                size.Width = GetDeviceCaps(hdc, HORZRES);
                size.Height = GetDeviceCaps(hdc, VERTRES);
                ReleaseDC(IntPtr.Zero, hdc);
                return size;
            }
        }
        // 当前系统DPI_X 大小 一般为96
        public static int DpiX
        {
            get
            {
                IntPtr hdc = GetDC(IntPtr.Zero);
                int DpiX = GetDeviceCaps(hdc, LOGPIXELSX);
                ReleaseDC(IntPtr.Zero, hdc);
                return DpiX;
            }
        }
        // 当前系统DPI_Y 大小 一般为96
        public static int DpiY
        {
            get
            {
                IntPtr hdc = GetDC(IntPtr.Zero);
                int DpiX = GetDeviceCaps(hdc, LOGPIXELSY);
                ReleaseDC(IntPtr.Zero, hdc);
                return DpiX;
            }
        }
        // 获取真实设置的桌面分辨率大小
        public static Size DesktopResolution
        {
            get
            {
                IntPtr hdc = GetDC(IntPtr.Zero);
                Size size = new Size();
                size.Width = GetDeviceCaps(hdc, DESKTOPHORZRES);
                size.Height = GetDeviceCaps(hdc, DESKTOPVERTRES);
                ReleaseDC(IntPtr.Zero, hdc);
                return size;
            }
        }
        // 获取宽度缩放百分比
        public static float ScaleX
        {
            get
            {
                IntPtr hdc = GetDC(IntPtr.Zero);
                float ScaleX = (float)GetDeviceCaps(hdc, DESKTOPHORZRES) / (float)GetDeviceCaps(hdc, HORZRES);
                ReleaseDC(IntPtr.Zero, hdc);
                return ScaleX;
            }
        }
        // 获取高度缩放百分比
        public static float ScaleY
        {
            get
            {
                IntPtr hdc = GetDC(IntPtr.Zero);
                float ScaleY = (float)(float)GetDeviceCaps(hdc, DESKTOPVERTRES) / (float)GetDeviceCaps(hdc, VERTRES);
                ReleaseDC(IntPtr.Zero, hdc);
                return ScaleY;
            }
        }

        #endregion
    }
}

这个类用到了user32.dllgdi32.dll这两个Win32动态链接库,并调用了其中的函数。如:

  • GetDC: 该函数返回指定窗口客户区域或屏幕的设备上下文(DC)。
  • ReleaseDC: 该函数释放由GetDC函数获得的指定设备上下文(DC)。
  • GetDeviceCaps: 该函数检索指定设备的某些功能,如分辨率,颜色深度,打印机输出分辨率等。

定义的常量参数分别为:

  • HORZRES:水平方向分辨率。
  • VERTRES:垂直方向分辨率。
  • LOGPIXELSX:水平方向 DPI。
  • LOGPIXELSY:垂直方向 DPI。
  • DESKTOPVERTRES:真实的桌面分辨率的垂直大小。
  • DESKTOPHORZRES:真实的桌面分辨率的水平大小。

参数的值是对应参数在 Win32 API 中的索引。

可获取的参数分别是:

  • WorkingArea:获取屏幕分辨率的物理大小,也就是去掉任务栏等占据屏幕空间后的大小。
  • DpiX:获取当前系统水平方向的 DPI ,DPI 是一个表示每英寸点数的度量单位,通常为 96。
  • DpiY:获取当前系统垂直方向的 DPI 。
  • DESKTOP:获取真实的桌面分辨率大小,包括任务栏等占据空间的部分。
  • ScaleX:获取宽度的缩放比例,即当前屏幕的实际宽度与标准宽度(DESKTOPHORZRES)的比值。
  • ScaleY:获取高度的缩放比例,即当前屏幕的实际高度与标准高度(DESKTOPVERTRES)的比值。

参考文档:

平台调用示例

用平台调用封送数据

标识 DLL 中的函数

C# API 获取系统DPI缩放倍数跟分辨率大小

原文链接:https://www.cnblogs.com/BoiledYakult/p/17355056.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 获取系统DPI缩放比例以及分辨率大小 - Python技术站

(0)
上一篇 2023年5月1日
下一篇 2023年5月2日

相关文章

  • Unity3D动态生成平面网格

    要动态生成平面网格,需要使用Unity3D中的Mesh类。下面是完整攻略: 步骤一:创建一个空物体 在Unity3D工程中,创建一个空物体,这将作为生成的平面网格的父物体。 步骤二:创建一个空的Mesh 使用Unity3D中的Mesh类来创建一个Mesh实例。这个Mesh实例将被用来存储我们动态生成的网格。 Mesh mesh = new Mesh(); 步…

    C# 2023年6月3日
    00
  • BootStrap实现带有增删改查功能的表格(DEMO详解)

    BootStrap实现带有增删改查功能的表格(DEMO详解) 在Web开发中,表格是一个非常常见的组件。为了提高表格的交互性和用户体验,我们通常会在表格中添加增删改查等功能。本文将介绍如何使用BootStrap实现带有增删改查功能的表格。 环境准备 在使用BootStrap实现带有增删改查功能的表格前,需要先了解以下知识: BootStrap:一个流行的前端…

    C# 2023年5月15日
    00
  • Unity使用ScrollRect制作翻页

    下面是使用ScrollRect制作翻页的完整攻略。 1. 准备工作 在使用ScrollRect制作翻页前,需要先准备两个物体: Content:承载所有的页面。 Page:单独的一页。 然后,需要将Page复制多次,并排列在Content中。排列好后,需要调整Content的大小,使其能够完整显示所有的Page。 2. 添加控制器 接下来,需要添加一个控制器…

    C# 2023年6月3日
    00
  • bootstrap datetimepicker 日期插件在火狐下出现一条报错信息的原因分析及解决办法

    好的。针对 “bootstrap datetimepicker 日期插件在火狐下出现一条报错信息的原因分析及解决办法” 这个问题,需要做如下解读: 确认问题:在使用 bootstrap datetimepicker 日期插件的过程中,在火狐浏览器下会出现一条报错信息。 原因分析:bootstrap datetimepicker 日期插件基于 jQuery,它…

    C# 2023年6月1日
    00
  • C#获取视频某一帧的缩略图的方法

    C#获取视频某一帧的缩略图的方法 在C#中,我们可以使用FFmpeg库和GDI+库来获取视频某一帧的缩略图。本文将提供详细的“C#获取视频某一帧的缩略图的方法”的完整攻略,包括如何使用FFmpeg库和GDI+库获取视频某一帧的缩略图,以及两个示例代码。 使用FFmpeg库获取视频某一帧的缩略图 在使用FFmpeg库获取视频某一帧的缩略图时,我们可以使用以下步…

    C# 2023年5月15日
    00
  • MASA MinimalAPI源码解析:为什么我们只写了一个app.MapGet,却生成了三个接口

    源码解析:为什么我们只写了一个app.MapGet,却生成了三个接口 1.ServiceBase 1.AutoMapRoute 源码如下: AutoMapRoute自动创建map路由,MinimalAPI会根据service中的方法,创建对应的api接口。 比如上文的一个方法: public async Task<WeatherForecast[]&g…

    C# 2023年5月5日
    00
  • C# DateTime.ToString根据不同语言生成相应的时间格式

    C#中的DateTime.ToString方法可以将日期时间格式化为指定的字符串。在不同的语言环境下,日期时间的格式也会有所不同。本文将介绍如何使用C#的DateTime.ToString方法根据不同语言生成相应的时间格式,并提供两个示例程序。 示例一:根据不同语言生成相应的时间格式 以下是一个C#程序的示例,它演示了如何根据不同语言生成相应的时间格式: u…

    C# 2023年5月15日
    00
  • C#匿名方法与Delegate类型转换错误分析

    下面我来详细讲解一下C#匿名方法与Delegate类型转换错误分析的完整攻略。 什么是匿名方法 匿名方法是在C#2.0中新增的特性,它可以在运行时动态地创建一段匿名代码块。匿名方法可以作为方法参数,或赋值给一个委托类型的变量,以便在稍后时间执行。 匿名方法的语法如下: delegate(parameters) { /* 方法体 */ } 其中,delegat…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部