5

I want to cancel the natural minimizing behavior and change a WPF form size instead.

I have a solution with the Window_StateChanged but it doesn't look so nice - the window first minimized then jumps back and does the size alteration. Is there a way to accomplish this? I Googled for Window_StateChanging but couldn't figure it out, some sort of external lib that I prefer not to use.

That's what I have:

private void Window_StateChanged(object sender, EventArgs e)
{
    switch (this.WindowState)
    {
        case WindowState.Minimized:
            {
                WindowState = System.Windows.WindowState.Normal;
                this.Width = 500;
                this.Height = 800;
                break;
            }
    }
}

Thanks,

EP

LazyZebra
  • 1,097
  • 16
  • 24

2 Answers2

13

You'll need to intercept the minimize command before your form fires Window_StateChanged, to avoid the minimize/restore dance you're seeing. I believe the easiest way to do this is to have your form listen for Windows messages and when the minimize command is received, cancel it and resize your form.

Register the SourceInitialized event, in your form constructor:

this.SourceInitialized += new EventHandler(OnSourceInitialized); 

Add these two handlers to your form:

private void OnSourceInitialized(object sender, EventArgs e) {
    HwndSource source = (HwndSource)PresentationSource.FromVisual(this);
    source.AddHook(new HwndSourceHook(HandleMessages));
} 

private IntPtr HandleMessages(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
    // 0x0112 == WM_SYSCOMMAND, 'Window' command message.
    // 0xF020 == SC_MINIMIZE, command to minimize the window.
    if (msg == 0x0112 && ((int)wParam & 0xFFF0) == 0xF020) {
        // Cancel the minimize.
        handled = true;

        // Resize the form.
        this.Width = 500;
        this.Height = 500;
    }

    return IntPtr.Zero;
} 

I suspect this is the approach you were hoping to avoid but boiled down to the code I show it's not too difficult to implement.

Code based on this SO question.

Community
  • 1
  • 1
Jay Riggs
  • 53,046
  • 9
  • 139
  • 151
1

Try this simple solution:

public partial class MainWindow : Window
{
    private int SC_MINIMIZE = 0xf020;
    private int SYSCOMMAND = 0x0112;

    public MainWindow()
    {
        InitializeComponent();
        SourceInitialized += (sender, e) =>
                                 {
                                     HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
                                     source.AddHook(WndProc);
                                 };
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        // process minimize button
        if (msg == SYSCOMMAND && SC_MINIMIZE == wParam.ToInt32())
        {
            //Minimize clicked
            handled = true;
        }
        return IntPtr.Zero;
    }
}
Ria
  • 10,237
  • 3
  • 33
  • 60