105

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

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

更新 2: Franci Penov 现在有一个看起来不错的适当解决方案,但我自己还没有尝试过。涉及到一些 Win32,但避免了离屏窗口的蹩脚创建。

4

14 回答 14

103

更新:

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

原答案:

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

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

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

要使 WPF 窗口WindowStyle=None也从任务切换器中隐藏,可以采用以下两种方式之一:

  • 使用上面的示例代码,使窗口成为一个小隐藏工具窗口的子窗口
  • 修改窗口样式以包括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=Noneand声明一个窗口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
于 2009-02-15T23:36:23.280 回答
44

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

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

就这么简单;很有魅力!

于 2013-07-27T02:19:37.730 回答
21

我找到了一个解决方案,但它并不漂亮。到目前为止,这是我尝试过的唯一真正有效的方法:

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=falseonw以防止它在显示时在任务栏中短暂闪烁。

于 2008-12-10T21:00:35.213 回答
14

这就是诀窍,无论您试图从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。最重要的是,主窗体的样式并不重要,完成隐藏的所有调整只是构造函数代码中的几行代码。

于 2010-04-30T03:33:46.087 回答
12

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

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

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

于 2010-04-23T11:35:27.963 回答
3

看到它:(来自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);
于 2010-05-11T13:09:37.537 回答
3

为什么要尝试这么多代码?只需将FormBorderStyle属性设置为FixedToolWindow. 希望能帮助到你。

于 2012-02-22T11:21:53.150 回答
2

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

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

它完美地工作:)

于 2011-01-02T16:27:19.400 回答
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 中,只是不在任务栏中。

于 2008-12-10T19:25:01.270 回答
1

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

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;
    }
}

更多细节

于 2012-09-27T18:50:13.920 回答
1

我试过这个。这个对我有用

  private void Particular_txt_KeyPress(object sender, KeyPressEventArgs e)
    {
        Form1 frm = new Form1();         
        frm.Owner = this;
        frm.Show();
    }
于 2021-01-28T13:02:09.003 回答
0

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

更多信息:http: //code.msdn.microsoft.com/TheNotifyIconExample

于 2008-12-29T16:32:36.940 回答
-1

就我个人而言,如果不以某种方式连接到窗口,这是不可能的,我什至不确定这将如何完成或是否可能。

根据您的需要,将您的应用程序上下文开发为 NotifyIcon(系统托盘)应用程序将允许它在不显示在 ALT + TAB 中的情况下运行。但是,如果您打开一个表单,该表单仍将遵循标准功能。

如果需要,我可以挖掘我的博客文章,了解如何创建默认情况下只有 NotifyIcon 的应用程序。

于 2008-12-10T19:02:58.570 回答
-1

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;
}>
于 2009-04-23T20:38:40.857 回答