从 WPF 窗口隐藏图标

Posted

技术标签:

【中文标题】从 WPF 窗口隐藏图标【英文标题】:Hide the icon from a WPF window 【发布时间】:2013-09-05 23:43:21 【问题描述】:

我知道有很多关于隐藏或删除WPF窗口左上角图标的问题,系统菜单所在的位置。我已经尝试了很多,但没有一个有效。以下是我的要求:

图标消失并且不占用任何空白空间(即没有透明图标) 窗口标题直接从窗口的左边缘开始 右上角的关闭按钮仍然存在并且可以使用 如果启用,最小化/最大化按钮仍然存在(可选,未对此进行测试) 没有自定义绘制整个窗框 在启用 Aero Glass 的 Windows 7 上工作(Windows 8 有人吗?) 适用于 32 位和 64 位 Windows(x86 和 x64 版本) 适用于 WPF .NET 4.0 不在 Visual Studio 之类的调试器中工作(如果它也能在调试器中工作,那就太好了) 应该也适用于 Windows XP(可选)

可用的答案基本上使用Windows API函数GetWindowLongSetWindowLong,有时还使用SetWindowPos来添加扩展窗口样式WS_EX_DLGMODALFRAME并调用SWP_FRAMECHANGED。有时,也会设置或取消设置其他样式。

不幸的是,这些都不起作用。我可以没有没有关闭按钮的图标,或者两者都在那里。但同样值得注意的是,所有这些内容都来自 2010 年或更早。似乎它针对的是早期的 .NET 或 Windows 版本,并且从那以后就失败了。

我已经将系统对话框的窗口样式(来自资源管理器)和我的 WPF 窗口与 Microsoft Spy++(包含在 Visual Studio 中)进行了比较。但我可以尝试将所有标志设置为相同,图标不会消失。这就像黑魔法,凌驾于所有其他 API 函数或物理之上。

有没有人有今天在指定环境中仍然有效的解决方案?

【问题讨论】:

Removing Icon from a WPF window的可能重复 【参考方案1】:

如果您只是将标题中的单词放入搜索引擎,而不是像我刚才所做的那样,那么您会发现比这些更多的结果。你可以在下面找到你的答案:

Removing Icon from a WPF window

Is it possible to display a wpf window without an icon in the title bar?

How to remove the icon of a WPF window

How to remove Icon from window titlebar

How to hide window icon in WPF


您关于这不适用于大型应用程序的最后评论让我想知道。因此,我随后将代码添加到大型应用程序中,它再次运行良好。但是,我继续对此进行测试,而您必须在您的应用程序中使用RibbonWindow,因为当我使用RibbonWindow 在大型应用程序上测试此代码时,代码没有 工作。

如果您使用的是普通的Window,那么试试这个代码(来自@MichalCiechan 对第一个链接帖子的回答):

首先添加这个类:

public static class IconHelper

    [DllImport("user32.dll")]
    static extern int GetWindowLong(IntPtr hwnd, int index);

    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

    [DllImport("user32.dll")]
    static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, 
int y, int width, int height, uint flags);

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr 
lParam);

    const int GWL_EXSTYLE = -20;
    const int WS_EX_DLGMODALFRAME = 0x0001;
    const int SWP_NOSIZE = 0x0001;
    const int SWP_NOMOVE = 0x0002;
    const int SWP_NOZORDER = 0x0004;
    const int SWP_FRAMECHANGED = 0x0020;
    const uint WM_SETICON = 0x0080;

    public static void RemoveIcon(Window window)
    
        // Get this window's handle
        IntPtr hwnd = new WindowInteropHelper(window).Handle;
        // Change the extended window style to not show a window icon
        int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
        SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
        // Update the window's non-client area to reflect the changes
        SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | 
SWP_NOZORDER | SWP_FRAMECHANGED);
    

然后将此添加到MainWindow.xaml.cs:

protected override void OnSourceInitialized(EventArgs e)

    IconHelper.RemoveIcon(this);

