从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中,有两种从任务切换器隐藏窗口的方法:
- 添加
WS_EX_TOOLWINDOW
扩展窗口样式 – 这是正确的方法。 - 使其成为另一个窗口的子窗口。
不幸的是,WPF不支持像Win32那样对窗口样式进行灵活的控制,因此WindowStyle=ToolWindow
的窗口最终以默认的WS_CAPTION
和WS_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=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互操作声明。 我已经从枚举中删除了所有不必要的样式,只是为了保持示例代码在这里很小。 此外,不幸的是,在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默认情况下,如果你想要的应用程序。