8

I know that there are many questions about hiding or removing the icon from the upper left corner of a WPF window, the place where the system menu is. I've tried many of them but none works. Here are my requirements:

  • The icon disappears and does not take any empty space (i. e. no transparent icon)
  • The window title starts directly at the left edge of the window
  • The close button in the upper right corner is still there and works
  • Minimise/maximise buttons are still there if enabled (optional, didn't test this)
  • No custom-drawing of the entire window frame
  • Works on Windows 7 with Aero Glass enabled (Windows 8 anybody?)
  • Works on 32 and 64 bit Windows (x86 and x64 build)
  • Works with WPF .NET 4.0
  • Works when not in a debugger like Visual Studio (would be nice if it also works in the debugger)
  • Should also work on Windows XP (optional)

The available answers basically use the Windows API functions GetWindowLong, SetWindowLong and sometimes also SetWindowPos to add the extended window style WS_EX_DLGMODALFRAME and call SWP_FRAMECHANGED. Sometimes, other styles are also set or unset.

Unfortunately, none of this works at all. I can either have no icon with no close button, or both are still there. But it's also noticeable that all of that content is from 2010 or eariler. It seems it's targeted at earlier .NET or Windows versions and fails since.

I've already compared the window styles of system dialogs (from Explorer) and my WPF windows with Microsoft Spy++ (included in Visual Studio). But I can try to set all flags the same, the icon won't go away. It's like black magic that overrules every other API function or physics.

Does anybody have a solution that still works today and in the indicated environment?

ygoe
  • 18,655
  • 23
  • 113
  • 210
  • 1
    possible duplicate of [Removing Icon from a WPF window](http://stackoverflow.com/questions/2341230/removing-icon-from-a-wpf-window) – Gayot Fow Sep 02 '13 at 21:41

3 Answers3

23

If you had just put the words in your title into a search engine instead of here as I just did, then you would have found many more results than these. You can find your answer in the following:

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


Your last comment about this not working on large scale applications made me wonder. As such, I then added the code to a large scale application and once again it worked just fine. However, I continued to test this and you must be using a RibbonWindow in your application, because when I tested this code on a large scale application with a RibbonWindow the code did not work.

If you are using a normal Window then give this code a try (From @MichalCiechan's answer to the first linked post):

First add this class:

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

Then add this to MainWindow.xaml.cs:

protected override void OnSourceInitialized(EventArgs e)
{
    IconHelper.RemoveIcon(this);
}

Oh... and one other thing to note... it won't work if you have set the Window.Icon property, but I'm guessing that you haven't done that if you don't want an icon to appear.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • 2
    Sorry, I've seen them all and nothing works. From your answer, I see that you didn't read my question and especially did not verify that these suggestions actually work. – ygoe Sep 03 '13 at 06:23
  • 1
    Strange. Then why doesn't it work in my case? Maybe I should add another important requirement: Works outside of test cases, in real-world applications that have non-empty windows and where multiple windows exist. If that helps at all. – ygoe Sep 03 '13 at 18:29
  • 3
    Maybe Sheridan should edit the first sentence - the rudeness is necessary for future readers who did use Google to get here. – Robin Mar 10 '14 at 10:23
  • 2
    I have found a difference: As soon as my .exe file contains an icon resource, the icon will be used in the window. If I leave the project setting to "default icon" and do not add other unmanaged icons to my .exe file, then it works. But as soon as a single icon is there, it is displayed. – ygoe Sep 04 '14 at 11:03
  • 6
    @Sheridan _"If you had just put the words in your title into a search engine instead of here as I just did, then you would have found many more results than these."_ - though probably useful at the time, I feel it is no longer relevant. My search with **Google** with the phrase _"hide icon for wpf window"_ **first match** landed here. Consider **removing** that **first sentence**. –  Nov 03 '14 at 05:03
  • The fact that this question now appears in the search results is irrelevant... anyone searching with the words in the title will still find *many more results* than shown here. – Sheridan Nov 03 '14 at 12:38
14

The above does not work, when creating a dialog window from a WPF application having an icon. However, when adding the following two lines, the icon correctly vanishes from the dialog window:

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)

o-toole-kit
  • 156
  • 1
  • 2
  • 1
    Thank you, this does indeed work. It seems to be required to avoid the .exe icon resource to be used. See my comment on the other answer. – ygoe Sep 04 '14 at 11:05
  • When used in a MPF project system, the above code removed the default process icon (VS2013) but left a generic icon in its place –  Nov 03 '14 at 05:23
  • Thanks a lot! I had the problem, that the icon was removed correctly when starting the application with debugger attached but not when starting a release build without debugger. Your solution fixed that! – JanDotNet Nov 22 '16 at 11:26
  • Microsoft has baleeted all Connect content. Where do these SendMessage lines go?? – Jonathan Gilbert Nov 15 '22 at 00:38
2

This is what I came up with after seeing different solutions to this question:

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

Example:

public partial class ExampleWindow : Window
{
    public ExampleWindow()
    {
        // Hides icon completely
        this.HideIcon();

        InitializeComponent();
    }
}
SameOldNick
  • 2,397
  • 24
  • 33