本文分享下回到桌面功能的實現方法,效果與快捷鍵(Win+D)相同。git
Windows回到桌面功能的實現方式有多種,能夠模擬快捷鍵,也能夠執行以下方法。其中方法一須要引用Shell32.dll,方法爲添加引用,選擇COM找到"Microsoft Shell Controls and Automation",選中並確認,還須要將其嵌入互操做類型置爲false。github
// 方法一,[參考連接](https://stackoverflow.com/questions/41598951/programmatically-show-the-desktop) Shell32.ShellClass objShel = new Shell32.ShellClass(); objShel.ToggleDesktop(); // 方法二,[參考連接](https://social.msdn.microsoft.com/Forums/vstudio/en-US/a27ca1e4-bd02-434b-8d02-06553c35f3d5/show-desktop-program-no-working) Type shellType = Type.GetTypeFromProgID("shell.application"); object shell = Activator.CreateInstance(shellType); shellType.InvokeMember("ToggleDesktop", BindingFlags.InvokeMethod, null, shell, new object[] { });
正常狀況下,這兩個方法均可以成功執行。shell
可是,今天碰到一臺設備操做未成功。場景是WPF應用收到udp消息時,執行回到桌面操做失敗。app
看到有網友說執行上述代碼時,需在STA thread中執行,不然會報錯。方法一是須要在STA thread中執行的,可是並不能解決該問題。測試
再次分析問題時發現,當WPF應用爲當前活動窗口時,操做執行成功,不然執行失敗。所以,先激活窗口,再執行上述代碼就能夠成功解決該問題了。this
在出問題的設備上,使用簡單的Show()、Active()方法激活窗口是不行的,只會在任務欄閃爍圖標,使用大佬提供的激活窗口的方法能夠成功激活。spa
該問題的難點在於並非全部設備都存在該問題,我手中有兩臺設備,操做系統是同樣的,但一臺是好的,一臺是不行的。出問題的設備代碼是執行了的,不知道爲何沒有效果,必須將應用置爲活動窗口才行,有了解該問題的小夥伴歡迎討論。操作系統
本文測試demo的部分代碼以下,詳細可見Github。.net
// Wpf主窗口 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); InitLogger(); InitUdpThread(); showDesktop = Method1; Logger.LogMessage(Severity.Info, $"start process, Main Thread id: {Thread.CurrentThread.ManagedThreadId}"); } private void InitLogger() { var file = new FileLogger("log.txt"); Logger.LogMessage(Severity.Info, "Init logger success"); } private void InitUdpThread() { Thread udpThread = new Thread(new ThreadStart(GetUdpMessage)); udpThread.IsBackground = true; udpThread.Start(); } private void GetUdpMessage() { UdpClient udpClient = null; try { udpClient = new UdpClient(10001); } catch (Exception) { Logger.LogMessage(Severity.Error, "create udp client failed"); return; } Logger.LogMessage(Severity.Info, "create udp client success"); IPEndPoint remotePoint = null; while (true) { try { byte[] receiveData = udpClient.Receive(ref remotePoint); string receiveString = Encoding.Default.GetString(receiveData); Logger.LogMessage(Severity.Info, $"receive udp message: {receiveString}"); if (receiveString.ToLower().Contains("showdesktop")) showDesktop?.Invoke(); } catch (Exception e) { Logger.LogMessage(Severity.Error, e.Message); } } } private void Button_Click(object sender, RoutedEventArgs e) { if (sender is Button btn) { switch (btn.Name) { case "method1": showDesktop = Method1; Logger.LogMessage(Severity.Info, "turn to method1"); break; case "method2": showDesktop = Method2; Logger.LogMessage(Severity.Info, "turn to method2"); break; case "activeFirst": showDesktop = ActiveFirst; Logger.LogMessage(Severity.Info, "turn to activeFirst method"); break; default: break; } } } private void Method1() { Thread newSta = new Thread(()=> { Shell32.ShellClass objShel = new Shell32.ShellClass(); objShel.ToggleDesktop(); Logger.LogMessage(Severity.Info, $"Current Thread id: {Thread.CurrentThread.ManagedThreadId}"); }); newSta.TrySetApartmentState(ApartmentState.STA); newSta.Start(); } private void Method2() { Type shellType = Type.GetTypeFromProgID("Shell.Application"); object shellObject = System.Activator.CreateInstance(shellType); shellType.InvokeMember("ToggleDesktop", System.Reflection.BindingFlags.InvokeMethod, null, shellObject, null); Logger.LogMessage(Severity.Info, $"Current Thread id: {Thread.CurrentThread.ManagedThreadId}"); } private void ActiveFirst() { App.Current.Dispatcher.Invoke(new Action(() => { Win32Api.SetWindowToForegroundWithAttachThreadInput(this); Method2(); })); } private Action showDesktop; }