在Windows系统中想要通过代码动态设定屏幕的显示方式和分辨率,就需要调用windows提供的API,不同的Windows系统,API可能会有点不一样,但大体上相同。要实现这个功能需要使用win32 API 中的EnumDisplaySettings,ChangeDisplaySettings 这两个函数。
1.EnumDisplaySettings 读取当前显示设置,并枚举所有受支持的显示设置。
2.ChangeDisplaySettings 设定新的显示设置
这两个 API 都具有指向 DEVMODE 结构的指针,所以需要先定义DEVMODE结构体,这个结构体的定义需要和系统相匹配,看代码
[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; } }
接下来需要定义一个调用win32 API 功能的类,用户读取和设定系统中屏幕的相关信息
public class WinAPI { // 平台调用的申明 [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; }
然后定义一个对对屏幕进行操作的通用类
/// <summary> /// 屏幕设置 /// </summary> public static class ScreenSetting { /// <summary> /// 改变分辨率 /// </summary> public static void 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 != WinAPI.EnumDisplaySettings(null, WinAPI.ENUM_CURRENT_SETTINGS, ref devmode)) { devmode.dmPelsWidth = width; devmode.dmPelsHeight = height; // 改变屏幕分辨率 int iRet = WinAPI.ChangeDisplaySettings(ref devmode, WinAPI.CDS_TEST); //int iRet = NativeMethods.ChangeDisplaySettings(ref devmode, 0); if (iRet == WinAPI.DISP_CHANGE_FAILED) { MessageBox.Show("不能执行你的请求", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { iRet = WinAPI.ChangeDisplaySettings(ref devmode, WinAPI.CDS_UPDATEREGISTRY); switch (iRet) { // 成功改变 case WinAPI.DISP_CHANGE_SUCCESSFUL: { break; } case WinAPI.DISP_CHANGE_RESTART: { MessageBox.Show("你需要重新启动电脑设置才能生效", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); break; } default: { MessageBox.Show("改变屏幕分辨率失败", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); break; } } } } } /// <summary> /// 改变显示方式 /// </summary> /// <param name="displayOrientation"></param> public static void ChangeDisplayOrientation(int displayOrientation) { // 初始化 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 != WinAPI.EnumDisplaySettings(null, WinAPI.ENUM_CURRENT_SETTINGS, ref devmode)) { int height = 0; int width = 0; switch (devmode.dmDisplayOrientation) { case WinAPI.DMDO_DEFAULT: height = devmode.dmPelsHeight; width = devmode.dmPelsWidth; break; case WinAPI.DMDO_270: width = devmode.dmPelsHeight; height = devmode.dmPelsWidth; break; case WinAPI.DMDO_180: height = devmode.dmPelsHeight; width = devmode.dmPelsWidth; break; case WinAPI.DMDO_90: width = devmode.dmPelsHeight; height = devmode.dmPelsWidth; break; default: // unknown orientation value break; } int temp = devmode.dmPelsHeight; devmode.dmPelsHeight = devmode.dmPelsWidth; devmode.dmPelsWidth = temp; if (devmode.dmDisplayOrientation != displayOrientation) { switch (displayOrientation) { case WinAPI.DMDO_DEFAULT: devmode.dmPelsHeight = height; devmode.dmPelsWidth = width; devmode.dmDisplayOrientation = WinAPI.DMDO_DEFAULT; break; case WinAPI.DMDO_270: devmode.dmPelsHeight = width; devmode.dmPelsWidth = height; devmode.dmDisplayOrientation = WinAPI.DMDO_270; break; case WinAPI.DMDO_180: devmode.dmPelsHeight = height; devmode.dmPelsWidth = width; devmode.dmDisplayOrientation = WinAPI.DMDO_180; break; case WinAPI.DMDO_90: devmode.dmPelsHeight = width; devmode.dmPelsWidth = height; devmode.dmDisplayOrientation = WinAPI.DMDO_90; break; default: // unknown orientation value break; } } else { return; } // 改变屏幕显示方式 int iRet = WinAPI.ChangeDisplaySettings(ref devmode, 0); if (iRet == WinAPI.DISP_CHANGE_FAILED) { MessageBox.Show("不能执行你的请求", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { iRet = WinAPI.ChangeDisplaySettings(ref devmode, WinAPI.CDS_UPDATEREGISTRY); switch (iRet) { // 成功改变 case WinAPI.DISP_CHANGE_SUCCESSFUL: { break; } case WinAPI.DISP_CHANGE_RESTART: { MessageBox.Show("你需要重新启动电脑设置才能生效", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); break; } default: { MessageBox.Show("改变屏幕分辨率失败", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information); break; } } } } } }
最后就是对所完成的功能进行测试,效果如下