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

我几年来一直是一个.NET开发人员,这仍然是我不知道如何正确执行的事情之一。 通过Windows窗体和WPF中的属性隐藏窗口很容易,但据我所知,这并不能保证(或者甚至影响)从Alt + Tab对话框中隐藏窗口。 我看到隐藏的窗口显示在Alt + ↹Tab中 ,我只是想知道什么是保证窗口永远不会出现(可见或不可见)在Alt + ↹Tab对话框中的最佳方法。

更新:请参阅下面我发布的解决scheme。 我不允许将自己的答案标记为解决scheme,但迄今为止,这是唯一可行的解​​决scheme。

更新2: Franci Penov现在有一个合适的解决scheme,看起来不错,但还没有尝试过。 涉及一些Win32,但避免了蹩脚的屏幕窗口创build。

更新:

根据@ donovan的说法,现代的WPF通过在XAML中设置ShowInTaskbar="False"Visibility="Hidden"来支持它。 (我还没有testing过这个,但是还是决定对这个评论的可见度做出反应)

原始答案:

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

  1. 添加WS_EX_TOOLWINDOW扩展窗口样式 – 这是正确的方法。
  2. 使其成为另一个窗口的子窗口。

不幸的是,WPF不支持像Win32那样对窗口样式进行灵活的控制,因此WindowStyle=ToolWindow的窗口最终以默认的WS_CAPTIONWS_SYSMENU样式结束,这样会有一个标题和一个closuresbutton。 另一方面,可以通过设置WindowStyle=None来删除这两个样式,但是不会设置WS_EX_TOOLWINDOW扩展样式,并且不会从任务切换器隐藏窗口。

要使WindowStyle=None的WPF窗口对于任务切换器也是隐藏的,可以采用以下两种方法之一:

  • 去上面的示例代码,使窗口一个小的隐藏工具窗口的子窗口
  • 修改窗口样式还包括WS_EX_TOOLWINDOW扩展样式。

我个人比较喜欢第二种方法。 然后我又做了一些先进的工作,比如在客户区扩展玻璃,并使WPF能够在标题中绘图,所以一点互操作性也不是什么大问题。

以下是Win32 interop解决scheme的示例代码。 首先,XAML部分:

 <Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="300" Width="300" ShowInTaskbar="False" WindowStyle="None" Loaded="Window_Loaded" > 

这里没什么特别的,我们只需要声明一个WindowStyle=NoneShowInTaskbar=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互操作声明。 我已经从枚举中删除了所有不必要的样式,只是为了保持示例代码在这里很小。 此外,不幸的是,在Windows XP上的user32.dll中找不到SetWindowLongPtr入口点,因此调用通过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; } } 

就这么简单 作品魅力!

我find了一个解决scheme,但并不漂亮。 到目前为止,这是我尝试过的唯一实际工作:

 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 

在这里find它。

一个更一般的,可重用的解决scheme将是很好的。 我想你可以创build一个单独的窗口'w',并将其用于你的应用中所有需要隐藏Alt + Tab的窗口

更新:好吧,所以我做的是移动上面的代码,减去this.Owner = w位(和w.Hide()后立即移动w.Show() ,这正常工作w.Show() ,我的应用程序的构造函数,创build一个公共静态Window称为OwnerWindow 。 每当我想要一个窗口来展示这种行为,我只需设置this.Owner = App.OwnerWindow 。 很好的工作,只涉及创build一个额外的(和不可见的)窗口。 你甚至可以设置this.Owner = null如果你想让窗口重新出现在Alt + Tab对话框中。

感谢Ivan Onuchin在MSDN论坛上提供的解决scheme。

更新2:你还应该在w上设置ShowInTaskBar=false ,以防止它在显示时在任务栏中短暂闪烁。

为什么如此复杂? 尝试这个:

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

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

这里有什么技巧,不pipe你试图从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。 最重要的是,主窗体的风格并不重要,所有调整来完成隐藏的只是构造函数代码中的几行。

为什么要这么多的代码? 只需将FormBorderStyle属性设置为FixedToolWindow 。 希望它有帮助。

看到它:(从http://bytes.com/topic/c-sharp/answers/442047-hide-alt-tab-list#post1683880

 [DllImport("user32.dll")] public static extern int SetWindowLong( IntPtr window, int index, int value); [DllImport("user32.dll")] public static extern int GetWindowLong( IntPtr window, int index); const int GWL_EXSTYLE = -20; const int WS_EX_TOOLWINDOW = 0x00000080; const int WS_EX_APPWINDOW = 0x00040000; private System.Windows.Forms.NotifyIcon notifyIcon1; // I use two icons depending of the status of the app normalIcon = new Icon(this.GetType(),"Normal.ico"); alertIcon = new Icon(this.GetType(),"Alert.ico"); notifyIcon1.Icon = normalIcon; this.WindowState = System.Windows.Forms.FormWindowState.Minimized; this.Visible = false; this.ShowInTaskbar = false; iconTimer.Start(); //Make it gone frmo the ALT+TAB int windowStyle = GetWindowLong(Handle, GWL_EXSTYLE); SetWindowLong(Handle, GWL_EXSTYLE, windowStyle | WS_EX_TOOLWINDOW); 

在XAML中设置ShowInTaskbar =“False”:

 <Window x:Class="WpfApplication5.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ShowInTaskbar="False" Title="Window1" Height="300" Width="300"> <Grid> </Grid> </Window> 

编辑:这仍然显示在Alt + Tab我猜,只是不在任务栏。

我试图将主窗体的可见性设置为false,只要它自动更改为true:

 private void Form1_VisibleChanged(object sender, EventArgs e) { if (this.Visible) { this.Visible = false; } } 

它完美的作品:)

不要显示表格。 使用隐形。

更多这里: http : //code.msdn.microsoft.com/TheNotifyIconExample

Form1属性:
FormBorderStyle:很大
WindowState:最小化
ShowInTaskbar:False

 private void Form1_Load(object sender, EventArgs e) { // Making the window invisible forces it to not show up in the ALT+TAB this.Visible = false; }> 

如果您希望表单是无边界的,那么您需要将以下语句添加到表单的构造函数中:

 this.FormBorderStyle = FormBorderStyle.None; this.ShowInTaskbar = false; 

而且您必须将以下方法添加到派生的Form类中:

 protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; // turn on WS_EX_TOOLWINDOW style bit cp.ExStyle |= 0x80; return cp; } } 

更多细节

就个人而言,据我所知,如果没有以某种方式挂在窗户上,这是不可能的,我甚至不知道如何做,或者如果可能的话。

根据您的需要,开发您的应用程序上下文作为NotifyIcon(系统托盘)应用程序将允许它运行,而不显示在ALT + TAB。 但是,如果你打开一个表单,那么这个表单仍然会遵循标准的function。

我可以挖掘我的博客文章关于创build一个只有一个NotifyIcon默认情况下,如果你想要的应用程序。