乐趣区

关于WPF:Win32Api-回到Windows桌面

本文分享下回到桌面性能的实现办法,成果与快捷键(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 = 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;
}
退出移动版