C# 开发技巧系列 如何动态设置屏幕分辨率
最后更新于:2022-04-02 00:10:23
# [C# 开发技巧系列]如何动态设置屏幕分辨率
因为最近在MSDN论坛和stackflow中看到一些朋友经常问到这个问题,所以写这篇文章来帮助大家遇到相同问题的时候可以很快的得到解决,下面就不啰嗦了,直接看代码如何解决这个问题的。
首先,大家应该明确,现在没有可用的API来给我们动态地设置屏幕分辨率,我们要实现这个需求,我们**只能在C#程序中调用Win32 API 函数来解决这个问题**的,这里用C#代码调用Win32 API 就涉及到一个问题的,即.NET 互操作性的问题,关于这个大家可以参考[我的互操作性系列](http://www.cnblogs.com/zhili/archive/2013/01/21/PInvoke.html)文章。这里我就不过多解释了。
我们要解决这个问题,首先大家肯定也会遇到一个经常遇到的问题,即**如何获得用户的分辨率**,对于这个问题,.NET中提供的单独的类给我们调用,我们可以使用[Screen](http://msdn.microsoft.com/zh-cn/library/vstudio/system.windows.forms.screen.aspx)这个类,具体看下面的示例代码:
然后就是如何改变屏幕的分辨率呢?要更改显示设置可以通过使用两个 Win32 API 来完成,这两个 API 都具有指向 [DEVMODE](http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx) 结构的指针,它们分别包含与显示设置有关的所有信息:
* 使用 [EnumDisplaySettings](http://msdn.microsoft.com/en-us/library/windows/desktop/dd162611(v=vs.85).aspx) 读取当前显示设置,并枚举所有受支持的显示设置。
* 使用 [ChangeDisplaySettings](http://msdn.microsoft.com/en-us/library/windows/desktop/dd183411(v=vs.85).aspx) 切换到新的显示设置。
第一步、我们要先定义DEVMODE 结构体,该结构的结构必须与DEVMODE的结构一致,下面是C#中对DEVMODE 结构体的定义代码:
```
// 映射 DEVMODE 结构
// 可以参照 DEVMODE结构的指针定义:
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public int dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
};
```
View Code
第二步、在托管环境下对Win 32 函数进行声明:
```
// Win32 函数在托管环境下的声明
public class NativeMethods
{
// 平台调用的申明
[DllImport("user32.dll")]
public static extern int EnumDisplaySettings(
string deviceName, int modeNum, ref DEVMODE devMode);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettings(
ref DEVMODE devMode, int flags);
// 控制改变屏幕分辨率的常量
public const int ENUM_CURRENT_SETTINGS = -1;
public const int CDS_UPDATEREGISTRY = 0x01;
public const int CDS_TEST = 0x02;
public const int DISP_CHANGE_SUCCESSFUL = 0;
public const int DISP_CHANGE_RESTART = 1;
public const int DISP_CHANGE_FAILED = -1;
// 控制改变方向的常量定义
public const int DMDO_DEFAULT = 0;
public const int DMDO_90 = 1;
public const int DMDO_180 = 2;
public const int DMDO_270 = 3;
}
```
View Code
第三步、调用[EnumDisplaySettings](http://msdn.microsoft.com/en-us/library/windows/desktop/dd162611(v=vs.85).aspx)和[ChangeDisplaySettings](http://msdn.microsoft.com/en-us/library/windows/desktop/dd183411(v=vs.85).aspx)这两个函数来实现动态改变屏幕分辨率,具体代码如下:
```
// 改变分辨率
public ChangeResolution(int width, int height)
{
// 初始化 DEVMODE结构
DEVMODE devmode = new DEVMODE();
devmode.dmDeviceName = new String(new char[32]);
devmode.dmFormName = new String(new char[32]);
devmode.dmSize = (short)Marshal.SizeOf(devmode);
if (0 != NativeMethods.EnumDisplaySettings(null, NativeMethods.ENUM_CURRENT_SETTINGS, ref devmode))
{
devmode.dmPelsWidth = width;
devmode.dmPelsHeight = height;
// 改变屏幕分辨率
int iRet = NativeMethods.ChangeDisplaySettings(ref devmode, NativeMethods.CDS_TEST);
if (iRet == NativeMethods.DISP_CHANGE_FAILED)
{
MessageBox.Show("不能执行你的请求", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
iRet = NativeMethods.ChangeDisplaySettings(ref devmode, NativeMethods.CDS_UPDATEREGISTRY);
switch (iRet)
{
// 成功改变
case NativeMethods.DISP_CHANGE_SUCCESSFUL:
{
break;
}
case NativeMethods.DISP_CHANGE_RESTART:
{
MessageBox.Show("你需要重新启动电脑设置才能生效", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
}
default:
{
MessageBox.Show("改变屏幕分辨率失败", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
}
}
}
}
}
```
View Code
为了大家更加形象地看到程序的运行结果,下面是一个演示效果:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-01-23_56a2eb30cda4c.gif)
实现源代码下载:[动态设置屏幕分辨率.zip](http://code.msdn.microsoft.com/fbd88266-e8af-4726-ae13-a760fec7542f/file/82…6%80%81%E8%AE%BE%E7%BD%AE%E5%B1%8F%E5%B9%95%E5%88%86%E8%BE%A8%E7%8E%87.zip)
';