本文分享下回到桌面功能的實作方法,效果與快捷鍵(Win+D)相同,
實作方法
Windows回到桌面功能的實作方式有多種,可以模擬快捷鍵,也可以執行如下方法,其中方法一需要參考Shell32.dll,方法為添加參考,選擇COM找到"Microsoft Shell Controls and Automation",選中并確認,還需要將其嵌入互操作型別置為false,
// 方法一,[參考鏈接](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[] { });
問題
正常情況下,這兩個方法都可以成功執行,
但是,今天碰到一臺設備操作未成功,場景是WPF應用收到udp訊息時,執行回到桌面操作失敗,
看到有網友說執行上述代碼時,需在STA thread中執行,否則會報錯,方法一是需要在STA thread中執行的,但是并不能解決該問題,
再次分析問題時發現,當WPF應用為當前活動視窗時,操作執行成功,否則執行失敗,因此,先激活視窗,再執行上述代碼就可以成功解決該問題了,
在出問題的設備上,使用簡單的Show()、Active()方法激活視窗是不行的,只會在任務欄閃爍圖示,使用大佬提供的激活視窗的方法可以成功激活,
該問題的難點在于并不是所有設備都存在該問題,我手中有兩臺設備,作業系統是一樣的,但一臺是好的,一臺是不行的,出問題的設備代碼是執行了的,不知道為什么沒有效果,必須將應用置為活動視窗才行,有了解該問題的小伙伴歡迎討論,
本文測驗demo的部分代碼如下,詳細可見Github,
// 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 = https://www.cnblogs.com/louzixl/p/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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/285418.html
標籤:WPF
上一篇:WPF加載高德地圖
