'WPF window without border expands outside of screen in maximize

I am styling a wpf window where I removed the window border and added the minimize, maximize and close buttons to menu control. This looks like this: http://prnt.sc/e3vusq

Now I have two issues: When I maximize, the window goes a bit outside the screen, that looks like this: http://prnt.sc/e3vvhz

This is my code for those 3 buttons

  private void Button_Click(object sender, RoutedEventArgs e)             //close button
    {
        if (MessageBox.Show("Želite shranit spremembe?", "Opozorilo", MessageBoxButton.YesNoCancel, MessageBoxImage.Exclamation) == MessageBoxResult.No)
        {
            this.Close();
        }
        else
        {
            if (saveChanges)
            {
                quickSave();
            }

        }
    }


    private void Button_Click_1(object sender, RoutedEventArgs e)               //maximize button
    {
        if(this.WindowState == WindowState.Maximized)
        {
            this.WindowState = WindowState.Normal;
        }
        else
        {
            this.WindowState = WindowState.Maximized;

        }
    }

    private void Button_Click_2(object sender, RoutedEventArgs e)           //minimize button
    {
        this.WindowState = WindowState.Minimized;
    }

How could I get rid of this problem? I was thinking of making a method, that sets the windows to the size of the screen n maximize, but this wouldn't work for the win7 drag-to-border maximize.

My other question is how can I make the menu bar a clic-to-drag-window control. Right now, I applied this code to window mouse down, but the same code doesn't work for the menu control

 private void Window_MouseDown(object sender, MouseButtonEventArgs e)
 {
     if (e.ChangedButton == MouseButton.Left)
         this.DragMove();
 }

XAML WPF snippet: https://codeshare.io/G6pJjg

EDIT: Attempted trigger:

 <Window.Style>
    <Style TargetType="Window">
        <Style.Triggers>
            <Trigger Property="WindowState" Value="Maximized">
                <Setter Property="Width" Value="{Binding Source={x:Static SystemParameters.FullPrimaryScreenWidth}}" />
                <Setter Property="Height" Value="{Binding Source={x:Static SystemParameters.FullPrimaryScreenHeight}}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Style>


Solution 1:[1]

One way (dirty) of removing parts of the windows overflowing to the other screen is to just add border to the edges of the window overflowing.

However, I suggest you use the hookproc callback function to limit the window's maximum dimensions.

Example that can be added to the code-behind:

   private void windowMain_SourceInitialized(object sender, EventArgs e)
    {
        ((HwndSource)PresentationSource.FromVisual(this)).AddHook(HookProc);
    }

    public static IntPtr HookProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_GETMINMAXINFO)
        {
            // We need to tell the system what our size should be when maximized. Otherwise it will
            // cover the whole screen, including the task bar.
            MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));

            // Adjust the maximized size and position to fit the work area of the correct monitor
            IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);

            if (monitor != IntPtr.Zero)
            {

                
                MONITORINFO monitorInfo = new MONITORINFO();
                monitorInfo.cbSize = Marshal.SizeOf(typeof(MONITORINFO));
                GetMonitorInfo(monitor, ref monitorInfo);
                RECT rcWorkArea = monitorInfo.rcWork;
                RECT rcMonitorArea = monitorInfo.rcMonitor;
                mmi.ptMaxPosition.X = Math.Abs(rcWorkArea.Left - rcMonitorArea.Left);
                mmi.ptMaxPosition.Y = Math.Abs(rcWorkArea.Top - rcMonitorArea.Top);
                mmi.ptMaxSize.X = Math.Abs(rcWorkArea.Right - rcWorkArea.Left);
                mmi.ptMaxSize.Y = Math.Abs(rcWorkArea.Bottom - rcWorkArea.Top);
            }

            Marshal.StructureToPtr(mmi, lParam, true);
        }

        return IntPtr.Zero;
    }

    private const int WM_GETMINMAXINFO = 0x0024;

    private const uint MONITOR_DEFAULTTONEAREST = 0x00000002;

    [DllImport("user32.dll")]
    private static extern IntPtr MonitorFromWindow(IntPtr handle, uint flags);

    [DllImport("user32.dll")]
    private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;

        public RECT(int left, int top, int right, int bottom)
        {
            this.Left = left;
            this.Top = top;
            this.Right = right;
            this.Bottom = bottom;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MONITORINFO
    {
        public int cbSize;
        public RECT rcMonitor;
        public RECT rcWork;
        public uint dwFlags;
    }

    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;

        public POINT(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MINMAXINFO
    {
        public POINT ptReserved;
        public POINT ptMaxSize;
        public POINT ptMaxPosition;
        public POINT ptMinTrackSize;
        public POINT ptMaxTrackSize;
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Changstein