In general, you should have windows that show both a window icon and a system menu. Having a window icon helps the user determine where they click to get the system menu (the window icon) and where they double click to maximize/restore their window (the area not taken up by the window icon and the minimize, restore, maximize, and close buttons).
Still, there are scenarios where folks really really don't want to show the window icon. And System.Windows.Forms.Form has the ShowIcon property because folks really really don't want to show the window icon. This post is for them 🙂
By default, if you don't specify an icon for a WPF Window, WPF will show an icon anyway, as determined by the algorithm described here. To override this behavior, you can use a p/invoke your way to an icon-less lifestyle using code like the following:
<!-- MainWindow.xaml -->
Title="<-- No Icon Here!"
using System; // IntPtr
using System.Windows; // Window, RoutedEventArgs
using System.Windows.Interop; // WindowInteropHelper
using System.Runtime.InteropServices; // DllImportAttribute
public partial class MainWindow : Window
static extern int GetWindowLong(IntPtr hwnd, int index);
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
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;
protected override void OnSourceInitialized(EventArgs e)
// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(this).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);
This has the effect that is demonstrated by the following figure.
In general, p/invoking to override default WPF Window behavior is totally fun, but possibly fraught with danger since WPF is essentially hWnd less ie you might do stuff to a WPF Window that makes it look weird, or that WPF simply ignores and overrides. Depending on your users, of course, weird may be good. But, nobody likes to be ignored 🙂
PS The sample with the code above is attached to this post.