以编程方式旋转显示器?

2024-01-03

我正在寻找一种以编程方式旋转其中一台显示器的显示的方法。 我在桌面上安装了两台显示器,在编程或使用各种其他程序时,我经常以不同的方向使用它们,为了改变方向,我跳入显示设置并以这种方式旋转它(这样我就可以有一个或两者都是纵向)。

可以说我很懒,因为我知道这几乎没有什么麻烦,但是如果我的任务栏上有一个快速的小可执行文件,我可以运行它来在需要时立即来回旋转一个屏幕,那就太好了。

我研究过它并发现使用 DEVMODE 结构等的各种解释,这一切似乎都是一个非常冗长的过程,真的没有更简单的方法来做到这一点吗?没有一个windows dll已经有这个功能了吗?

提前致谢。


使用提到的 DEVMODE 结构和本机调用来实现这一点并不难。 我写了一个小包装来执行此操作:

using System;
using System.Runtime.InteropServices;

public class Display
    {
        public enum Orientations
        {
            DEGREES_CW_0 = 0,
            DEGREES_CW_90 = 3,
            DEGREES_CW_180 = 2,
            DEGREES_CW_270 = 1
        }

        public static bool Rotate(uint DisplayNumber, Orientations Orientation)
        {
            if(DisplayNumber == 0)
                throw new ArgumentOutOfRangeException("DisplayNumber", DisplayNumber, "First display is 1.");

            bool result = false;

            DISPLAY_DEVICE d = new DISPLAY_DEVICE();
            d.cb = Marshal.SizeOf(d);

            DEVMODE dm = new DEVMODE();

           if(!NativeMethods.EnumDisplayDevices(null, DisplayNumber-1, ref d, 0))
                throw new ArgumentOutOfRangeException("DisplayNumber", DisplayNumber, "Number is greater than connected displays.");

            if (0 != NativeMethods.EnumDisplaySettings(
                d.DeviceName, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm))
            {
                if ((dm.dmDisplayOrientation + (int)Orientation) % 2 == 1) // Need to swap height and width?
                {
                    int temp = dm.dmPelsHeight;
                    dm.dmPelsHeight = dm.dmPelsWidth;
                    dm.dmPelsWidth = temp;
                }

                switch (Orientation)
                {
                    case Orientations.DEGREES_CW_90:
                        dm.dmDisplayOrientation = NativeMethods.DMDO_270;
                        break;
                    case Orientations.DEGREES_CW_180:
                        dm.dmDisplayOrientation = NativeMethods.DMDO_180;
                        break;
                    case Orientations.DEGREES_CW_270:
                        dm.dmDisplayOrientation = NativeMethods.DMDO_90;
                        break;
                    case Orientations.DEGREES_CW_0:
                        dm.dmDisplayOrientation = NativeMethods.DMDO_DEFAULT;
                        break;
                    default:
                        break;
                }

                DISP_CHANGE ret = NativeMethods.ChangeDisplaySettingsEx(
                    d.DeviceName, ref dm, IntPtr.Zero,
                    DisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero);

                result = ret == 0;
            }

            return result;
        }

        public static void ResetAllRotations()
        {
            try
            {
                uint i = 0;
                while (++i <= 64)
                {
                    Rotate(i, Orientations.DEGREES_CW_0);
                }
            }
            catch(ArgumentOutOfRangeException ex)
            {
                // Everything is fine, just reached the last display
            }
        }
    }

    internal class NativeMethods
    {
        [DllImport("user32.dll")]
        internal static extern DISP_CHANGE ChangeDisplaySettingsEx(
            string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd,
            DisplaySettingsFlags dwflags, IntPtr lParam);

        [DllImport("user32.dll")]
        internal static extern bool EnumDisplayDevices(
            string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice,
            uint dwFlags);

        [DllImport("user32.dll", CharSet = CharSet.Ansi)]
        internal static extern int EnumDisplaySettings(
            string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);

        public const int DMDO_DEFAULT = 0;
        public const int DMDO_90 = 1;
        public const int DMDO_180 = 2;
        public const int DMDO_270 = 3;

        public const int ENUM_CURRENT_SETTINGS = -1;

    }

    // See: https://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx
    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
    internal struct DEVMODE
    {
        public const int CCHDEVICENAME = 32;
        public const int CCHFORMNAME = 32;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
        [System.Runtime.InteropServices.FieldOffset(0)]
        public string dmDeviceName;
        [System.Runtime.InteropServices.FieldOffset(32)]
        public Int16 dmSpecVersion;
        [System.Runtime.InteropServices.FieldOffset(34)]
        public Int16 dmDriverVersion;
        [System.Runtime.InteropServices.FieldOffset(36)]
        public Int16 dmSize;
        [System.Runtime.InteropServices.FieldOffset(38)]
        public Int16 dmDriverExtra;
        [System.Runtime.InteropServices.FieldOffset(40)]
        public DM dmFields;

        [System.Runtime.InteropServices.FieldOffset(44)]
        Int16 dmOrientation;
        [System.Runtime.InteropServices.FieldOffset(46)]
        Int16 dmPaperSize;
        [System.Runtime.InteropServices.FieldOffset(48)]
        Int16 dmPaperLength;
        [System.Runtime.InteropServices.FieldOffset(50)]
        Int16 dmPaperWidth;
        [System.Runtime.InteropServices.FieldOffset(52)]
        Int16 dmScale;
        [System.Runtime.InteropServices.FieldOffset(54)]
        Int16 dmCopies;
        [System.Runtime.InteropServices.FieldOffset(56)]
        Int16 dmDefaultSource;
        [System.Runtime.InteropServices.FieldOffset(58)]
        Int16 dmPrintQuality;

        [System.Runtime.InteropServices.FieldOffset(44)]
        public POINTL dmPosition;
        [System.Runtime.InteropServices.FieldOffset(52)]
        public Int32 dmDisplayOrientation;
        [System.Runtime.InteropServices.FieldOffset(56)]
        public Int32 dmDisplayFixedOutput;

        [System.Runtime.InteropServices.FieldOffset(60)]
        public short dmColor;
        [System.Runtime.InteropServices.FieldOffset(62)]
        public short dmDuplex;
        [System.Runtime.InteropServices.FieldOffset(64)]
        public short dmYResolution;
        [System.Runtime.InteropServices.FieldOffset(66)]
        public short dmTTOption;
        [System.Runtime.InteropServices.FieldOffset(68)]
        public short dmCollate;
        [System.Runtime.InteropServices.FieldOffset(72)]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
        public string dmFormName;
        [System.Runtime.InteropServices.FieldOffset(102)]
        public Int16 dmLogPixels;
        [System.Runtime.InteropServices.FieldOffset(104)]
        public Int32 dmBitsPerPel;
        [System.Runtime.InteropServices.FieldOffset(108)]
        public Int32 dmPelsWidth;
        [System.Runtime.InteropServices.FieldOffset(112)]
        public Int32 dmPelsHeight;
        [System.Runtime.InteropServices.FieldOffset(116)]
        public Int32 dmDisplayFlags;
        [System.Runtime.InteropServices.FieldOffset(116)]
        public Int32 dmNup;
        [System.Runtime.InteropServices.FieldOffset(120)]
        public Int32 dmDisplayFrequency;
    }

    // See: https://msdn.microsoft.com/en-us/library/windows/desktop/dd183569(v=vs.85).aspx
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    internal struct DISPLAY_DEVICE
    {
        [MarshalAs(UnmanagedType.U4)]
        public int cb;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string DeviceName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceString;
        [MarshalAs(UnmanagedType.U4)]
        public DisplayDeviceStateFlags StateFlags;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceID;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceKey;
    }

    // See: https://msdn.microsoft.com/de-de/library/windows/desktop/dd162807(v=vs.85).aspx
    [StructLayout(LayoutKind.Sequential)]
    internal struct POINTL
    {
        long x;
        long y;
    }

    internal enum DISP_CHANGE : int
    {
        Successful = 0,
        Restart = 1,
        Failed = -1,
        BadMode = -2,
        NotUpdated = -3,
        BadFlags = -4,
        BadParam = -5,
        BadDualView = -6
    }

    // http://www.pinvoke.net/default.aspx/Enums/DisplayDeviceStateFlags.html
    [Flags()]
    internal enum DisplayDeviceStateFlags : int
    {
        /// <summary>The device is part of the desktop.</summary>
        AttachedToDesktop = 0x1,
        MultiDriver = 0x2,
        /// <summary>The device is part of the desktop.</summary>
        PrimaryDevice = 0x4,
        /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
        MirroringDriver = 0x8,
        /// <summary>The device is VGA compatible.</summary>
        VGACompatible = 0x10,
        /// <summary>The device is removable; it cannot be the primary display.</summary>
        Removable = 0x20,
        /// <summary>The device has more display modes than its output devices support.</summary>
        ModesPruned = 0x8000000,
        Remote      = 0x4000000,
        Disconnect  = 0x2000000
    }

    // http://www.pinvoke.net/default.aspx/user32/ChangeDisplaySettingsFlags.html
    [Flags()]
    internal enum DisplaySettingsFlags : int
    {
        CDS_NONE = 0,
        CDS_UPDATEREGISTRY      = 0x00000001,
        CDS_TEST                = 0x00000002,
        CDS_FULLSCREEN          = 0x00000004,
        CDS_GLOBAL              = 0x00000008,
        CDS_SET_PRIMARY         = 0x00000010,
        CDS_VIDEOPARAMETERS     = 0x00000020,
        CDS_ENABLE_UNSAFE_MODES = 0x00000100,
        CDS_DISABLE_UNSAFE_MODES= 0x00000200,
        CDS_RESET               = 0x40000000,
        CDS_RESET_EX            = 0x20000000,
        CDS_NORESET             = 0x10000000
    }

    [Flags()]
    internal enum DM : int
    {
        Orientation         = 0x00000001,
        PaperSize           = 0x00000002,
        PaperLength         = 0x00000004,
        PaperWidth          = 0x00000008,
        Scale               = 0x00000010,
        Position            = 0x00000020,
        NUP                 = 0x00000040,
        DisplayOrientation  = 0x00000080,
        Copies              = 0x00000100,
        DefaultSource       = 0x00000200,
        PrintQuality        = 0x00000400,
        Color               = 0x00000800,
        Duplex              = 0x00001000,
        YResolution         = 0x00002000,
        TTOption            = 0x00004000,
        Collate             = 0x00008000,
        FormName            = 0x00010000,
        LogPixels           = 0x00020000,
        BitsPerPixel        = 0x00040000,
        PelsWidth           = 0x00080000,
        PelsHeight          = 0x00100000,
        DisplayFlags        = 0x00200000,
        DisplayFrequency    = 0x00400000,
        ICMMethod           = 0x00800000,
        ICMIntent           = 0x01000000,
        MediaType           = 0x02000000,
        DitherType          = 0x04000000,
        PanningWidth        = 0x08000000,
        PanningHeight       = 0x10000000,
        DisplayFixedOutput  = 0x20000000
    }

