当前位置:  开发笔记 > Android > 正文

从Alt-Tab程序切换器隐藏窗口的最佳方法是什么?

如何解决《从Alt-Tab程序切换器隐藏窗口的最佳方法是什么?》经验,为你挑选了5个好方法。

我已经成为.NET开发人员已有好几年了,这仍然是我不知道如何正确完成的事情之一.通过Windows窗体和WPF中的属性很容易从任务栏隐藏窗口,但据我所知,这并不能保证(或必然会影响)它从Alt+ ↹Tab对话框中隐藏.我已经看到隐形窗口显示在Alt+中↹Tab,我只是想知道什么是保证窗口永远不会出现(可见或不可见)Alt+ ↹Tab对话框的最佳方法.

更新:请参阅下面我发布的解决方案.我不允许将自己的答案标记为解决方案,但到目前为止,它是唯一有效的解决方案.

更新2:弗朗西·佩诺夫现在有一个看起来很不错的正确解决方案,但我自己没有尝试过.涉及一些Win32,但避免了屏幕外窗口的蹩脚创建.



1> Franci Penov..:

更新:

根据@donovan,现代WPF通过设置ShowInTaskbar="False"Visibility="Hidden"XAML 本地支持这一点 .(我还没有对此进行测试,但仍然决定提高评论的可见性)

原始答案:

在Win32 API中有两种方法可以从任务切换器隐藏窗口:

    添加WS_EX_TOOLWINDOW扩展窗口样式 - 这是正确的方法.

    使它成为另一个窗口的子窗口.

不幸的是,WPF不支持像Win32一样灵活地控制窗口样式,因此窗口WindowStyle=ToolWindow最后会显示默认WS_CAPTIONWS_SYSMENU样式,这会导致它有一个标题和一个关闭按钮.另一方面,您可以通过设置删除这两种样式WindowStyle=None,但是不会设置WS_EX_TOOLWINDOW扩展样式,并且不会从任务切换器隐藏窗口.

WindowStyle=None在任务切换器中隐藏一个带有WPF窗口的WPF窗口,可以采用以下两种方式之一:

使用上面的示例代码,使窗口成为一个小隐藏工具窗口的子窗口

修改窗口样式也包括WS_EX_TOOLWINDOW扩展样式.

我个人更喜欢第二种方法.然后,我做了一些高级的事情,比如在客户区扩展玻璃并在标题中启用WPF绘图,所以一点点互操作不是一个大问题.

这是Win32互操作解决方案方法的示例代码.首先,XAML部分:


这里没什么太花哨的,我们只是用WindowStyle=None和声明一个窗口ShowInTaskbar=False.我们还为Loaded事件添加了一个处理程序,我们将修改扩展窗口样式.我们不能在构造函数中完成这项工作,因为那时还没有窗口句柄.事件处理程序本身非常简单:

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        WindowInteropHelper wndHelper = new WindowInteropHelper(this);

        int exStyle = (int)GetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE);

        exStyle |= (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW;
        SetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
    }

和Win32互操作声明.我已从枚举中删除了所有不必要的样式,只是为了使示例代码保持较小.此外,遗憾的SetWindowLongPtr是,在Windows XP上的user32.dll中找不到入口点,因此通过SetWindowLong而不是路由调用.

    #region Window styles
    [Flags]
    public enum ExtendedWindowStyles
    {
        // ...
        WS_EX_TOOLWINDOW = 0x00000080,
        // ...
    }

    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


@ J4N - 偶尔会有一些P/Invoke出现问题:-)
没有验证这一点,但听起来你知道你在说什么.:)如果我需要再次这样做,我会记住这一点,但是因为我的其他解决方案工作正常(自从我关闭这本书以来已经有一段时间了)我不想弄乱和破坏某些东西.谢谢!

2> Danny Becket..:

在表单类中,添加以下内容:

protected override CreateParams CreateParams
{
    get
    {
        var Params = base.CreateParams;
        Params.ExStyle |= 0x80;
        return Params;
    }
}

就这么简单; 有魅力!


还需要将ShowInTaskbar设置为false才能使其正常工作.
对我来说很棒.

3> devios1..:

我找到了一个解决方案,但它并不漂亮.到目前为止,这是我尝试过的唯一可行的方法:

Window w = new Window(); // Create helper window
w.Top = -100; // Location of new window is outside of visible part of screen
w.Left = -100;
w.Width = 1; // size of window is enough small to avoid its appearance at the beginning
w.Height = 1;
w.WindowStyle = WindowStyle.ToolWindow; // Set window style as ToolWindow to avoid its icon in AltTab 
w.Show(); // We need to show window before set is as owner to our main window
this.Owner = w; // Okey, this will result to disappear icon for main window.
w.Hide(); // Hide helper window just in case

在这里找到它.

更通用,可重复使用的解决方案会很好.我想你可以创建一个单独的窗口'w',并将其重用于应用程序中需要隐藏Alt+的所有窗口↹Tab.

更新:好了,所以我所做的就是移动上面的代码,减去this.Owner = w位(和移动w.Hide()w.Show(),其正常工作)到我的应用程序的构造,建立一个公共静态WindowOwnerWindow.每当我想要一个窗口展示这种行为时,我只需设置this.Owner = App.OwnerWindow.效果很好,只涉及创建一个额外(和不可见)窗口.您甚至可以设置this.Owner = null是否要在Alt+ ↹Tab对话框中重新显示该窗口.

感谢Ivan Onuchin在MSDN论坛上的解决方案.

更新2:您还应该ShowInTaskBar=false启用w以防止它在显示时在任务栏中短暂闪烁.



4> 小智..:

为什么这么复杂?试试这个:

me.FormBorderStyle = FormBorderStyle.SizableToolWindow
me.ShowInTaskbar = false

从这里获取的想法:http://www.csharp411.com/hide-form-from-alttab/



5> 小智..:

下面是什么呢,无论你正试图从隐藏窗口的风格的伎俩,Alt+ ↹Tab.

将以下内容放入表单的构造函数中:

// Keep this program out of the Alt-Tab menu

ShowInTaskbar = false;

Form form1 = new Form ( );

form1.FormBorderStyle = FormBorderStyle.FixedToolWindow;
form1.ShowInTaskbar = false;

Owner = form1;

基本上,您使表单成为不可见窗口的子窗口,该窗口具有正确的样式和ShowInTaskbar设置,以使其不在Alt-Tab列表之外.您还必须将自己的表单的ShowInTaskbar属性设置为false.最重要的是,它与您的主要表单的样式无关,并且完成隐藏的所有调整只是构造函数代码中的几行.

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有