我已经成为 .NET 开发人员好几年了,但这仍然是我不知道如何正确做的事情之一。通过 Windows 窗体和 WPF 中的属性从任务栏隐藏窗口很容易,但据我所知,这并不能保证(甚至不一定影响)它从任务栏隐藏。 替代+↹选项卡 对话。我见过 无形的 窗口出现在 替代+↹选项卡, ,我只是想知道保证窗口的最佳方法是什么 绝不 出现(可见或不可见)在 替代+↹选项卡 对话。

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

更新2: 现在弗朗西·佩诺夫(Franci Penov)提出了一个看起来不错的解决方案,但我自己还没有尝试过。涉及一些 Win32,但避免了屏幕外窗口的蹩脚创建。

有帮助吗?

解决方案

更新:

根据 @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=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 互操作声明。我已从枚举中删除了所有不必要的样式,只是为了保持此处的示例代码较小。另外,不幸的是 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”和重用它在你的应用程序,需要从隐藏所有窗口的<大骨节病>替代 + <大骨节病>↹Tab

更新:确定所以我所做的就是移动上面的代码,减去this.Owner = w位(和移动w.Hide()后立即w.Show(),其正常工作)到我的应用程序的构造函数,创建一个名为公共静态Window OwnerWindow。每当我想要一个窗口出现此问题,我简单地设置this.Owner = App.OwnerWindow。伟大工程,只有涉及到创建一个额外的(无形)窗口。你甚至可以设置this.Owner = null如果你想在窗口中重新出现在<大骨节病>替代 + <大骨节病>↹Tab对话框。

由于伊万Onuchin超过上MSDN论坛的溶液。

<强>更新2:您还应该设置上ShowInTaskBar=false w以防止它所示,当在任务栏简要地闪烁

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

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

从这里取出点子: http://www.csharp411.com/hide - 形式从 - alttab /

下面是什么做的伎俩,无论您正试图从隐藏窗口的风格的<大骨节病>替代 + <大骨节病>↹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 = “假”:

<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每当它会自动变为真:

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

它完美:)

不显示的形式。使用不可见性。

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

Form1中性能:结果 FormBorderStyle:可调整大小的结果 的WindowState:最小化结果 ShowInTaskbar:假

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表示运行。但是,如果你打开一个表格,该表格仍将遵循的标准功能。

我可以挖我的博客文章中有关创建一个应用程序,如果你想那只是一个NotifyIcon的默认。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top