• 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;
    }
    
    转载请注明出处,欢迎交流。
  • 相关阅读:
    HTML 常见标签part1
    HTML 初始
    jenkins远程执行脚本不退出
    jenkins 持续集成工具安装
    jenkins 杀掉衍生进程解决办法
    日志分割工具-crononlog
    可视化库 pygal 生成png中文乱码
    可视化库 pygal 无法保存成本地文件
    一个很好用的ORM库--peewee
    3 种进度条 -- 记录
  • 原文地址:https://www.cnblogs.com/louzixl/p/14810338.html
Copyright © 2020-2023  润新知