private unsafe void CreatePen()
        {
            if (_width > 1)
            {
                // Geometric pen.
                // From MSDN: if width > 1, the style must be PS_NULL, PS_SOLID, or PS_INSIDEFRAME.
                _style |= Gdi32.PS.GEOMETRIC | Gdi32.PS.SOLID;
            }

            if (_wndBrush == null)
            {
                _nativeHandle = Gdi32.CreatePen(_style, _width, ColorTranslator.ToWin32(_color));
            }
            else
            {
                var lb = new Gdi32.LOGBRUSH
                {
                    lbColor = ColorTranslator.ToWin32(_wndBrush.Color),
                    lbStyle = Gdi32.BS.SOLID,
                    lbHatch = IntPtr.Zero
                };

                // Note: We currently don't support custom styles, that's why 0 and null for last two params.
                _nativeHandle = Gdi32.ExtCreatePen(_style, _width, ref lb, 0, null);
            }
        }
        private static void DrawAndFillEllipse(Gdi32.HDC hdc, Gdi32.HPEN borderPen, Gdi32.HBRUSH fieldBrush, Rectangle bounds)
        {
            Debug.Assert(!hdc.IsNull, "Calling DrawAndFillEllipse with null wg");
            if (hdc.IsNull)
            {
                return;
            }

            hdc.FillRectangle(fieldBrush, new Rectangle(bounds.X + 2, bounds.Y + 2, 8, 8));
            hdc.FillRectangle(fieldBrush, new Rectangle(bounds.X + 4, bounds.Y + 1, 4, 10));
            hdc.FillRectangle(fieldBrush, new Rectangle(bounds.X + 1, bounds.Y + 4, 10, 4));

            hdc.DrawLine(borderPen, new Point(bounds.X + 4, bounds.Y + 0), new Point(bounds.X + 8, bounds.Y + 0));
            hdc.DrawLine(borderPen, new Point(bounds.X + 4, bounds.Y + 11), new Point(bounds.X + 8, bounds.Y + 11));

            hdc.DrawLine(borderPen, new Point(bounds.X + 2, bounds.Y + 1), new Point(bounds.X + 4, bounds.Y + 1));
            hdc.DrawLine(borderPen, new Point(bounds.X + 8, bounds.Y + 1), new Point(bounds.X + 10, bounds.Y + 1));

            hdc.DrawLine(borderPen, new Point(bounds.X + 2, bounds.Y + 10), new Point(bounds.X + 4, bounds.Y + 10));
            hdc.DrawLine(borderPen, new Point(bounds.X + 8, bounds.Y + 10), new Point(bounds.X + 10, bounds.Y + 10));

            hdc.DrawLine(borderPen, new Point(bounds.X + 0, bounds.Y + 4), new Point(bounds.X + 0, bounds.Y + 8));
            hdc.DrawLine(borderPen, new Point(bounds.X + 11, bounds.Y + 4), new Point(bounds.X + 11, bounds.Y + 8));

            hdc.DrawLine(borderPen, new Point(bounds.X + 1, bounds.Y + 2), new Point(bounds.X + 1, bounds.Y + 4));
            hdc.DrawLine(borderPen, new Point(bounds.X + 1, bounds.Y + 8), new Point(bounds.X + 1, bounds.Y + 10));

            hdc.DrawLine(borderPen, new Point(bounds.X + 10, bounds.Y + 2), new Point(bounds.X + 10, bounds.Y + 4));
            hdc.DrawLine(borderPen, new Point(bounds.X + 10, bounds.Y + 8), new Point(bounds.X + 10, bounds.Y + 10));
        }
        internal static void DrawRectangle(this Gdi32.HDC hdc, Rectangle rectangle, Gdi32.HPEN hpen)
        {
            using var penScope   = new Gdi32.SelectObjectScope(hdc, hpen);
            using var ropScope   = new Gdi32.SetRop2Scope(hdc, Gdi32.R2.COPYPEN);
            using var brushScope = new Gdi32.SelectObjectScope(hdc, Gdi32.GetStockObject(Gdi32.StockObject.HOLLOW_BRUSH));

            Gdi32.Rectangle(hdc, rectangle.X, rectangle.Y, rectangle.Right, rectangle.Bottom);
        }
 internal static void DrawRectangle(
     this DeviceContextHdcScope hdc,
     int left,
     int top,
     int right,
     int bottom,
     Gdi32.HPEN hpen)
 => DrawRectangle(hdc.HDC, left, top, right, bottom, hpen);
        internal unsafe static void DrawLine(this Gdi32.HDC hdc, Gdi32.HPEN pen, int x1, int y1, int x2, int y2)
        {
            using var ropScope  = new Gdi32.SetRop2Scope(hdc, Gdi32.R2.COPYPEN);
            using var bkScope   = new Gdi32.SetBkModeScope(hdc, Gdi32.BKMODE.TRANSPARENT);
            using var selection = new Gdi32.SelectObjectScope(hdc, pen);

            Point oldPoint = new Point();

            Gdi32.MoveToEx(hdc, x1, y1, &oldPoint);
            Gdi32.LineTo(hdc, x2, y2);
            Gdi32.MoveToEx(hdc, oldPoint.X, oldPoint.Y, &oldPoint);
        }
        internal static void DrawRectangle(
            this Gdi32.HDC hdc,
            int left,
            int top,
            int right,
            int bottom,
            Gdi32.HPEN hpen)
        {
            using var penScope   = new Gdi32.SelectObjectScope(hdc, hpen);
            using var ropScope   = new Gdi32.SetRop2Scope(hdc, Gdi32.R2.COPYPEN);
            using var brushScope = new Gdi32.SelectObjectScope(hdc, Gdi32.GetStockObject(Gdi32.StockObject.NULL_BRUSH));

            Gdi32.Rectangle(hdc, left, top, right, bottom);
        }
        internal static void DrawAndFillEllipse(
            this Gdi32.HDC hdc,
            Gdi32.HPEN pen,
            Gdi32.HBRUSH brush,
            int left,
            int top,
            int right,
            int bottom)
        {
            using var penSelection = pen.IsNull ? default : new Gdi32.SelectObjectScope(hdc, pen);

                                     using var brushSelection = brush.IsNull ? default : new Gdi32.SelectObjectScope(hdc, brush);

                                                                Gdi32.Ellipse(hdc, left, top, right, bottom);
        }
        /// <summary>
        ///  Draws lines with the <paramref name="hpen"/> using points defined in <paramref name="lines"/>.
        /// </summary>
        /// <param name="lines">
        ///  MUST be a mulitple of 4. Each group of 4 represents x1, y1, x2, y2.
        /// </param>
        internal unsafe static void DrawLines(this Gdi32.HDC hdc, Gdi32.HPEN hpen, ReadOnlySpan <int> lines)
        {
            Debug.Assert((lines.Length % 4) == 0);

            using var ropScope  = new Gdi32.SetRop2Scope(hdc, Gdi32.R2.COPYPEN);
            using var bkScope   = new Gdi32.SetBkModeScope(hdc, Gdi32.BKMODE.TRANSPARENT);
            using var selection = new Gdi32.SelectObjectScope(hdc, hpen);

            Point oldPoint = new Point();

            for (int i = 0; i < lines.Length; i += 4)
            {
                Gdi32.MoveToEx(hdc, lines[i], lines[i + 1], &oldPoint);
                Gdi32.LineTo(hdc, lines[i + 2], lines[i + 3]);
                Gdi32.MoveToEx(hdc, oldPoint.X, oldPoint.Y, null);
            }
        }
        void Dispose(bool disposing)
        {
            if (!_nativeHandle.IsNull && _dc != null)
            {
                _dc.DeleteObject(_nativeHandle, GdiObjectType.Pen);
                _nativeHandle = default;
            }

            if (_wndBrush != null)
            {
                _wndBrush.Dispose();
                _wndBrush = null;
            }

            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
        internal unsafe static void DrawLine(this Gdi32.HDC hdc, Gdi32.HPEN hpen, int x1, int y1, int x2, int y2)
        {
            ReadOnlySpan <int> lines = stackalloc int[] { x1, y1, x2, y2 };

            DrawLines(hdc, hpen, lines);
        }
 internal unsafe static void DrawLine(this DeviceContextHdcScope hdc, Gdi32.HPEN hpen, int x1, int y1, int x2, int y2)
 => DrawLine(hdc.HDC, hpen, x1, y1, x2, y2);
 internal static void DrawLine(this Gdi32.HDC hdc, Gdi32.HPEN hpen, Point p1, Point p2)
 => DrawLine(hdc, hpen, p1.X, p1.Y, p2.X, p2.Y);
 internal static void DrawLine(this DeviceContextHdcScope hdc, Gdi32.HPEN hpen, Point p1, Point p2)
 => DrawLine(hdc.HDC, hpen, p1.X, p1.Y, p2.X, p2.Y);
 internal static void DrawRectangle(this DeviceContextHdcScope hdc, Rectangle rectangle, Gdi32.HPEN hpen)
 => DrawRectangle(hdc.HDC, rectangle, hpen);
 internal static void DrawRectangle(this Gdi32.CreateDcScope hdc, Rectangle rectangle, Gdi32.HPEN hpen)
 => DrawRectangle(hdc.HDC, rectangle, hpen);
 internal static void DrawRectangle(this DeviceContextHdcScope hdc, Rectangle rectangle, Gdi32.HPEN hpen)
 => DrawRectangle(hdc.HDC, rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom, hpen);
 internal static void DrawRectangle(this User32.GetDcScope hdc, Rectangle rectangle, Gdi32.HPEN hpen)
 => DrawRectangle(hdc.HDC, rectangle, hpen);
 /// <summary>
 ///  Draws lines with the <paramref name="hpen"/> using points defined in <paramref name="lines"/>.
 /// </summary>
 /// <param name="lines">
 ///  MUST be a mulitple of 4. Each group of 4 represents x1, y1, x2, y2.
 /// </param>
 internal unsafe static void DrawLines(this DeviceContextHdcScope hdc, Gdi32.HPEN hpen, ReadOnlySpan <int> lines)
 => DrawLines(hdc.HDC, hpen, lines);
 internal static void DrawLine(this User32.GetDcScope hdc, Gdi32.HPEN pen, int x1, int y1, int x2, int y2)
 => DrawLine(hdc.HDC, pen, x1, y1, x2, y2);
 internal static void DrawAndFillEllipse(
     this DeviceContextHdcScope hdc,
     Gdi32.HPEN pen,
     Gdi32.HBRUSH brush,
     Rectangle bounds)
 => DrawAndFillEllipse(hdc.HDC, pen, brush, bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);
 internal static void DrawAndFillEllipse(this Gdi32.HDC hdc, Gdi32.HPEN pen, Gdi32.HBRUSH brush, Rectangle bounds)
 => DrawEllipse(hdc, pen, brush, bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);