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);