1
votes

On my WPF window, I have set

Width="300" MinWidth="300" MaxWidth="300"

When I maximize this window, it docks to the left screen border with this fixed with, but the bottom part of the window is UNDERNEATH the Windows 8 taskbar.

I have tried

public MainWindow()
{
    ...
    this.MaxHeight = System.Windows.SystemParameters.WorkArea.Height;
}

, but this results in a few pixels of free space between the taskbar and my app.

I'd like to

  • have a fixed width window
  • dock it to the RIGHT border on maximize
  • not cover/go under the taskbar in the maximized state
1

1 Answers

5
votes

Unfortunately, your three requirements does not seem to be achievable using just MinWidth, MaxWidth and WindowState.

But regardless, it's still possible to achieve something similar. What you need to do is to emulate the maximized state of the window. You need to move the window to the correct position, get the right height, and make it unmovable. The first two parts are easy, the last one requires some more advanced stuff.

Start out with the window you have, with Width, MaxWidth and MinWidth set to 300, and add an event handler to StateChanged.

Width="300" MinWidth="300" MaxWidth="300" StateChanged="MainWindow_OnStateChanged"

And the event handler, and helper methods:

private bool isMaximized;
private Rect normalBounds;
private void MainWindow_OnStateChanged(object sender, EventArgs e)
{
    if (WindowState == WindowState.Maximized && !isMaximized)
    {
        WindowState = WindowState.Normal;
        isMaximized = true;

        normalBounds = RestoreBounds;

        Height = SystemParameters.WorkArea.Height;
        MaxHeight = Height;
        MinHeight = Height;
        Top = 0;
        Left = SystemParameters.WorkArea.Right - Width;
        SetMovable(false);
    }
    else if(WindowState == WindowState.Maximized && isMaximized)
    {
        WindowState = WindowState.Normal;
        isMaximized = false;

        MaxHeight = Double.PositiveInfinity;
        MinHeight = 0;

        Top = normalBounds.Top;
        Left = normalBounds.Left;
        Width = normalBounds.Width;
        Height = normalBounds.Height;
        SetMovable(true);
    }
}

private void SetMovable(bool enable)
{
    HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);

    if(enable)
        source.RemoveHook(WndProc);
    else
        source.AddHook(WndProc);
}

private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_MOVE = 0xF010;

    switch (msg)
    {
        case WM_SYSCOMMAND:
            int command = wParam.ToInt32() & 0xfff0;
            if (command == SC_MOVE)
                handled = true;
            break;
    }

    return IntPtr.Zero;
}