close

 

■ 參考資料

 Disconnect and Reconnect Displays Programmatically  

● How do I enable a second monitor in C#?

● How to disable a secondary monitor (with ChangeDisplaySettingsEx)?
● Use Windows API from C# to set primary monitor

 

程式片段

需要下載底下兩個project並build出 dll ,開關外接螢幕需要使用到裡面的function

https://github.com/Jaykul/MultiMonitorHelper/tree/master/MultiMonitorHelper

https://github.com/regueiro/CCDWrapper/tree/master/CCDWrapper

●主程式 ( WPF )
using MultiMonitorHelper;

 public MainWindow()
 {
            InitializeComponent();

            IDisplayModel displayModel = DisplayFactory.GetDisplayModel();
            List<Display> displayList = displayModel.GetActiveDisplays().ToList();
            displayList[0].DisconnectDisplay(1); // 關閉外接螢幕 , 1是外接螢幕的DisplayNumber

            

            //等待12秒,讓外接螢幕有時間進入power save mode(沒有backlight),我使用的外接螢幕

            //會有提示將進入power save mode;進入後螢幕的power 鍵轉成呼吸燈號模式
            System.Threading.Thread.Sleep(12000); 
           

            displayList[0].ReconnectDisplays();

  }

 

  --------------------------------------------------------------------------------------------------------------------------
●MultiMonitorHelper-master\MultiMonitorHelper\Display.cs

加上底下兩個method

 public void ReconnectDisplays()
 {         

            //底下DisplaySwitch.exe這段方法是網友提供的

            //這是windows內建的程式 ,執行後會出現像下圖的東西 ,等同於按 win +p 

            //但實際上這方法對已經進入powersave mode的外接螢幕沒轍

            //執行程式後沒辦法 wake 外接螢幕  

            //保留在這邊讓其他人少走一點冤枉路
             /*Process DisplayChanger = new Process
            {
                StartInfo =
            {
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden,
                FileName = @"C:\Windows\Sysnative\DisplaySwitch.exe",
                Arguments = "/clone"   //extend
            }
            };
            DisplayChanger.Start();*/

            //******************************************************************************************

            int id = 1;
            var device = new DisplayDevice();
            var deviceMode = new DevMode();
            device.cb = Marshal.SizeOf(device);

            XPWrapper.EnumDisplayDevices(null, id, ref device, 0);
            XPWrapper.EnumDisplaySettings(device.DeviceName, -1, ref deviceMode);

            XPWrapper.ChangeDisplaySettingsEx(
                device.DeviceName,
                ref deviceMode,
                (IntPtr)null,
                (CdsFlags.UpdateRegistry | CdsFlags.Noreset),
                IntPtr.Zero);

            //紅字這段很重要一定要加,這是為了讓ChangeDisplaySettingsEX生效用的

            //附上網友這段話,寫得很清楚
             //for some weird reason, you must first store the change in the registry
             
//(with or without CDS_NORESET, it doesn't matter),
             
//and then use again ChangeDisplaySettingsEx with NULL values to make the changes happen.
             
//This might have something to do both monitors connected to the same display device, I'm not sure...
            //還沒看到這段話之前, survey資料的時候看到其他人這樣使用還不知道原因是什麼咧
...
               //這也可以解釋為什麼在MultiMonitorHelper-master\MultiMonitorHelper\DisplayModels\XP\XPWrapper.cs

            //要宣告兩個 ChangeDisplaySettingsEx (如下)

/*[DllImport("user32.dll", CharSet = CharSet.Ansi)]
       public static extern DispChange ChangeDisplaySettingsEx(string deviceName, ref DevMode lpDevMode,
            IntPtr hwnd, CdsFlags dwflags, IntPtr lParam);

// A signature for ChangeDisplaySettingsEx with a DevMode struct as the second parameter won't allow you to pass in IntPtr.Zero,  so create an overload

 [DllImport("user32.dll", CharSet = CharSet.Ansi)]
        public static extern DispChange ChangeDisplaySettingsEx(string deviceName, IntPtr devmode,
            IntPtr hwnd, CdsFlags dwflags, IntPtr lParam);*/

            // Apply settings
            XPWrapper.ChangeDisplaySettingsEx(null, IntPtr.Zero, (IntPtr)null, CdsFlags.None, (IntPtr)null);


            // ReconnectDisplay
            Wrapper.SetDisplayConfig(0, IntPtr.Zero, 0, IntPtr.Zero, (SdcFlags.Apply | SdcFlags.AllowChanges | SdcFlags.UseSuppliedDisplayConfig));

        }

public void DisconnectDisplay(int displayNumber)
 {
            // Get the necessary display information
            int numPathArrayElements = -1;
            int numModeInfoArrayElements = -1;
            StatusCode error = Wrapper.GetDisplayConfigBufferSizes(
               QueryDisplayFlags.OnlyActivePaths,
               out numPathArrayElements,
               out numModeInfoArrayElements);

            DisplayConfigPathInfo[] pathInfoArray = new DisplayConfigPathInfo[numPathArrayElements];
            DisplayConfigModeInfo[] modeInfoArray = new DisplayConfigModeInfo[numModeInfoArrayElements];
            error = Wrapper.QueryDisplayConfig(
               QueryDisplayFlags.OnlyActivePaths,
               ref numPathArrayElements,
               pathInfoArray,
               ref numModeInfoArrayElements,
               modeInfoArray,
               IntPtr.Zero);
            if (error != StatusCode.Success)
            {
                Console.WriteLine("error=" + error);
                // QueryDisplayConfig failed
            }

            // Check the index
            if (pathInfoArray[displayNumber].sourceInfo.modeInfoIdx < modeInfoArray.Length)
            {
                // Disable and reset the display configuration
                pathInfoArray[displayNumber].flags = DisplayConfigFlags.Zero;
                error = Wrapper.SetDisplayConfig(
                    pathInfoArray.Length,
                    pathInfoArray,
                    modeInfoArray.Length,
                    modeInfoArray,
                    (SdcFlags.Apply | SdcFlags.AllowChanges | SdcFlags.UseSuppliedDisplayConfig));
                if (error != StatusCode.Success)
                {
                    // SetDisplayConfig failed
                }
            }
}


  --------------------------------------------------------------------------------------------------------------------------

●其他

過程中一定會有build error , 但都是很好解決的問題

比如:

無法存取其他class成員(改成public即可)

找不到變數(因為程式碼我有做一點更動,所以其他地方也要做相對應的修改)

 

工程師除了要會上網google程式碼複製貼上

另外一定要有解決build error的能力

在這邊就不贅述解法


 


 

 
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 iam9527 的頭像
    iam9527

    翁丸的育兒筆記

    iam9527 發表在 痞客邦 留言(0) 人氣()