目前只有C++版的,本人用了两天时间,在经理的提点下完成了C#版的修改。
其中遇到了很多问题一一的解决了,还好时间花费不是太多。比较大的问题有:
1.C++类型与C#类型的转换
2.C++中Union关键字在C#中的表现形式。
3.对Api提供的大量枚举进行分析(这个尤其累)返回的错误码请参照微软 WinError。这个只是个预览版可以初步修改显示器位置罢了。
虽然在Api中存在分辨率,可是不能修改,一修改就报错,目前无解决方案,只能用旧的 ChangeDisplaySettings了。开始上代码

解决方案 »

  1.   

    代码是 .net 4.0 的,如果是2.0请自己去掉System.Linq的命名空间引用。CommonHelper.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;namespace TestDiaplay
    {
        public class CommonHelper
        {
            public static byte[] StrutsToBytesArray(object structObj)
            {
                //得到结构体的大小   
                int size = Marshal.SizeOf(structObj);
                //创建byte数组   
                byte[] bytes = new byte[size];
                //分配结构体大小的内存空间   
                IntPtr structPtr = Marshal.AllocHGlobal(size);
                //将结构体拷到分配好的内存空间   
                Marshal.StructureToPtr(structObj, structPtr, false);
                //从内存空间拷到byte数组   
                Marshal.Copy(structPtr, bytes, 0, size);
                //释放内存空间   
                Marshal.FreeHGlobal(structPtr);
                //返回byte数组   
                return bytes;
            }
            public static object BytesToStruts(byte[] bytes, Type type)
            {
                //得到结构体的大小   
                int size = Marshal.SizeOf(type);
                //byte数组长度小于结构体的大小   
                if (size > bytes.Length)
                {
                    //返回空   
                    return null;
                }
                //分配结构体大小的内存空间   
                IntPtr structPtr = Marshal.AllocHGlobal(size);
                //将byte数组拷到分配好的内存空间   
                Marshal.Copy(bytes, 0, structPtr, size);
                //将内存空间转换为目标结构体   
                object obj = Marshal.PtrToStructure(structPtr, type);
                //释放内存空间   
                Marshal.FreeHGlobal(structPtr);
                //返回结构体   
                return obj;
            }
        }
    }
      

  2.   

    Program.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;namespace TestDiaplay
    {
        class Program
        {
            [DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]
            public static extern IntPtr LoadLibrary(string lpFileName);        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true)]
            public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProceName);        struct LUID
            {
                UInt32 LowPart;
                UInt32 HighPart;
            }        struct POINTL      /* ptl  */
            {
                public Int32 x;
                public Int32 y;
            }        struct DISPLAYCONFIG_2DREGION
            {
                public UInt32 cx;
                public UInt32 cy;
            }        enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY
            {
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = -1,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = 0x8000000,
                DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = 0xFFFFFFF
            }        enum DISPLAYCONFIG_ROTATION
            {
                DISPLAYCONFIG_ROTATION_IDENTITY = 1,
                DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
                DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
                DISPLAYCONFIG_ROTATION_ROTATE270 = 4,
                DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFF
            }        enum DISPLAYCONFIG_SCALING
            {
                DISPLAYCONFIG_SCALING_IDENTITY = 1,
                DISPLAYCONFIG_SCALING_CENTERED = 2,
                DISPLAYCONFIG_SCALING_STRETCHED = 3,
                DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
                DISPLAYCONFIG_SCALING_CUSTOM = 5,
                DISPLAYCONFIG_SCALING_PREFERRED = 128,
                DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFF
            }
            struct DISPLAYCONFIG_RATIONAL
            {
                UInt32 Numerator;
                UInt32 Denominator;
            }        enum DISPLAYCONFIG_SCANLINE_ORDERING
            {
                DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
                DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
                DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
                DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
                DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
                DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFF
            }        enum DISPLAYCONFIG_PIXELFORMAT
            {
                DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
                DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
                DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
                DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
                DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
                DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xfffffff
            }
            enum DISPLAYCONFIG_MODE_INFO_TYPE
            {
                DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
                DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
                DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFF
            }        enum DISPLAYCONFIG_TOPOLOGY_ID
            {
                DISPLAYCONFIG_TOPOLOGY_INTERNAL = 0x00000001,
                DISPLAYCONFIG_TOPOLOGY_CLONE = 0x00000002,
                DISPLAYCONFIG_TOPOLOGY_EXTEND = 0x00000004,
                DISPLAYCONFIG_TOPOLOGY_EXTERNAL = 0x00000008,
                DISPLAYCONFIG_TOPOLOGY_FORCE_UINT32 = 0xFFFFFFF
            }        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            struct DISPLAYCONFIG_PATH_TARGET_INFO
            {
                LUID adapterId;
                UInt32 id;
                UInt32 modeInfoIdx;
                DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
                DISPLAYCONFIG_ROTATION rotation;
                DISPLAYCONFIG_SCALING scaling;
                DISPLAYCONFIG_RATIONAL refreshRate;
                DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
                Boolean targetAvailable;
                UInt32 statusFlags;
            }        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
            struct DISPLAYCONFIG_PATH_SOURCE_INFO
            {
                [FieldOffset(0)]
                LUID adapterId;
                [FieldOffset(8)]
                UInt32 id;
                [FieldOffset(12)]
                UInt32 modeInfoIdx;
                [FieldOffset(16)]
                UInt32 statusFlags;
            }        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
            struct DISPLAYCONFIG_PATH_INFO
            {
                [FieldOffset(0)]
                DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
                [FieldOffset(20)]
                DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
                [FieldOffset(68)]
                UInt32 flags;
            }        struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
            {
                public UInt64 pixelRate;
                public DISPLAYCONFIG_RATIONAL hSyncFreq;
                public DISPLAYCONFIG_RATIONAL vSyncFreq;
                public DISPLAYCONFIG_2DREGION activeSize;
                public DISPLAYCONFIG_2DREGION totalSize;
                public UInt32 videoStandard;
                public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
            }        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            struct DISPLAYCONFIG_TARGET_MODE
            {
                public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;
            }        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            struct DISPLAYCONFIG_SOURCE_MODE
            {
                public UInt32 width;
                public UInt32 height;
                public DISPLAYCONFIG_PIXELFORMAT pixelFormat;
                public POINTL position;
            }        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
            struct DISPLAYCONFIG_MODE_INFO
            {
                [FieldOffset(0)]
                public DISPLAYCONFIG_MODE_INFO_TYPE infoType;
                [FieldOffset(8)]
                public UInt32 id;
                [FieldOffset(12)]
                public LUID adapterId;            [FieldOffset(16)]
                public DISPLAYCONFIG_TARGET_MODE targetMode;
                [FieldOffset(16)]
                public DISPLAYCONFIG_SOURCE_MODE sourceMode;        }
      

  3.   


            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            class DisplayPathInfos
            {
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
                public DISPLAYCONFIG_PATH_INFO[] DISPLAYCONFIG_PATH_INFO_ARRAY;
            }        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            class DisplayConfigModeInfos
            {
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
                public DISPLAYCONFIG_MODE_INFO[] DISPLAYCONFIG_MODE_INFO_ARRAY;
            }        static UInt32 QDC_ONLY_ACTIVE_PATHS = 0x00000002;
            static UInt32 SDC_TOPOLOGY_INTERNAL = 0x00000001;
            static UInt32 SDC_TOPOLOGY_CLONE = 0x00000002;
            static UInt32 SDC_TOPOLOGY_EXTEND = 0x00000004;
            static UInt32 SDC_TOPOLOGY_EXTERNAL = 0x00000008;
            static UInt32 SDC_TOPOLOGY_SUPPLIED = 0x00000010;
            static UInt32 SDC_USE_DATABASE_CURRENT = (SDC_TOPOLOGY_INTERNAL | SDC_TOPOLOGY_CLONE | SDC_TOPOLOGY_EXTEND | SDC_TOPOLOGY_EXTERNAL);        static UInt32 SDC_USE_SUPPLIED_DISPLAY_CONFIG = 0x00000020;
            static UInt32 SDC_VALIDATE = 0x00000040;
            static UInt32 SDC_APPLY = 0x00000080;
            static UInt32 SDC_NO_OPTIMIZATION = 0x00000100;
            static UInt32 SDC_SAVE_TO_DATABASE = 0x00000200;
            static UInt32 SDC_ALLOW_CHANGES = 0x00000400;
            static UInt32 SDC_PATH_PERSIST_IF_REQUIRED = 0x00000800;
            static UInt32 SDC_FORCE_MODE_ENUMERATION = 0x00001000;
            static UInt32 SDC_ALLOW_PATH_ORDER_CHANGES = 0x00002000;        unsafe delegate UInt32 SETDISPLAYCONFIGFUNC(UInt32 numPathArrayElements,
                                    byte* pathArray,
                                    UInt32 numModeInfoArrayElements,
                                    byte* modeInfoArray,
                                    UInt32 Flags
                                            );        delegate UInt32 GETDISPLAYBUFFERSIZESFUNC(
                                     UInt32 Flags,
                                     ref  UInt32 pNumPathArrayElements,
                                     ref  UInt32 pNumModeInfoArrayElements
                                     );        unsafe delegate UInt32 QUERYDISPLAYCONFIGFUNC(
                                    UInt32 Flags,
                                    ref    UInt32 pNumPathArrayElements,
                                    byte* pPathInfoArray,
                                    ref    UInt32 pNumModeInfoArrayElements,
                                    byte* pModeInfoArray,
                                    IntPtr handler
                                    );        static void Main(string[] args)
            {
                IntPtr hMod = LoadLibrary("user32.dll");
                SETDISPLAYCONFIGFUNC SetDisplayConfig = (SETDISPLAYCONFIGFUNC)GetProcAddress<SETDISPLAYCONFIGFUNC>(hMod, "SetDisplayConfig");
                GETDISPLAYBUFFERSIZESFUNC GetDisplayConfigBufferSizes = (GETDISPLAYBUFFERSIZESFUNC)GetProcAddress<GETDISPLAYBUFFERSIZESFUNC>(hMod, "GetDisplayConfigBufferSizes");
                QUERYDISPLAYCONFIGFUNC QueryDisplayConfig = (QUERYDISPLAYCONFIGFUNC)GetProcAddress<QUERYDISPLAYCONFIGFUNC>(hMod, "QueryDisplayConfig");            if (SetDisplayConfig != null && GetDisplayConfigBufferSizes != null && QueryDisplayConfig != null)
                {
                    UInt32 NumPathArrayElements = 0;
                    UInt32 NumModeInfoArrayElements = 0;
                    if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, ref NumPathArrayElements, ref NumModeInfoArrayElements) != 0)
                    {
                        throw new Exception("");
                    }                DISPLAYCONFIG_PATH_INFO[] pPathInfoArray = new DISPLAYCONFIG_PATH_INFO[100];
                    DISPLAYCONFIG_MODE_INFO[] pModeInfoArray = new DISPLAYCONFIG_MODE_INFO[100];
                    DisplayPathInfos displayPathInfos = new DisplayPathInfos();
                    displayPathInfos.DISPLAYCONFIG_PATH_INFO_ARRAY = pPathInfoArray;                DisplayConfigModeInfos displayConfigModeInfos = new DisplayConfigModeInfos();
                    displayConfigModeInfos.DISPLAYCONFIG_MODE_INFO_ARRAY = pModeInfoArray;                if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, ref NumPathArrayElements, ref NumModeInfoArrayElements) != 0)
                    {
                        throw new Exception("");
                    }
                    DISPLAYCONFIG_TOPOLOGY_ID topLOGYID = DISPLAYCONFIG_TOPOLOGY_ID.DISPLAYCONFIG_TOPOLOGY_CLONE;                byte[] pathArrayBytes = CommonHelper.StrutsToBytesArray(displayPathInfos);
                    byte[] modeInfoArrayBytes = CommonHelper.StrutsToBytesArray(displayConfigModeInfos);                unsafe
                    {
                        fixed (byte* bp = &pathArrayBytes[0])
                        {
                            fixed (byte* bp2 = &modeInfoArrayBytes[0])
                            {                            if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, ref NumPathArrayElements, bp, ref NumModeInfoArrayElements, bp2, IntPtr.Zero) != 0)
                                {
                                    throw new Exception("");
                                }
                            }
                        }
                    }                displayPathInfos = (DisplayPathInfos)CommonHelper.BytesToStruts(pathArrayBytes, typeof(DisplayPathInfos));
                    displayConfigModeInfos = (DisplayConfigModeInfos)CommonHelper.BytesToStruts(modeInfoArrayBytes, typeof(DisplayConfigModeInfos));                displayConfigModeInfos.DISPLAYCONFIG_MODE_INFO_ARRAY[3].sourceMode.position.x = 1920;
                    displayConfigModeInfos.DISPLAYCONFIG_MODE_INFO_ARRAY[3].sourceMode.position.y = 0;                pathArrayBytes = CommonHelper.StrutsToBytesArray(displayPathInfos);
                    modeInfoArrayBytes = CommonHelper.StrutsToBytesArray(displayConfigModeInfos);                unsafe
                    {
                        fixed (byte* bp = &pathArrayBytes[0])
                        {
                            fixed (byte* bp2 = &modeInfoArrayBytes[0])
                            {
                                if (SetDisplayConfig(NumPathArrayElements, bp, NumModeInfoArrayElements, bp2, SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | SDC_SAVE_TO_DATABASE) != 0)
                                {
                                    throw new Exception("");
                                }
                            }
                        }
                    }            }
            }        private static Delegate GetProcAddress<T>(IntPtr lib, string procName) /* where T : Delegate */
            {
                var procAddress = GetProcAddress(lib, procName);            if (procAddress == IntPtr.Zero)
                    return null;            return System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(procAddress, typeof(T));
            }    }
    }

    以下这两句代码是修改位置的,当然这个是根据每台机器显卡接口会变的。
    所以具体怎么改需要你自己调整。
    注意 x 不能有间距也不能重叠。
    displayConfigModeInfos.DISPLAYCONFIG_MODE_INFO_ARRAY[3].sourceMode.position.x = 1920;
                    displayConfigModeInfos.DISPLAYCONFIG_MODE_INFO_ARRAY[3].sourceMode.position.y = 0;
      

  4.   

    晕,主要是这个API比较复杂。其实功能很简单就是修改显示器位置。
    因为在修改分辨率的时候偶尔会把显示器位置切换错误,所以就要重新纠正显示器位置。这个东西这么冷门么?都没人用。。