从 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函数GetWindowLong
、SetWindowLong
,有时还使用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 窗口隐藏图标的主要内容,如果未能解决你的问题,请参考以下文章