• 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

  • 相关阅读:
    poj 2676 Suduku (dfs)
    poj 1562 Oil Deposits (dfs)
    poj 2907 Collecting Beepers (dfs)
    poj 1655 Balancing Act (树形dfs)
    poj 3411 Paid Roads (dfs)
    hdu 2896 病毒侵袭 (AC)
    hdu 3065 病毒侵袭持续中 (AC)
    poj 2251 Dungeon Master (bfs)
    java中debug使用
    Swing入门级小项目总结
  • 原文地址:https://www.cnblogs.com/lindexi/p/12086539.html
Copyright © 2020-2023  润新知