我已经成为.NET开发人员已有好几年了,这仍然是我不知道如何正确完成的事情之一.通过Windows窗体和WPF中的属性很容易从任务栏隐藏窗口,但据我所知,这并不能保证(或必然会影响)它从Alt+ ↹Tab对话框中隐藏.我已经看到隐形窗口显示在Alt+中↹Tab,我只是想知道什么是保证窗口永远不会出现(可见或不可见)Alt+ ↹Tab对话框的最佳方法.
更新:请参阅下面我发布的解决方案.我不允许将自己的答案标记为解决方案,但到目前为止,它是唯一有效的解决方案.
更新2:弗朗西·佩诺夫现在有一个看起来很不错的正确解决方案,但我自己没有尝试过.涉及一些Win32,但避免了屏幕外窗口的蹩脚创建.
更新:
根据@donovan,现代WPF通过设置ShowInTaskbar="False"
和Visibility="Hidden"
XAML 本地支持这一点
.(我还没有对此进行测试,但仍然决定提高评论的可见性)
原始答案:
在Win32 API中有两种方法可以从任务切换器隐藏窗口:
添加WS_EX_TOOLWINDOW
扩展窗口样式 - 这是正确的方法.
使它成为另一个窗口的子窗口.
不幸的是,WPF不支持像Win32一样灵活地控制窗口样式,因此窗口WindowStyle=ToolWindow
最后会显示默认WS_CAPTION
和WS_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
在表单类中,添加以下内容:
protected override CreateParams CreateParams { get { var Params = base.CreateParams; Params.ExStyle |= 0x80; return Params; } }
就这么简单; 有魅力!
我找到了一个解决方案,但它并不漂亮.到目前为止,这是我尝试过的唯一可行的方法:
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()
,其正常工作)到我的应用程序的构造,建立一个公共静态Window
叫OwnerWindow
.每当我想要一个窗口展示这种行为时,我只需设置this.Owner = App.OwnerWindow
.效果很好,只涉及创建一个额外(和不可见)窗口.您甚至可以设置this.Owner = null
是否要在Alt+ ↹Tab对话框中重新显示该窗口.
感谢Ivan Onuchin在MSDN论坛上的解决方案.
更新2:您还应该ShowInTaskBar=false
启用w
以防止它在显示时在任务栏中短暂闪烁.
为什么这么复杂?试试这个:
me.FormBorderStyle = FormBorderStyle.SizableToolWindow me.ShowInTaskbar = false
从这里获取的想法:http://www.csharp411.com/hide-form-from-alttab/
下面是什么呢,无论你正试图从隐藏窗口的风格的伎俩,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.最重要的是,它与您的主要表单的样式无关,并且完成隐藏的所有调整只是构造函数代码中的几行.