2018-4-15-WPF-at-Alt+Tab-hide window

title author date CreateTime categories
WPF hide window in Alt+Tab
lindexi
2018-04-15 10:13:40 +0800
2018-3-1 11:32:9 +0800
WPF

Recently, we are developing a Toast window, because this window cannot be closed after display, because the user may keep the window displayed, so only Hide. But I will see this window in the switch window, so I found a way to make WPF window not display in the switch window.

Now, as long as the WPF program is set not to be displayed in the taskbar, and the window Visibility="Hidden" is set, it can not be displayed in the switching window. The setting method can be to add the following code in xaml

ShowInTaskbar="False" Visibility="Hidden"

But as you can see, if there is BitmapCache and a hidden window, the software cannot render after the screen is locked. Please see github , so don't use this method. So what else is there besides this method?

In fact, when switching between windows and not displaying windows, windows are required to be: WS_EX_TOOLWINDOW or other window's child window, but you can see that Toast is not a child window of other windows, so you can only set the window.

Because as long as the window is set to WS_EX_TOOLWINDOW will not be displayed in the switching window, so you need to use some special code.

First, get the window handle after the Load of the window. Note that it is not added after SourceInitialized

public ToastWindow()
        {
            InitializeComponent();

            Loaded += ToastWindow_Loaded;
        }

Then use the code of hidden window in 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);
        }

If you copy the above code directly, you can't run it, because you need to write several functions

The first function is ExtendedWindowStyles. Please see below. Actually, WS is used_ EX_ TOOLWINDOW

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

If you can't see the code above, look 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

See: https://stackoverflow.com/a/551847/6116637

Tags: Windows github

Posted on Sun, 31 May 2020 09:09:43 -0400 by avvishnu