2

I recently implemented the solutions from this question to hide a WPF Window's icon. I found that when that solution is used in conjunction with ResizeMode=NoResize, the app's title bar context menu fails to disable Min/Max/Resize options.

The odd thing is the context menu doesn't incorrectly enable certain options, it just leaves the state of the context menu from before the icon was hidden. I found this using a simple test app that can make the necessary calls to hide the icon, and can update the Window's ResizeMode on the fly.

Icon Shown, ResizeMode=CanResize

Title bar buttons and context menu are correct.

enter image description here

Icon Hidden, ResizeMode=CanResize

Still correct

enter image description here

Icon Hidden, ResizeMode=NoResize

Title bar buttons are correctly hidden, but the context menu retains it's previous state. If I switch to CanMinimize then to NoResize, the context menu would only have "Minimize" enabled.

enter image description here

This becomes a problem when a resize-able WPF Window launches another Window which is set to NoResize (and you are hiding the icon).

Question

Are there additional Windows API functions that can force the Context Menu to reevaluate its state? What about the NoResize option might be causing this weird behavior? As this only affects the NoResize option, could there be a workaround at the WPF level?

EDIT - My goal is to avoid using WindowStyle=ToolWindow or the WS_EX_TOOLWINDOW extended window style. I've found a few problems with that window style in the past, one is desribed on this question. One of my goals with this whole approach was to emulate the look of ToolWindow without actually having to use it.

Community
  • 1
  • 1
Michael
  • 426
  • 3
  • 12
  • Which solution did you adopt? o-toole-kit's or Sheridan's one? – Il Vic Oct 21 '16 at 13:01
  • A combination. I do `SetWindowLong...SendMessage...SendMessage...SetWindowPos`. Using just one or the other didn't seem to work. – Michael Oct 21 '16 at 13:04

1 Answers1

1

Using .NET 4.0 and Windows 8.1 Enterprise (I do not know if it works with other .NET versions or a different OS), you just need to use the WS_EX_TOOLWINDOW extended style instead of the WS_EX_DLGMODALFRAME one.

So the code will be:

public partial class MainWindow : Window
{
    [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);

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

    public MainWindow()
    {
        InitializeComponent();
        ResizeMode = System.Windows.ResizeMode.NoResize;
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        IntPtr hwnd = new WindowInteropHelper(this).Handle;

        int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
        SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TOOLWINDOW);

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

        SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | 
            SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
    }
}

Let's hope it can help you.

Il Vic
  • 5,576
  • 4
  • 26
  • 37
  • I think this is a valid answer but I'm trying to avoid using `ToolWindow`. As described [on this question](http://stackoverflow.com/questions/2146230/wpf-tool-window-style-application-not-visible-in-alttab), `ToolWindow` has some undesirable side effects. I'll update my question accordingly. – Michael Oct 25 '16 at 14:08
  • I am afraid there is no other way @Michael if you want to use `SetWindowLong`. Did you consider creating an empty icon and using it for your window? – Il Vic Oct 26 '16 at 12:28
  • That's probably the way we'll go for the time being. When a window is set to use `NoResize`, just display a stub transparent icon instead of hiding it. Not ideal, but ya probably the best for now. – Michael Oct 26 '16 at 18:26