我已经成为.NET开发人员已有好几年了,这仍然是我不知道如何正确完成的事情之一。通过Windows窗体和WPF中的属性很容易从任务栏隐藏窗口,但据我所知,这并不能保证(或必然会影响)它从 Alt + ↹Tab对话框。我见过隐形窗口显示在 Alt + ↹Tab中,我只是想知道什么是保证窗口的最佳方法永远不会在 Alt + ↹Tab对话框中出现(可见或不可见)。
更新:请参阅下面发布的解决方案。我不允许将自己的答案标记为解决方案,但到目前为止它是唯一有效的答案。
更新2: Franci Penov现在有一个看起来很不错的正确解决方案,但是我自己没试过。涉及一些Win32,但避免了屏幕外窗口的蹩脚创建。
答案 0 :(得分:85)
<强>更新强>
根据@donovan,现代WPF通过设置原生支持
XAML中的ShowInTaskbar="False"
和Visibility="Hidden"
。 (我还没有对此进行测试,但仍决定提高评论的可见性)
原始回答:
在Win32 API中有两种隐藏任务切换器窗口的方法:
WS_EX_TOOLWINDOW
扩展窗口样式 - 这是正确的方法。不幸的是,WPF不支持像Win32一样灵活地控制窗口样式,因此WindowStyle=ToolWindow
的窗口最终会使用默认的WS_CAPTION
和WS_SYSMENU
样式,这会导致它有一个标题和一个关闭按钮。另一方面,您可以通过设置WindowStyle=None
来删除这两种样式,但不会设置WS_EX_TOOLWINDOW
扩展样式,并且不会从任务切换器隐藏窗口。
要使WindowStyle=None
的WPF窗口也在任务切换器中隐藏,可以采用以下两种方式之一:
WS_EX_TOOLWINDOW
扩展样式。我个人更喜欢第二种方法。然后,我做了一些高级的东西,比如在客户区扩展玻璃并在标题中启用WPF绘图,所以一点点互操作不是一个大问题。
以下是Win32互操作解决方案方法的示例代码。首先,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
答案 1 :(得分:37)
在表单类中,添加以下内容:
protected override CreateParams CreateParams
{
get
{
var Params = base.CreateParams;
Params.ExStyle |= 0x80;
return Params;
}
}
就这么简单;有魅力!
答案 2 :(得分:19)
我找到了一个解决方案,但它并不漂亮。到目前为止,这是我尝试过的唯一的实际上有用的东西:
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
找到它here。
更通用,可重复使用的解决方案会很好。我想你可以创建一个单独的窗口'w',并将其重用于应用程序中需要隐藏 Alt + ↹Tab的所有窗口。
更新:好的,我所做的就是移动上面的代码,减去this.Owner = w
位(并在w.Hide()
之后立即移动w.Show()
,这样可以正常工作)进入我的应用程序的构造函数,创建一个名为Window
的公共静态OwnerWindow
。每当我想要一个窗口展示这种行为时,我只需设置this.Owner = App.OwnerWindow
。效果很好,只涉及创建一个额外(和不可见)窗口。如果您希望窗口重新出现在 Alt + ↹Tab对话框中,您甚至可以设置this.Owner = null
。
感谢Ivan Onuchin在MSDN论坛上的解决方案。
更新2:您还应在ShowInTaskBar=false
上设置w
,以防止它在显示时在任务栏中短暂闪烁。
答案 3 :(得分:10)
为什么这么复杂? 试试这个:
me.FormBorderStyle = FormBorderStyle.SizableToolWindow
me.ShowInTaskbar = false
答案 4 :(得分:8)
这就是诀窍,无论你试图隐藏的窗口风格如何 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。最重要的是,它与您的主要表单的样式无关,并且完成隐藏的所有调整只是构造函数代码中的几行。
答案 5 :(得分:3)
为什么要尝试这么多代码?
只需将FormBorderStyle
属性设置为FixedToolWindow
即可。
希望它有所帮助。
答案 6 :(得分:2)
看到它:(来自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);
答案 7 :(得分:1)
在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中显示它,我想,不在任务栏中。
答案 8 :(得分:1)
我尝试将主窗体的可见性设置为false,只要它自动更改为true:
private void Form1_VisibleChanged(object sender, EventArgs e)
{
if (this.Visible)
{
this.Visible = false;
}
}
完美无缺:)
答案 9 :(得分:1)
我试过这个。对我有用
private void Particular_txt_KeyPress(object sender, KeyPressEventArgs e)
{
Form1 frm = new Form1();
frm.Owner = this;
frm.Show();
}
答案 10 :(得分:0)
不要显示表格。使用隐身。
答案 11 :(得分:0)
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;
}>
答案 12 :(得分:0)
如果您希望表单无边框,则需要将以下语句添加到表单的构造函数中:
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;
}
}
答案 13 :(得分:-1)
就个人而言,据我所知,如果不以某种方式挂钩窗户是不可能的,我甚至不确定如何做到这一点或是否有可能。
根据您的需要,将应用程序上下文开发为NotifyIcon(系统托盘)应用程序将允许它在ALT + TAB中显示而不显示。但是,如果您打开表单,该表单仍将遵循标准功能。
如果你愿意,我可以在博客上挖掘一篇关于创建一个默认只有NotifyIcon的应用程序的文章。