WPFBorderless form

Previously, I wrote a base form for a borderless form that supports size transformation. The code is as follows:

public class LBaseWindow : Window
    {
        /// <summary>
        /// Base form
        /// </summary>
        public LBaseWindow()
        {
            Initialize();
        }
        /// <summary>
        /// Whether to display the taskbar. If the taskbar is not displayed, the form covers the entire screen.
        /// </summary>
        public Visibility TaskbarVisibility
        {
            get
            {
                return _taskbarVisibility;
            }
            set
            {
                if (_taskbarVisibility != value)
                {
                    _taskbarVisibility = value;
                    SetTaskbarChange();
                }
            }
        }
        /// <summary>
        /// Source data initialization
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
            if (hwndSource != null)
            {
                hwndSource.AddHook(new HwndSourceHook(this.WndProc));
                _handle = hwndSource.Handle;
            }
        }
        /// <summary>
        /// Message interception
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <param name="handled"></param>
        /// <returns></returns>
        protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
                #region[Form size modification]
                case WM_NCHITTEST:
                    this.mousePoint.X = (lParam.ToInt32() & amp; 0xFFFF);
                    this.mousePoint.Y = (lParam.ToInt32() >> 16);
                    double left = this.WindowState == System.Windows.WindowState.Maximized ? 0 : this.Left;
                    double top = this.WindowState == System.Windows.WindowState.Maximized ? 0 : this.Top;
                    // Upper left corner of window
                    if (this.mousePoint.Y - this.Top <= this.agWidth
                        & amp; & amp; this.mousePoint.X - left <= this.agWidth)
                    {
                        handled = true;
                        return new IntPtr((int)HitTest.HTTOPLEFT);
                    }
                    //Lower left corner of window
                    else if (this.ActualHeight + top - this.mousePoint.Y <= this.agWidth
                        & amp; & amp; this.mousePoint.X - left <= this.agWidth)
                    {
                        handled = true;
                        return new IntPtr((int)HitTest.HTBOTTOMLEFT);
                    }
                    // Upper right corner of window
                    else if (this.mousePoint.Y - top <= this.agWidth
                        & amp; & amp; this.ActualWidth + left - this.mousePoint.X <= this.agWidth)
                    {
                        handled = true;
                        return new IntPtr((int)HitTest.HTTOPRIGHT);
                    }
                    //Lower right corner of window
                    else if (this.ActualWidth + left - this.mousePoint.X <= this.agWidth
                        & amp; & amp; this.ActualHeight + top - this.mousePoint.Y <= this.agWidth)
                    {
                        handled = true;
                        return new IntPtr((int)HitTest.HTBOTTOMRIGHT);
                    }
                    //left side of window
                    else if (this.mousePoint.X - left <= this.bThickness)
                    {
                        handled = true;
                        return new IntPtr((int)HitTest.HTLEFT);
                    }
                    // right side of window
                    else if (this.ActualWidth + left - this.mousePoint.X <= this.bThickness)
                    {
                        handled = true;
                        return new IntPtr((int)HitTest.HTRIGHT);
                    }
                    // top of window
                    else if (this.mousePoint.Y - top <= this.bThickness)
                    {
                        handled = true;
                        return new IntPtr((int)HitTest.HTTOP);
                    }
                    // Below the window
                    else if (this.ActualHeight + top - this.mousePoint.Y <= this.bThickness)
                    {
                        handled = true;
                        return new IntPtr((int)HitTest.HTBOTTOM);
                    }
                    else
                    {
                        return IntPtr.Zero;
                        //handled = true;
                        //return new IntPtr((int)HitTest.HTCAPTION);
                    }
                #endregion
                #region[Form Maximization Control]
                case WM_GETMINMAXINFO:
                    WMGetMinMaxInfo(hwnd, lParam);
                    handled = true;
                    break;
                #endregion
            }
            return IntPtr.Zero;
        }
        /// <summary>
        /// Control the window to maximize
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="lParam"></param>
        protected virtual void WMGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
        {
            MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
            // Adjust the maximized size and position to fit the work area of the correct monitor
            int MONITOR_DEFAULTTONEAREST = 0x00000002;
            System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
            if (monitor != System.IntPtr.Zero)
            {
                MONITORINFO monitorInfo = new MONITORINFO();
                GetMonitorInfo(monitor, monitorInfo);
                RECT rcWorkArea = monitorInfo.rcWork;
                RECT rcMonitorArea = monitorInfo.rcMonitor;
                if (TaskbarVisibility == System.Windows.Visibility.Visible)
                {
                    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);
                }
                else
                {
                    mmi.ptMaxPosition.x = 0;
                    mmi.ptMaxPosition.y = 0;
                    mmi.ptMaxSize.x = rcMonitorArea.right;
                    mmi.ptMaxSize.y = rcMonitorArea.bottom;
                }
            }
            Marshal.StructureToPtr(mmi, lParam, true);
        }
        /// <summary>
        /// Settings modify taskbar changes
        /// </summary>
        private void SetTaskbarChange()
        {
            WindowState state = this.WindowState;
            this.Opacity = 0;
            this.WindowState = System.Windows.WindowState.Minimized;
            this.WindowState = state;
            this.Opacity = 1;
        }
        /// <summary>
        /// Modify form shadow radius
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ShadowRadiusChanged()
        {
            ControlTemplate template = (ControlTemplate)this.Resources["WindowTemplate"];
            if (template == null) return;
            Grid grid = (Grid)template.FindName("ClientGrid", this);
            if (grid == null) return;
            if (this.WindowState != System.Windows.WindowState.Maximized)
                grid.Margin = new Thickness(10);
            else
                grid.Margin = new Thickness(0);
            if (this.Opacity == 0)
                this.Opacity = 1;
        }
        /// <summary>
        /// Initialization
        /// </summary>
        private void Initialize()
        {
            this.Opacity = 0;
            this.Loaded + = (sender, e) => InitializeEvent();
            this.ContentRendered + = (sender, e) => ShadowRadiusChanged();
            this.SizeChanged + = (sender, e) => ShadowRadiusChanged();
        }
        /// <summary>
        /// Initialization event
        /// </summary>
        private void InitializeEvent()
        {
            ResourceDictionary resource = new ResourceDictionary();
            resource.Source = new Uri(@"pack://application:,,,/DepthView;component/View/Styles/WindowStyle.xaml", UriKind.RelativeOrAbsolute);
            this.Resources.MergedDictionaries.Add(resource);
            this.Style = (Style)this.Resources["WindowStyleKey"];
        }

        private const int WM_SYSCOMMAND = 0x112;
        private const int WM_GETMINMAXINFO = 0x0024;
        private const int SC_CLOSE = 0xF060;
        private const int SC_MINIMIZE = 0xF020;
        private const int SC_MAXIMIZE = 0xF030;
        private const int WM_NCHITTEST = 0x0084;
        private readonly int agWidth = 12; //Corner width
        private readonly int bThickness = 4; // border width
        private Point mousePoint = new Point(); //mouse coordinates
        private Visibility _taskbarVisibility;
        privateIntPtr_handle;

        [DllImport("user32.dll")]
        internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32")]
        internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
        [DllImport("User32")]
        internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class MONITORINFO
        {
            /// <summary>
            /// </summary>
            public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
            /// <summary>
            /// </summary>
            public RECT rcMonitor = new RECT();
            /// <summary>
            /// </summary>
            public RECT rcWork = new RECT();
            /// <summary>
            /// </summary>
            public int dwFlags = 0;
        }
        /// <summary>
        /// Rectangle
        /// </summary>
        [StructLayout(LayoutKind.Sequential, Pack = 0)]
        public struct RECT
        {
            /// <summary>
            /// Left boundary coordinates
            /// </summary>
            public int left;
            /// <summary>
            /// Upper boundary coordinates
            /// </summary>
            public int top;
            /// <summary>
            /// Right boundary coordinates
            /// </summary>
            public int right;
            /// <summary>
            ///Lower boundary coordinates
            /// </summary>
            public int bottom;
        }
        /// <summary>
        /// Window size information
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct MINMAXINFO
        {
            public POINT ptReserved;
            public POINT ptMaxSize;
            public POINT ptMaxPosition;
            public POINT ptMinTrackSize;
            public POINT ptMaxTrackSize;
        };
        /// <summary>
        ///POINT aka POINTAPI
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            /// <summary>
            /// x coordinate of point.
            /// </summary>
            public int x;
            /// <summary>
            /// y coordinate of point.
            /// </summary>
            public int y;

            /// <summary>
            /// Construct a point of coordinates (x,y).
            /// </summary>
            public POINT(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }
        /// <summary>
        ///Mouse click information
        /// </summary>
        public enum HitTest : int
        {
            HTERROR = -2,
            HTTRANSPARENT = -1,
            HTNOWHERE = 0,
            HTCLIENT = 1,
            HTCAPTION = 2,
            HTSYSMENU = 3,
            HTGROWBOX = 4,
            HTSIZE = HTGROWBOX,
            HTMENU = 5,
            HTHSCROLL = 6,
            HTVSCROLL = 7,
            HTMINBUTTON = 8,
            HTMAXBUTTON = 9,
            HTLEFT = 10,
            HTRIGHT = 11,
            HTTOP = 12,
            HTTOPLEFT = 13,
            HTTOPRIGHT = 14,
            HTBOTTOM = 15,
            HTBOTTOMLEFT = 16,
            HTBOTTOMRIGHT = 17,
            HTBORDER = 18,
            HTREDUCE = HTMINBUTTON,
            HTZOOM = HTMAXBUTTON,
            HTSIZEFIRST = HTLEFT,
            HTSIZELAST = HTBOTTOMRIGHT,
            HTOBJECT = 19,
            HTCLOSE = 20,
            HTHELP = 21,
        }
    }

Xaml:

 <ControlTemplate x:Key="WindowTemplate" TargetType="{x:Type Window}">
        <Grid x:Name="ClientGrid" Margin="10">
            <Border Background="{x:Null}" BorderBrush="{TemplateBinding Background}" BorderThickness="2" CornerRadius="3">
                <Border.Effect>
                    <DropShadowEffect x:Name="shadow" BlurRadius="10" ShadowDepth="0"/>
                </Border.Effect>
            </Border>
            <Border Background="{x:Null}"
                          BorderBrush="{TemplateBinding BorderBrush}"
                          BorderThickness="{TemplateBinding BorderThickness}"
                          Padding="{TemplateBinding Margin}"
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                          CornerRadius="3">
                <ContentPresenter />
            </Border>
        </Grid>
    </ControlTemplate>
    <Style x:Key="WindowStyleKey" TargetType="{x:Type Window}">
        <Setter Property="Template" Value="{DynamicResource ResourceKey=WindowTemplate}"></Setter>
    </Style>

There is a question about whether to display the taskbar in full screen. Currently, minimization and then maximization are used to trigger WndProc. This should be improved, and we will look at it later.