• 2018-4-15-WPF-在-Alt+Tab-隐藏窗口


    title author date CreateTime categories
    WPF 在 Alt+Tab 隐藏窗口
    lindexi
    2018-04-15 10:13:40 +0800
    2018-3-1 11:32:9 +0800
    WPF

    最近在开发一个 Toast 窗口,因为这个窗口不能在显示之后关闭,因为可能用户会不停让窗口显示,所以只能 Hide 。但是这样会在 切换窗口看到这个窗口,所以我找到了一个方法来让 WPF 窗口不在切换窗口显示。

    现在的 WPF 程序只要设置了不在任务栏显示,而且设置窗口Visibility="Hidden"就可以不在切换窗口显示窗口。设置方法可以是在 xaml 添加下面代码

    ShowInTaskbar="False" Visibility="Hidden"

    但是如大家见到,如果存在 BitmapCache 和 一个隐藏的窗口,那么就会在锁屏之后软件无法渲染,请看github ,所以不要使用这个方法。那么除了这个方法外还有什么方法?

    实际上在切换窗口不显示窗口要求窗口是:WS_EX_TOOLWINDOW 或其他窗口的子窗口,但是可以看到 Toast 不是其他窗口的子窗口,所以只能设置窗口。

    因为只要设置窗口是WS_EX_TOOLWINDOW就不会在切换窗口显示,所以需要使用一些特殊的代码。

    首先在窗口的 Load 之后拿到窗口句柄,注意不是在 SourceInitialized 之后添加的

            public ToastWindow()
            {
                InitializeComponent();
    
                Loaded += ToastWindow_Loaded;
            }

    然后在 Load 里面使用隐藏窗口的代码

            private void HideAltTab()
            {
                var windowInterop = new WindowInteropHelper(this);
                var exStyle = GetWindowLong(windowInterop.Handle, GWL_EXSTYLE);
                exStyle |= WS_EX_TOOLWINDOW;
                Win32.SetWindowLong(windowInterop.Handle, GWL_EXSTYLE, exStyle);
            }

    如果你直接复制上面的代码是无法运行的,因为需要写几个函数

    第一个函数是 ExtendedWindowStyles 请看下面,实际使用 WS_EX_TOOLWINDOW

    <script src="https://gist.github.com/lindexi/21e4e640d53b3dcac3e6a6c69fc09db8.js"></script>

    如果看不到上面的代码,请看ExtendedWindowStyles code from msdn

    #region Window styles
    
        public enum GetWindowLongFields
        {
            // ...
            GWL_EXSTYLE = (-20),
            // ...
        }
    
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
    
        public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
        {
            int error = 0;
            IntPtr result = IntPtr.Zero;
            // Win32 SetWindowLong doesn't clear error on success
            SetLastError(0);
    
            if (IntPtr.Size == 4)
            {
                // use SetWindowLong
                Int32 tempResult = IntSetWindowLong(hWnd, nIndex, IntPtrToInt32(dwNewLong));
                error = Marshal.GetLastWin32Error();
                result = new IntPtr(tempResult);
            }
            else
            {
                // use SetWindowLongPtr
                result = IntSetWindowLongPtr(hWnd, nIndex, dwNewLong);
                error = Marshal.GetLastWin32Error();
            }
    
            if ((result == IntPtr.Zero) && (error != 0))
            {
                throw new System.ComponentModel.Win32Exception(error);
            }
    
            return result;
        }
    
        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
        private static extern IntPtr IntSetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
    
        [DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
        private static extern Int32 IntSetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong);
    
        private static int IntPtrToInt32(IntPtr intPtr)
        {
            return unchecked((int)intPtr.ToInt64());
        }
    
        [DllImport("kernel32.dll", EntryPoint = "SetLastError")]
        public static extern void SetLastError(int dwErrorCode);
        #endregion

    参见:https://stackoverflow.com/a/551847/6116637

  • 相关阅读:
    idea 使用jedis连接不上 redis解决办法
    EFCore 连接 MySql 间歇性报错:你的主机中的软件中止了一个已建立的连接
    初学Ansible(管理Window主机)
    茹炳晟-API自动化测试笔记
    Xpath路径
    kibana Dev Tools --常用命令
    kibana Dev Tools--修改语句示例
    kibana Dev Tools--增删改查语句
    记一次出名记录
    脚本:bat实现自动转换windows远程端口
  • 原文地址:https://www.cnblogs.com/lindexi/p/12086538.html
Copyright © 2020-2023  润新知