WM平台旋转屏幕的编程实现
2010-11-28 15:53
471 查看
有些情况下,应用程序需要更改屏幕方向,因为有的功能被设计为在特定模式下运行得最好。其中一个例子就是 Microsoft Office PowerPoint 中的“幻灯片放映”:PowerPoint 以横向模式运行。即使正在纵向模式下使用 Tablet PC,当开始幻灯片放映时,应用程序也会切换到横向方向。当用户结束幻灯片放映时,PowerPoint 会切换回原来的设置。
更改显示设置可以通过使用两个 Win32 API 来完成,这两个 API 都具有指向 DEVMODE 结构的指针,它们分别包含与显示设置有关的所有信息:
使用 EnumDisplaySettings 读取当前显示设置,并枚举所有受支持的显示设置。
使用 ChangeDisplaySettings 切换到新的显示设置。
获取当前显示设置
要获取当前显示设置,请将 iModeNum 参数中的 ENUM_CURRENT_SETTINGS 常量传递给 EnumDisplaySettings API,如以下 C++ 代码所示。
枚举所有受支持的显示设置
要枚举当前显示设备支持的所有显示设置,请将 iModeNum 参数中的 0 传递给 EnumDisplaySettings API,然后继续以递增的 iModeNum 值调用它,直到该函数返回零,如以下 C++ 代码所示。
更改显示设置
要更改显示设置,请将指向有效 DEVMODE 结构的指针传递给 ChangeDisplaySettings API。以下 C++ 代码演示如何使屏幕方向顺时针旋转 90 度。请注意,这段代码只对支持相应显示设置的设备起作用。遵守 ChangeDisplaySettings API 的返回值十分重要,因为有些操作为了在图形模式下工作,需要计算机重启。
在托管代码中获取并更改显示设置
映射 API
为了在托管代码中更改显示设置,必须使用平台调用服务 (PInvoke) 调用 EnumDisplaySettings 和 ChangeDisplaySettings API。对此,一个好的做法是创建一个名为 NativeMethods 的类,该类可以将封装这些 API 的公共静态方法公开。该类应该包含 API 所对应的所有必需的常量定义。以下代码示例演示了这种做法。该类的完整实现可在 NativeMethods.cs 文件中找到,该文件是示例应用程序的一部分。
映射 DEVMODE 结构
在将 DEVMODE 结构映射到托管结构时,应该注意以下几个问题:
因为 DEVMODE 结构包含联合 (union),所以必须挑选出我们所需要的那些成员。
在 .NET Framework 中映射到字符串的数组必须作为相同大小的字符串封送。
为简单起见,可以将嵌套结构平面化(例如,将 POINTL 结构替换为两个托管的 int 类型。)
在 .NET Framework 中初始化 DEVMODE 结构的新实例时,请确保 dmDeviceName、dmFormName 和 dmSize 值设置恰当。为此,我在示例应用程序的 NativeMethods 类中添加了以下方法:
在 C# 中旋转屏幕
以下 C# 代码将前面讨论的技术结合起来,并展示了如何在托管代码中顺时针旋转屏幕。请注意,这段代码只对支持相应显示设置的设备起作用。
更改显示设置可以通过使用两个 Win32 API 来完成,这两个 API 都具有指向 DEVMODE 结构的指针,它们分别包含与显示设置有关的所有信息:
使用 EnumDisplaySettings 读取当前显示设置,并枚举所有受支持的显示设置。
使用 ChangeDisplaySettings 切换到新的显示设置。
获取当前显示设置
要获取当前显示设置,请将 iModeNum 参数中的 ENUM_CURRENT_SETTINGS 常量传递给 EnumDisplaySettings API,如以下 C++ 代码所示。
DEVMODE dm; // initialize the DEVMODE structure ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)) { // inspect the DEVMODE structure to obtain details // about the display settings such as // - Orientation // - Width and Height // - Frequency // - etc. }
枚举所有受支持的显示设置
要枚举当前显示设备支持的所有显示设置,请将 iModeNum 参数中的 0 传递给 EnumDisplaySettings API,然后继续以递增的 iModeNum 值调用它,直到该函数返回零,如以下 C++ 代码所示。
int index = 0; DEVMODE dm; // initialize the DEVMODE structure ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); while (0 != EnumDisplaySettings(NULL, index++, &dm)) { // inspect the DEVMODE structure to obtain details // about the display settings such as // - Orientation // - Width and Height // - Frequency // - etc. }
更改显示设置
要更改显示设置,请将指向有效 DEVMODE 结构的指针传递给 ChangeDisplaySettings API。以下 C++ 代码演示如何使屏幕方向顺时针旋转 90 度。请注意,这段代码只对支持相应显示设置的设备起作用。遵守 ChangeDisplaySettings API 的返回值十分重要,因为有些操作为了在图形模式下工作,需要计算机重启。
DEVMODE dm; // initialize the DEVMODE structure ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)) { // swap height and width DWORD dwTemp = dm.dmPelsHeight; dm.dmPelsHeight= dm.dmPelsWidth; dm.dmPelsWidth = dwTemp; // determine new orientaion switch (dm.dmDisplayOrientation) { case DMDO_DEFAULT: dm.dmDisplayOrientation = DMDO_270; break; case DMDO_270: dm.dmDisplayOrientation = DMDO_180; break; case DMDO_180: dm.dmDisplayOrientation = DMDO_90; break; case DMDO_90: dm.dmDisplayOrientation = DMDO_DEFAULT; break; default: // unknown orientation value // add exception handling here break; } long lRet = ChangeDisplaySettings(&dm, 0); if (DISP_CHANGE_SUCCESSFUL != lRet) { // add exception handling here } }
在托管代码中获取并更改显示设置
映射 API
为了在托管代码中更改显示设置,必须使用平台调用服务 (PInvoke) 调用 EnumDisplaySettings 和 ChangeDisplaySettings API。对此,一个好的做法是创建一个名为 NativeMethods 的类,该类可以将封装这些 API 的公共静态方法公开。该类应该包含 API 所对应的所有必需的常量定义。以下代码示例演示了这种做法。该类的完整实现可在 NativeMethods.cs 文件中找到,该文件是示例应用程序的一部分。
using System.Runtime.InteropServices; ... public class NativeMethods { // PInvoke declaration for EnumDisplaySettings Win32 API [DllImport("user32.dll", CharSet=CharSet.Ansi)] public static extern int EnumDisplaySettings( string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode); // PInvoke declaration for ChangeDisplaySettings Win32 API [DllImport("user32.dll, CharSet=CharSet.Ansi")] public static extern int ChangeDisplaySettings( ref DEVMODE lpDevMode, int dwFlags); // add more functions as needed ?? // constants public const int ENUM_CURRENT_SETTINGS = -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; // add more constants as needed ?? }
映射 DEVMODE 结构
在将 DEVMODE 结构映射到托管结构时,应该注意以下几个问题:
因为 DEVMODE 结构包含联合 (union),所以必须挑选出我们所需要的那些成员。
在 .NET Framework 中映射到字符串的数组必须作为相同大小的字符串封送。
为简单起见,可以将嵌套结构平面化(例如,将 POINTL 结构替换为两个托管的 int 类型。)
[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; };
在 .NET Framework 中初始化 DEVMODE 结构的新实例时,请确保 dmDeviceName、dmFormName 和 dmSize 值设置恰当。为此,我在示例应用程序的 NativeMethods 类中添加了以下方法:
public static DEVMODE CreateDevmode() { DEVMODE dm = new DEVMODE(); dm.dmDeviceName = new String(new char[32]); dm.dmFormName = new String(new char[32]); dm.dmSize = (short)Marshal.SizeOf(dm); return dm; }
在 C# 中旋转屏幕
以下 C# 代码将前面讨论的技术结合起来,并展示了如何在托管代码中顺时针旋转屏幕。请注意,这段代码只对支持相应显示设置的设备起作用。
// initialize the DEVMODE structure DEVMODE dm = new DEVMODE(); dm.dmDeviceName = new string(new char[32]); dm.dmFormName = new string(new char[32]); dm.dmSize = Marshal.SizeOf(dm); if (0 != NativeMethods.EnumDisplaySettings( null, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm)) { // swap width and height int temp = dm.dmPelsHeight; dm.dmPelsHeight = dm.dmPelsWidth; dm.dmPelsWidth = temp; // determine new orientation switch(dm.dmDisplayOrientation) { case NativeMethods.DMDO_DEFAULT: dm.dmDisplayOrientation = NativeMethods.DMDO_270; break; case NativeMethods.DMDO_270: dm.dmDisplayOrientation = NativeMethods.DMDO_180; break; case NativeMethods.DMDO_180: dm.dmDisplayOrientation = NativeMethods.DMDO_90; break; case NativeMethods.DMDO_90: dm.dmDisplayOrientation = NativeMethods.DMDO_DEFAULT; break; default: // unknown orientation value // add exception handling here break; } int iRet = NativeMethods.ChangeDisplaySettings(ref dm, 0); if (NativeMethods.DISP_CHANGE_SUCCESSFUL != iRet) { // add exception handling here } }
相关文章推荐
- Android 平台上编程实现 GPS 定位
- cocos2dx 2.0 的屏幕旋转如果实现
- 【极客学院】点九在Android平台的运用开发,实现屏幕的完整适配
- css3实例教程 一款纯css3实现的发光屏幕旋转特效
- iOS实现屏幕旋转
- iOS多线程编程之多社交平台同步推送的设计与实现
- C++读取、旋转和保存bmp图像文件编程实现
- iOS传感器:实现一个随屏幕旋转的图片
- 64位系统vs2010平台下实现C++与matlab R2014混合编程方法示例
- 【数字图像处理】C++读取、旋转和保存bmp图像文件编程实现
- 【Unity Shader编程】之十六 基于MatCap实现适于移动平台的“次时代”车漆Shader
- Android实现屏幕旋转方法总结
- 基于.NET平台的Windows编程实战(五)—— 问卷管理功能的实现
- WinCE实现屏幕旋转方法
- iOS编程——Swift实现一个3D可旋转的立方体(可做菜单页)
- 滑动屏幕旋转模型功能实现
- 利用GSensor让屏幕实现360度旋转
- iOS 5.1实现旋转屏幕
- Android编程实现屏幕禁止休眠的方法
- vitamio videoView 用隐藏除videoview的控件,并旋转屏幕方向实现的全屏功能,出现的画面不能填充满videoview(画面不完整)