哦...还有一件事要注意...如果您设置了 Window.Icon 属性,它将不起作用,但我猜如果您不想要图标。

【讨论】:

抱歉,我都看过了,但没有任何效果。从您的回答中,我看到您没有阅读我的问题,尤其是没有验证这些建议是否确实有效。 奇怪。那为什么它在我的情况下不起作用?也许我应该添加另一个重要要求:在测试用例之外工作,在具有非空窗口且存在多个窗口的实际应用程序中。如果这有帮助的话。 也许 Sheridan 应该编辑第一句话 - 对于未来使用 Google 的读者来说,粗鲁是必要的。 我发现了一个不同之处:只要我的 .exe 文件包含图标资源,该图标就会在窗口中使用。如果我将项目设置保留为“默认图标”并且不将其他非托管图标添加到我的 .exe 文件中,那么它可以工作。但只要有一个图标,它就会显示出来。 @Sheridan “如果您只是将标题中的单词放入搜索引擎,而不是像我刚才所做的那样,那么您会找到比这些更多的结果。” i> - 虽然当时可能有用,但我觉得它不再相关。我在 Google 中使用短语 "hide icon for wpf window" first match 进行了搜索。考虑删除那个第一句【参考方案2】:

从具有图标的 WPF 应用程序创建对话框窗口时,上述方法不起作用。 但是,当添加以下两行时,图标会正确地从对话窗口中消失:

SendMessage(hwnd, WM_SETICON, new IntPtr(1), IntPtr.Zero);
SendMessage(hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero);

(s.a.https://connect.microsoft.com/VisualStudio/feedback/details/745230/wpf-window-cannot-be-displayed-without-titlebar-icon)

【讨论】:

谢谢,这确实有效。似乎需要避免使用 .exe 图标资源。请参阅我对其他答案的评论。 在 MPF 项目系统中使用时,上述代码删除了默认进程图标(VS2013),但在其位置留下了通用图标 非常感谢!我遇到了问题,在启动带有调试器的应用程序时,图标被正确删除,但在没有调试器的情况下启动发布版本时却没有。您的解决方案解决了这个问题!【参考方案3】:

这是我在看到这个问题的不同解决方案后想到的:

    internal const int SWP_NOSIZE = 0x0001;
    internal const int SWP_NOMOVE = 0x0002;
    internal const int SWP_NOZORDER = 0x0004;
    internal const int SWP_FRAMECHANGED = 0x0020;
    internal const int GWL_EXSTYLE = -20;
    internal const int WS_EX_DLGMODALFRAME = 0x0001;

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    [DllImport("user32.dll")]
    internal static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);

    /// <summary>
    /// Hides icon for window.
    /// If this is called before InitializeComponent() then the icon will be completely removed from the title bar
    /// If this is called after InitializeComponent() then an empty image is used but there will be empty space between window border and title
    /// </summary>
    /// <param name="window">Window class</param>
    internal static void HideIcon(this Window window)
    
        if (window.IsInitialized)
        
            window.Icon = BitmapSource.Create(1, 1, 96, 96, PixelFormats.Bgra32, null, new byte[] 0, 0, 0, 0, 4);
        
        else
        
            window.SourceInitialized += delegate
            
                // Get this window's handle
                var hwnd = new WindowInteropHelper(window).Handle;

                // Change the extended window style to not show a window icon
                int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
                SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);

                // Update the window's non-client area to reflect the changes
                SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
            ;
        
    

例子:

public partial class ExampleWindow : Window

    public ExampleWindow()
    
        // Hides icon completely
        this.HideIcon();

        InitializeComponent();
    

【讨论】:

以上是关于从 WPF 窗口隐藏图标的主要内容,如果未能解决你的问题,请参考以下文章

如何从进程中恢复隐藏的 wpf 窗口

如何关闭 WPF 中隐藏的主窗口?

[WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口

隐藏WPF窗口上的最小化最大化按钮

QT:标题栏隐藏图标和隐藏后移动窗口

在空中隐藏新窗口的停靠图标