您只需使用要旋转的显示器编号(显示器 1=1、显示器 2=2 等)和所需的角度来调用静态旋转函数。 像这样:

Display.Rotate(1, Display.Orientations.DEGREES_CW_180);

还有一点速记功能ResetAllRotations()重置所有显示。

Regards

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以编程方式旋转显示器? 的相关文章

随机推荐

  • T-SQL 如何匹配多行

    有两个表 包装表和产品表 就我而言 包装中包含多种产品 我们需要识别多个产品是否可以与包裹记录中已有的包裹匹配 一些脚本如下 DECLARE tblPackage TABLE PackageID int ProductID int INSE
  • Mailgun Laravel 发送电子邮件错误 客户端错误消息

    在 Laravel 5 1 上设置 mailgun 后 我确实收到错误消息 客户端错误响应 url https api mailgun net v3 messages mime https api mailgun net v3 messag
  • 如何在脚本化 ssh 命令中使用简单引号和双引号

    我正在编写一个小型 bash 脚本 并希望通过 ssh 执行以下命令 sudo i mysql uroot pPASSWORD execute select user host password last changed from mysq
  • ICU 资源包是否用于消息翻译资源

    我了解 ICU 的本地化部分 日期 时间和货币格式 排序规则等 当谈到消息翻译时 我看到人们说 ICU 不提供消息翻译功能 例如检查这个 SOF 问题 https stackoverflow com questions 5644412 ph
  • 工作单元模式的实现

    我首先使用 ASP NET MVC 和实体框架代码创建一个应用程序 我正在使用存储库和工作单元模式 并受到以下链接的影响 http www asp net mvc tutorials getting started with ef 5 us
  • Intellij 在新块中添加额外的行

    当我在 Intellij 中编写代码时 我经常通过键入以下类型的序列来创建新块 if test 键入左大括号会导致 Intellij 自动插入右大括号并将光标移动到两个大括号之间 if test 此时 我只需按 Enter 即可获得一个格式
  • 谷歌地图打开时的信息窗口事件

    您好 我正在使用谷歌融合表和谷歌地图 问题是我的标记显示正确 但我想在信息窗口中插入一些图像 所以问题是我进行查询来查找这些标记的位置 并且这些标记可以有许多类别 这就是为什么我无法使用合并表 当用户单击标记时 信息窗口将显示并显示标记上的
  • Java URL:未知协议“C”

    我知道有similar对这个问题的提问 比如this https stackoverflow com questions 7243550 unknown protocol c jdom a saxbuilder一 但是 在读完 类似标题的问
  • Facebook 如何禁用浏览器的集成开发人员工具?

    显然 由于最近的诈骗 开发人员工具被人们利用来发布垃圾邮件 甚至用于 破解 帐户 Facebook 屏蔽了开发者工具 我什至无法使用控制台 他们是怎么做到的 Stack Overflow 上的一篇帖子声称这是不可能的 https stack
  • Angular2 - 具有登录结构的路由器出口

    我正在构建 angular2 应用程序 目前我有一个带有导航栏 工具栏和路由器出口的主组件用于主要内容 我想为登录机制添加一个额外的页面 因此 如果用户未经过身份验证 登录页面将显示在整个屏幕上 用户登录后将导航到具有上述结构的组件 我该如
  • 使用pm2将环境变量传递给node.js

    我正在尝试将一些参数传递给由 pm2 运行的 Express 应用程序 他们的文档中没有任何提示这样做 但显然可以将一些 EV 传递到您的节点应用程序 例如SOME STUFF xxx pm2 start app js 注意 更新环境中的环
  • Spring Integration 中下游流完成后,如何从队列中一次轮询 1 条消息

    我目前正在努力提高集成流程的性能 尝试并行化消息处理 我已经使用 Java DSL 实现了所有内容 当前的集成流程从具有固定轮询器的队列通道获取消息 并通过多个处理程序依次处理该消息 直到到达最终处理程序 该处理程序会考虑前一个处理程序的每
  • 未捕获的 ReferenceError:无法处理与 Ajax 的绑定

    我有两个分层的 MVC4 NET 应用程序 带有 DAL 层和 Web 层 我在尝试将数据与 Ajax 返回的数据绑定时遇到问题 在 Html 上 我试图获取 SubcriteriaList 成员并在填写每个成员的值时为每个成员创建表 HT
  • 我们是否可以设置持久的默认参数,这些参数在明确更改之前一直保持设置状态?

    下面是一个函数fn预期结果是a b c在每次调用时定义fn 是否传递对象参数 如果传递设置属性的对象 则应仅为该对象设置属性 const fn opts a 1 b 2 c 3 gt console log opts 当不带参数调用时 结果
  • C unix 域套接字,recvfrom() 未设置 struct sockaddr* src_addr

    我正在编写一个通过 unix 域套接字侦听 UDP 数据包的应用程序 考虑以下代码块 int sockfd struct sockaddr un servaddr sockfd socket AF LOCAL SOCK DGRAM 0 if
  • 将插件版本集中在(类似于)BOM 中?

    我开始使用 BOM 来集中项目中常见依赖项的版本 但是 它似乎不适用于插件版本 如果我在 BOM 中添加一个 pluginManagement 部分 那么在那里声明的插件版本似乎不会影响导入 BOM 的项目的插件版本 Maven 抱怨版本尚
  • 在 Haskell 中构造循环列表的最便宜的方法

    那么 如果我想构造一个由 n 个 0 和 1 个 1 组成的循环列表 以下哪种方法更好 更便宜 还有更好 更便宜的方法吗 考虑到 n 是Integer并且可能很大 尽管实际上它不会超过 2 32 aZerosAndOnes Integer
  • 循环访问多个组件链接以获取 SDL Tridion 2011 中 Dreamweaver TBB 中链接组件的架构名称

    我正在研究 Dreamweaver 模板构建块并为页面实现 SiteEdit 我正在使用 SDL Tridion 2011 SP1 和 Site Edit 2012 以及默认 Dream Weaver 模板 我的架构有一个 组件链接 类型的
  • 如何使用 Express 提供部分动态 HTML 页面?

    好吧 这是我的问题 我有一个我很满意的 HTML 页面 但我希望使其动态 我正在使用 Node 和 Express 我想知道是否有任何方法可以修改然后渲染纯 HTML 我不会使用 Jade 或任何其他模板引擎 我的服务器 js var ht
  • 以编程方式旋转显示器?

    我正在寻找一种以编程方式旋转其中一台显示器的显示的方法 我在桌面上安装了两台显示器 在编程或使用各种其他程序时 我经常以不同的方向使用它们 为了改变方向 我跳入显示设置并以这种方式旋转它 这样我就可以有一个或两者都是纵向 可以说我很懒 因为