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); }
/// <summary> /// Draws the text in the given bounds, using the given Font, foreColor and backColor, and according to the specified /// TextFormatFlags flags. /// /// If font is null, the font currently selected in the hdc is used. /// /// If foreColor and/or backColor are Color.Empty, the hdc current text and/or background color are used. /// </summary> public static void DrawText( this Gdi32.HDC hdc, ReadOnlySpan <char> text, FontCache.Scope font, Rectangle bounds, Color foreColor, User32.DT flags, Color backColor = default, TextPaddingOptions padding = default) { if (text.IsEmpty || foreColor == Color.Transparent) { return; } ValidateFlags(flags); // DrawText requires default text alignment. using var alignment = new Gdi32.SetTextAlignmentScope(hdc, default); // Color empty means use the one currently selected in the dc. using var textColor = foreColor.IsEmpty ? default : new Gdi32.SetTextColorScope(hdc, foreColor); using var fontSelection = new Gdi32.SelectObjectScope(hdc, (Gdi32.HFONT)font); Gdi32.BKMODE newBackGroundMode = (backColor.IsEmpty || backColor == Color.Transparent) ? Gdi32.BKMODE.TRANSPARENT : Gdi32.BKMODE.OPAQUE; using var backgroundMode = new Gdi32.SetBkModeScope(hdc, newBackGroundMode); using var backgroundColor = newBackGroundMode != Gdi32.BKMODE.TRANSPARENT ? new Gdi32.SetBackgroundColorScope(hdc, backColor) : default; User32.DRAWTEXTPARAMS dtparams = GetTextMargins(font, padding); bounds = AdjustForVerticalAlignment(hdc, text, bounds, flags, ref dtparams); // Adjust unbounded rect to avoid overflow since Rectangle ctr does not do param validation. if (bounds.Width == TextRenderer.MaxSize.Width) { bounds.Width -= bounds.X; } if (bounds.Height == TextRenderer.MaxSize.Height) { bounds.Height -= bounds.Y; } RECT rect = bounds; User32.DrawTextExW(hdc, text, ref rect, flags, ref dtparams); }
/// <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); } }