From cfb52cc2d9429b32e8952c7da04b59b4b183ebfe Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:57:46 +0800 Subject: [PATCH 01/13] Migrate WinForms library to .NET 10 and add SkiaSharp painting --- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 ++++++----- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 ++++++----- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 29 +++++ ST.Library.UI/ST.Library.UI.csproj | 105 +++--------------- 4 files changed, 110 insertions(+), 153 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..1a3751b --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,29 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + internal static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + From 8195e47daf6ca5b3d7df18ffc595310eb64be450 Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:08:46 +0800 Subject: [PATCH 02/13] Expand SkiaSharp migration for panel and WinForms demo controls --- .../NodeEditor/STNodeEditorPannel.cs | 35 ++--- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 2 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 ++-- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +-- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 ++-- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 ++-- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 ++---------------- 7 files changed, 90 insertions(+), 164 deletions(-) diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..04abfe6 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; using System.Runtime.InteropServices; using System.ComponentModel; @@ -210,23 +211,25 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } + }); } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs index 1a3751b..99bb321 100644 --- a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -3,7 +3,7 @@ using SkiaSharp; namespace ST.Library.UI.NodeEditor { - internal static class SkiaDrawingHelper { + public static class SkiaDrawingHelper { public static SKColor ToSKColor(Color color) { return new SKColor(color.R, color.G, color.B, color.A); } diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + From 9baf0321ce176c53cfff608810b70a3f936f52d4 Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:22:51 +0800 Subject: [PATCH 03/13] Migrate remaining demo/property rendering paths from GDI+ to Skia --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +++--- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++++----- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 ++++----- .../NodeEditor/STNodeEditorPannel.cs | 35 ++--- .../NodeEditor/STNodePropertyAttribute.cs | 39 +++--- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 ++++++ ST.Library.UI/ST.Library.UI.csproj | 105 +++------------ WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 ++-- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +-- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 ++-- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 ++-- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 ++---------------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 30 files changed, 297 insertions(+), 420 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..04abfe6 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; using System.Runtime.InteropServices; using System.ComponentModel; @@ -210,23 +211,25 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } + }); } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From ec270aa010f4b79673f0c19825efad133372838e Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:36:06 +0800 Subject: [PATCH 04/13] Migrate core control/treeview paint entry points to SkiaSharp --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +++--- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++++----- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 ++++----- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 ++-- .../NodeEditor/STNodeEditorPannel.cs | 35 ++--- .../NodeEditor/STNodePropertyAttribute.cs | 39 +++--- ST.Library.UI/NodeEditor/STNodeTreeView.cs | 36 +++--- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 ++++++ ST.Library.UI/ST.Library.UI.csproj | 105 +++------------ WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 ++-- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +-- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 ++-- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 ++-- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 ++---------------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 32 files changed, 329 insertions(+), 449 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..04abfe6 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; using System.Runtime.InteropServices; using System.ComponentModel; @@ -210,23 +211,25 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } + }); } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..3e3c99b 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,7 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; /* MIT License @@ -478,25 +479,22 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } + } + }); } /// /// 当开始绘制树节点的每一个节点时候发生 diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From 497af978dbbd9e45d68455d594a093810e90916f Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:50:19 +0800 Subject: [PATCH 05/13] Continue SkiaSharp migration for STNode, STNodeEditor and STNodePropertyGrid --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +++--- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++++----- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 ++++----- ST.Library.UI/NodeEditor/STNode.cs | 96 +++++++------- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 ++-- ST.Library.UI/NodeEditor/STNodeEditor.cs | 37 +++--- .../NodeEditor/STNodeEditorPannel.cs | 35 ++--- .../NodeEditor/STNodePropertyAttribute.cs | 39 +++--- .../NodeEditor/STNodePropertyGrid.cs | 22 ++-- ST.Library.UI/NodeEditor/STNodeTreeView.cs | 36 +++--- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 ++++++ ST.Library.UI/ST.Library.UI.csproj | 105 +++------------ WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 ++-- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +-- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 ++-- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 ++-- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 ++---------------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 35 files changed, 409 insertions(+), 524 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..3cf6f5f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -581,11 +582,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +599,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -737,15 +734,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..0e1ba3f 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,7 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; /* MIT License @@ -979,22 +980,21 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); int n = 5 - (int)(this._CanvasOffsetX / nIncrement); for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); n = 5 - (int)(this._CanvasOffsetY / nIncrement); for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); + canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } - } + }); } /// /// 当绘制 Node 时候发生 @@ -1145,12 +1145,15 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } + }); } /// /// 绘制超出视觉区域的 Node 位置提示信息 diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..04abfe6 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; using System.Runtime.InteropServices; using System.ComponentModel; @@ -210,23 +211,25 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } + }); } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..b972d02 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; /* MIT License @@ -568,14 +569,19 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t)) / 2; + canvas.DrawText(t ?? string.Empty, x, y, text); + } + }); if (this._ReadOnlyModel) { m_brush.Color = this.ForeColor; diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..3e3c99b 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,7 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; /* MIT License @@ -478,25 +479,22 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } + } + }); } /// /// 当开始绘制树节点的每一个节点时候发生 diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From 3793651efa46672b0f80508d440edcb9e4440f31 Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:17:33 +0800 Subject: [PATCH 06/13] Move STNodeTreeView to SKControl with direct Skia surface rendering --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 ++-- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++--- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 +++--- ST.Library.UI/NodeEditor/STNode.cs | 96 ++++---- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 +- ST.Library.UI/NodeEditor/STNodeEditor.cs | 37 +-- .../NodeEditor/STNodeEditorPannel.cs | 35 +-- .../NodeEditor/STNodePropertyAttribute.cs | 39 ++-- .../NodeEditor/STNodePropertyGrid.cs | 22 +- ST.Library.UI/NodeEditor/STNodeTreeView.cs | 215 ++++++++++-------- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 ++++ ST.Library.UI/ST.Library.UI.csproj | 105 ++------- WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 +- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 +- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 ++- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 +--------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 35 files changed, 506 insertions(+), 606 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..3cf6f5f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -581,11 +582,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +599,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -737,15 +734,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..0e1ba3f 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,7 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; /* MIT License @@ -979,22 +980,21 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); int n = 5 - (int)(this._CanvasOffsetX / nIncrement); for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); n = 5 - (int)(this._CanvasOffsetY / nIncrement); for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); + canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } - } + }); } /// /// 当绘制 Node 时候发生 @@ -1145,12 +1145,15 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } + }); } /// /// 绘制超出视觉区域的 Node 位置提示信息 diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..04abfe6 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; using System.Runtime.InteropServices; using System.ComponentModel; @@ -210,23 +211,25 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } + }); } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..b972d02 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; /* MIT License @@ -568,14 +569,19 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t)) / 2; + canvas.DrawText(t ?? string.Empty, x, y, text); + } + }); if (this._ReadOnlyModel) { m_brush.Color = this.ForeColor; diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..28131ec 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -41,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeTreeView : Control + public class STNodeTreeView : SKControl { private Color _ItemBackColor = Color.FromArgb(255, 45, 45, 45); /// @@ -195,6 +197,7 @@ public STNodePropertyGrid PropertyGrid { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); @@ -366,21 +369,22 @@ protected override void OnResize(EventArgs e) { m_rect_clear = new Rectangle(this.Width - 20, 9, 12, 12); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); m_nOffsetY = string.IsNullOrEmpty(m_str_search) ? m_nSourceOffsetY : m_nSearchOffsetY; - Graphics g = e.Graphics; - m_dt.Graphics = g; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - g.TranslateTransform(0, m_nOffsetY); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas.Save(); + m_canvas.Translate(0, m_nOffsetY); int nCounter = 0; foreach (STNodeTreeCollection v in m_items_draw) nCounter = this.OnStartDrawItem(m_dt, v, nCounter, 0); m_nVHeight = (nCounter + 1) * m_nItemHeight; foreach (STNodeTreeCollection v in m_items_draw) this.OnDrawSwitch(m_dt, v); - g.ResetTransform(); + m_canvas.Restore(); this.OnDrawSearch(m_dt); + m_canvas = null; } protected override void OnMouseMove(MouseEventArgs e) { @@ -478,24 +482,20 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + if (m_canvas == null) return; + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + m_canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + m_canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + m_canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + m_canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + m_canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + m_canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } } } /// @@ -507,7 +507,6 @@ protected virtual void OnDrawSearch(DrawingTools dt) { /// 当前位于第几级子集合 /// 已经绘制个数 protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; Items.DisplayRectangle = new Rectangle(0, m_nItemHeight * (nCounter + 1), this.Width, m_nItemHeight); Items.SwitchRectangle = new Rectangle(5 + nLevel * 10, (nCounter + 1) * m_nItemHeight, 10, m_nItemHeight); if (this._ShowInfoButton && Items.STNodeType != null) @@ -534,23 +533,26 @@ protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Item /// 已经绘制个数的计数器 /// 当前位于第几级子集合 protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; - m_brush.Color = nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, items.DisplayRectangle); - if (items == m_item_hover) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, items.DisplayRectangle); - } - Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); - m_pen.Color = Color.FromArgb(100, 125, 125, 125); - g.DrawLine(m_pen, 9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2); - if (nCounter != 0) { - for (int i = 0; i <= nLevel; i++) { - g.DrawLine(m_pen, 9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var line = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor(nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); + if (items == m_item_hover) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); } + Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); + line.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(100, 125, 125, 125)); + m_canvas.DrawLine(9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2, line); + if (nCounter != 0) { + for (int i = 0; i <= nLevel; i++) { + m_canvas.DrawLine(9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1, line); + } + } + this.OnDrawItemText(dt, items, rect); + this.OnDrawItemIcon(dt, items, rect); } - this.OnDrawItemText(dt, items, rect); - this.OnDrawItemIcon(dt, items, rect); } /// /// 当绘制树节点展开与关闭开关时候发生 @@ -558,15 +560,15 @@ protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, i /// 绘制工具 /// 当前需要绘制的集合 protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.Count != 0) { - m_pen.Color = this._SwitchColor; - m_brush.Color = m_pen.Color; - int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; - g.DrawRectangle(m_pen, items.SwitchRectangle.Left, nT, 8, 8); - g.DrawLine(m_pen, items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4); - if (items.IsOpen) return; - g.DrawLine(m_pen, items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SwitchColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; + m_canvas.DrawRect(items.SwitchRectangle.Left, nT, 8, 8, stroke); + m_canvas.DrawLine(items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4, stroke); + if (items.IsOpen) return; + m_canvas.DrawLine(items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7, stroke); + } //if (items.IsOpen) { // //g.FillPolygon(m_brush, new Point[]{ // // new Point(items.DotRectangle.Left + 0, items.DotRectangle.Top + m_nItemHeight / 2 - 2), @@ -594,28 +596,30 @@ protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; rect.Width -= 20; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - if (!string.IsNullOrEmpty(m_str_search)) { - int nIndex = items.NameLower.IndexOf(m_str_search); - if (nIndex != -1) { - CharacterRange[] chrs = { new CharacterRange(nIndex, m_str_search.Length) };//global - m_sf.SetMeasurableCharacterRanges(chrs); - Region[] regions = g.MeasureCharacterRanges(items.Name, this.Font, rect, m_sf); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Intersect); - m_brush.Color = this._HightLightTextColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Exclude); - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 1 / 2, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - return; + using (var textNormal = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textHi = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HightLightTextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = textNormal.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + string name = items.Name ?? string.Empty; + if (!string.IsNullOrEmpty(m_str_search)) { + int idx = items.NameLower.IndexOf(m_str_search); + if (idx >= 0) { + string pre = name.Substring(0, idx); + string hit = name.Substring(idx, Math.Min(m_str_search.Length, name.Length - idx)); + string suf = name.Substring(idx + hit.Length); + float x = rect.Left; + m_canvas.DrawText(pre, x, y, textNormal); + x += textNormal.MeasureText(pre); + m_canvas.DrawText(hit, x, y, textHi); + x += textHi.MeasureText(hit); + m_canvas.DrawText(suf, x, y, textNormal); + return; + } } + m_canvas.DrawText(name, rect.Left, y, textNormal); } - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); } /// /// 当绘制树节点图标时候发生 @@ -624,43 +628,52 @@ protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection item /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemIcon(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.STNodeType != null) { - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan; - m_brush.Color = Color.LightGray; - g.DrawRectangle(m_pen, rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.FillRectangle(m_brush, rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - g.FillRectangle(m_brush, rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - if (m_item_hover == items && m_bHoverInfo) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, items.InfoRectangle); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = SKColors.LightGray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10, stroke); + m_canvas.DrawRect(rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + m_canvas.DrawRect(rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + if (m_item_hover == items && m_bHoverInfo) { + fill.Color = SkiaDrawingHelper.ToSKColor(this.BackColor); + m_canvas.DrawRect(items.InfoRectangle.Left, items.InfoRectangle.Top, items.InfoRectangle.Width, items.InfoRectangle.Height, fill); + } + } + using (var info = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11, info); + m_canvas.DrawLine(items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10, info); + } + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1, box); } - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor; - m_pen.Width = 2; - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11); - g.DrawLine(m_pen, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1); } else { - if (items.IsLibraryRoot) { - Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.DrawRectangle(Pens.Gray, rect_box); - g.DrawLine(Pens.Cyan, rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top); - g.DrawLine(Pens.Cyan, rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2); - g.DrawLine(Pens.Cyan, rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom); - g.DrawLine(Pens.Cyan, rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2); - } else { - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3)); - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9)); + using (var stroke = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (items.IsLibraryRoot) { + Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); + stroke.Color = SKColors.Gray; + m_canvas.DrawRect(rect_box.Left, rect_box.Top, rect_box.Width, rect_box.Height, stroke); + stroke.Color = SKColors.Cyan; + m_canvas.DrawLine(rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top, stroke); + m_canvas.DrawLine(rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2, stroke); + m_canvas.DrawLine(rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom, stroke); + m_canvas.DrawLine(rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2, stroke); + } else { + stroke.Color = SKColors.Goldenrod; + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3, stroke); + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9, stroke); + } } if (!this._ShowFolderCount) return; - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this._FolderCountColor; - rect.X -= 4; - g.DrawString("[" + items.STNodeCount.ToString() + "]", this.Font, m_brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Near; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._FolderCountColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + string t = "[" + items.STNodeCount.ToString() + "]"; + float w = text.MeasureText(t); + var fm = text.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(t, rect.Right - w - 4, y, text); + } } } diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From d16579bcd11168178cb872a5de79315850fa8a24 Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:25:18 +0800 Subject: [PATCH 07/13] Move PropertyGrid and EditorPannel to direct SKControl surface rendering --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +-- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++-- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 +++-- ST.Library.UI/NodeEditor/STNode.cs | 96 +++---- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 +- ST.Library.UI/NodeEditor/STNodeEditor.cs | 37 +-- .../NodeEditor/STNodeEditorPannel.cs | 44 +-- .../NodeEditor/STNodePropertyAttribute.cs | 39 +-- .../NodeEditor/STNodePropertyGrid.cs | 261 ++++++------------ ST.Library.UI/NodeEditor/STNodeTreeView.cs | 215 ++++++++------- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 +++ ST.Library.UI/ST.Library.UI.csproj | 105 +------ WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 +- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 +- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 +- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 +------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 35 files changed, 580 insertions(+), 780 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..3cf6f5f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -581,11 +582,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +599,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -737,15 +734,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..0e1ba3f 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,7 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; /* MIT License @@ -979,22 +980,21 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); int n = 5 - (int)(this._CanvasOffsetX / nIncrement); for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); n = 5 - (int)(this._CanvasOffsetY / nIncrement); for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); + canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } - } + }); } /// /// 当绘制 Node 时候发生 @@ -1145,12 +1145,15 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } + }); } /// /// 绘制超出视觉区域的 Node 位置提示信息 diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..62c91d4 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,12 +5,14 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; +using SkiaSharp.Views.Desktop; using System.Runtime.InteropServices; using System.ComponentModel; namespace ST.Library.UI.NodeEditor { - public class STNodeEditorPannel : Control + public class STNodeEditorPannel : SKControl { private bool _LeftLayout = true; /// @@ -123,7 +125,6 @@ public STNodePropertyGrid PropertyGrid { private Point m_pt_down; private bool m_is_mx; private bool m_is_my; - private Pen m_pen; private bool m_nInited; private Dictionary m_dic_status_key = new Dictionary(); @@ -163,7 +164,6 @@ public STNodeEditorPannel() { this.MinimumSize = new Size(250, 250); this.BackColor = Color.FromArgb(255, 34, 34, 34); - m_pen = new Pen(this.BackColor, 3); Type t = typeof(ConnectionStatus); var vv = Enum.GetValues(t); @@ -208,25 +208,27 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound base.SetBoundsCore(x, y, width, height, specified); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + var canvas = e.Surface.Canvas; + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..47abf96 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,8 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -43,7 +45,7 @@ namespace ST.Library.UI.NodeEditor /// /// STNode节点属性编辑器 /// - public class STNodePropertyGrid : Control + public class STNodePropertyGrid : SKControl { #region properties ========== @@ -261,6 +263,7 @@ public bool ReadOnlyModel { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; /// /// 构造一个节点属性编辑器 @@ -364,31 +367,19 @@ private void SetItemRectangle() { /// 当控件重绘时候发生 /// /// 事件参数 - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_dt.Graphics = g; - - m_nOffsetY = m_b_current_draw_info ? m_nInfoOffsetY : m_nPropertyOffsetY; - g.TranslateTransform(0, m_nOffsetY); - - if (m_b_current_draw_info) { - m_nVHeight = m_nInfoVHeight; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + if (this._InfoFirstOnDraw) { this.OnDrawInfo(m_dt); } else { - m_nVHeight = m_nPropertyVHeight; - for (int i = 0; i < m_lst_item.Count; i++) { - this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); - } + for (int i = 0; i < m_lst_item.Count; i++) this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); } - - g.ResetTransform(); - if (this._ShowTitle) this.OnDrawTitle(m_dt); - m_sf.FormatFlags = 0; if (!string.IsNullOrEmpty(m_str_err)) this.OnDrawErrorInfo(m_dt); if (!string.IsNullOrEmpty(m_str_desc)) this.OnDrawDescription(m_dt); + m_canvas = null; } /// /// 当鼠标在控件上移动时候发生 @@ -533,33 +524,29 @@ protected override void OnResize(EventArgs e) { /// 目标属性选项描述器 /// 选项所在索引 protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescriptor item, int nIndex) { - Graphics g = dt.Graphics; - m_brush.Color = (nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, item.Rectangle); - if (item == m_item_hover || item == m_item_selected) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, item.Rectangle); - } - if (m_item_selected == item) { - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height); - if (this._AutoColor && this._STNode != null) - m_brush.Color = this._STNode.TitleColor; - else - m_brush.Color = this._ItemSelectedColor; - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor((nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + if (item == m_item_hover || item == m_item_selected) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + } + if (m_item_selected == item) { + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height, fill); + fill.Color = SkiaDrawingHelper.ToSKColor((this._AutoColor && this._STNode != null) ? this._STNode.TitleColor : this._ItemSelectedColor); + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8, fill); + } + var fm = text.FontMetrics; + float y = item.RectangleL.Top + (item.RectangleL.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = item.RectangleL.Right - text.MeasureText(item.Name ?? string.Empty) - 2; + m_canvas.DrawText(item.Name ?? string.Empty, x, y, text); } - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this.ForeColor; - g.DrawString(item.Name, this.Font, m_brush, item.RectangleL, m_sf); - item.OnDrawValueRectangle(m_dt); - if (this._ReadOnlyModel) { - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, item.RectangleR); - m_pen.Color = this.ForeColor; - //g.DrawLine(m_pen, - // item.RectangleR.Left - 2, item.RectangleR.Top + item.RectangleR.Height / 2, - // item.RectangleR.Right + 1, item.RectangleR.Top + item.RectangleR.Height / 2); + if (this._ReadOnlyModel && m_canvas != null) { + using (var overlay = new SKPaint { Color = new SKColor(125, 125, 125, 125), Style = SKPaintStyle.Fill, IsAntialias = true }) + m_canvas.DrawRect(item.RectangleR.Left, item.RectangleR.Top, item.RectangleR.Width, item.RectangleR.Height, overlay); } } /// @@ -567,159 +554,79 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { - Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); - - if (this._ReadOnlyModel) { - m_brush.Color = this.ForeColor; - g.FillRectangle(dt.SolidBrush, 4, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 6, 5, 2, 2); - g.FillRectangle(dt.SolidBrush, 8, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 3, 9, 8, 6); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + m_canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t ?? string.Empty)) / 2; + m_canvas.DrawText(t ?? string.Empty, x, y, text); } - //是否绘制面板切换按钮 - if (m_node_attribute == null || m_lst_item.Count == 0) return; - if (m_b_hover_switch) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, m_rect_switch); - } - m_pen.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_brush.Color = m_pen.Color; - int nT1 = m_rect_switch.Top + m_rect_switch.Height / 2 - 2; - int nT2 = m_rect_switch.Top + m_rect_switch.Height / 2 + 1; - g.DrawRectangle(m_pen, m_rect_switch.Left, m_rect_switch.Top, m_rect_switch.Width - 1, m_rect_switch.Height - 1); - - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), new Point(m_rect_switch.Right - 3, nT1), - new Point(m_rect_switch.Left + 3, nT1 - 1), new Point(m_rect_switch.Right - 3, nT1 - 1) - }); - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT2), new Point(m_rect_switch.Right - 3, nT2), - new Point(m_rect_switch.Left + 2, nT2 + 1), new Point(m_rect_switch.Right - 4, nT2 + 1), - }); - - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), - new Point(m_rect_switch.Left + 7, nT1), - new Point(m_rect_switch.Left + 7, m_rect_switch.Top ), - }); - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Right - 2, nT2), - new Point(m_rect_switch.Right - 7, nT2), - new Point(m_rect_switch.Right - 7, m_rect_switch.Bottom - 2 ), - }); } /// /// 当需要绘制属性描述信息时发生 /// /// 绘制工具 protected virtual void OnDrawDescription(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_desc)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_desc, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, this.Height - (int)szf.Height - 4, this.Width, (int)szf.Height + 4); - m_brush.Color = this._DescriptionColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._DescriptionColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_desc, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_desc) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_desc, ref bounds); + Rectangle rect_desc = new Rectangle(0, this.Height - (int)Math.Ceiling(bounds.Height) - 8, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_desc, rect_desc.Left + 4, y, text); + } } /// /// 当需要绘制错误信息时发生 /// /// 绘制工具 protected virtual void OnDrawErrorInfo(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_err)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_err, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)szf.Height + 4); - m_brush.Color = this._ErrorColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._ErrorColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_err, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_err) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_err, ref bounds); + Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_err, rect_desc.Left + 4, y, text); + } } /// /// 当绘制节点信息时候发生 /// /// 绘制工具 protected virtual void OnDrawInfo(DrawingTools dt) { - if (m_node_attribute == null) return; + if (m_node_attribute == null || m_canvas == null) return; var attr = m_node_attribute; - Graphics g = dt.Graphics; - Color clr_r = Color.FromArgb(this.ForeColor.A / 2, this.ForeColor); - m_sf.Alignment = StringAlignment.Near; - Rectangle rect = new Rectangle(0, this._ShowTitle ? m_nTitleHeight : 0, this.Width, m_item_height); - Rectangle rect_l = new Rectangle(2, rect.Top, m_nInfoLeft - 2, m_item_height); - Rectangle rect_r = new Rectangle(m_nInfoLeft, rect.Top, this.Width - m_nInfoLeft, m_item_height); - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_KeysString[0], this.Font, m_brush, rect_l, m_sf); //author - m_brush.Color = clr_r; - g.DrawString(attr.Author, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_1; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[1], this.Font, m_brush, rect_l, m_sf); //mail - m_brush.Color = clr_r; - g.DrawString(attr.Mail, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[2], this.Font, m_brush, rect_l, m_sf); //link_key - m_brush.Color = clr_r; - g.DrawString(attr.Link, this.Font, Brushes.CornflowerBlue, rect_r, m_sf); //link - if (!string.IsNullOrEmpty(attr.Link)) m_rect_link = rect_r; - //fill left - m_brush.Color = Color.FromArgb(40, 125, 125, 125); - g.FillRectangle(m_brush, 0, this._ShowTitle ? m_nTitleHeight : 0, m_nInfoLeft - 1, m_item_height * 3); - - rect.X = 5; rect.Y += m_item_height; - rect.Width = this.Width - 10; - if (!string.IsNullOrEmpty(m_node_attribute.Description)) { - float h = g.MeasureString(m_node_attribute.Description, this.Font, rect.Width).Height; - rect.Height = (int)Math.Ceiling(h / m_item_height) * m_item_height; - m_brush.Color = clr_r; - m_sf.FormatFlags = 0; - g.DrawString(m_node_attribute.Description, this.Font, m_brush, rect, m_sf); - } - m_nInfoVHeight = rect.Bottom; - bool bHasHelp = STNodeAttribute.GetHelpMethod(m_type) != null; - rect.X = 5; rect.Y += rect.Height; - rect.Height = m_item_height; - m_sf.Alignment = StringAlignment.Center; - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, rect); - if (bHasHelp) m_brush.Color = Color.CornflowerBlue; - g.DrawString(m_KeysString[3], this.Font, m_brush, rect, m_sf); - if (bHasHelp) m_rect_help = rect; - else { - int w = (int)g.MeasureString(m_KeysString[3], this.Font).Width + 1; - int x = rect.X + (rect.Width - w) / 2, y = rect.Y + rect.Height / 2; - m_pen.Color = m_brush.Color; - g.DrawLine(m_pen, x, y, x + w, y); + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textDim = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this.ForeColor.A / 2, this.ForeColor)), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) { + int top = this._ShowTitle ? m_nTitleHeight : 0; + int y = top; + void row(SKColor bg,string key,string val,SKPaint vp){ + fill.Color=bg; m_canvas.DrawRect(0,y,this.Width,m_item_height,fill); + var fm=text.FontMetrics; float ty=y+(m_item_height-(fm.Descent-fm.Ascent))/2-fm.Ascent; + m_canvas.DrawText(key,2,ty,text); m_canvas.DrawText(val??string.Empty,m_nInfoLeft,ty,vp); y+=m_item_height; + } + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[0],attr.Author,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_1),m_KeysString[1],attr.Mail,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[2],attr.Link,new SKPaint{Color=SKColors.CornflowerBlue,TextSize=text.TextSize,IsAntialias=true}); + m_nInfoVHeight = y + m_item_height; } - m_nInfoVHeight = rect.Bottom; } /// /// 当在属性面板鼠标点下时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..28131ec 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -41,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeTreeView : Control + public class STNodeTreeView : SKControl { private Color _ItemBackColor = Color.FromArgb(255, 45, 45, 45); /// @@ -195,6 +197,7 @@ public STNodePropertyGrid PropertyGrid { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); @@ -366,21 +369,22 @@ protected override void OnResize(EventArgs e) { m_rect_clear = new Rectangle(this.Width - 20, 9, 12, 12); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); m_nOffsetY = string.IsNullOrEmpty(m_str_search) ? m_nSourceOffsetY : m_nSearchOffsetY; - Graphics g = e.Graphics; - m_dt.Graphics = g; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - g.TranslateTransform(0, m_nOffsetY); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas.Save(); + m_canvas.Translate(0, m_nOffsetY); int nCounter = 0; foreach (STNodeTreeCollection v in m_items_draw) nCounter = this.OnStartDrawItem(m_dt, v, nCounter, 0); m_nVHeight = (nCounter + 1) * m_nItemHeight; foreach (STNodeTreeCollection v in m_items_draw) this.OnDrawSwitch(m_dt, v); - g.ResetTransform(); + m_canvas.Restore(); this.OnDrawSearch(m_dt); + m_canvas = null; } protected override void OnMouseMove(MouseEventArgs e) { @@ -478,24 +482,20 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + if (m_canvas == null) return; + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + m_canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + m_canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + m_canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + m_canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + m_canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + m_canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } } } /// @@ -507,7 +507,6 @@ protected virtual void OnDrawSearch(DrawingTools dt) { /// 当前位于第几级子集合 /// 已经绘制个数 protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; Items.DisplayRectangle = new Rectangle(0, m_nItemHeight * (nCounter + 1), this.Width, m_nItemHeight); Items.SwitchRectangle = new Rectangle(5 + nLevel * 10, (nCounter + 1) * m_nItemHeight, 10, m_nItemHeight); if (this._ShowInfoButton && Items.STNodeType != null) @@ -534,23 +533,26 @@ protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Item /// 已经绘制个数的计数器 /// 当前位于第几级子集合 protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; - m_brush.Color = nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, items.DisplayRectangle); - if (items == m_item_hover) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, items.DisplayRectangle); - } - Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); - m_pen.Color = Color.FromArgb(100, 125, 125, 125); - g.DrawLine(m_pen, 9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2); - if (nCounter != 0) { - for (int i = 0; i <= nLevel; i++) { - g.DrawLine(m_pen, 9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var line = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor(nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); + if (items == m_item_hover) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); } + Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); + line.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(100, 125, 125, 125)); + m_canvas.DrawLine(9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2, line); + if (nCounter != 0) { + for (int i = 0; i <= nLevel; i++) { + m_canvas.DrawLine(9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1, line); + } + } + this.OnDrawItemText(dt, items, rect); + this.OnDrawItemIcon(dt, items, rect); } - this.OnDrawItemText(dt, items, rect); - this.OnDrawItemIcon(dt, items, rect); } /// /// 当绘制树节点展开与关闭开关时候发生 @@ -558,15 +560,15 @@ protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, i /// 绘制工具 /// 当前需要绘制的集合 protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.Count != 0) { - m_pen.Color = this._SwitchColor; - m_brush.Color = m_pen.Color; - int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; - g.DrawRectangle(m_pen, items.SwitchRectangle.Left, nT, 8, 8); - g.DrawLine(m_pen, items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4); - if (items.IsOpen) return; - g.DrawLine(m_pen, items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SwitchColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; + m_canvas.DrawRect(items.SwitchRectangle.Left, nT, 8, 8, stroke); + m_canvas.DrawLine(items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4, stroke); + if (items.IsOpen) return; + m_canvas.DrawLine(items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7, stroke); + } //if (items.IsOpen) { // //g.FillPolygon(m_brush, new Point[]{ // // new Point(items.DotRectangle.Left + 0, items.DotRectangle.Top + m_nItemHeight / 2 - 2), @@ -594,28 +596,30 @@ protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; rect.Width -= 20; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - if (!string.IsNullOrEmpty(m_str_search)) { - int nIndex = items.NameLower.IndexOf(m_str_search); - if (nIndex != -1) { - CharacterRange[] chrs = { new CharacterRange(nIndex, m_str_search.Length) };//global - m_sf.SetMeasurableCharacterRanges(chrs); - Region[] regions = g.MeasureCharacterRanges(items.Name, this.Font, rect, m_sf); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Intersect); - m_brush.Color = this._HightLightTextColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Exclude); - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 1 / 2, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - return; + using (var textNormal = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textHi = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HightLightTextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = textNormal.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + string name = items.Name ?? string.Empty; + if (!string.IsNullOrEmpty(m_str_search)) { + int idx = items.NameLower.IndexOf(m_str_search); + if (idx >= 0) { + string pre = name.Substring(0, idx); + string hit = name.Substring(idx, Math.Min(m_str_search.Length, name.Length - idx)); + string suf = name.Substring(idx + hit.Length); + float x = rect.Left; + m_canvas.DrawText(pre, x, y, textNormal); + x += textNormal.MeasureText(pre); + m_canvas.DrawText(hit, x, y, textHi); + x += textHi.MeasureText(hit); + m_canvas.DrawText(suf, x, y, textNormal); + return; + } } + m_canvas.DrawText(name, rect.Left, y, textNormal); } - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); } /// /// 当绘制树节点图标时候发生 @@ -624,43 +628,52 @@ protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection item /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemIcon(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.STNodeType != null) { - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan; - m_brush.Color = Color.LightGray; - g.DrawRectangle(m_pen, rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.FillRectangle(m_brush, rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - g.FillRectangle(m_brush, rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - if (m_item_hover == items && m_bHoverInfo) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, items.InfoRectangle); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = SKColors.LightGray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10, stroke); + m_canvas.DrawRect(rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + m_canvas.DrawRect(rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + if (m_item_hover == items && m_bHoverInfo) { + fill.Color = SkiaDrawingHelper.ToSKColor(this.BackColor); + m_canvas.DrawRect(items.InfoRectangle.Left, items.InfoRectangle.Top, items.InfoRectangle.Width, items.InfoRectangle.Height, fill); + } + } + using (var info = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11, info); + m_canvas.DrawLine(items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10, info); + } + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1, box); } - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor; - m_pen.Width = 2; - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11); - g.DrawLine(m_pen, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1); } else { - if (items.IsLibraryRoot) { - Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.DrawRectangle(Pens.Gray, rect_box); - g.DrawLine(Pens.Cyan, rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top); - g.DrawLine(Pens.Cyan, rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2); - g.DrawLine(Pens.Cyan, rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom); - g.DrawLine(Pens.Cyan, rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2); - } else { - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3)); - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9)); + using (var stroke = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (items.IsLibraryRoot) { + Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); + stroke.Color = SKColors.Gray; + m_canvas.DrawRect(rect_box.Left, rect_box.Top, rect_box.Width, rect_box.Height, stroke); + stroke.Color = SKColors.Cyan; + m_canvas.DrawLine(rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top, stroke); + m_canvas.DrawLine(rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2, stroke); + m_canvas.DrawLine(rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom, stroke); + m_canvas.DrawLine(rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2, stroke); + } else { + stroke.Color = SKColors.Goldenrod; + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3, stroke); + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9, stroke); + } } if (!this._ShowFolderCount) return; - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this._FolderCountColor; - rect.X -= 4; - g.DrawString("[" + items.STNodeCount.ToString() + "]", this.Font, m_brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Near; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._FolderCountColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + string t = "[" + items.STNodeCount.ToString() + "]"; + float w = text.MeasureText(t); + var fm = text.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(t, rect.Right - w - 4, y, text); + } } } diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From d841eace2ad2bfefaf0df086809b4d64c86e660a Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Thu, 12 Mar 2026 09:11:02 +0800 Subject: [PATCH 08/13] Change STNodeEditor base control to SKControl --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +-- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++-- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 +++-- ST.Library.UI/NodeEditor/STNode.cs | 96 +++---- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 +- ST.Library.UI/NodeEditor/STNodeEditor.cs | 40 +-- .../NodeEditor/STNodeEditorPannel.cs | 44 +-- .../NodeEditor/STNodePropertyAttribute.cs | 39 +-- .../NodeEditor/STNodePropertyGrid.cs | 261 ++++++------------ ST.Library.UI/NodeEditor/STNodeTreeView.cs | 215 ++++++++------- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 +++ ST.Library.UI/ST.Library.UI.csproj | 105 +------ WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 +- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 +- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 +- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 +------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 35 files changed, 582 insertions(+), 781 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..3cf6f5f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -581,11 +582,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +599,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -737,15 +734,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..b105963 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,8 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -44,7 +46,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeEditor : Control + public class STNodeEditor : SKControl { private const UInt32 WM_MOUSEHWHEEL = 0x020E; protected static readonly Type m_type_node = typeof(STNode); @@ -979,22 +981,21 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); int n = 5 - (int)(this._CanvasOffsetX / nIncrement); for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); n = 5 - (int)(this._CanvasOffsetY / nIncrement); for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); + canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } - } + }); } /// /// 当绘制 Node 时候发生 @@ -1145,12 +1146,15 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } + }); } /// /// 绘制超出视觉区域的 Node 位置提示信息 diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..62c91d4 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,12 +5,14 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; +using SkiaSharp.Views.Desktop; using System.Runtime.InteropServices; using System.ComponentModel; namespace ST.Library.UI.NodeEditor { - public class STNodeEditorPannel : Control + public class STNodeEditorPannel : SKControl { private bool _LeftLayout = true; /// @@ -123,7 +125,6 @@ public STNodePropertyGrid PropertyGrid { private Point m_pt_down; private bool m_is_mx; private bool m_is_my; - private Pen m_pen; private bool m_nInited; private Dictionary m_dic_status_key = new Dictionary(); @@ -163,7 +164,6 @@ public STNodeEditorPannel() { this.MinimumSize = new Size(250, 250); this.BackColor = Color.FromArgb(255, 34, 34, 34); - m_pen = new Pen(this.BackColor, 3); Type t = typeof(ConnectionStatus); var vv = Enum.GetValues(t); @@ -208,25 +208,27 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound base.SetBoundsCore(x, y, width, height, specified); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + var canvas = e.Surface.Canvas; + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..47abf96 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,8 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -43,7 +45,7 @@ namespace ST.Library.UI.NodeEditor /// /// STNode节点属性编辑器 /// - public class STNodePropertyGrid : Control + public class STNodePropertyGrid : SKControl { #region properties ========== @@ -261,6 +263,7 @@ public bool ReadOnlyModel { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; /// /// 构造一个节点属性编辑器 @@ -364,31 +367,19 @@ private void SetItemRectangle() { /// 当控件重绘时候发生 /// /// 事件参数 - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_dt.Graphics = g; - - m_nOffsetY = m_b_current_draw_info ? m_nInfoOffsetY : m_nPropertyOffsetY; - g.TranslateTransform(0, m_nOffsetY); - - if (m_b_current_draw_info) { - m_nVHeight = m_nInfoVHeight; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + if (this._InfoFirstOnDraw) { this.OnDrawInfo(m_dt); } else { - m_nVHeight = m_nPropertyVHeight; - for (int i = 0; i < m_lst_item.Count; i++) { - this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); - } + for (int i = 0; i < m_lst_item.Count; i++) this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); } - - g.ResetTransform(); - if (this._ShowTitle) this.OnDrawTitle(m_dt); - m_sf.FormatFlags = 0; if (!string.IsNullOrEmpty(m_str_err)) this.OnDrawErrorInfo(m_dt); if (!string.IsNullOrEmpty(m_str_desc)) this.OnDrawDescription(m_dt); + m_canvas = null; } /// /// 当鼠标在控件上移动时候发生 @@ -533,33 +524,29 @@ protected override void OnResize(EventArgs e) { /// 目标属性选项描述器 /// 选项所在索引 protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescriptor item, int nIndex) { - Graphics g = dt.Graphics; - m_brush.Color = (nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, item.Rectangle); - if (item == m_item_hover || item == m_item_selected) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, item.Rectangle); - } - if (m_item_selected == item) { - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height); - if (this._AutoColor && this._STNode != null) - m_brush.Color = this._STNode.TitleColor; - else - m_brush.Color = this._ItemSelectedColor; - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor((nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + if (item == m_item_hover || item == m_item_selected) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + } + if (m_item_selected == item) { + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height, fill); + fill.Color = SkiaDrawingHelper.ToSKColor((this._AutoColor && this._STNode != null) ? this._STNode.TitleColor : this._ItemSelectedColor); + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8, fill); + } + var fm = text.FontMetrics; + float y = item.RectangleL.Top + (item.RectangleL.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = item.RectangleL.Right - text.MeasureText(item.Name ?? string.Empty) - 2; + m_canvas.DrawText(item.Name ?? string.Empty, x, y, text); } - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this.ForeColor; - g.DrawString(item.Name, this.Font, m_brush, item.RectangleL, m_sf); - item.OnDrawValueRectangle(m_dt); - if (this._ReadOnlyModel) { - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, item.RectangleR); - m_pen.Color = this.ForeColor; - //g.DrawLine(m_pen, - // item.RectangleR.Left - 2, item.RectangleR.Top + item.RectangleR.Height / 2, - // item.RectangleR.Right + 1, item.RectangleR.Top + item.RectangleR.Height / 2); + if (this._ReadOnlyModel && m_canvas != null) { + using (var overlay = new SKPaint { Color = new SKColor(125, 125, 125, 125), Style = SKPaintStyle.Fill, IsAntialias = true }) + m_canvas.DrawRect(item.RectangleR.Left, item.RectangleR.Top, item.RectangleR.Width, item.RectangleR.Height, overlay); } } /// @@ -567,159 +554,79 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { - Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); - - if (this._ReadOnlyModel) { - m_brush.Color = this.ForeColor; - g.FillRectangle(dt.SolidBrush, 4, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 6, 5, 2, 2); - g.FillRectangle(dt.SolidBrush, 8, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 3, 9, 8, 6); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + m_canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t ?? string.Empty)) / 2; + m_canvas.DrawText(t ?? string.Empty, x, y, text); } - //是否绘制面板切换按钮 - if (m_node_attribute == null || m_lst_item.Count == 0) return; - if (m_b_hover_switch) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, m_rect_switch); - } - m_pen.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_brush.Color = m_pen.Color; - int nT1 = m_rect_switch.Top + m_rect_switch.Height / 2 - 2; - int nT2 = m_rect_switch.Top + m_rect_switch.Height / 2 + 1; - g.DrawRectangle(m_pen, m_rect_switch.Left, m_rect_switch.Top, m_rect_switch.Width - 1, m_rect_switch.Height - 1); - - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), new Point(m_rect_switch.Right - 3, nT1), - new Point(m_rect_switch.Left + 3, nT1 - 1), new Point(m_rect_switch.Right - 3, nT1 - 1) - }); - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT2), new Point(m_rect_switch.Right - 3, nT2), - new Point(m_rect_switch.Left + 2, nT2 + 1), new Point(m_rect_switch.Right - 4, nT2 + 1), - }); - - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), - new Point(m_rect_switch.Left + 7, nT1), - new Point(m_rect_switch.Left + 7, m_rect_switch.Top ), - }); - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Right - 2, nT2), - new Point(m_rect_switch.Right - 7, nT2), - new Point(m_rect_switch.Right - 7, m_rect_switch.Bottom - 2 ), - }); } /// /// 当需要绘制属性描述信息时发生 /// /// 绘制工具 protected virtual void OnDrawDescription(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_desc)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_desc, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, this.Height - (int)szf.Height - 4, this.Width, (int)szf.Height + 4); - m_brush.Color = this._DescriptionColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._DescriptionColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_desc, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_desc) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_desc, ref bounds); + Rectangle rect_desc = new Rectangle(0, this.Height - (int)Math.Ceiling(bounds.Height) - 8, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_desc, rect_desc.Left + 4, y, text); + } } /// /// 当需要绘制错误信息时发生 /// /// 绘制工具 protected virtual void OnDrawErrorInfo(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_err)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_err, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)szf.Height + 4); - m_brush.Color = this._ErrorColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._ErrorColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_err, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_err) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_err, ref bounds); + Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_err, rect_desc.Left + 4, y, text); + } } /// /// 当绘制节点信息时候发生 /// /// 绘制工具 protected virtual void OnDrawInfo(DrawingTools dt) { - if (m_node_attribute == null) return; + if (m_node_attribute == null || m_canvas == null) return; var attr = m_node_attribute; - Graphics g = dt.Graphics; - Color clr_r = Color.FromArgb(this.ForeColor.A / 2, this.ForeColor); - m_sf.Alignment = StringAlignment.Near; - Rectangle rect = new Rectangle(0, this._ShowTitle ? m_nTitleHeight : 0, this.Width, m_item_height); - Rectangle rect_l = new Rectangle(2, rect.Top, m_nInfoLeft - 2, m_item_height); - Rectangle rect_r = new Rectangle(m_nInfoLeft, rect.Top, this.Width - m_nInfoLeft, m_item_height); - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_KeysString[0], this.Font, m_brush, rect_l, m_sf); //author - m_brush.Color = clr_r; - g.DrawString(attr.Author, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_1; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[1], this.Font, m_brush, rect_l, m_sf); //mail - m_brush.Color = clr_r; - g.DrawString(attr.Mail, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[2], this.Font, m_brush, rect_l, m_sf); //link_key - m_brush.Color = clr_r; - g.DrawString(attr.Link, this.Font, Brushes.CornflowerBlue, rect_r, m_sf); //link - if (!string.IsNullOrEmpty(attr.Link)) m_rect_link = rect_r; - //fill left - m_brush.Color = Color.FromArgb(40, 125, 125, 125); - g.FillRectangle(m_brush, 0, this._ShowTitle ? m_nTitleHeight : 0, m_nInfoLeft - 1, m_item_height * 3); - - rect.X = 5; rect.Y += m_item_height; - rect.Width = this.Width - 10; - if (!string.IsNullOrEmpty(m_node_attribute.Description)) { - float h = g.MeasureString(m_node_attribute.Description, this.Font, rect.Width).Height; - rect.Height = (int)Math.Ceiling(h / m_item_height) * m_item_height; - m_brush.Color = clr_r; - m_sf.FormatFlags = 0; - g.DrawString(m_node_attribute.Description, this.Font, m_brush, rect, m_sf); - } - m_nInfoVHeight = rect.Bottom; - bool bHasHelp = STNodeAttribute.GetHelpMethod(m_type) != null; - rect.X = 5; rect.Y += rect.Height; - rect.Height = m_item_height; - m_sf.Alignment = StringAlignment.Center; - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, rect); - if (bHasHelp) m_brush.Color = Color.CornflowerBlue; - g.DrawString(m_KeysString[3], this.Font, m_brush, rect, m_sf); - if (bHasHelp) m_rect_help = rect; - else { - int w = (int)g.MeasureString(m_KeysString[3], this.Font).Width + 1; - int x = rect.X + (rect.Width - w) / 2, y = rect.Y + rect.Height / 2; - m_pen.Color = m_brush.Color; - g.DrawLine(m_pen, x, y, x + w, y); + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textDim = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this.ForeColor.A / 2, this.ForeColor)), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) { + int top = this._ShowTitle ? m_nTitleHeight : 0; + int y = top; + void row(SKColor bg,string key,string val,SKPaint vp){ + fill.Color=bg; m_canvas.DrawRect(0,y,this.Width,m_item_height,fill); + var fm=text.FontMetrics; float ty=y+(m_item_height-(fm.Descent-fm.Ascent))/2-fm.Ascent; + m_canvas.DrawText(key,2,ty,text); m_canvas.DrawText(val??string.Empty,m_nInfoLeft,ty,vp); y+=m_item_height; + } + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[0],attr.Author,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_1),m_KeysString[1],attr.Mail,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[2],attr.Link,new SKPaint{Color=SKColors.CornflowerBlue,TextSize=text.TextSize,IsAntialias=true}); + m_nInfoVHeight = y + m_item_height; } - m_nInfoVHeight = rect.Bottom; } /// /// 当在属性面板鼠标点下时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..28131ec 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -41,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeTreeView : Control + public class STNodeTreeView : SKControl { private Color _ItemBackColor = Color.FromArgb(255, 45, 45, 45); /// @@ -195,6 +197,7 @@ public STNodePropertyGrid PropertyGrid { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); @@ -366,21 +369,22 @@ protected override void OnResize(EventArgs e) { m_rect_clear = new Rectangle(this.Width - 20, 9, 12, 12); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); m_nOffsetY = string.IsNullOrEmpty(m_str_search) ? m_nSourceOffsetY : m_nSearchOffsetY; - Graphics g = e.Graphics; - m_dt.Graphics = g; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - g.TranslateTransform(0, m_nOffsetY); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas.Save(); + m_canvas.Translate(0, m_nOffsetY); int nCounter = 0; foreach (STNodeTreeCollection v in m_items_draw) nCounter = this.OnStartDrawItem(m_dt, v, nCounter, 0); m_nVHeight = (nCounter + 1) * m_nItemHeight; foreach (STNodeTreeCollection v in m_items_draw) this.OnDrawSwitch(m_dt, v); - g.ResetTransform(); + m_canvas.Restore(); this.OnDrawSearch(m_dt); + m_canvas = null; } protected override void OnMouseMove(MouseEventArgs e) { @@ -478,24 +482,20 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + if (m_canvas == null) return; + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + m_canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + m_canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + m_canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + m_canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + m_canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + m_canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } } } /// @@ -507,7 +507,6 @@ protected virtual void OnDrawSearch(DrawingTools dt) { /// 当前位于第几级子集合 /// 已经绘制个数 protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; Items.DisplayRectangle = new Rectangle(0, m_nItemHeight * (nCounter + 1), this.Width, m_nItemHeight); Items.SwitchRectangle = new Rectangle(5 + nLevel * 10, (nCounter + 1) * m_nItemHeight, 10, m_nItemHeight); if (this._ShowInfoButton && Items.STNodeType != null) @@ -534,23 +533,26 @@ protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Item /// 已经绘制个数的计数器 /// 当前位于第几级子集合 protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; - m_brush.Color = nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, items.DisplayRectangle); - if (items == m_item_hover) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, items.DisplayRectangle); - } - Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); - m_pen.Color = Color.FromArgb(100, 125, 125, 125); - g.DrawLine(m_pen, 9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2); - if (nCounter != 0) { - for (int i = 0; i <= nLevel; i++) { - g.DrawLine(m_pen, 9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var line = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor(nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); + if (items == m_item_hover) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); } + Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); + line.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(100, 125, 125, 125)); + m_canvas.DrawLine(9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2, line); + if (nCounter != 0) { + for (int i = 0; i <= nLevel; i++) { + m_canvas.DrawLine(9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1, line); + } + } + this.OnDrawItemText(dt, items, rect); + this.OnDrawItemIcon(dt, items, rect); } - this.OnDrawItemText(dt, items, rect); - this.OnDrawItemIcon(dt, items, rect); } /// /// 当绘制树节点展开与关闭开关时候发生 @@ -558,15 +560,15 @@ protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, i /// 绘制工具 /// 当前需要绘制的集合 protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.Count != 0) { - m_pen.Color = this._SwitchColor; - m_brush.Color = m_pen.Color; - int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; - g.DrawRectangle(m_pen, items.SwitchRectangle.Left, nT, 8, 8); - g.DrawLine(m_pen, items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4); - if (items.IsOpen) return; - g.DrawLine(m_pen, items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SwitchColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; + m_canvas.DrawRect(items.SwitchRectangle.Left, nT, 8, 8, stroke); + m_canvas.DrawLine(items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4, stroke); + if (items.IsOpen) return; + m_canvas.DrawLine(items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7, stroke); + } //if (items.IsOpen) { // //g.FillPolygon(m_brush, new Point[]{ // // new Point(items.DotRectangle.Left + 0, items.DotRectangle.Top + m_nItemHeight / 2 - 2), @@ -594,28 +596,30 @@ protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; rect.Width -= 20; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - if (!string.IsNullOrEmpty(m_str_search)) { - int nIndex = items.NameLower.IndexOf(m_str_search); - if (nIndex != -1) { - CharacterRange[] chrs = { new CharacterRange(nIndex, m_str_search.Length) };//global - m_sf.SetMeasurableCharacterRanges(chrs); - Region[] regions = g.MeasureCharacterRanges(items.Name, this.Font, rect, m_sf); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Intersect); - m_brush.Color = this._HightLightTextColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Exclude); - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 1 / 2, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - return; + using (var textNormal = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textHi = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HightLightTextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = textNormal.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + string name = items.Name ?? string.Empty; + if (!string.IsNullOrEmpty(m_str_search)) { + int idx = items.NameLower.IndexOf(m_str_search); + if (idx >= 0) { + string pre = name.Substring(0, idx); + string hit = name.Substring(idx, Math.Min(m_str_search.Length, name.Length - idx)); + string suf = name.Substring(idx + hit.Length); + float x = rect.Left; + m_canvas.DrawText(pre, x, y, textNormal); + x += textNormal.MeasureText(pre); + m_canvas.DrawText(hit, x, y, textHi); + x += textHi.MeasureText(hit); + m_canvas.DrawText(suf, x, y, textNormal); + return; + } } + m_canvas.DrawText(name, rect.Left, y, textNormal); } - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); } /// /// 当绘制树节点图标时候发生 @@ -624,43 +628,52 @@ protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection item /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemIcon(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.STNodeType != null) { - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan; - m_brush.Color = Color.LightGray; - g.DrawRectangle(m_pen, rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.FillRectangle(m_brush, rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - g.FillRectangle(m_brush, rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - if (m_item_hover == items && m_bHoverInfo) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, items.InfoRectangle); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = SKColors.LightGray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10, stroke); + m_canvas.DrawRect(rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + m_canvas.DrawRect(rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + if (m_item_hover == items && m_bHoverInfo) { + fill.Color = SkiaDrawingHelper.ToSKColor(this.BackColor); + m_canvas.DrawRect(items.InfoRectangle.Left, items.InfoRectangle.Top, items.InfoRectangle.Width, items.InfoRectangle.Height, fill); + } + } + using (var info = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11, info); + m_canvas.DrawLine(items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10, info); + } + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1, box); } - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor; - m_pen.Width = 2; - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11); - g.DrawLine(m_pen, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1); } else { - if (items.IsLibraryRoot) { - Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.DrawRectangle(Pens.Gray, rect_box); - g.DrawLine(Pens.Cyan, rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top); - g.DrawLine(Pens.Cyan, rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2); - g.DrawLine(Pens.Cyan, rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom); - g.DrawLine(Pens.Cyan, rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2); - } else { - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3)); - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9)); + using (var stroke = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (items.IsLibraryRoot) { + Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); + stroke.Color = SKColors.Gray; + m_canvas.DrawRect(rect_box.Left, rect_box.Top, rect_box.Width, rect_box.Height, stroke); + stroke.Color = SKColors.Cyan; + m_canvas.DrawLine(rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top, stroke); + m_canvas.DrawLine(rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2, stroke); + m_canvas.DrawLine(rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom, stroke); + m_canvas.DrawLine(rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2, stroke); + } else { + stroke.Color = SKColors.Goldenrod; + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3, stroke); + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9, stroke); + } } if (!this._ShowFolderCount) return; - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this._FolderCountColor; - rect.X -= 4; - g.DrawString("[" + items.STNodeCount.ToString() + "]", this.Font, m_brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Near; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._FolderCountColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + string t = "[" + items.STNodeCount.ToString() + "]"; + float w = text.MeasureText(t); + var fm = text.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(t, rect.Right - w - 4, y, text); + } } } diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From 1e6a74e59f0b8fb9dd9bdb1014e671c7888a2031 Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Thu, 12 Mar 2026 09:27:43 +0800 Subject: [PATCH 09/13] Advance STNodeEditor repaint path toward SKCanvas rendering --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +-- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++-- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 +++-- ST.Library.UI/NodeEditor/STNode.cs | 96 +++---- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 +- ST.Library.UI/NodeEditor/STNodeEditor.cs | 86 ++++-- .../NodeEditor/STNodeEditorPannel.cs | 44 +-- .../NodeEditor/STNodePropertyAttribute.cs | 39 +-- .../NodeEditor/STNodePropertyGrid.cs | 261 ++++++------------ ST.Library.UI/NodeEditor/STNodeTreeView.cs | 215 ++++++++------- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 +++ ST.Library.UI/ST.Library.UI.csproj | 105 +------ WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 +- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 +- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 +- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 +------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 35 files changed, 618 insertions(+), 791 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..3cf6f5f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -581,11 +582,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +599,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -737,15 +734,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..b77f883 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,8 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -44,7 +46,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeEditor : Control + public class STNodeEditor : SKControl { private const UInt32 WM_MOUSEHWHEEL = 0x020E; protected static readonly Type m_type_node = typeof(STNode); @@ -462,6 +464,7 @@ public STNodeEditor() { #region private fields -------------------------------------------------------------------------------------- private DrawingTools m_drawing_tools; + private SKCanvas m_canvas; private NodeFindInfo m_find = new NodeFindInfo(); private MagnetInfo m_mi = new MagnetInfo(); @@ -645,23 +648,34 @@ protected override void WndProc(ref Message m) { } catch { /*add code*/ } } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + using (var bmp = new Bitmap(Math.Max(this.Width, 1), Math.Max(this.Height, 1))) + using (var g = Graphics.FromImage(bmp)) { + this.RenderEditorToGraphics(g); + using (var skb = SkiaDrawingHelper.ToSKBitmap(bmp)) { + if (skb != null) m_canvas.DrawBitmap(skb, 0, 0); + } + } + m_canvas = null; + } + + private void RenderEditorToGraphics(Graphics g) { g.Clear(this.BackColor); g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; m_drawing_tools.Graphics = g; - SolidBrush brush = m_drawing_tools.SolidBrush; if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); - g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); //移动坐标系 - g.ScaleTransform(this._CanvasScale, this._CanvasScale); //缩放绘图表面 + g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); + g.ScaleTransform(this._CanvasScale, this._CanvasScale); this.OnDrawConnectedLine(m_drawing_tools); this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); - if (m_ca == CanvasAction.ConnectOption) { //如果正在连线 + if (m_ca == CanvasAction.ConnectOption) { m_drawing_tools.Pen.Color = this._HighLineColor; g.SmoothingMode = SmoothingMode.HighQuality; if (m_option_down.IsInput) @@ -669,17 +683,17 @@ protected override void OnPaint(PaintEventArgs e) { else this.DrawBezier(g, m_drawing_tools.Pen, m_pt_dot_down, m_pt_in_canvas, this._Curvature); } - //重置绘图坐标 我认为除了节点以外的其它 修饰相关的绘制不应该在Canvas坐标系中绘制 而应该使用控件的坐标进行绘制 不然会受到缩放比影响 + g.ResetTransform(); switch (m_ca) { - case CanvasAction.MoveNode: //移动过程中 绘制对齐参考线 + case CanvasAction.MoveNode: if (this._ShowMagnet && this._ActiveNode != null) this.OnDrawMagnet(m_drawing_tools, m_mi); break; - case CanvasAction.SelectRectangle: //绘制矩形选取 + case CanvasAction.SelectRectangle: this.OnDrawSelectedRectangle(m_drawing_tools, this.CanvasToControl(m_rect_select)); break; - case CanvasAction.DrawMarkDetails: //绘制标记信息详情 + case CanvasAction.DrawMarkDetails: if (!string.IsNullOrEmpty(m_find.Mark)) this.OnDrawMark(m_drawing_tools); break; } @@ -979,21 +993,35 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 + if (m_canvas != null) { + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); int n = 5 - (int)(this._CanvasOffsetX / nIncrement); for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + m_canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); n = 5 - (int)(this._CanvasOffsetY / nIncrement); for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); + m_canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + m_canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + m_canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } + return; + } + Graphics g = dt.Graphics; + using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) + using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { + float nIncrement = (20 * this._CanvasScale); + int n = 5 - (int)(this._CanvasOffsetX / nIncrement); + for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) + g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + n = 5 - (int)(this._CanvasOffsetY / nIncrement); + for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) + g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); + p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); + g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); + g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); } } /// @@ -1145,12 +1173,14 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + if (m_canvas == null) return; + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } } /// /// 绘制超出视觉区域的 Node 位置提示信息 diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..62c91d4 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,12 +5,14 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; +using SkiaSharp.Views.Desktop; using System.Runtime.InteropServices; using System.ComponentModel; namespace ST.Library.UI.NodeEditor { - public class STNodeEditorPannel : Control + public class STNodeEditorPannel : SKControl { private bool _LeftLayout = true; /// @@ -123,7 +125,6 @@ public STNodePropertyGrid PropertyGrid { private Point m_pt_down; private bool m_is_mx; private bool m_is_my; - private Pen m_pen; private bool m_nInited; private Dictionary m_dic_status_key = new Dictionary(); @@ -163,7 +164,6 @@ public STNodeEditorPannel() { this.MinimumSize = new Size(250, 250); this.BackColor = Color.FromArgb(255, 34, 34, 34); - m_pen = new Pen(this.BackColor, 3); Type t = typeof(ConnectionStatus); var vv = Enum.GetValues(t); @@ -208,25 +208,27 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound base.SetBoundsCore(x, y, width, height, specified); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + var canvas = e.Surface.Canvas; + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..47abf96 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,8 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -43,7 +45,7 @@ namespace ST.Library.UI.NodeEditor /// /// STNode节点属性编辑器 /// - public class STNodePropertyGrid : Control + public class STNodePropertyGrid : SKControl { #region properties ========== @@ -261,6 +263,7 @@ public bool ReadOnlyModel { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; /// /// 构造一个节点属性编辑器 @@ -364,31 +367,19 @@ private void SetItemRectangle() { /// 当控件重绘时候发生 /// /// 事件参数 - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_dt.Graphics = g; - - m_nOffsetY = m_b_current_draw_info ? m_nInfoOffsetY : m_nPropertyOffsetY; - g.TranslateTransform(0, m_nOffsetY); - - if (m_b_current_draw_info) { - m_nVHeight = m_nInfoVHeight; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + if (this._InfoFirstOnDraw) { this.OnDrawInfo(m_dt); } else { - m_nVHeight = m_nPropertyVHeight; - for (int i = 0; i < m_lst_item.Count; i++) { - this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); - } + for (int i = 0; i < m_lst_item.Count; i++) this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); } - - g.ResetTransform(); - if (this._ShowTitle) this.OnDrawTitle(m_dt); - m_sf.FormatFlags = 0; if (!string.IsNullOrEmpty(m_str_err)) this.OnDrawErrorInfo(m_dt); if (!string.IsNullOrEmpty(m_str_desc)) this.OnDrawDescription(m_dt); + m_canvas = null; } /// /// 当鼠标在控件上移动时候发生 @@ -533,33 +524,29 @@ protected override void OnResize(EventArgs e) { /// 目标属性选项描述器 /// 选项所在索引 protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescriptor item, int nIndex) { - Graphics g = dt.Graphics; - m_brush.Color = (nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, item.Rectangle); - if (item == m_item_hover || item == m_item_selected) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, item.Rectangle); - } - if (m_item_selected == item) { - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height); - if (this._AutoColor && this._STNode != null) - m_brush.Color = this._STNode.TitleColor; - else - m_brush.Color = this._ItemSelectedColor; - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor((nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + if (item == m_item_hover || item == m_item_selected) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + } + if (m_item_selected == item) { + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height, fill); + fill.Color = SkiaDrawingHelper.ToSKColor((this._AutoColor && this._STNode != null) ? this._STNode.TitleColor : this._ItemSelectedColor); + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8, fill); + } + var fm = text.FontMetrics; + float y = item.RectangleL.Top + (item.RectangleL.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = item.RectangleL.Right - text.MeasureText(item.Name ?? string.Empty) - 2; + m_canvas.DrawText(item.Name ?? string.Empty, x, y, text); } - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this.ForeColor; - g.DrawString(item.Name, this.Font, m_brush, item.RectangleL, m_sf); - item.OnDrawValueRectangle(m_dt); - if (this._ReadOnlyModel) { - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, item.RectangleR); - m_pen.Color = this.ForeColor; - //g.DrawLine(m_pen, - // item.RectangleR.Left - 2, item.RectangleR.Top + item.RectangleR.Height / 2, - // item.RectangleR.Right + 1, item.RectangleR.Top + item.RectangleR.Height / 2); + if (this._ReadOnlyModel && m_canvas != null) { + using (var overlay = new SKPaint { Color = new SKColor(125, 125, 125, 125), Style = SKPaintStyle.Fill, IsAntialias = true }) + m_canvas.DrawRect(item.RectangleR.Left, item.RectangleR.Top, item.RectangleR.Width, item.RectangleR.Height, overlay); } } /// @@ -567,159 +554,79 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { - Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); - - if (this._ReadOnlyModel) { - m_brush.Color = this.ForeColor; - g.FillRectangle(dt.SolidBrush, 4, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 6, 5, 2, 2); - g.FillRectangle(dt.SolidBrush, 8, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 3, 9, 8, 6); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + m_canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t ?? string.Empty)) / 2; + m_canvas.DrawText(t ?? string.Empty, x, y, text); } - //是否绘制面板切换按钮 - if (m_node_attribute == null || m_lst_item.Count == 0) return; - if (m_b_hover_switch) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, m_rect_switch); - } - m_pen.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_brush.Color = m_pen.Color; - int nT1 = m_rect_switch.Top + m_rect_switch.Height / 2 - 2; - int nT2 = m_rect_switch.Top + m_rect_switch.Height / 2 + 1; - g.DrawRectangle(m_pen, m_rect_switch.Left, m_rect_switch.Top, m_rect_switch.Width - 1, m_rect_switch.Height - 1); - - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), new Point(m_rect_switch.Right - 3, nT1), - new Point(m_rect_switch.Left + 3, nT1 - 1), new Point(m_rect_switch.Right - 3, nT1 - 1) - }); - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT2), new Point(m_rect_switch.Right - 3, nT2), - new Point(m_rect_switch.Left + 2, nT2 + 1), new Point(m_rect_switch.Right - 4, nT2 + 1), - }); - - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), - new Point(m_rect_switch.Left + 7, nT1), - new Point(m_rect_switch.Left + 7, m_rect_switch.Top ), - }); - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Right - 2, nT2), - new Point(m_rect_switch.Right - 7, nT2), - new Point(m_rect_switch.Right - 7, m_rect_switch.Bottom - 2 ), - }); } /// /// 当需要绘制属性描述信息时发生 /// /// 绘制工具 protected virtual void OnDrawDescription(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_desc)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_desc, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, this.Height - (int)szf.Height - 4, this.Width, (int)szf.Height + 4); - m_brush.Color = this._DescriptionColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._DescriptionColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_desc, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_desc) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_desc, ref bounds); + Rectangle rect_desc = new Rectangle(0, this.Height - (int)Math.Ceiling(bounds.Height) - 8, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_desc, rect_desc.Left + 4, y, text); + } } /// /// 当需要绘制错误信息时发生 /// /// 绘制工具 protected virtual void OnDrawErrorInfo(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_err)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_err, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)szf.Height + 4); - m_brush.Color = this._ErrorColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._ErrorColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_err, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_err) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_err, ref bounds); + Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_err, rect_desc.Left + 4, y, text); + } } /// /// 当绘制节点信息时候发生 /// /// 绘制工具 protected virtual void OnDrawInfo(DrawingTools dt) { - if (m_node_attribute == null) return; + if (m_node_attribute == null || m_canvas == null) return; var attr = m_node_attribute; - Graphics g = dt.Graphics; - Color clr_r = Color.FromArgb(this.ForeColor.A / 2, this.ForeColor); - m_sf.Alignment = StringAlignment.Near; - Rectangle rect = new Rectangle(0, this._ShowTitle ? m_nTitleHeight : 0, this.Width, m_item_height); - Rectangle rect_l = new Rectangle(2, rect.Top, m_nInfoLeft - 2, m_item_height); - Rectangle rect_r = new Rectangle(m_nInfoLeft, rect.Top, this.Width - m_nInfoLeft, m_item_height); - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_KeysString[0], this.Font, m_brush, rect_l, m_sf); //author - m_brush.Color = clr_r; - g.DrawString(attr.Author, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_1; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[1], this.Font, m_brush, rect_l, m_sf); //mail - m_brush.Color = clr_r; - g.DrawString(attr.Mail, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[2], this.Font, m_brush, rect_l, m_sf); //link_key - m_brush.Color = clr_r; - g.DrawString(attr.Link, this.Font, Brushes.CornflowerBlue, rect_r, m_sf); //link - if (!string.IsNullOrEmpty(attr.Link)) m_rect_link = rect_r; - //fill left - m_brush.Color = Color.FromArgb(40, 125, 125, 125); - g.FillRectangle(m_brush, 0, this._ShowTitle ? m_nTitleHeight : 0, m_nInfoLeft - 1, m_item_height * 3); - - rect.X = 5; rect.Y += m_item_height; - rect.Width = this.Width - 10; - if (!string.IsNullOrEmpty(m_node_attribute.Description)) { - float h = g.MeasureString(m_node_attribute.Description, this.Font, rect.Width).Height; - rect.Height = (int)Math.Ceiling(h / m_item_height) * m_item_height; - m_brush.Color = clr_r; - m_sf.FormatFlags = 0; - g.DrawString(m_node_attribute.Description, this.Font, m_brush, rect, m_sf); - } - m_nInfoVHeight = rect.Bottom; - bool bHasHelp = STNodeAttribute.GetHelpMethod(m_type) != null; - rect.X = 5; rect.Y += rect.Height; - rect.Height = m_item_height; - m_sf.Alignment = StringAlignment.Center; - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, rect); - if (bHasHelp) m_brush.Color = Color.CornflowerBlue; - g.DrawString(m_KeysString[3], this.Font, m_brush, rect, m_sf); - if (bHasHelp) m_rect_help = rect; - else { - int w = (int)g.MeasureString(m_KeysString[3], this.Font).Width + 1; - int x = rect.X + (rect.Width - w) / 2, y = rect.Y + rect.Height / 2; - m_pen.Color = m_brush.Color; - g.DrawLine(m_pen, x, y, x + w, y); + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textDim = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this.ForeColor.A / 2, this.ForeColor)), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) { + int top = this._ShowTitle ? m_nTitleHeight : 0; + int y = top; + void row(SKColor bg,string key,string val,SKPaint vp){ + fill.Color=bg; m_canvas.DrawRect(0,y,this.Width,m_item_height,fill); + var fm=text.FontMetrics; float ty=y+(m_item_height-(fm.Descent-fm.Ascent))/2-fm.Ascent; + m_canvas.DrawText(key,2,ty,text); m_canvas.DrawText(val??string.Empty,m_nInfoLeft,ty,vp); y+=m_item_height; + } + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[0],attr.Author,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_1),m_KeysString[1],attr.Mail,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[2],attr.Link,new SKPaint{Color=SKColors.CornflowerBlue,TextSize=text.TextSize,IsAntialias=true}); + m_nInfoVHeight = y + m_item_height; } - m_nInfoVHeight = rect.Bottom; } /// /// 当在属性面板鼠标点下时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..28131ec 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -41,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeTreeView : Control + public class STNodeTreeView : SKControl { private Color _ItemBackColor = Color.FromArgb(255, 45, 45, 45); /// @@ -195,6 +197,7 @@ public STNodePropertyGrid PropertyGrid { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); @@ -366,21 +369,22 @@ protected override void OnResize(EventArgs e) { m_rect_clear = new Rectangle(this.Width - 20, 9, 12, 12); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); m_nOffsetY = string.IsNullOrEmpty(m_str_search) ? m_nSourceOffsetY : m_nSearchOffsetY; - Graphics g = e.Graphics; - m_dt.Graphics = g; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - g.TranslateTransform(0, m_nOffsetY); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas.Save(); + m_canvas.Translate(0, m_nOffsetY); int nCounter = 0; foreach (STNodeTreeCollection v in m_items_draw) nCounter = this.OnStartDrawItem(m_dt, v, nCounter, 0); m_nVHeight = (nCounter + 1) * m_nItemHeight; foreach (STNodeTreeCollection v in m_items_draw) this.OnDrawSwitch(m_dt, v); - g.ResetTransform(); + m_canvas.Restore(); this.OnDrawSearch(m_dt); + m_canvas = null; } protected override void OnMouseMove(MouseEventArgs e) { @@ -478,24 +482,20 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + if (m_canvas == null) return; + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + m_canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + m_canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + m_canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + m_canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + m_canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + m_canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } } } /// @@ -507,7 +507,6 @@ protected virtual void OnDrawSearch(DrawingTools dt) { /// 当前位于第几级子集合 /// 已经绘制个数 protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; Items.DisplayRectangle = new Rectangle(0, m_nItemHeight * (nCounter + 1), this.Width, m_nItemHeight); Items.SwitchRectangle = new Rectangle(5 + nLevel * 10, (nCounter + 1) * m_nItemHeight, 10, m_nItemHeight); if (this._ShowInfoButton && Items.STNodeType != null) @@ -534,23 +533,26 @@ protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Item /// 已经绘制个数的计数器 /// 当前位于第几级子集合 protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; - m_brush.Color = nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, items.DisplayRectangle); - if (items == m_item_hover) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, items.DisplayRectangle); - } - Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); - m_pen.Color = Color.FromArgb(100, 125, 125, 125); - g.DrawLine(m_pen, 9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2); - if (nCounter != 0) { - for (int i = 0; i <= nLevel; i++) { - g.DrawLine(m_pen, 9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var line = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor(nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); + if (items == m_item_hover) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); } + Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); + line.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(100, 125, 125, 125)); + m_canvas.DrawLine(9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2, line); + if (nCounter != 0) { + for (int i = 0; i <= nLevel; i++) { + m_canvas.DrawLine(9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1, line); + } + } + this.OnDrawItemText(dt, items, rect); + this.OnDrawItemIcon(dt, items, rect); } - this.OnDrawItemText(dt, items, rect); - this.OnDrawItemIcon(dt, items, rect); } /// /// 当绘制树节点展开与关闭开关时候发生 @@ -558,15 +560,15 @@ protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, i /// 绘制工具 /// 当前需要绘制的集合 protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.Count != 0) { - m_pen.Color = this._SwitchColor; - m_brush.Color = m_pen.Color; - int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; - g.DrawRectangle(m_pen, items.SwitchRectangle.Left, nT, 8, 8); - g.DrawLine(m_pen, items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4); - if (items.IsOpen) return; - g.DrawLine(m_pen, items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SwitchColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; + m_canvas.DrawRect(items.SwitchRectangle.Left, nT, 8, 8, stroke); + m_canvas.DrawLine(items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4, stroke); + if (items.IsOpen) return; + m_canvas.DrawLine(items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7, stroke); + } //if (items.IsOpen) { // //g.FillPolygon(m_brush, new Point[]{ // // new Point(items.DotRectangle.Left + 0, items.DotRectangle.Top + m_nItemHeight / 2 - 2), @@ -594,28 +596,30 @@ protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; rect.Width -= 20; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - if (!string.IsNullOrEmpty(m_str_search)) { - int nIndex = items.NameLower.IndexOf(m_str_search); - if (nIndex != -1) { - CharacterRange[] chrs = { new CharacterRange(nIndex, m_str_search.Length) };//global - m_sf.SetMeasurableCharacterRanges(chrs); - Region[] regions = g.MeasureCharacterRanges(items.Name, this.Font, rect, m_sf); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Intersect); - m_brush.Color = this._HightLightTextColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Exclude); - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 1 / 2, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - return; + using (var textNormal = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textHi = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HightLightTextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = textNormal.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + string name = items.Name ?? string.Empty; + if (!string.IsNullOrEmpty(m_str_search)) { + int idx = items.NameLower.IndexOf(m_str_search); + if (idx >= 0) { + string pre = name.Substring(0, idx); + string hit = name.Substring(idx, Math.Min(m_str_search.Length, name.Length - idx)); + string suf = name.Substring(idx + hit.Length); + float x = rect.Left; + m_canvas.DrawText(pre, x, y, textNormal); + x += textNormal.MeasureText(pre); + m_canvas.DrawText(hit, x, y, textHi); + x += textHi.MeasureText(hit); + m_canvas.DrawText(suf, x, y, textNormal); + return; + } } + m_canvas.DrawText(name, rect.Left, y, textNormal); } - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); } /// /// 当绘制树节点图标时候发生 @@ -624,43 +628,52 @@ protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection item /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemIcon(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.STNodeType != null) { - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan; - m_brush.Color = Color.LightGray; - g.DrawRectangle(m_pen, rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.FillRectangle(m_brush, rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - g.FillRectangle(m_brush, rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - if (m_item_hover == items && m_bHoverInfo) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, items.InfoRectangle); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = SKColors.LightGray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10, stroke); + m_canvas.DrawRect(rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + m_canvas.DrawRect(rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + if (m_item_hover == items && m_bHoverInfo) { + fill.Color = SkiaDrawingHelper.ToSKColor(this.BackColor); + m_canvas.DrawRect(items.InfoRectangle.Left, items.InfoRectangle.Top, items.InfoRectangle.Width, items.InfoRectangle.Height, fill); + } + } + using (var info = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11, info); + m_canvas.DrawLine(items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10, info); + } + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1, box); } - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor; - m_pen.Width = 2; - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11); - g.DrawLine(m_pen, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1); } else { - if (items.IsLibraryRoot) { - Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.DrawRectangle(Pens.Gray, rect_box); - g.DrawLine(Pens.Cyan, rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top); - g.DrawLine(Pens.Cyan, rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2); - g.DrawLine(Pens.Cyan, rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom); - g.DrawLine(Pens.Cyan, rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2); - } else { - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3)); - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9)); + using (var stroke = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (items.IsLibraryRoot) { + Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); + stroke.Color = SKColors.Gray; + m_canvas.DrawRect(rect_box.Left, rect_box.Top, rect_box.Width, rect_box.Height, stroke); + stroke.Color = SKColors.Cyan; + m_canvas.DrawLine(rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top, stroke); + m_canvas.DrawLine(rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2, stroke); + m_canvas.DrawLine(rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom, stroke); + m_canvas.DrawLine(rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2, stroke); + } else { + stroke.Color = SKColors.Goldenrod; + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3, stroke); + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9, stroke); + } } if (!this._ShowFolderCount) return; - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this._FolderCountColor; - rect.X -= 4; - g.DrawString("[" + items.STNodeCount.ToString() + "]", this.Font, m_brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Near; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._FolderCountColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + string t = "[" + items.STNodeCount.ToString() + "]"; + float w = text.MeasureText(t); + var fm = text.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(t, rect.Right - w - 4, y, text); + } } } diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From 0e75e94b84fb7748c4db0a513d29b4ba049a035f Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Thu, 12 Mar 2026 09:55:51 +0800 Subject: [PATCH 10/13] Refactor STNodeEditor paint entry to SKCanvas renderer --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +-- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++-- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 +++-- ST.Library.UI/NodeEditor/STNode.cs | 96 +++---- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 +- ST.Library.UI/NodeEditor/STNodeEditor.cs | 140 ++++++---- .../NodeEditor/STNodeEditorPannel.cs | 44 +-- .../NodeEditor/STNodePropertyAttribute.cs | 39 +-- .../NodeEditor/STNodePropertyGrid.cs | 261 ++++++------------ ST.Library.UI/NodeEditor/STNodeTreeView.cs | 215 ++++++++------- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 +++ ST.Library.UI/ST.Library.UI.csproj | 105 +------ WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 +- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 +- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 +- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 +------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 35 files changed, 648 insertions(+), 815 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..3cf6f5f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -581,11 +582,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +599,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -737,15 +734,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..f845abe 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,8 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -44,7 +46,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeEditor : Control + public class STNodeEditor : SKControl { private const UInt32 WM_MOUSEHWHEEL = 0x020E; protected static readonly Type m_type_node = typeof(STNode); @@ -462,6 +464,7 @@ public STNodeEditor() { #region private fields -------------------------------------------------------------------------------------- private DrawingTools m_drawing_tools; + private SKCanvas m_canvas; private NodeFindInfo m_find = new NodeFindInfo(); private MagnetInfo m_mi = new MagnetInfo(); @@ -645,47 +648,64 @@ protected override void WndProc(ref Message m) { } catch { /*add code*/ } } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.Clear(this.BackColor); - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_drawing_tools.Graphics = g; - SolidBrush brush = m_drawing_tools.SolidBrush; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + this.RenderEditorToCanvas(m_canvas); + m_canvas = null; + } - if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); + private void RenderEditorToCanvas(SKCanvas canvas) { + if (canvas == null) return; + using (var bmp = this.RenderEditorToBitmap()) + using (var skb = SkiaDrawingHelper.ToSKBitmap(bmp)) { + if (skb != null) canvas.DrawBitmap(skb, 0, 0); + } + } - g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); //移动坐标系 - g.ScaleTransform(this._CanvasScale, this._CanvasScale); //缩放绘图表面 + private Bitmap RenderEditorToBitmap() { + var bmp = new Bitmap(Math.Max(this.Width, 1), Math.Max(this.Height, 1)); + using (var g = Graphics.FromImage(bmp)) { + g.Clear(this.BackColor); + g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; + m_drawing_tools.Graphics = g; - this.OnDrawConnectedLine(m_drawing_tools); - this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); + if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); - if (m_ca == CanvasAction.ConnectOption) { //如果正在连线 - m_drawing_tools.Pen.Color = this._HighLineColor; - g.SmoothingMode = SmoothingMode.HighQuality; - if (m_option_down.IsInput) - this.DrawBezier(g, m_drawing_tools.Pen, m_pt_in_canvas, m_pt_dot_down, this._Curvature); - else - this.DrawBezier(g, m_drawing_tools.Pen, m_pt_dot_down, m_pt_in_canvas, this._Curvature); - } - //重置绘图坐标 我认为除了节点以外的其它 修饰相关的绘制不应该在Canvas坐标系中绘制 而应该使用控件的坐标进行绘制 不然会受到缩放比影响 - g.ResetTransform(); + g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); + g.ScaleTransform(this._CanvasScale, this._CanvasScale); - switch (m_ca) { - case CanvasAction.MoveNode: //移动过程中 绘制对齐参考线 - if (this._ShowMagnet && this._ActiveNode != null) this.OnDrawMagnet(m_drawing_tools, m_mi); - break; - case CanvasAction.SelectRectangle: //绘制矩形选取 - this.OnDrawSelectedRectangle(m_drawing_tools, this.CanvasToControl(m_rect_select)); - break; - case CanvasAction.DrawMarkDetails: //绘制标记信息详情 - if (!string.IsNullOrEmpty(m_find.Mark)) this.OnDrawMark(m_drawing_tools); - break; - } + this.OnDrawConnectedLine(m_drawing_tools); + this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); + + if (m_ca == CanvasAction.ConnectOption) { + m_drawing_tools.Pen.Color = this._HighLineColor; + g.SmoothingMode = SmoothingMode.HighQuality; + if (m_option_down.IsInput) + this.DrawBezier(g, m_drawing_tools.Pen, m_pt_in_canvas, m_pt_dot_down, this._Curvature); + else + this.DrawBezier(g, m_drawing_tools.Pen, m_pt_dot_down, m_pt_in_canvas, this._Curvature); + } + + g.ResetTransform(); + + switch (m_ca) { + case CanvasAction.MoveNode: + if (this._ShowMagnet && this._ActiveNode != null) this.OnDrawMagnet(m_drawing_tools, m_mi); + break; + case CanvasAction.SelectRectangle: + this.OnDrawSelectedRectangle(m_drawing_tools, this.CanvasToControl(m_rect_select)); + break; + case CanvasAction.DrawMarkDetails: + if (!string.IsNullOrEmpty(m_find.Mark)) this.OnDrawMark(m_drawing_tools); + break; + } - if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, this.Size, m_lst_node_out); - this.OnDrawAlert(g); + if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, this.Size, m_lst_node_out); + this.OnDrawAlert(g); + } + return bmp; } protected override void OnMouseDown(MouseEventArgs e) { @@ -979,21 +999,35 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 + if (m_canvas != null) { + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); int n = 5 - (int)(this._CanvasOffsetX / nIncrement); for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + m_canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); n = 5 - (int)(this._CanvasOffsetY / nIncrement); for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); + m_canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + m_canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + m_canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } + return; + } + Graphics g = dt.Graphics; + using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) + using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { + float nIncrement = (20 * this._CanvasScale); + int n = 5 - (int)(this._CanvasOffsetX / nIncrement); + for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) + g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + n = 5 - (int)(this._CanvasOffsetY / nIncrement); + for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) + g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); + p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); + g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); + g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); } } /// @@ -1145,12 +1179,14 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + if (m_canvas == null) return; + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } } /// /// 绘制超出视觉区域的 Node 位置提示信息 diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..62c91d4 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,12 +5,14 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; +using SkiaSharp.Views.Desktop; using System.Runtime.InteropServices; using System.ComponentModel; namespace ST.Library.UI.NodeEditor { - public class STNodeEditorPannel : Control + public class STNodeEditorPannel : SKControl { private bool _LeftLayout = true; /// @@ -123,7 +125,6 @@ public STNodePropertyGrid PropertyGrid { private Point m_pt_down; private bool m_is_mx; private bool m_is_my; - private Pen m_pen; private bool m_nInited; private Dictionary m_dic_status_key = new Dictionary(); @@ -163,7 +164,6 @@ public STNodeEditorPannel() { this.MinimumSize = new Size(250, 250); this.BackColor = Color.FromArgb(255, 34, 34, 34); - m_pen = new Pen(this.BackColor, 3); Type t = typeof(ConnectionStatus); var vv = Enum.GetValues(t); @@ -208,25 +208,27 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound base.SetBoundsCore(x, y, width, height, specified); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + var canvas = e.Surface.Canvas; + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..47abf96 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,8 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -43,7 +45,7 @@ namespace ST.Library.UI.NodeEditor /// /// STNode节点属性编辑器 /// - public class STNodePropertyGrid : Control + public class STNodePropertyGrid : SKControl { #region properties ========== @@ -261,6 +263,7 @@ public bool ReadOnlyModel { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; /// /// 构造一个节点属性编辑器 @@ -364,31 +367,19 @@ private void SetItemRectangle() { /// 当控件重绘时候发生 /// /// 事件参数 - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_dt.Graphics = g; - - m_nOffsetY = m_b_current_draw_info ? m_nInfoOffsetY : m_nPropertyOffsetY; - g.TranslateTransform(0, m_nOffsetY); - - if (m_b_current_draw_info) { - m_nVHeight = m_nInfoVHeight; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + if (this._InfoFirstOnDraw) { this.OnDrawInfo(m_dt); } else { - m_nVHeight = m_nPropertyVHeight; - for (int i = 0; i < m_lst_item.Count; i++) { - this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); - } + for (int i = 0; i < m_lst_item.Count; i++) this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); } - - g.ResetTransform(); - if (this._ShowTitle) this.OnDrawTitle(m_dt); - m_sf.FormatFlags = 0; if (!string.IsNullOrEmpty(m_str_err)) this.OnDrawErrorInfo(m_dt); if (!string.IsNullOrEmpty(m_str_desc)) this.OnDrawDescription(m_dt); + m_canvas = null; } /// /// 当鼠标在控件上移动时候发生 @@ -533,33 +524,29 @@ protected override void OnResize(EventArgs e) { /// 目标属性选项描述器 /// 选项所在索引 protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescriptor item, int nIndex) { - Graphics g = dt.Graphics; - m_brush.Color = (nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, item.Rectangle); - if (item == m_item_hover || item == m_item_selected) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, item.Rectangle); - } - if (m_item_selected == item) { - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height); - if (this._AutoColor && this._STNode != null) - m_brush.Color = this._STNode.TitleColor; - else - m_brush.Color = this._ItemSelectedColor; - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor((nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + if (item == m_item_hover || item == m_item_selected) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + } + if (m_item_selected == item) { + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height, fill); + fill.Color = SkiaDrawingHelper.ToSKColor((this._AutoColor && this._STNode != null) ? this._STNode.TitleColor : this._ItemSelectedColor); + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8, fill); + } + var fm = text.FontMetrics; + float y = item.RectangleL.Top + (item.RectangleL.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = item.RectangleL.Right - text.MeasureText(item.Name ?? string.Empty) - 2; + m_canvas.DrawText(item.Name ?? string.Empty, x, y, text); } - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this.ForeColor; - g.DrawString(item.Name, this.Font, m_brush, item.RectangleL, m_sf); - item.OnDrawValueRectangle(m_dt); - if (this._ReadOnlyModel) { - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, item.RectangleR); - m_pen.Color = this.ForeColor; - //g.DrawLine(m_pen, - // item.RectangleR.Left - 2, item.RectangleR.Top + item.RectangleR.Height / 2, - // item.RectangleR.Right + 1, item.RectangleR.Top + item.RectangleR.Height / 2); + if (this._ReadOnlyModel && m_canvas != null) { + using (var overlay = new SKPaint { Color = new SKColor(125, 125, 125, 125), Style = SKPaintStyle.Fill, IsAntialias = true }) + m_canvas.DrawRect(item.RectangleR.Left, item.RectangleR.Top, item.RectangleR.Width, item.RectangleR.Height, overlay); } } /// @@ -567,159 +554,79 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { - Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); - - if (this._ReadOnlyModel) { - m_brush.Color = this.ForeColor; - g.FillRectangle(dt.SolidBrush, 4, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 6, 5, 2, 2); - g.FillRectangle(dt.SolidBrush, 8, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 3, 9, 8, 6); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + m_canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t ?? string.Empty)) / 2; + m_canvas.DrawText(t ?? string.Empty, x, y, text); } - //是否绘制面板切换按钮 - if (m_node_attribute == null || m_lst_item.Count == 0) return; - if (m_b_hover_switch) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, m_rect_switch); - } - m_pen.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_brush.Color = m_pen.Color; - int nT1 = m_rect_switch.Top + m_rect_switch.Height / 2 - 2; - int nT2 = m_rect_switch.Top + m_rect_switch.Height / 2 + 1; - g.DrawRectangle(m_pen, m_rect_switch.Left, m_rect_switch.Top, m_rect_switch.Width - 1, m_rect_switch.Height - 1); - - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), new Point(m_rect_switch.Right - 3, nT1), - new Point(m_rect_switch.Left + 3, nT1 - 1), new Point(m_rect_switch.Right - 3, nT1 - 1) - }); - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT2), new Point(m_rect_switch.Right - 3, nT2), - new Point(m_rect_switch.Left + 2, nT2 + 1), new Point(m_rect_switch.Right - 4, nT2 + 1), - }); - - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), - new Point(m_rect_switch.Left + 7, nT1), - new Point(m_rect_switch.Left + 7, m_rect_switch.Top ), - }); - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Right - 2, nT2), - new Point(m_rect_switch.Right - 7, nT2), - new Point(m_rect_switch.Right - 7, m_rect_switch.Bottom - 2 ), - }); } /// /// 当需要绘制属性描述信息时发生 /// /// 绘制工具 protected virtual void OnDrawDescription(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_desc)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_desc, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, this.Height - (int)szf.Height - 4, this.Width, (int)szf.Height + 4); - m_brush.Color = this._DescriptionColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._DescriptionColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_desc, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_desc) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_desc, ref bounds); + Rectangle rect_desc = new Rectangle(0, this.Height - (int)Math.Ceiling(bounds.Height) - 8, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_desc, rect_desc.Left + 4, y, text); + } } /// /// 当需要绘制错误信息时发生 /// /// 绘制工具 protected virtual void OnDrawErrorInfo(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_err)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_err, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)szf.Height + 4); - m_brush.Color = this._ErrorColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._ErrorColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_err, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_err) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_err, ref bounds); + Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_err, rect_desc.Left + 4, y, text); + } } /// /// 当绘制节点信息时候发生 /// /// 绘制工具 protected virtual void OnDrawInfo(DrawingTools dt) { - if (m_node_attribute == null) return; + if (m_node_attribute == null || m_canvas == null) return; var attr = m_node_attribute; - Graphics g = dt.Graphics; - Color clr_r = Color.FromArgb(this.ForeColor.A / 2, this.ForeColor); - m_sf.Alignment = StringAlignment.Near; - Rectangle rect = new Rectangle(0, this._ShowTitle ? m_nTitleHeight : 0, this.Width, m_item_height); - Rectangle rect_l = new Rectangle(2, rect.Top, m_nInfoLeft - 2, m_item_height); - Rectangle rect_r = new Rectangle(m_nInfoLeft, rect.Top, this.Width - m_nInfoLeft, m_item_height); - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_KeysString[0], this.Font, m_brush, rect_l, m_sf); //author - m_brush.Color = clr_r; - g.DrawString(attr.Author, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_1; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[1], this.Font, m_brush, rect_l, m_sf); //mail - m_brush.Color = clr_r; - g.DrawString(attr.Mail, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[2], this.Font, m_brush, rect_l, m_sf); //link_key - m_brush.Color = clr_r; - g.DrawString(attr.Link, this.Font, Brushes.CornflowerBlue, rect_r, m_sf); //link - if (!string.IsNullOrEmpty(attr.Link)) m_rect_link = rect_r; - //fill left - m_brush.Color = Color.FromArgb(40, 125, 125, 125); - g.FillRectangle(m_brush, 0, this._ShowTitle ? m_nTitleHeight : 0, m_nInfoLeft - 1, m_item_height * 3); - - rect.X = 5; rect.Y += m_item_height; - rect.Width = this.Width - 10; - if (!string.IsNullOrEmpty(m_node_attribute.Description)) { - float h = g.MeasureString(m_node_attribute.Description, this.Font, rect.Width).Height; - rect.Height = (int)Math.Ceiling(h / m_item_height) * m_item_height; - m_brush.Color = clr_r; - m_sf.FormatFlags = 0; - g.DrawString(m_node_attribute.Description, this.Font, m_brush, rect, m_sf); - } - m_nInfoVHeight = rect.Bottom; - bool bHasHelp = STNodeAttribute.GetHelpMethod(m_type) != null; - rect.X = 5; rect.Y += rect.Height; - rect.Height = m_item_height; - m_sf.Alignment = StringAlignment.Center; - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, rect); - if (bHasHelp) m_brush.Color = Color.CornflowerBlue; - g.DrawString(m_KeysString[3], this.Font, m_brush, rect, m_sf); - if (bHasHelp) m_rect_help = rect; - else { - int w = (int)g.MeasureString(m_KeysString[3], this.Font).Width + 1; - int x = rect.X + (rect.Width - w) / 2, y = rect.Y + rect.Height / 2; - m_pen.Color = m_brush.Color; - g.DrawLine(m_pen, x, y, x + w, y); + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textDim = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this.ForeColor.A / 2, this.ForeColor)), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) { + int top = this._ShowTitle ? m_nTitleHeight : 0; + int y = top; + void row(SKColor bg,string key,string val,SKPaint vp){ + fill.Color=bg; m_canvas.DrawRect(0,y,this.Width,m_item_height,fill); + var fm=text.FontMetrics; float ty=y+(m_item_height-(fm.Descent-fm.Ascent))/2-fm.Ascent; + m_canvas.DrawText(key,2,ty,text); m_canvas.DrawText(val??string.Empty,m_nInfoLeft,ty,vp); y+=m_item_height; + } + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[0],attr.Author,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_1),m_KeysString[1],attr.Mail,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[2],attr.Link,new SKPaint{Color=SKColors.CornflowerBlue,TextSize=text.TextSize,IsAntialias=true}); + m_nInfoVHeight = y + m_item_height; } - m_nInfoVHeight = rect.Bottom; } /// /// 当在属性面板鼠标点下时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..28131ec 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -41,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeTreeView : Control + public class STNodeTreeView : SKControl { private Color _ItemBackColor = Color.FromArgb(255, 45, 45, 45); /// @@ -195,6 +197,7 @@ public STNodePropertyGrid PropertyGrid { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); @@ -366,21 +369,22 @@ protected override void OnResize(EventArgs e) { m_rect_clear = new Rectangle(this.Width - 20, 9, 12, 12); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); m_nOffsetY = string.IsNullOrEmpty(m_str_search) ? m_nSourceOffsetY : m_nSearchOffsetY; - Graphics g = e.Graphics; - m_dt.Graphics = g; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - g.TranslateTransform(0, m_nOffsetY); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas.Save(); + m_canvas.Translate(0, m_nOffsetY); int nCounter = 0; foreach (STNodeTreeCollection v in m_items_draw) nCounter = this.OnStartDrawItem(m_dt, v, nCounter, 0); m_nVHeight = (nCounter + 1) * m_nItemHeight; foreach (STNodeTreeCollection v in m_items_draw) this.OnDrawSwitch(m_dt, v); - g.ResetTransform(); + m_canvas.Restore(); this.OnDrawSearch(m_dt); + m_canvas = null; } protected override void OnMouseMove(MouseEventArgs e) { @@ -478,24 +482,20 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + if (m_canvas == null) return; + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + m_canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + m_canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + m_canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + m_canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + m_canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + m_canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } } } /// @@ -507,7 +507,6 @@ protected virtual void OnDrawSearch(DrawingTools dt) { /// 当前位于第几级子集合 /// 已经绘制个数 protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; Items.DisplayRectangle = new Rectangle(0, m_nItemHeight * (nCounter + 1), this.Width, m_nItemHeight); Items.SwitchRectangle = new Rectangle(5 + nLevel * 10, (nCounter + 1) * m_nItemHeight, 10, m_nItemHeight); if (this._ShowInfoButton && Items.STNodeType != null) @@ -534,23 +533,26 @@ protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Item /// 已经绘制个数的计数器 /// 当前位于第几级子集合 protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; - m_brush.Color = nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, items.DisplayRectangle); - if (items == m_item_hover) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, items.DisplayRectangle); - } - Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); - m_pen.Color = Color.FromArgb(100, 125, 125, 125); - g.DrawLine(m_pen, 9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2); - if (nCounter != 0) { - for (int i = 0; i <= nLevel; i++) { - g.DrawLine(m_pen, 9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var line = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor(nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); + if (items == m_item_hover) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); } + Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); + line.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(100, 125, 125, 125)); + m_canvas.DrawLine(9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2, line); + if (nCounter != 0) { + for (int i = 0; i <= nLevel; i++) { + m_canvas.DrawLine(9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1, line); + } + } + this.OnDrawItemText(dt, items, rect); + this.OnDrawItemIcon(dt, items, rect); } - this.OnDrawItemText(dt, items, rect); - this.OnDrawItemIcon(dt, items, rect); } /// /// 当绘制树节点展开与关闭开关时候发生 @@ -558,15 +560,15 @@ protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, i /// 绘制工具 /// 当前需要绘制的集合 protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.Count != 0) { - m_pen.Color = this._SwitchColor; - m_brush.Color = m_pen.Color; - int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; - g.DrawRectangle(m_pen, items.SwitchRectangle.Left, nT, 8, 8); - g.DrawLine(m_pen, items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4); - if (items.IsOpen) return; - g.DrawLine(m_pen, items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SwitchColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; + m_canvas.DrawRect(items.SwitchRectangle.Left, nT, 8, 8, stroke); + m_canvas.DrawLine(items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4, stroke); + if (items.IsOpen) return; + m_canvas.DrawLine(items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7, stroke); + } //if (items.IsOpen) { // //g.FillPolygon(m_brush, new Point[]{ // // new Point(items.DotRectangle.Left + 0, items.DotRectangle.Top + m_nItemHeight / 2 - 2), @@ -594,28 +596,30 @@ protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; rect.Width -= 20; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - if (!string.IsNullOrEmpty(m_str_search)) { - int nIndex = items.NameLower.IndexOf(m_str_search); - if (nIndex != -1) { - CharacterRange[] chrs = { new CharacterRange(nIndex, m_str_search.Length) };//global - m_sf.SetMeasurableCharacterRanges(chrs); - Region[] regions = g.MeasureCharacterRanges(items.Name, this.Font, rect, m_sf); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Intersect); - m_brush.Color = this._HightLightTextColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Exclude); - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 1 / 2, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - return; + using (var textNormal = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textHi = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HightLightTextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = textNormal.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + string name = items.Name ?? string.Empty; + if (!string.IsNullOrEmpty(m_str_search)) { + int idx = items.NameLower.IndexOf(m_str_search); + if (idx >= 0) { + string pre = name.Substring(0, idx); + string hit = name.Substring(idx, Math.Min(m_str_search.Length, name.Length - idx)); + string suf = name.Substring(idx + hit.Length); + float x = rect.Left; + m_canvas.DrawText(pre, x, y, textNormal); + x += textNormal.MeasureText(pre); + m_canvas.DrawText(hit, x, y, textHi); + x += textHi.MeasureText(hit); + m_canvas.DrawText(suf, x, y, textNormal); + return; + } } + m_canvas.DrawText(name, rect.Left, y, textNormal); } - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); } /// /// 当绘制树节点图标时候发生 @@ -624,43 +628,52 @@ protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection item /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemIcon(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.STNodeType != null) { - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan; - m_brush.Color = Color.LightGray; - g.DrawRectangle(m_pen, rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.FillRectangle(m_brush, rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - g.FillRectangle(m_brush, rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - if (m_item_hover == items && m_bHoverInfo) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, items.InfoRectangle); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = SKColors.LightGray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10, stroke); + m_canvas.DrawRect(rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + m_canvas.DrawRect(rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + if (m_item_hover == items && m_bHoverInfo) { + fill.Color = SkiaDrawingHelper.ToSKColor(this.BackColor); + m_canvas.DrawRect(items.InfoRectangle.Left, items.InfoRectangle.Top, items.InfoRectangle.Width, items.InfoRectangle.Height, fill); + } + } + using (var info = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11, info); + m_canvas.DrawLine(items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10, info); + } + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1, box); } - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor; - m_pen.Width = 2; - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11); - g.DrawLine(m_pen, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1); } else { - if (items.IsLibraryRoot) { - Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.DrawRectangle(Pens.Gray, rect_box); - g.DrawLine(Pens.Cyan, rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top); - g.DrawLine(Pens.Cyan, rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2); - g.DrawLine(Pens.Cyan, rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom); - g.DrawLine(Pens.Cyan, rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2); - } else { - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3)); - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9)); + using (var stroke = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (items.IsLibraryRoot) { + Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); + stroke.Color = SKColors.Gray; + m_canvas.DrawRect(rect_box.Left, rect_box.Top, rect_box.Width, rect_box.Height, stroke); + stroke.Color = SKColors.Cyan; + m_canvas.DrawLine(rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top, stroke); + m_canvas.DrawLine(rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2, stroke); + m_canvas.DrawLine(rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom, stroke); + m_canvas.DrawLine(rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2, stroke); + } else { + stroke.Color = SKColors.Goldenrod; + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3, stroke); + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9, stroke); + } } if (!this._ShowFolderCount) return; - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this._FolderCountColor; - rect.X -= 4; - g.DrawString("[" + items.STNodeCount.ToString() + "]", this.Font, m_brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Near; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._FolderCountColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + string t = "[" + items.STNodeCount.ToString() + "]"; + float w = text.MeasureText(t); + var fm = text.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(t, rect.Right - w - 4, y, text); + } } } diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From c92b9fa18cb45d12ce9b4229828c5867fa1eeb9a Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:16:51 +0800 Subject: [PATCH 11/13] Use SKBitmap/SKCanvas in RenderEditorToBitmap --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +-- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 +++-- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 +++-- ST.Library.UI/NodeEditor/STNode.cs | 96 +++---- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 +- ST.Library.UI/NodeEditor/STNodeEditor.cs | 150 ++++++---- .../NodeEditor/STNodeEditorPannel.cs | 44 +-- .../NodeEditor/STNodePropertyAttribute.cs | 39 +-- .../NodeEditor/STNodePropertyGrid.cs | 261 ++++++------------ ST.Library.UI/NodeEditor/STNodeTreeView.cs | 215 ++++++++------- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 +++ ST.Library.UI/ST.Library.UI.csproj | 105 +------ WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 +- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 +- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 +- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 +------- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 35 files changed, 658 insertions(+), 815 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..3cf6f5f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -581,11 +582,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +599,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -737,15 +734,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..9f05680 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,8 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -44,7 +46,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeEditor : Control + public class STNodeEditor : SKControl { private const UInt32 WM_MOUSEHWHEEL = 0x020E; protected static readonly Type m_type_node = typeof(STNode); @@ -462,6 +464,7 @@ public STNodeEditor() { #region private fields -------------------------------------------------------------------------------------- private DrawingTools m_drawing_tools; + private SKCanvas m_canvas; private NodeFindInfo m_find = new NodeFindInfo(); private MagnetInfo m_mi = new MagnetInfo(); @@ -645,47 +648,74 @@ protected override void WndProc(ref Message m) { } catch { /*add code*/ } } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.Clear(this.BackColor); - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_drawing_tools.Graphics = g; - SolidBrush brush = m_drawing_tools.SolidBrush; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + this.RenderEditorToCanvas(m_canvas); + m_canvas = null; + } - if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); + private void RenderEditorToCanvas(SKCanvas canvas) { + if (canvas == null) return; + using (var bitmap = this.RenderEditorToBitmap()) { + canvas.DrawBitmap(bitmap, 0, 0); + } + } - g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); //移动坐标系 - g.ScaleTransform(this._CanvasScale, this._CanvasScale); //缩放绘图表面 + private SKBitmap RenderEditorToBitmap() { + var bitmap = new SKBitmap(Math.Max(this.Width, 1), Math.Max(this.Height, 1), true); + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + this.RenderEditorToCanvasLegacy(canvas); + } + return bitmap; + } - this.OnDrawConnectedLine(m_drawing_tools); - this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); + private void RenderEditorToCanvasLegacy(SKCanvas canvas) { + using (var bmp = new Bitmap(Math.Max(this.Width, 1), Math.Max(this.Height, 1))) + using (var g = Graphics.FromImage(bmp)) { + g.Clear(this.BackColor); + g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; + m_drawing_tools.Graphics = g; - if (m_ca == CanvasAction.ConnectOption) { //如果正在连线 - m_drawing_tools.Pen.Color = this._HighLineColor; - g.SmoothingMode = SmoothingMode.HighQuality; - if (m_option_down.IsInput) - this.DrawBezier(g, m_drawing_tools.Pen, m_pt_in_canvas, m_pt_dot_down, this._Curvature); - else - this.DrawBezier(g, m_drawing_tools.Pen, m_pt_dot_down, m_pt_in_canvas, this._Curvature); - } - //重置绘图坐标 我认为除了节点以外的其它 修饰相关的绘制不应该在Canvas坐标系中绘制 而应该使用控件的坐标进行绘制 不然会受到缩放比影响 - g.ResetTransform(); + if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); - switch (m_ca) { - case CanvasAction.MoveNode: //移动过程中 绘制对齐参考线 - if (this._ShowMagnet && this._ActiveNode != null) this.OnDrawMagnet(m_drawing_tools, m_mi); - break; - case CanvasAction.SelectRectangle: //绘制矩形选取 - this.OnDrawSelectedRectangle(m_drawing_tools, this.CanvasToControl(m_rect_select)); - break; - case CanvasAction.DrawMarkDetails: //绘制标记信息详情 - if (!string.IsNullOrEmpty(m_find.Mark)) this.OnDrawMark(m_drawing_tools); - break; - } + g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); + g.ScaleTransform(this._CanvasScale, this._CanvasScale); + + this.OnDrawConnectedLine(m_drawing_tools); + this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); + + if (m_ca == CanvasAction.ConnectOption) { + m_drawing_tools.Pen.Color = this._HighLineColor; + g.SmoothingMode = SmoothingMode.HighQuality; + if (m_option_down.IsInput) + this.DrawBezier(g, m_drawing_tools.Pen, m_pt_in_canvas, m_pt_dot_down, this._Curvature); + else + this.DrawBezier(g, m_drawing_tools.Pen, m_pt_dot_down, m_pt_in_canvas, this._Curvature); + } + + g.ResetTransform(); + + switch (m_ca) { + case CanvasAction.MoveNode: + if (this._ShowMagnet && this._ActiveNode != null) this.OnDrawMagnet(m_drawing_tools, m_mi); + break; + case CanvasAction.SelectRectangle: + this.OnDrawSelectedRectangle(m_drawing_tools, this.CanvasToControl(m_rect_select)); + break; + case CanvasAction.DrawMarkDetails: + if (!string.IsNullOrEmpty(m_find.Mark)) this.OnDrawMark(m_drawing_tools); + break; + } - if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, this.Size, m_lst_node_out); - this.OnDrawAlert(g); + if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, this.Size, m_lst_node_out); + this.OnDrawAlert(g); + using (var skBitmap = SkiaDrawingHelper.ToSKBitmap(bmp)) { + if (skBitmap != null) canvas.DrawBitmap(skBitmap, 0, 0); + } + } } protected override void OnMouseDown(MouseEventArgs e) { @@ -979,21 +1009,35 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 + if (m_canvas != null) { + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); int n = 5 - (int)(this._CanvasOffsetX / nIncrement); for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + m_canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); n = 5 - (int)(this._CanvasOffsetY / nIncrement); for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); + m_canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + m_canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + m_canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } + return; + } + Graphics g = dt.Graphics; + using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) + using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { + float nIncrement = (20 * this._CanvasScale); + int n = 5 - (int)(this._CanvasOffsetX / nIncrement); + for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) + g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + n = 5 - (int)(this._CanvasOffsetY / nIncrement); + for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) + g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); + p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); + g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); + g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); } } /// @@ -1145,12 +1189,14 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + if (m_canvas == null) return; + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } } /// /// 绘制超出视觉区域的 Node 位置提示信息 diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..62c91d4 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,12 +5,14 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; +using SkiaSharp.Views.Desktop; using System.Runtime.InteropServices; using System.ComponentModel; namespace ST.Library.UI.NodeEditor { - public class STNodeEditorPannel : Control + public class STNodeEditorPannel : SKControl { private bool _LeftLayout = true; /// @@ -123,7 +125,6 @@ public STNodePropertyGrid PropertyGrid { private Point m_pt_down; private bool m_is_mx; private bool m_is_my; - private Pen m_pen; private bool m_nInited; private Dictionary m_dic_status_key = new Dictionary(); @@ -163,7 +164,6 @@ public STNodeEditorPannel() { this.MinimumSize = new Size(250, 250); this.BackColor = Color.FromArgb(255, 34, 34, 34); - m_pen = new Pen(this.BackColor, 3); Type t = typeof(ConnectionStatus); var vv = Enum.GetValues(t); @@ -208,25 +208,27 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound base.SetBoundsCore(x, y, width, height, specified); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + var canvas = e.Surface.Canvas; + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..47abf96 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,8 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -43,7 +45,7 @@ namespace ST.Library.UI.NodeEditor /// /// STNode节点属性编辑器 /// - public class STNodePropertyGrid : Control + public class STNodePropertyGrid : SKControl { #region properties ========== @@ -261,6 +263,7 @@ public bool ReadOnlyModel { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; /// /// 构造一个节点属性编辑器 @@ -364,31 +367,19 @@ private void SetItemRectangle() { /// 当控件重绘时候发生 /// /// 事件参数 - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_dt.Graphics = g; - - m_nOffsetY = m_b_current_draw_info ? m_nInfoOffsetY : m_nPropertyOffsetY; - g.TranslateTransform(0, m_nOffsetY); - - if (m_b_current_draw_info) { - m_nVHeight = m_nInfoVHeight; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + if (this._InfoFirstOnDraw) { this.OnDrawInfo(m_dt); } else { - m_nVHeight = m_nPropertyVHeight; - for (int i = 0; i < m_lst_item.Count; i++) { - this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); - } + for (int i = 0; i < m_lst_item.Count; i++) this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); } - - g.ResetTransform(); - if (this._ShowTitle) this.OnDrawTitle(m_dt); - m_sf.FormatFlags = 0; if (!string.IsNullOrEmpty(m_str_err)) this.OnDrawErrorInfo(m_dt); if (!string.IsNullOrEmpty(m_str_desc)) this.OnDrawDescription(m_dt); + m_canvas = null; } /// /// 当鼠标在控件上移动时候发生 @@ -533,33 +524,29 @@ protected override void OnResize(EventArgs e) { /// 目标属性选项描述器 /// 选项所在索引 protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescriptor item, int nIndex) { - Graphics g = dt.Graphics; - m_brush.Color = (nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, item.Rectangle); - if (item == m_item_hover || item == m_item_selected) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, item.Rectangle); - } - if (m_item_selected == item) { - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height); - if (this._AutoColor && this._STNode != null) - m_brush.Color = this._STNode.TitleColor; - else - m_brush.Color = this._ItemSelectedColor; - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor((nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + if (item == m_item_hover || item == m_item_selected) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + } + if (m_item_selected == item) { + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height, fill); + fill.Color = SkiaDrawingHelper.ToSKColor((this._AutoColor && this._STNode != null) ? this._STNode.TitleColor : this._ItemSelectedColor); + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8, fill); + } + var fm = text.FontMetrics; + float y = item.RectangleL.Top + (item.RectangleL.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = item.RectangleL.Right - text.MeasureText(item.Name ?? string.Empty) - 2; + m_canvas.DrawText(item.Name ?? string.Empty, x, y, text); } - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this.ForeColor; - g.DrawString(item.Name, this.Font, m_brush, item.RectangleL, m_sf); - item.OnDrawValueRectangle(m_dt); - if (this._ReadOnlyModel) { - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, item.RectangleR); - m_pen.Color = this.ForeColor; - //g.DrawLine(m_pen, - // item.RectangleR.Left - 2, item.RectangleR.Top + item.RectangleR.Height / 2, - // item.RectangleR.Right + 1, item.RectangleR.Top + item.RectangleR.Height / 2); + if (this._ReadOnlyModel && m_canvas != null) { + using (var overlay = new SKPaint { Color = new SKColor(125, 125, 125, 125), Style = SKPaintStyle.Fill, IsAntialias = true }) + m_canvas.DrawRect(item.RectangleR.Left, item.RectangleR.Top, item.RectangleR.Width, item.RectangleR.Height, overlay); } } /// @@ -567,159 +554,79 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { - Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); - - if (this._ReadOnlyModel) { - m_brush.Color = this.ForeColor; - g.FillRectangle(dt.SolidBrush, 4, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 6, 5, 2, 2); - g.FillRectangle(dt.SolidBrush, 8, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 3, 9, 8, 6); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + m_canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t ?? string.Empty)) / 2; + m_canvas.DrawText(t ?? string.Empty, x, y, text); } - //是否绘制面板切换按钮 - if (m_node_attribute == null || m_lst_item.Count == 0) return; - if (m_b_hover_switch) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, m_rect_switch); - } - m_pen.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_brush.Color = m_pen.Color; - int nT1 = m_rect_switch.Top + m_rect_switch.Height / 2 - 2; - int nT2 = m_rect_switch.Top + m_rect_switch.Height / 2 + 1; - g.DrawRectangle(m_pen, m_rect_switch.Left, m_rect_switch.Top, m_rect_switch.Width - 1, m_rect_switch.Height - 1); - - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), new Point(m_rect_switch.Right - 3, nT1), - new Point(m_rect_switch.Left + 3, nT1 - 1), new Point(m_rect_switch.Right - 3, nT1 - 1) - }); - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT2), new Point(m_rect_switch.Right - 3, nT2), - new Point(m_rect_switch.Left + 2, nT2 + 1), new Point(m_rect_switch.Right - 4, nT2 + 1), - }); - - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), - new Point(m_rect_switch.Left + 7, nT1), - new Point(m_rect_switch.Left + 7, m_rect_switch.Top ), - }); - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Right - 2, nT2), - new Point(m_rect_switch.Right - 7, nT2), - new Point(m_rect_switch.Right - 7, m_rect_switch.Bottom - 2 ), - }); } /// /// 当需要绘制属性描述信息时发生 /// /// 绘制工具 protected virtual void OnDrawDescription(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_desc)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_desc, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, this.Height - (int)szf.Height - 4, this.Width, (int)szf.Height + 4); - m_brush.Color = this._DescriptionColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._DescriptionColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_desc, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_desc) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_desc, ref bounds); + Rectangle rect_desc = new Rectangle(0, this.Height - (int)Math.Ceiling(bounds.Height) - 8, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_desc, rect_desc.Left + 4, y, text); + } } /// /// 当需要绘制错误信息时发生 /// /// 绘制工具 protected virtual void OnDrawErrorInfo(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_err)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_err, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)szf.Height + 4); - m_brush.Color = this._ErrorColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._ErrorColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_err, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_err) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_err, ref bounds); + Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_err, rect_desc.Left + 4, y, text); + } } /// /// 当绘制节点信息时候发生 /// /// 绘制工具 protected virtual void OnDrawInfo(DrawingTools dt) { - if (m_node_attribute == null) return; + if (m_node_attribute == null || m_canvas == null) return; var attr = m_node_attribute; - Graphics g = dt.Graphics; - Color clr_r = Color.FromArgb(this.ForeColor.A / 2, this.ForeColor); - m_sf.Alignment = StringAlignment.Near; - Rectangle rect = new Rectangle(0, this._ShowTitle ? m_nTitleHeight : 0, this.Width, m_item_height); - Rectangle rect_l = new Rectangle(2, rect.Top, m_nInfoLeft - 2, m_item_height); - Rectangle rect_r = new Rectangle(m_nInfoLeft, rect.Top, this.Width - m_nInfoLeft, m_item_height); - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_KeysString[0], this.Font, m_brush, rect_l, m_sf); //author - m_brush.Color = clr_r; - g.DrawString(attr.Author, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_1; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[1], this.Font, m_brush, rect_l, m_sf); //mail - m_brush.Color = clr_r; - g.DrawString(attr.Mail, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[2], this.Font, m_brush, rect_l, m_sf); //link_key - m_brush.Color = clr_r; - g.DrawString(attr.Link, this.Font, Brushes.CornflowerBlue, rect_r, m_sf); //link - if (!string.IsNullOrEmpty(attr.Link)) m_rect_link = rect_r; - //fill left - m_brush.Color = Color.FromArgb(40, 125, 125, 125); - g.FillRectangle(m_brush, 0, this._ShowTitle ? m_nTitleHeight : 0, m_nInfoLeft - 1, m_item_height * 3); - - rect.X = 5; rect.Y += m_item_height; - rect.Width = this.Width - 10; - if (!string.IsNullOrEmpty(m_node_attribute.Description)) { - float h = g.MeasureString(m_node_attribute.Description, this.Font, rect.Width).Height; - rect.Height = (int)Math.Ceiling(h / m_item_height) * m_item_height; - m_brush.Color = clr_r; - m_sf.FormatFlags = 0; - g.DrawString(m_node_attribute.Description, this.Font, m_brush, rect, m_sf); - } - m_nInfoVHeight = rect.Bottom; - bool bHasHelp = STNodeAttribute.GetHelpMethod(m_type) != null; - rect.X = 5; rect.Y += rect.Height; - rect.Height = m_item_height; - m_sf.Alignment = StringAlignment.Center; - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, rect); - if (bHasHelp) m_brush.Color = Color.CornflowerBlue; - g.DrawString(m_KeysString[3], this.Font, m_brush, rect, m_sf); - if (bHasHelp) m_rect_help = rect; - else { - int w = (int)g.MeasureString(m_KeysString[3], this.Font).Width + 1; - int x = rect.X + (rect.Width - w) / 2, y = rect.Y + rect.Height / 2; - m_pen.Color = m_brush.Color; - g.DrawLine(m_pen, x, y, x + w, y); + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textDim = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this.ForeColor.A / 2, this.ForeColor)), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) { + int top = this._ShowTitle ? m_nTitleHeight : 0; + int y = top; + void row(SKColor bg,string key,string val,SKPaint vp){ + fill.Color=bg; m_canvas.DrawRect(0,y,this.Width,m_item_height,fill); + var fm=text.FontMetrics; float ty=y+(m_item_height-(fm.Descent-fm.Ascent))/2-fm.Ascent; + m_canvas.DrawText(key,2,ty,text); m_canvas.DrawText(val??string.Empty,m_nInfoLeft,ty,vp); y+=m_item_height; + } + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[0],attr.Author,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_1),m_KeysString[1],attr.Mail,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[2],attr.Link,new SKPaint{Color=SKColors.CornflowerBlue,TextSize=text.TextSize,IsAntialias=true}); + m_nInfoVHeight = y + m_item_height; } - m_nInfoVHeight = rect.Bottom; } /// /// 当在属性面板鼠标点下时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..28131ec 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -41,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeTreeView : Control + public class STNodeTreeView : SKControl { private Color _ItemBackColor = Color.FromArgb(255, 45, 45, 45); /// @@ -195,6 +197,7 @@ public STNodePropertyGrid PropertyGrid { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); @@ -366,21 +369,22 @@ protected override void OnResize(EventArgs e) { m_rect_clear = new Rectangle(this.Width - 20, 9, 12, 12); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); m_nOffsetY = string.IsNullOrEmpty(m_str_search) ? m_nSourceOffsetY : m_nSearchOffsetY; - Graphics g = e.Graphics; - m_dt.Graphics = g; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - g.TranslateTransform(0, m_nOffsetY); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas.Save(); + m_canvas.Translate(0, m_nOffsetY); int nCounter = 0; foreach (STNodeTreeCollection v in m_items_draw) nCounter = this.OnStartDrawItem(m_dt, v, nCounter, 0); m_nVHeight = (nCounter + 1) * m_nItemHeight; foreach (STNodeTreeCollection v in m_items_draw) this.OnDrawSwitch(m_dt, v); - g.ResetTransform(); + m_canvas.Restore(); this.OnDrawSearch(m_dt); + m_canvas = null; } protected override void OnMouseMove(MouseEventArgs e) { @@ -478,24 +482,20 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + if (m_canvas == null) return; + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + m_canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + m_canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + m_canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + m_canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + m_canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + m_canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } } } /// @@ -507,7 +507,6 @@ protected virtual void OnDrawSearch(DrawingTools dt) { /// 当前位于第几级子集合 /// 已经绘制个数 protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; Items.DisplayRectangle = new Rectangle(0, m_nItemHeight * (nCounter + 1), this.Width, m_nItemHeight); Items.SwitchRectangle = new Rectangle(5 + nLevel * 10, (nCounter + 1) * m_nItemHeight, 10, m_nItemHeight); if (this._ShowInfoButton && Items.STNodeType != null) @@ -534,23 +533,26 @@ protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Item /// 已经绘制个数的计数器 /// 当前位于第几级子集合 protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; - m_brush.Color = nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, items.DisplayRectangle); - if (items == m_item_hover) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, items.DisplayRectangle); - } - Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); - m_pen.Color = Color.FromArgb(100, 125, 125, 125); - g.DrawLine(m_pen, 9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2); - if (nCounter != 0) { - for (int i = 0; i <= nLevel; i++) { - g.DrawLine(m_pen, 9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var line = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor(nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); + if (items == m_item_hover) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); } + Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); + line.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(100, 125, 125, 125)); + m_canvas.DrawLine(9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2, line); + if (nCounter != 0) { + for (int i = 0; i <= nLevel; i++) { + m_canvas.DrawLine(9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1, line); + } + } + this.OnDrawItemText(dt, items, rect); + this.OnDrawItemIcon(dt, items, rect); } - this.OnDrawItemText(dt, items, rect); - this.OnDrawItemIcon(dt, items, rect); } /// /// 当绘制树节点展开与关闭开关时候发生 @@ -558,15 +560,15 @@ protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, i /// 绘制工具 /// 当前需要绘制的集合 protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.Count != 0) { - m_pen.Color = this._SwitchColor; - m_brush.Color = m_pen.Color; - int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; - g.DrawRectangle(m_pen, items.SwitchRectangle.Left, nT, 8, 8); - g.DrawLine(m_pen, items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4); - if (items.IsOpen) return; - g.DrawLine(m_pen, items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SwitchColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; + m_canvas.DrawRect(items.SwitchRectangle.Left, nT, 8, 8, stroke); + m_canvas.DrawLine(items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4, stroke); + if (items.IsOpen) return; + m_canvas.DrawLine(items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7, stroke); + } //if (items.IsOpen) { // //g.FillPolygon(m_brush, new Point[]{ // // new Point(items.DotRectangle.Left + 0, items.DotRectangle.Top + m_nItemHeight / 2 - 2), @@ -594,28 +596,30 @@ protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; rect.Width -= 20; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - if (!string.IsNullOrEmpty(m_str_search)) { - int nIndex = items.NameLower.IndexOf(m_str_search); - if (nIndex != -1) { - CharacterRange[] chrs = { new CharacterRange(nIndex, m_str_search.Length) };//global - m_sf.SetMeasurableCharacterRanges(chrs); - Region[] regions = g.MeasureCharacterRanges(items.Name, this.Font, rect, m_sf); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Intersect); - m_brush.Color = this._HightLightTextColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Exclude); - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 1 / 2, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - return; + using (var textNormal = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textHi = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HightLightTextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = textNormal.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + string name = items.Name ?? string.Empty; + if (!string.IsNullOrEmpty(m_str_search)) { + int idx = items.NameLower.IndexOf(m_str_search); + if (idx >= 0) { + string pre = name.Substring(0, idx); + string hit = name.Substring(idx, Math.Min(m_str_search.Length, name.Length - idx)); + string suf = name.Substring(idx + hit.Length); + float x = rect.Left; + m_canvas.DrawText(pre, x, y, textNormal); + x += textNormal.MeasureText(pre); + m_canvas.DrawText(hit, x, y, textHi); + x += textHi.MeasureText(hit); + m_canvas.DrawText(suf, x, y, textNormal); + return; + } } + m_canvas.DrawText(name, rect.Left, y, textNormal); } - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); } /// /// 当绘制树节点图标时候发生 @@ -624,43 +628,52 @@ protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection item /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemIcon(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.STNodeType != null) { - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan; - m_brush.Color = Color.LightGray; - g.DrawRectangle(m_pen, rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.FillRectangle(m_brush, rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - g.FillRectangle(m_brush, rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - if (m_item_hover == items && m_bHoverInfo) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, items.InfoRectangle); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = SKColors.LightGray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10, stroke); + m_canvas.DrawRect(rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + m_canvas.DrawRect(rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + if (m_item_hover == items && m_bHoverInfo) { + fill.Color = SkiaDrawingHelper.ToSKColor(this.BackColor); + m_canvas.DrawRect(items.InfoRectangle.Left, items.InfoRectangle.Top, items.InfoRectangle.Width, items.InfoRectangle.Height, fill); + } + } + using (var info = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11, info); + m_canvas.DrawLine(items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10, info); + } + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1, box); } - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor; - m_pen.Width = 2; - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11); - g.DrawLine(m_pen, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1); } else { - if (items.IsLibraryRoot) { - Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.DrawRectangle(Pens.Gray, rect_box); - g.DrawLine(Pens.Cyan, rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top); - g.DrawLine(Pens.Cyan, rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2); - g.DrawLine(Pens.Cyan, rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom); - g.DrawLine(Pens.Cyan, rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2); - } else { - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3)); - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9)); + using (var stroke = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (items.IsLibraryRoot) { + Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); + stroke.Color = SKColors.Gray; + m_canvas.DrawRect(rect_box.Left, rect_box.Top, rect_box.Width, rect_box.Height, stroke); + stroke.Color = SKColors.Cyan; + m_canvas.DrawLine(rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top, stroke); + m_canvas.DrawLine(rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2, stroke); + m_canvas.DrawLine(rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom, stroke); + m_canvas.DrawLine(rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2, stroke); + } else { + stroke.Color = SKColors.Goldenrod; + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3, stroke); + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9, stroke); + } } if (!this._ShowFolderCount) return; - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this._FolderCountColor; - rect.X -= 4; - g.DrawString("[" + items.STNodeCount.ToString() + "]", this.Font, m_brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Near; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._FolderCountColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + string t = "[" + items.STNodeCount.ToString() + "]"; + float w = text.MeasureText(t); + var fm = text.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(t, rect.Right - w - 4, y, text); + } } } diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From 8c089a54d431265bb509cd7d0aa80d062bebf5f5 Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:29:47 +0800 Subject: [PATCH 12/13] Switch STNodeEditor overlay drawing methods to SKCanvas --- .../NodeEditor/FrmNodePreviewPanel.cs | 38 +- .../NodeEditor/FrmSTNodePropertyInput.cs | 65 ++-- .../NodeEditor/FrmSTNodePropertySelect.cs | 64 ++-- ST.Library.UI/NodeEditor/STNode.cs | 96 +++-- ST.Library.UI/NodeEditor/STNodeControl.cs | 25 +- ST.Library.UI/NodeEditor/STNodeEditor.cs | 342 ++++++++++-------- .../NodeEditor/STNodeEditorPannel.cs | 44 +-- .../NodeEditor/STNodePropertyAttribute.cs | 39 +- .../NodeEditor/STNodePropertyGrid.cs | 261 +++++-------- ST.Library.UI/NodeEditor/STNodeTreeView.cs | 215 +++++------ ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 38 ++ ST.Library.UI/ST.Library.UI.csproj | 105 +----- WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 25 +- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 +- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 +- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 10 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 +------ WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 35 files changed, 754 insertions(+), 911 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..13010eb 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -122,23 +121,24 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); + var border = SkiaDrawingHelper.ToSKColor(this.AutoBorderColor ? m_node.TitleColor : this.BorderColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var stroke = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = border, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var thick = new SKPaint { Color = border, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, stroke); + canvas.DrawRect(m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2, fill); + Rectangle rect = this.RectangleToClient(m_rect_handle); + rect.Y = (m_nHandleSize - 14) / 2; + rect.X += rect.Y + 1; + rect.Width = rect.Height = 14; + canvas.DrawLine(rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6, thick); + canvas.DrawLine(rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11, thick); + canvas.DrawLine(rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10, thick); + canvas.DrawRect(rect.X, rect.Y, rect.Width - 1, rect.Height - 1, stroke); + } + }); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..7e88a9a 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,38 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) + var strokeColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var inputBackColor = m_tbx == null ? this.BackColor : m_tbx.BackColor; + var fillColor = SkiaDrawingHelper.ToSKColor(inputBackColor); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + canvas.DrawRect(1, 1, this.Width - 2 - m_rect.Height, this.Height - 2, fill); + canvas.DrawPoints(SKPointMode.Polygon, new[] { + new SKPoint(this.Width - 21, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 2), + new SKPoint(this.Width - 14, this.Height - 8) + }, fill); + + void Line(float x1, float y1, float x2, float y2) => canvas.DrawLine(x1, y1, x2, y2, stroke); + Line(this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); + Line(this.Width - 4, this.Height - 3, this.Width - 4, 14); + Line(this.Width - 8, 13, this.Width - 4, 13); + Line(this.Width - 19, 11, this.Width - 4, 11); + Line(this.Width - 19, 3, this.Width - 16, 3); + Line(this.Width - 19, 6, this.Width - 16, 6); + Line(this.Width - 19, 9, this.Width - 16, 9); + Line(this.Width - 19, 3, this.Width - 19, 9); + Line(this.Width - 13, 3, this.Width - 10, 3); + Line(this.Width - 13, 6, this.Width - 10, 6); + Line(this.Width - 13, 9, this.Width - 10, 9); + Line(this.Width - 13, 3, this.Width - 13, 6); + Line(this.Width - 10, 6, this.Width - 10, 9); + Line(this.Width - 7, 3, this.Width - 4, 3); + Line(this.Width - 7, 9, this.Width - 4, 9); + Line(this.Width - 7, 3, this.Width - 7, 9); + } }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..6e4735e 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,40 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); + var borderColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.AutoColor ? m_descriptor.Node.TitleColor : m_descriptor.Control.ItemSelectedColor); + var textColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ForeColor); + var selectedColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemSelectedColor); + var hoverColor = SkiaDrawingHelper.ToSKColor(m_descriptor.Control.ItemHoverColor); + var rowColor1 = SkiaDrawingHelper.ToSKColor(m_clr_item_1); + var rowColor2 = SkiaDrawingHelper.ToSKColor(m_clr_item_2); + var fontSize = Math.Max(10f, m_descriptor.Control.Font.Size); + + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var border = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = borderColor, IsAntialias = true }) + using (var text = new SKPaint { Style = SKPaintStyle.Fill, Color = textColor, TextSize = fontSize, IsAntialias = true }) { + float y = 0; + string strVal = m_descriptor.GetStringFromValue(); + int nIndex = 0; + foreach (var v in m_lst_item) { + fill.Color = (nIndex++ % 2 == 0) ? rowColor1 : rowColor2; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + if (v == m_item_hover) { + fill.Color = hoverColor; + canvas.DrawRect(0, y, this.Width, m_nItemHeight, fill); + } + if (v.ToString() == strVal) { + fill.Color = selectedColor; + canvas.DrawRect(4, y + 10, 5, 5, fill); + } + var metrics = text.FontMetrics; + float textY = y + (m_nItemHeight - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 10, textY, text); + y += m_nItemHeight; + } + canvas.DrawRect(0, 0, this.Width - 1, this.Height - 1, border); } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); + }); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..3cf6f5f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -581,11 +582,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +599,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -737,15 +734,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..671ac1d 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,16 +196,20 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + canvas.DrawText(this._Text, x, y, text); + } + } + }); if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..fd00781 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,8 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -44,7 +46,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeEditor : Control + public class STNodeEditor : SKControl { private const UInt32 WM_MOUSEHWHEEL = 0x020E; protected static readonly Type m_type_node = typeof(STNode); @@ -462,6 +464,7 @@ public STNodeEditor() { #region private fields -------------------------------------------------------------------------------------- private DrawingTools m_drawing_tools; + private SKCanvas m_canvas; private NodeFindInfo m_find = new NodeFindInfo(); private MagnetInfo m_mi = new MagnetInfo(); @@ -645,47 +648,74 @@ protected override void WndProc(ref Message m) { } catch { /*add code*/ } } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.Clear(this.BackColor); - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_drawing_tools.Graphics = g; - SolidBrush brush = m_drawing_tools.SolidBrush; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + this.RenderEditorToCanvas(m_canvas); + m_canvas = null; + } - if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); + private void RenderEditorToCanvas(SKCanvas canvas) { + if (canvas == null) return; + using (var bitmap = this.RenderEditorToBitmap()) { + canvas.DrawBitmap(bitmap, 0, 0); + } + } - g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); //移动坐标系 - g.ScaleTransform(this._CanvasScale, this._CanvasScale); //缩放绘图表面 + private SKBitmap RenderEditorToBitmap() { + var bitmap = new SKBitmap(Math.Max(this.Width, 1), Math.Max(this.Height, 1), true); + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + this.RenderEditorToCanvasLegacy(canvas); + } + return bitmap; + } + + private void RenderEditorToCanvasLegacy(SKCanvas canvas) { + using (var bmp = new Bitmap(Math.Max(this.Width, 1), Math.Max(this.Height, 1))) + using (var g = Graphics.FromImage(bmp)) { + g.Clear(this.BackColor); + g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; + m_drawing_tools.Graphics = g; - this.OnDrawConnectedLine(m_drawing_tools); - this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); + if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); - if (m_ca == CanvasAction.ConnectOption) { //如果正在连线 - m_drawing_tools.Pen.Color = this._HighLineColor; - g.SmoothingMode = SmoothingMode.HighQuality; - if (m_option_down.IsInput) - this.DrawBezier(g, m_drawing_tools.Pen, m_pt_in_canvas, m_pt_dot_down, this._Curvature); - else - this.DrawBezier(g, m_drawing_tools.Pen, m_pt_dot_down, m_pt_in_canvas, this._Curvature); - } - //重置绘图坐标 我认为除了节点以外的其它 修饰相关的绘制不应该在Canvas坐标系中绘制 而应该使用控件的坐标进行绘制 不然会受到缩放比影响 - g.ResetTransform(); + g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); + g.ScaleTransform(this._CanvasScale, this._CanvasScale); - switch (m_ca) { - case CanvasAction.MoveNode: //移动过程中 绘制对齐参考线 - if (this._ShowMagnet && this._ActiveNode != null) this.OnDrawMagnet(m_drawing_tools, m_mi); - break; - case CanvasAction.SelectRectangle: //绘制矩形选取 - this.OnDrawSelectedRectangle(m_drawing_tools, this.CanvasToControl(m_rect_select)); - break; - case CanvasAction.DrawMarkDetails: //绘制标记信息详情 - if (!string.IsNullOrEmpty(m_find.Mark)) this.OnDrawMark(m_drawing_tools); - break; - } + this.OnDrawConnectedLine(m_drawing_tools); + this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); + + if (m_ca == CanvasAction.ConnectOption) { + m_drawing_tools.Pen.Color = this._HighLineColor; + g.SmoothingMode = SmoothingMode.HighQuality; + if (m_option_down.IsInput) + this.DrawBezier(g, m_drawing_tools.Pen, m_pt_in_canvas, m_pt_dot_down, this._Curvature); + else + this.DrawBezier(g, m_drawing_tools.Pen, m_pt_dot_down, m_pt_in_canvas, this._Curvature); + } + + g.ResetTransform(); + + switch (m_ca) { + case CanvasAction.MoveNode: + if (this._ShowMagnet && this._ActiveNode != null) this.OnDrawMagnet(m_drawing_tools, m_mi); + break; + case CanvasAction.SelectRectangle: + this.OnDrawSelectedRectangle(m_drawing_tools, this.CanvasToControl(m_rect_select)); + break; + case CanvasAction.DrawMarkDetails: + if (!string.IsNullOrEmpty(m_find.Mark)) this.OnDrawMark(m_drawing_tools); + break; + } - if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, this.Size, m_lst_node_out); - this.OnDrawAlert(g); + if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, this.Size, m_lst_node_out); + this.OnDrawAlert(); + using (var skBitmap = SkiaDrawingHelper.ToSKBitmap(bmp)) { + if (skBitmap != null) canvas.DrawBitmap(skBitmap, 0, 0); + } + } } protected override void OnMouseDown(MouseEventArgs e) { @@ -979,21 +1009,35 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 + if (m_canvas != null) { + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); int n = 5 - (int)(this._CanvasOffsetX / nIncrement); for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + m_canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); n = 5 - (int)(this._CanvasOffsetY / nIncrement); for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); + m_canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + m_canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + m_canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } + return; + } + Graphics g = dt.Graphics; + using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) + using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { + float nIncrement = (20 * this._CanvasScale); + int n = 5 - (int)(this._CanvasOffsetX / nIncrement); + for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) + g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); + n = 5 - (int)(this._CanvasOffsetY / nIncrement); + for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) + g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); + p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); + g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); + g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); } } /// @@ -1070,34 +1114,33 @@ protected virtual void OnDrawConnectedLine(DrawingTools dt) { /// /// 绘制工具 protected virtual void OnDrawMark(DrawingTools dt) { - Graphics g = dt.Graphics; - SizeF sz = g.MeasureString(m_find.Mark, this.Font); //确认文字需要的大小 - Rectangle rect = new Rectangle(m_pt_in_control.X + 15, - m_pt_in_control.Y + 10, - (int)sz.Width + 6, - 4 + (this.Font.Height + 4) * m_find.MarkLines.Length); //sz.Height并没有考虑文字的行距 所以这里高度自己计算 - - if (rect.Right > this.Width) rect.X = this.Width - rect.Width; - if (rect.Bottom > this.Height) rect.Y = this.Height - rect.Height; - if (rect.X < 0) rect.X = 0; - if (rect.Y < 0) rect.Y = 0; - - dt.SolidBrush.Color = this._MarkBackColor; - g.SmoothingMode = SmoothingMode.None; - g.FillRectangle(dt.SolidBrush, rect); //绘制背景区域 - rect.Width--; rect.Height--; - dt.Pen.Color = Color.FromArgb(255, this._MarkBackColor); - g.DrawRectangle(dt.Pen, rect); - dt.SolidBrush.Color = this._MarkForeColor; - - m_sf.LineAlignment = StringAlignment.Center; - //g.SmoothingMode = SmoothingMode.HighQuality; - rect.X += 2; rect.Width -= 3; - rect.Height = this.Font.Height + 4; - int nY = rect.Y + 2; - for (int i = 0; i < m_find.MarkLines.Length; i++) { //绘制文字 - rect.Y = nY + i * (this.Font.Height + 4); - g.DrawString(m_find.MarkLines[i], this.Font, dt.SolidBrush, rect, m_sf); + if (m_canvas == null || string.IsNullOrEmpty(m_find.Mark)) return; + using (var textPaint = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float textWidth = textPaint.MeasureText(m_find.Mark); + Rectangle rect = new Rectangle(m_pt_in_control.X + 15, + m_pt_in_control.Y + 10, + (int)Math.Ceiling(textWidth) + 6, + 4 + (this.Font.Height + 4) * m_find.MarkLines.Length); + + if (rect.Right > this.Width) rect.X = this.Width - rect.Width; + if (rect.Bottom > this.Height) rect.Y = this.Height - rect.Height; + if (rect.X < 0) rect.X = 0; + if (rect.Y < 0) rect.Y = 0; + + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._MarkBackColor), Style = SKPaintStyle.Fill, IsAntialias = false }) + using (var border = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(255, this._MarkBackColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = false }) + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._MarkForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width - 1, rect.Height - 1, border); + + var fm = fg.FontMetrics; + float baseY = rect.Y + 2 - fm.Ascent; + float textX = rect.X + 4; + for (int i = 0; i < m_find.MarkLines.Length; i++) { + float y = baseY + i * (this.Font.Height + 4); + m_canvas.DrawText(m_find.MarkLines[i], textX, y, fg); + } + } } } /// @@ -1106,38 +1149,39 @@ protected virtual void OnDrawMark(DrawingTools dt) { /// 绘制工具 /// 匹配的磁铁信息 protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { - if (this._ActiveNode == null) return; - Graphics g = dt.Graphics; - Pen pen = m_drawing_tools.Pen; - SolidBrush brush = dt.SolidBrush; - pen.Color = this._MagnetColor; - brush.Color = Color.FromArgb(this._MagnetColor.A / 3, this._MagnetColor); - g.SmoothingMode = SmoothingMode.None; - int nL = this._ActiveNode.Left, nMX = this._ActiveNode.Left + this._ActiveNode.Width / 2, nR = this._ActiveNode.Right; - int nT = this._ActiveNode.Top, nMY = this._ActiveNode.Top + this._ActiveNode.Height / 2, nB = this._ActiveNode.Bottom; - if (mi.XMatched) g.DrawLine(pen, this.CanvasToControl(mi.X, true), 0, this.CanvasToControl(mi.X, true), this.Height); - if (mi.YMatched) g.DrawLine(pen, 0, this.CanvasToControl(mi.Y, false), this.Width, this.CanvasToControl(mi.Y, false)); - g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); //移动坐标系 - g.ScaleTransform(this._CanvasScale, this._CanvasScale); //缩放绘图表面 - if (mi.XMatched) { - //g.DrawLine(pen, this.CanvasToControl(mi.X, true), 0, this.CanvasToControl(mi.X, true), this.Height); - foreach (STNode n in this._Nodes) { - if (n.Left == mi.X || n.Right == mi.X || n.Left + n.Width / 2 == mi.X) { - //g.DrawRectangle(pen, n.Left, n.Top, n.Width - 1, n.Height - 1); - g.FillRectangle(brush, n.Rectangle); + if (m_canvas == null || this._ActiveNode == null) return; + using (var line = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._MagnetColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = false }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._MagnetColor.A / 3, this._MagnetColor)), Style = SKPaintStyle.Fill, IsAntialias = false }) { + if (mi.XMatched) { + float x = this.CanvasToControl(mi.X, true); + m_canvas.DrawLine(x, 0, x, this.Height, line); + } + if (mi.YMatched) { + float y = this.CanvasToControl(mi.Y, false); + m_canvas.DrawLine(0, y, this.Width, y, line); + } + + m_canvas.Save(); + m_canvas.Translate(this._CanvasOffsetX, this._CanvasOffsetY); + m_canvas.Scale(this._CanvasScale, this._CanvasScale); + + if (mi.XMatched) { + foreach (STNode n in this._Nodes) { + if (n.Left == mi.X || n.Right == mi.X || n.Left + n.Width / 2 == mi.X) { + m_canvas.DrawRect(n.Left, n.Top, n.Width, n.Height, fill); + } } } - } - if (mi.YMatched) { - //g.DrawLine(pen, 0, this.CanvasToControl(mi.Y, false), this.Width, this.CanvasToControl(mi.Y, false)); - foreach (STNode n in this._Nodes) { - if (n.Top == mi.Y || n.Bottom == mi.Y || n.Top + n.Height / 2 == mi.Y) { - //g.DrawRectangle(pen, n.Left, n.Top, n.Width - 1, n.Height - 1); - g.FillRectangle(brush, n.Rectangle); + if (mi.YMatched) { + foreach (STNode n in this._Nodes) { + if (n.Top == mi.Y || n.Bottom == mi.Y || n.Top + n.Height / 2 == mi.Y) { + m_canvas.DrawRect(n.Left, n.Top, n.Width, n.Height, fill); + } } } + + m_canvas.Restore(); } - g.ResetTransform(); } /// /// 绘制选择的矩形区域 @@ -1145,12 +1189,14 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + if (m_canvas == null) return; + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } } /// /// 绘制超出视觉区域的 Node 位置提示信息 @@ -1159,25 +1205,25 @@ protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf /// 提示框边距 /// 超出视觉区域的 Node 位置信息 protected virtual void OnDrawNodeOutLocation(DrawingTools dt, Size sz, List lstPts) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - brush.Color = this._LocationBackColor; - g.SmoothingMode = SmoothingMode.None; - if (lstPts.Count == this._Nodes.Count && this._Nodes.Count != 0) { //如果超出个数和集合个数一样多 则全部超出 绘制外切矩形 - g.FillRectangle(brush, this.CanvasToControl(this._CanvasValidBounds)); - } - g.FillRectangle(brush, 0, 0, 4, sz.Height); //绘制四边背景 - g.FillRectangle(brush, sz.Width - 4, 0, 4, sz.Height); - g.FillRectangle(brush, 4, 0, sz.Width - 8, 4); - g.FillRectangle(brush, 4, sz.Height - 4, sz.Width - 8, 4); - brush.Color = this._LocationForeColor; - foreach (var v in lstPts) { //绘制点 - var pt = this.CanvasToControl(v); - if (pt.X < 0) pt.X = 0; - if (pt.Y < 0) pt.Y = 0; - if (pt.X > sz.Width) pt.X = sz.Width - 4; - if (pt.Y > sz.Height) pt.Y = sz.Height - 4; - g.FillRectangle(brush, pt.X, pt.Y, 4, 4); + if (m_canvas == null) return; + using (var back = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._LocationBackColor), Style = SKPaintStyle.Fill, IsAntialias = false }) + using (var fore = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._LocationForeColor), Style = SKPaintStyle.Fill, IsAntialias = false }) { + if (lstPts.Count == this._Nodes.Count && this._Nodes.Count != 0) { + Rectangle r = this.CanvasToControl(this._CanvasValidBounds); + m_canvas.DrawRect(r.Left, r.Top, r.Width, r.Height, back); + } + m_canvas.DrawRect(0, 0, 4, sz.Height, back); + m_canvas.DrawRect(sz.Width - 4, 0, 4, sz.Height, back); + m_canvas.DrawRect(4, 0, sz.Width - 8, 4, back); + m_canvas.DrawRect(4, sz.Height - 4, sz.Width - 8, 4, back); + foreach (var v in lstPts) { + var pt = this.CanvasToControl(v); + if (pt.X < 0) pt.X = 0; + if (pt.Y < 0) pt.Y = 0; + if (pt.X > sz.Width) pt.X = sz.Width - 4; + if (pt.Y > sz.Height) pt.Y = sz.Height - 4; + m_canvas.DrawRect(pt.X, pt.Y, 4, 4, fore); + } } } /// @@ -1190,21 +1236,17 @@ protected virtual void OnDrawNodeOutLocation(DrawingTools dt, Size sz, List信息背景色 /// 信息位置 protected virtual void OnDrawAlert(DrawingTools dt, Rectangle rect, string strText, Color foreColor, Color backColor, AlertLocation al) { - if (m_alpha_alert == 0) return; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - - g.SmoothingMode = SmoothingMode.None; - brush.Color = backColor; - dt.Pen.Color = brush.Color; - g.FillRectangle(brush, rect); - g.DrawRectangle(dt.Pen, rect.Left, rect.Top, rect.Width - 1, rect.Height - 1); - - brush.Color = foreColor; - m_sf.Alignment = StringAlignment.Center; - m_sf.LineAlignment = StringAlignment.Center; - g.SmoothingMode = SmoothingMode.HighQuality; - g.DrawString(strText, this.Font, brush, rect, m_sf); + if (m_alpha_alert == 0 || m_canvas == null) return; + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(backColor), Style = SKPaintStyle.Fill, IsAntialias = false }) + using (var border = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(backColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = false }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(foreColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width - 1, rect.Height - 1, border); + var fm = text.FontMetrics; + float x = rect.Left + (rect.Width - text.MeasureText(strText)) / 2f; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2f - fm.Ascent; + m_canvas.DrawText(strText, x, y, text); + } } /// /// 获取提示信息需要绘制的矩形区域 @@ -1213,10 +1255,13 @@ protected virtual void OnDrawAlert(DrawingTools dt, Rectangle rect, string strTe /// 需要绘制文本 /// 信息位置 /// 矩形区域 - protected virtual Rectangle GetAlertRectangle(Graphics g, string strText, AlertLocation al) { - SizeF szf = g.MeasureString(m_str_alert, this.Font); - Size sz = new Size((int)Math.Round(szf.Width + 10), (int)Math.Round(szf.Height + 4)); - Rectangle rect = new Rectangle(4, this.Height - sz.Height - 4, sz.Width, sz.Height); + protected virtual Rectangle GetAlertRectangle(string strText, AlertLocation al) { + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float w = text.MeasureText(m_str_alert); + float h = fm.Descent - fm.Ascent; + Size sz = new Size((int)Math.Round(w + 10), (int)Math.Round(h + 4)); + Rectangle rect = new Rectangle(4, this.Height - sz.Height - 4, sz.Width, sz.Height); switch (al) { case AlertLocation.Left: @@ -1248,7 +1293,8 @@ protected virtual Rectangle GetAlertRectangle(Graphics g, string strText, AlertL rect.X = this.Width - sz.Width - 4; break; } - return rect; + return rect; + } } #endregion protected @@ -1262,8 +1308,8 @@ internal void BuildLinePath() { this.Invalidate(); } - internal void OnDrawAlert(Graphics g) { - m_rect_alert = this.GetAlertRectangle(g, m_str_alert, m_al); + internal void OnDrawAlert() { + m_rect_alert = this.GetAlertRectangle(m_str_alert, m_al); Color clr_fore = Color.FromArgb((int)((float)m_alpha_alert / 255 * m_forecolor_alert.A), m_forecolor_alert); Color clr_back = Color.FromArgb((int)((float)m_alpha_alert / 255 * m_backcolor_alert.A), m_backcolor_alert); this.OnDrawAlert(m_drawing_tools, m_rect_alert, m_str_alert, clr_fore, clr_back, m_al); diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..62c91d4 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,12 +5,14 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; +using SkiaSharp.Views.Desktop; using System.Runtime.InteropServices; using System.ComponentModel; namespace ST.Library.UI.NodeEditor { - public class STNodeEditorPannel : Control + public class STNodeEditorPannel : SKControl { private bool _LeftLayout = true; /// @@ -123,7 +125,6 @@ public STNodePropertyGrid PropertyGrid { private Point m_pt_down; private bool m_is_mx; private bool m_is_my; - private Pen m_pen; private bool m_nInited; private Dictionary m_dic_status_key = new Dictionary(); @@ -163,7 +164,6 @@ public STNodeEditorPannel() { this.MinimumSize = new Size(250, 250); this.BackColor = Color.FromArgb(255, 34, 34, 34); - m_pen = new Pen(this.BackColor, 3); Type t = typeof(ConnectionStatus); var vv = Enum.GetValues(t); @@ -208,25 +208,27 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound base.SetBoundsCore(x, y, width, height, specified); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + var canvas = e.Surface.Canvas; + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..b9eaf44 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, ctrl.Size, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..47abf96 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,8 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -43,7 +45,7 @@ namespace ST.Library.UI.NodeEditor /// /// STNode节点属性编辑器 /// - public class STNodePropertyGrid : Control + public class STNodePropertyGrid : SKControl { #region properties ========== @@ -261,6 +263,7 @@ public bool ReadOnlyModel { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; /// /// 构造一个节点属性编辑器 @@ -364,31 +367,19 @@ private void SetItemRectangle() { /// 当控件重绘时候发生 /// /// 事件参数 - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_dt.Graphics = g; - - m_nOffsetY = m_b_current_draw_info ? m_nInfoOffsetY : m_nPropertyOffsetY; - g.TranslateTransform(0, m_nOffsetY); - - if (m_b_current_draw_info) { - m_nVHeight = m_nInfoVHeight; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + if (this._InfoFirstOnDraw) { this.OnDrawInfo(m_dt); } else { - m_nVHeight = m_nPropertyVHeight; - for (int i = 0; i < m_lst_item.Count; i++) { - this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); - } + for (int i = 0; i < m_lst_item.Count; i++) this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); } - - g.ResetTransform(); - if (this._ShowTitle) this.OnDrawTitle(m_dt); - m_sf.FormatFlags = 0; if (!string.IsNullOrEmpty(m_str_err)) this.OnDrawErrorInfo(m_dt); if (!string.IsNullOrEmpty(m_str_desc)) this.OnDrawDescription(m_dt); + m_canvas = null; } /// /// 当鼠标在控件上移动时候发生 @@ -533,33 +524,29 @@ protected override void OnResize(EventArgs e) { /// 目标属性选项描述器 /// 选项所在索引 protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescriptor item, int nIndex) { - Graphics g = dt.Graphics; - m_brush.Color = (nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, item.Rectangle); - if (item == m_item_hover || item == m_item_selected) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, item.Rectangle); - } - if (m_item_selected == item) { - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height); - if (this._AutoColor && this._STNode != null) - m_brush.Color = this._STNode.TitleColor; - else - m_brush.Color = this._ItemSelectedColor; - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor((nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + if (item == m_item_hover || item == m_item_selected) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + } + if (m_item_selected == item) { + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height, fill); + fill.Color = SkiaDrawingHelper.ToSKColor((this._AutoColor && this._STNode != null) ? this._STNode.TitleColor : this._ItemSelectedColor); + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8, fill); + } + var fm = text.FontMetrics; + float y = item.RectangleL.Top + (item.RectangleL.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = item.RectangleL.Right - text.MeasureText(item.Name ?? string.Empty) - 2; + m_canvas.DrawText(item.Name ?? string.Empty, x, y, text); } - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this.ForeColor; - g.DrawString(item.Name, this.Font, m_brush, item.RectangleL, m_sf); - item.OnDrawValueRectangle(m_dt); - if (this._ReadOnlyModel) { - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, item.RectangleR); - m_pen.Color = this.ForeColor; - //g.DrawLine(m_pen, - // item.RectangleR.Left - 2, item.RectangleR.Top + item.RectangleR.Height / 2, - // item.RectangleR.Right + 1, item.RectangleR.Top + item.RectangleR.Height / 2); + if (this._ReadOnlyModel && m_canvas != null) { + using (var overlay = new SKPaint { Color = new SKColor(125, 125, 125, 125), Style = SKPaintStyle.Fill, IsAntialias = true }) + m_canvas.DrawRect(item.RectangleR.Left, item.RectangleR.Top, item.RectangleR.Width, item.RectangleR.Height, overlay); } } /// @@ -567,159 +554,79 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { - Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); - - if (this._ReadOnlyModel) { - m_brush.Color = this.ForeColor; - g.FillRectangle(dt.SolidBrush, 4, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 6, 5, 2, 2); - g.FillRectangle(dt.SolidBrush, 8, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 3, 9, 8, 6); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + m_canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t ?? string.Empty)) / 2; + m_canvas.DrawText(t ?? string.Empty, x, y, text); } - //是否绘制面板切换按钮 - if (m_node_attribute == null || m_lst_item.Count == 0) return; - if (m_b_hover_switch) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, m_rect_switch); - } - m_pen.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_brush.Color = m_pen.Color; - int nT1 = m_rect_switch.Top + m_rect_switch.Height / 2 - 2; - int nT2 = m_rect_switch.Top + m_rect_switch.Height / 2 + 1; - g.DrawRectangle(m_pen, m_rect_switch.Left, m_rect_switch.Top, m_rect_switch.Width - 1, m_rect_switch.Height - 1); - - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), new Point(m_rect_switch.Right - 3, nT1), - new Point(m_rect_switch.Left + 3, nT1 - 1), new Point(m_rect_switch.Right - 3, nT1 - 1) - }); - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT2), new Point(m_rect_switch.Right - 3, nT2), - new Point(m_rect_switch.Left + 2, nT2 + 1), new Point(m_rect_switch.Right - 4, nT2 + 1), - }); - - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), - new Point(m_rect_switch.Left + 7, nT1), - new Point(m_rect_switch.Left + 7, m_rect_switch.Top ), - }); - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Right - 2, nT2), - new Point(m_rect_switch.Right - 7, nT2), - new Point(m_rect_switch.Right - 7, m_rect_switch.Bottom - 2 ), - }); } /// /// 当需要绘制属性描述信息时发生 /// /// 绘制工具 protected virtual void OnDrawDescription(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_desc)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_desc, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, this.Height - (int)szf.Height - 4, this.Width, (int)szf.Height + 4); - m_brush.Color = this._DescriptionColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._DescriptionColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_desc, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_desc) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_desc, ref bounds); + Rectangle rect_desc = new Rectangle(0, this.Height - (int)Math.Ceiling(bounds.Height) - 8, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_desc, rect_desc.Left + 4, y, text); + } } /// /// 当需要绘制错误信息时发生 /// /// 绘制工具 protected virtual void OnDrawErrorInfo(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_err)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_err, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)szf.Height + 4); - m_brush.Color = this._ErrorColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._ErrorColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_err, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_err) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_err, ref bounds); + Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_err, rect_desc.Left + 4, y, text); + } } /// /// 当绘制节点信息时候发生 /// /// 绘制工具 protected virtual void OnDrawInfo(DrawingTools dt) { - if (m_node_attribute == null) return; + if (m_node_attribute == null || m_canvas == null) return; var attr = m_node_attribute; - Graphics g = dt.Graphics; - Color clr_r = Color.FromArgb(this.ForeColor.A / 2, this.ForeColor); - m_sf.Alignment = StringAlignment.Near; - Rectangle rect = new Rectangle(0, this._ShowTitle ? m_nTitleHeight : 0, this.Width, m_item_height); - Rectangle rect_l = new Rectangle(2, rect.Top, m_nInfoLeft - 2, m_item_height); - Rectangle rect_r = new Rectangle(m_nInfoLeft, rect.Top, this.Width - m_nInfoLeft, m_item_height); - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_KeysString[0], this.Font, m_brush, rect_l, m_sf); //author - m_brush.Color = clr_r; - g.DrawString(attr.Author, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_1; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[1], this.Font, m_brush, rect_l, m_sf); //mail - m_brush.Color = clr_r; - g.DrawString(attr.Mail, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[2], this.Font, m_brush, rect_l, m_sf); //link_key - m_brush.Color = clr_r; - g.DrawString(attr.Link, this.Font, Brushes.CornflowerBlue, rect_r, m_sf); //link - if (!string.IsNullOrEmpty(attr.Link)) m_rect_link = rect_r; - //fill left - m_brush.Color = Color.FromArgb(40, 125, 125, 125); - g.FillRectangle(m_brush, 0, this._ShowTitle ? m_nTitleHeight : 0, m_nInfoLeft - 1, m_item_height * 3); - - rect.X = 5; rect.Y += m_item_height; - rect.Width = this.Width - 10; - if (!string.IsNullOrEmpty(m_node_attribute.Description)) { - float h = g.MeasureString(m_node_attribute.Description, this.Font, rect.Width).Height; - rect.Height = (int)Math.Ceiling(h / m_item_height) * m_item_height; - m_brush.Color = clr_r; - m_sf.FormatFlags = 0; - g.DrawString(m_node_attribute.Description, this.Font, m_brush, rect, m_sf); - } - m_nInfoVHeight = rect.Bottom; - bool bHasHelp = STNodeAttribute.GetHelpMethod(m_type) != null; - rect.X = 5; rect.Y += rect.Height; - rect.Height = m_item_height; - m_sf.Alignment = StringAlignment.Center; - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, rect); - if (bHasHelp) m_brush.Color = Color.CornflowerBlue; - g.DrawString(m_KeysString[3], this.Font, m_brush, rect, m_sf); - if (bHasHelp) m_rect_help = rect; - else { - int w = (int)g.MeasureString(m_KeysString[3], this.Font).Width + 1; - int x = rect.X + (rect.Width - w) / 2, y = rect.Y + rect.Height / 2; - m_pen.Color = m_brush.Color; - g.DrawLine(m_pen, x, y, x + w, y); + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textDim = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this.ForeColor.A / 2, this.ForeColor)), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) { + int top = this._ShowTitle ? m_nTitleHeight : 0; + int y = top; + void row(SKColor bg,string key,string val,SKPaint vp){ + fill.Color=bg; m_canvas.DrawRect(0,y,this.Width,m_item_height,fill); + var fm=text.FontMetrics; float ty=y+(m_item_height-(fm.Descent-fm.Ascent))/2-fm.Ascent; + m_canvas.DrawText(key,2,ty,text); m_canvas.DrawText(val??string.Empty,m_nInfoLeft,ty,vp); y+=m_item_height; + } + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[0],attr.Author,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_1),m_KeysString[1],attr.Mail,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[2],attr.Link,new SKPaint{Color=SKColors.CornflowerBlue,TextSize=text.TextSize,IsAntialias=true}); + m_nInfoVHeight = y + m_item_height; } - m_nInfoVHeight = rect.Bottom; } /// /// 当在属性面板鼠标点下时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..28131ec 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -41,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeTreeView : Control + public class STNodeTreeView : SKControl { private Color _ItemBackColor = Color.FromArgb(255, 45, 45, 45); /// @@ -195,6 +197,7 @@ public STNodePropertyGrid PropertyGrid { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); @@ -366,21 +369,22 @@ protected override void OnResize(EventArgs e) { m_rect_clear = new Rectangle(this.Width - 20, 9, 12, 12); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); m_nOffsetY = string.IsNullOrEmpty(m_str_search) ? m_nSourceOffsetY : m_nSearchOffsetY; - Graphics g = e.Graphics; - m_dt.Graphics = g; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - g.TranslateTransform(0, m_nOffsetY); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas.Save(); + m_canvas.Translate(0, m_nOffsetY); int nCounter = 0; foreach (STNodeTreeCollection v in m_items_draw) nCounter = this.OnStartDrawItem(m_dt, v, nCounter, 0); m_nVHeight = (nCounter + 1) * m_nItemHeight; foreach (STNodeTreeCollection v in m_items_draw) this.OnDrawSwitch(m_dt, v); - g.ResetTransform(); + m_canvas.Restore(); this.OnDrawSearch(m_dt); + m_canvas = null; } protected override void OnMouseMove(MouseEventArgs e) { @@ -478,24 +482,20 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + if (m_canvas == null) return; + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + m_canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + m_canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + m_canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + m_canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + m_canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + m_canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } } } /// @@ -507,7 +507,6 @@ protected virtual void OnDrawSearch(DrawingTools dt) { /// 当前位于第几级子集合 /// 已经绘制个数 protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; Items.DisplayRectangle = new Rectangle(0, m_nItemHeight * (nCounter + 1), this.Width, m_nItemHeight); Items.SwitchRectangle = new Rectangle(5 + nLevel * 10, (nCounter + 1) * m_nItemHeight, 10, m_nItemHeight); if (this._ShowInfoButton && Items.STNodeType != null) @@ -534,23 +533,26 @@ protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Item /// 已经绘制个数的计数器 /// 当前位于第几级子集合 protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; - m_brush.Color = nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, items.DisplayRectangle); - if (items == m_item_hover) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, items.DisplayRectangle); - } - Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); - m_pen.Color = Color.FromArgb(100, 125, 125, 125); - g.DrawLine(m_pen, 9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2); - if (nCounter != 0) { - for (int i = 0; i <= nLevel; i++) { - g.DrawLine(m_pen, 9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var line = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor(nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); + if (items == m_item_hover) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); } + Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); + line.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(100, 125, 125, 125)); + m_canvas.DrawLine(9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2, line); + if (nCounter != 0) { + for (int i = 0; i <= nLevel; i++) { + m_canvas.DrawLine(9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1, line); + } + } + this.OnDrawItemText(dt, items, rect); + this.OnDrawItemIcon(dt, items, rect); } - this.OnDrawItemText(dt, items, rect); - this.OnDrawItemIcon(dt, items, rect); } /// /// 当绘制树节点展开与关闭开关时候发生 @@ -558,15 +560,15 @@ protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, i /// 绘制工具 /// 当前需要绘制的集合 protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.Count != 0) { - m_pen.Color = this._SwitchColor; - m_brush.Color = m_pen.Color; - int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; - g.DrawRectangle(m_pen, items.SwitchRectangle.Left, nT, 8, 8); - g.DrawLine(m_pen, items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4); - if (items.IsOpen) return; - g.DrawLine(m_pen, items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SwitchColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; + m_canvas.DrawRect(items.SwitchRectangle.Left, nT, 8, 8, stroke); + m_canvas.DrawLine(items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4, stroke); + if (items.IsOpen) return; + m_canvas.DrawLine(items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7, stroke); + } //if (items.IsOpen) { // //g.FillPolygon(m_brush, new Point[]{ // // new Point(items.DotRectangle.Left + 0, items.DotRectangle.Top + m_nItemHeight / 2 - 2), @@ -594,28 +596,30 @@ protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; rect.Width -= 20; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - if (!string.IsNullOrEmpty(m_str_search)) { - int nIndex = items.NameLower.IndexOf(m_str_search); - if (nIndex != -1) { - CharacterRange[] chrs = { new CharacterRange(nIndex, m_str_search.Length) };//global - m_sf.SetMeasurableCharacterRanges(chrs); - Region[] regions = g.MeasureCharacterRanges(items.Name, this.Font, rect, m_sf); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Intersect); - m_brush.Color = this._HightLightTextColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Exclude); - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 1 / 2, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - return; + using (var textNormal = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textHi = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HightLightTextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = textNormal.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + string name = items.Name ?? string.Empty; + if (!string.IsNullOrEmpty(m_str_search)) { + int idx = items.NameLower.IndexOf(m_str_search); + if (idx >= 0) { + string pre = name.Substring(0, idx); + string hit = name.Substring(idx, Math.Min(m_str_search.Length, name.Length - idx)); + string suf = name.Substring(idx + hit.Length); + float x = rect.Left; + m_canvas.DrawText(pre, x, y, textNormal); + x += textNormal.MeasureText(pre); + m_canvas.DrawText(hit, x, y, textHi); + x += textHi.MeasureText(hit); + m_canvas.DrawText(suf, x, y, textNormal); + return; + } } + m_canvas.DrawText(name, rect.Left, y, textNormal); } - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); } /// /// 当绘制树节点图标时候发生 @@ -624,43 +628,52 @@ protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection item /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemIcon(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.STNodeType != null) { - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan; - m_brush.Color = Color.LightGray; - g.DrawRectangle(m_pen, rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.FillRectangle(m_brush, rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - g.FillRectangle(m_brush, rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - if (m_item_hover == items && m_bHoverInfo) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, items.InfoRectangle); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = SKColors.LightGray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10, stroke); + m_canvas.DrawRect(rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + m_canvas.DrawRect(rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + if (m_item_hover == items && m_bHoverInfo) { + fill.Color = SkiaDrawingHelper.ToSKColor(this.BackColor); + m_canvas.DrawRect(items.InfoRectangle.Left, items.InfoRectangle.Top, items.InfoRectangle.Width, items.InfoRectangle.Height, fill); + } + } + using (var info = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11, info); + m_canvas.DrawLine(items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10, info); + } + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1, box); } - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor; - m_pen.Width = 2; - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11); - g.DrawLine(m_pen, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1); } else { - if (items.IsLibraryRoot) { - Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.DrawRectangle(Pens.Gray, rect_box); - g.DrawLine(Pens.Cyan, rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top); - g.DrawLine(Pens.Cyan, rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2); - g.DrawLine(Pens.Cyan, rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom); - g.DrawLine(Pens.Cyan, rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2); - } else { - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3)); - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9)); + using (var stroke = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (items.IsLibraryRoot) { + Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); + stroke.Color = SKColors.Gray; + m_canvas.DrawRect(rect_box.Left, rect_box.Top, rect_box.Width, rect_box.Height, stroke); + stroke.Color = SKColors.Cyan; + m_canvas.DrawLine(rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top, stroke); + m_canvas.DrawLine(rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2, stroke); + m_canvas.DrawLine(rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom, stroke); + m_canvas.DrawLine(rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2, stroke); + } else { + stroke.Color = SKColors.Goldenrod; + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3, stroke); + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9, stroke); + } } if (!this._ShowFolderCount) return; - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this._FolderCountColor; - rect.X -= 4; - g.DrawString("[" + items.STNodeCount.ToString() + "]", this.Font, m_brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Near; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._FolderCountColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + string t = "[" + items.STNodeCount.ToString() + "]"; + float w = text.MeasureText(t); + var fm = text.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(t, rect.Right - w - 4, y, text); + } } } diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToGraphics(Graphics graphics, Size size, Action renderAction) { + using (var bitmap = new SKBitmap(Math.Max(size.Width, 1), Math.Max(size.Height, 1), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SKColors.Transparent); + renderAction(canvas); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new System.IO.MemoryStream(data.ToArray())) + using (var gdiImage = Image.FromStream(ms)) { + graphics.DrawImageUnscaled(gdiImage, 0, 0); + } + } + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..adb8196 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..8caaa59 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -5,6 +5,8 @@ using System.Drawing; using System.Windows.Forms; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -17,7 +19,6 @@ public class FrmEnumSelect : Form private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; public Enum Enum { get; set; } @@ -31,9 +32,6 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -48,13 +46,18 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { + canvas.Scale(m_scale, m_scale); + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float y = 0; + foreach (var v in m_lst) { + var metrics = text.FontMetrics; + float textY = y + (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(v.ToString(), 0, textY, text); + y += 20; + } + } + }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..804fe8d 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..01598f3 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..d59e670 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..baf770b 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..29204be 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..29d154a 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -24,13 +26,13 @@ protected override void InitializeItem(ToolStripItem item) { protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(34,34,34,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.AffectedBounds.Left, e.AffectedBounds.Top, e.AffectedBounds.Width, e.AffectedBounds.Height, p);} }); } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1 }) { canvas.DrawRect(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1, p);} }); base.OnRenderToolStripBorder(e); } @@ -58,7 +60,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { lgb.WrapMode = WrapMode.TileFlipX; using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var sp = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawLine(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Right, ptEnd.Y, sp);} }); } } //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); @@ -67,7 +69,7 @@ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); + SkiaDrawingHelper.RenderToGraphics(e.Graphics, e.ToolStrip.Size, canvas => { using (var p = new SKPaint { Color = new SKColor(52,86,141,255), Style = SKPaintStyle.Fill }) { canvas.DrawRect(e.Item.ContentRectangle.Left, e.Item.ContentRectangle.Top, e.Item.ContentRectangle.Width, e.Item.ContentRectangle.Height, p);} }); else base.OnRenderMenuItemBackground(e); } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..c9bca3f 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..066cc44 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,7 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } + SkiaDrawingHelper.RenderToGraphics(e.Graphics, this.Size, canvas => { canvas.Scale(m_scale, m_scale); using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { float y=0; foreach (var v in m_lst) { var fm=text.FontMetrics; float ty = y + (20 - (fm.Descent - fm.Ascent))/2 - fm.Ascent; canvas.DrawText(v.ToString(),0,ty,text); y += 20; } } }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..8d682a2 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..1f0b336 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5d8800f 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Size, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..53abcee 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(e.DrawingTools.Graphics, c.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..84f4b76 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..ca698b5 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Control.Size, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..84ad62a 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..cd23712 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToGraphics(dt.Graphics, this.Owner.Owner.Size, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ + From fb5a2840782de8d595e518e2a6046fdaaa1d91cc Mon Sep 17 00:00:00 2001 From: dianke09 <80498124+dianke09@users.noreply.github.com> Date: Thu, 12 Mar 2026 11:06:03 +0800 Subject: [PATCH 13/13] Fix SkiaDrawingHelper after RenderToGraphics removal --- .../NodeEditor/FrmNodePreviewPanel.cs | 26 +- .../NodeEditor/FrmSTNodePropertyInput.cs | 35 +- .../NodeEditor/FrmSTNodePropertySelect.cs | 32 +- ST.Library.UI/NodeEditor/STNode.cs | 250 +++++---- ST.Library.UI/NodeEditor/STNodeControl.cs | 23 +- ST.Library.UI/NodeEditor/STNodeEditor.cs | 498 ++++++++++-------- .../NodeEditor/STNodeEditorDataType.cs | 3 +- .../NodeEditor/STNodeEditorPannel.cs | 44 +- ST.Library.UI/NodeEditor/STNodeHub.cs | 4 +- .../NodeEditor/STNodePropertyAttribute.cs | 39 +- .../NodeEditor/STNodePropertyGrid.cs | 309 ++++------- ST.Library.UI/NodeEditor/STNodeTreeView.cs | 215 ++++---- ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs | 29 + ST.Library.UI/ST.Library.UI.csproj | 105 +--- WinNodeEditorDemo/AttrTestNode.cs | 6 +- WinNodeEditorDemo/Blender/FrmEnumSelect.cs | 26 +- WinNodeEditorDemo/Blender/STNodeCheckBox.cs | 20 +- WinNodeEditorDemo/Blender/STNodeProgress.cs | 24 +- WinNodeEditorDemo/Blender/STNodeSelectBox.cs | 26 +- WinNodeEditorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- WinNodeEditorDemo/ImageNode/ImageInputNode.cs | 8 +- WinNodeEditorDemo/NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WinNodeEditorDemo/ToolStripRendererEx.cs | 31 +- WinNodeEditorDemo/WinNodeEditorDemo.csproj | 122 +---- WpfNodeEdittorDemo/AttrTestNode.cs | 6 +- WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs | 8 +- WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeProgress.cs | 9 +- WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs | 12 +- WpfNodeEdittorDemo/CalcNode.cs | 7 +- .../ImageNode/ImageChannelNode.cs | 5 +- .../ImageNode/ImageInputNode.cs | 8 +- .../NumberNode/NumberAddNode.cs | 3 +- .../NumberNode/NumberInputNode.cs | 4 +- WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj | 1 + 37 files changed, 835 insertions(+), 1131 deletions(-) create mode 100644 ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs diff --git a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs index 09b61f2..04c769c 100644 --- a/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs +++ b/ST.Library.UI/NodeEditor/FrmNodePreviewPanel.cs @@ -7,6 +7,7 @@ using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -27,8 +28,6 @@ internal class FrmNodePreviewPanel : Form private STNodeEditor m_editor; private STNodePropertyGrid m_property; - private Pen m_pen = new Pen(Color.Black); - private SolidBrush m_brush = new SolidBrush(Color.Black); private static FrmNodePreviewPanel m_last_frm; [DllImport("user32.dll")] @@ -91,11 +90,7 @@ protected override void OnLoad(EventArgs e) { m_rect_panel.Y = this.Top; m_region = new Region(new Rectangle(Point.Empty, this.Size)); m_region.Exclude(m_rect_exclude); - using (Graphics g = this.CreateGraphics()) { - IntPtr h = m_region.GetHrgn(g); - FrmNodePreviewPanel.SetWindowRgn(this.Handle, h, false); - m_region.ReleaseHrgn(h); - } + FrmNodePreviewPanel.SetWindowRgn(this.Handle, IntPtr.Zero, false); this.MouseLeave += Event_MouseLeave; m_editor.MouseLeave += Event_MouseLeave; @@ -122,23 +117,6 @@ void Event_MouseLeave(object sender, EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Color = this.AutoBorderColor ? m_node.TitleColor : this.BorderColor; - m_brush.Color = m_pen.Color; - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); - g.FillRectangle(m_brush, m_rect_exclude.X - 1, m_rect_exclude.Y - 1, m_rect_exclude.Width + 2, m_rect_exclude.Height + 2); - - Rectangle rect = this.RectangleToClient(m_rect_handle); - rect.Y = (m_nHandleSize - 14) / 2; - rect.X += rect.Y + 1; - rect.Width = rect.Height = 14; - m_pen.Width = 2; - g.DrawLine(m_pen, rect.X + 4, rect.Y + 3, rect.X + 10, rect.Y + 3); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 6, rect.X + 10, rect.Y + 6); - g.DrawLine(m_pen, rect.X + 4, rect.Y + 11, rect.X + 10, rect.Y + 11); - g.DrawLine(m_pen, rect.X + 7, rect.Y + 7, rect.X + 7, rect.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); } } } diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs index d5574e4..98b81ca 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertyInput.cs @@ -6,6 +6,7 @@ using System.Windows.Forms; using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace ST.Library.UI { @@ -13,8 +14,6 @@ internal class FrmSTNodePropertyInput : Form { private STNodePropertyDescriptor m_descriptor; private Rectangle m_rect; - private Pen m_pen; - private SolidBrush m_brush; private TextBox m_tbx; public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { @@ -29,8 +28,6 @@ public FrmSTNodePropertyInput(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.BackColor = descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor; - m_pen = new Pen(descriptor.Control.ForeColor, 1); - m_brush = new SolidBrush(this.BackColor); } protected override void OnLoad(EventArgs e) { @@ -57,36 +54,6 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 1, 1, this.Width - 2 - m_rect.Height, this.Height - 2); - m_brush.Color = m_descriptor.Control.ForeColor; - //Enter - g.FillPolygon(m_brush, new Point[]{ - new Point(this.Width - 21, this.Height - 2), - new Point(this.Width - 14, this.Height - 2), - new Point(this.Width - 14, this.Height - 8) - }); - g.DrawLine(m_pen, this.Width - 14, this.Height - 3, this.Width - 4, this.Height - 3); - g.DrawLine(m_pen, this.Width - 4, this.Height - 3, this.Width - 4, 14); - g.DrawLine(m_pen, this.Width - 8, 13, this.Width - 4, 13); - //---- - g.DrawLine(m_pen, this.Width - 19, 11, this.Width - 4, 11); - //E - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 16, 3); - g.DrawLine(m_pen, this.Width - 19, 6, this.Width - 16, 6); - g.DrawLine(m_pen, this.Width - 19, 9, this.Width - 16, 9); - g.DrawLine(m_pen, this.Width - 19, 3, this.Width - 19, 9); - //S - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 10, 3); - g.DrawLine(m_pen, this.Width - 13, 6, this.Width - 10, 6); - g.DrawLine(m_pen, this.Width - 13, 9, this.Width - 10, 9); - g.DrawLine(m_pen, this.Width - 13, 3, this.Width - 13, 6); - g.DrawLine(m_pen, this.Width - 10, 6, this.Width - 10, 9); - //C - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 4, 3); - g.DrawLine(m_pen, this.Width - 7, 9, this.Width - 4, 9); - g.DrawLine(m_pen, this.Width - 7, 3, this.Width - 7, 9); } void tbx_KeyDown(object sender, KeyEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs index 3adf24e..94b85ef 100644 --- a/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs +++ b/ST.Library.UI/NodeEditor/FrmSTNodePropertySelect.cs @@ -5,6 +5,7 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -14,9 +15,6 @@ internal class FrmSTNodePropertySelect : Form private int m_nItemHeight = 25; private static Type m_t_bool = typeof(bool); - private Pen m_pen; - private SolidBrush m_brush; - private StringFormat m_sf; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); private object m_item_hover; @@ -33,11 +31,6 @@ public FrmSTNodePropertySelect(STNodePropertyDescriptor descriptor) { this.ShowInTaskbar = false; this.BackColor = descriptor.Control.BackColor; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - m_pen = new Pen(descriptor.Control.AutoColor ? descriptor.Node.TitleColor : descriptor.Control.ItemSelectedColor, 1); - m_brush = new SolidBrush(this.BackColor); - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - m_sf.FormatFlags = StringFormatFlags.NoWrap; } private List m_lst_item = new List(); @@ -65,29 +58,6 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - Rectangle rect_back = new Rectangle(0, 0, this.Width, m_nItemHeight); - Rectangle rect_font = new Rectangle(10, 0, this.Width - 13, m_nItemHeight); - int nIndex = 0; - string strVal = m_descriptor.GetStringFromValue(); - foreach (var v in m_lst_item) { - m_brush.Color = nIndex++ % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, rect_back); - if (v == m_item_hover) { - m_brush.Color = m_descriptor.Control.ItemHoverColor; - g.FillRectangle(m_brush, rect_back); - } - if (v.ToString() == strVal) { - m_brush.Color = m_descriptor.Control.ItemSelectedColor; - g.FillRectangle(m_brush, 4, rect_back.Top + 10, 5, 5); - } - m_brush.Color = m_descriptor.Control.ForeColor; - g.DrawString(v.ToString(), m_descriptor.Control.Font, m_brush, rect_font, m_sf); - rect_back.Y += m_nItemHeight; - rect_font.Y += m_nItemHeight; - } - g.DrawRectangle(m_pen, 0, 0, this.Width - 1, this.Height - 1); } protected override void OnMouseMove(MouseEventArgs e) { diff --git a/ST.Library.UI/NodeEditor/STNode.cs b/ST.Library.UI/NodeEditor/STNode.cs index e3e6397..c80fd2f 100644 --- a/ST.Library.UI/NodeEditor/STNode.cs +++ b/ST.Library.UI/NodeEditor/STNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections; +using SkiaSharp; /* MIT License @@ -499,20 +500,18 @@ public STNode() { protected internal void BuildSize(bool bBuildNode, bool bBuildMark, bool bRedraw) { if (this._Owner == null) return; - using (Graphics g = this._Owner.CreateGraphics()) { - if (this._AutoSize && bBuildNode) { - Size sz = this.GetDefaultNodeSize(g); - if (this._Width != sz.Width || this._Height != sz.Height) { - this._Width = sz.Width; - this._Height = sz.Height; - this.SetOptionsLocation(); - this.OnResize(EventArgs.Empty); - } - } - if (bBuildMark && !string.IsNullOrEmpty(this._Mark)) { - this._MarkRectangle = this.OnBuildMarkRectangle(g); + if (this._AutoSize && bBuildNode) { + Size sz = this.GetDefaultNodeSize(); + if (this._Width != sz.Width || this._Height != sz.Height) { + this._Width = sz.Width; + this._Height = sz.Height; + this.SetOptionsLocation(); + this.OnResize(EventArgs.Empty); } } + if (bBuildMark && !string.IsNullOrEmpty(this._Mark)) { + this._MarkRectangle = this.OnBuildMarkRectangle(); + } if (bRedraw) this._Owner.Invalidate(); } @@ -581,11 +580,12 @@ protected virtual void OnCreate() { } /// /// 绘制工具 protected internal virtual void OnDrawNode(DrawingTools dt) { - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - //Fill background if (this._BackColor.A != 0) { - dt.SolidBrush.Color = this._BackColor; - dt.Graphics.FillRectangle(dt.SolidBrush, this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this._Left, this._Top + this._TitleHeight, this._Width, this.Height - this._TitleHeight, bg); + } + }); } this.OnDrawTitle(dt); this.OnDrawBody(dt); @@ -597,43 +597,38 @@ protected internal virtual void OnDrawNode(DrawingTools dt) { protected virtual void OnDrawTitle(DrawingTools dt) { m_sf.Alignment = StringAlignment.Center; m_sf.LineAlignment = StringAlignment.Center; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (this._TitleColor.A != 0) { - brush.Color = this._TitleColor; - g.FillRectangle(brush, this.TitleRectangle); - } - if (this._LockOption) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(dt.SolidBrush, this._Left + 4, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 6, n + 0, 2, 2); - g.FillRectangle(dt.SolidBrush, this._Left + 8, n + 0, 2, 4); - g.FillRectangle(dt.SolidBrush, this._Left + 3, n + 4, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - //g.DrawRectangle(dt.Pen, this._Left + 3, n + 0, 6, 3); - //g.DrawRectangle(dt.Pen, this._Left + 2, n + 3, 8, 6); - //g.DrawLine(dt.Pen, this._Left + 6, n + 5, this._Left + 6, n + 7); - - } - if (this._LockLocation) { - //dt.Pen.Color = this.ForeColor; - brush.Color = this._ForeColor; - int n = this._Top + this._TitleHeight / 2 - 5; - g.FillRectangle(brush, this.Right - 9, n, 4, 4); - g.FillRectangle(brush, this.Right - 11, n + 4, 8, 2); - g.FillRectangle(brush, this.Right - 8, n + 6, 2, 4); - //g.DrawLine(dt.Pen, this.Right - 10, n + 6, this.Right - 4, n + 6); - //g.DrawLine(dt.Pen, this.Right - 10, n, this.Right - 4, n); - //g.DrawLine(dt.Pen, this.Right - 11, n + 6, this.Right - 3, n + 6); - //g.DrawLine(dt.Pen, this.Right - 7, n + 7, this.Right - 7, n + 9); - } - if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { - brush.Color = this._ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawString(this._Title, this._Font, brush, this.TitleRectangle, m_sf); - } + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { + if (this._TitleColor.A != 0) { + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(this.TitleRectangle.Left, this.TitleRectangle.Top, this.TitleRectangle.Width, this.TitleRectangle.Height, title); + } + } + if (this._LockOption) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this._Left + 4, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 6, n + 0, 2, 2, fg); + canvas.DrawRect(this._Left + 8, n + 0, 2, 4, fg); + canvas.DrawRect(this._Left + 3, n + 4, 8, 6, fg); + } + } + if (this._LockLocation) { + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + int n = this._Top + this._TitleHeight / 2 - 5; + canvas.DrawRect(this.Right - 9, n, 4, 4, fg); + canvas.DrawRect(this.Right - 11, n + 4, 8, 2, fg); + canvas.DrawRect(this.Right - 8, n + 6, 2, 4, fg); + } + } + if (!string.IsNullOrEmpty(this._Title) && this._ForeColor.A != 0) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = this.TitleRectangle.Top + (this.TitleRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = this.TitleRectangle.Left + (this.TitleRectangle.Width - text.MeasureText(this._Title)) / 2; + canvas.DrawText(this._Title, x, y, text); + } + } + }); } /// /// 绘制Node主体部分 除去标题部分 @@ -652,23 +647,21 @@ protected virtual void OnDrawBody(DrawingTools dt) { this.OnDrawOptionText(dt, op); } if (this._Controls.Count != 0) { //绘制子控件 - //将坐标原点与节点对齐 - //dt.Graphics.ResetTransform(); - dt.Graphics.TranslateTransform(this._Left, this._Top + this._TitleHeight); - Point pt = Point.Empty; //当前需要偏移的量 - Point pt_last = Point.Empty; //最后一个控件相对于节点的坐标 - foreach (STNodeControl v in this._Controls) { - if (!v.Visable) continue; - pt.X = v.Left - pt_last.X; - pt.Y = v.Top - pt_last.Y; - pt_last = v.Location; - dt.Graphics.TranslateTransform(pt.X, pt.Y); //将原点坐标移动至控件位置 - dt.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - v.OnPaint(dt); + if (dt.Canvas != null) { + dt.Canvas.Save(); + dt.Canvas.Translate(this._Left, this._Top + this._TitleHeight); + Point pt = Point.Empty; + Point pt_last = Point.Empty; + foreach (STNodeControl v in this._Controls) { + if (!v.Visable) continue; + pt.X = v.Left - pt_last.X; + pt.Y = v.Top - pt_last.Y; + pt_last = v.Location; + dt.Canvas.Translate(pt.X, pt.Y); + v.OnPaint(dt); + } + dt.Canvas.Restore(); } - //dt.Graphics.TranslateTransform(-pt_last.X, -pt_last.Y); 还原坐标 - dt.Graphics.TranslateTransform(-this._Left - pt_last.X, -this._Top - this._TitleHeight - pt_last.Y); - //dt.Graphics. } } /// @@ -676,27 +669,24 @@ protected virtual void OnDrawBody(DrawingTools dt) { /// /// 绘制工具 protected internal virtual void OnDrawMark(DrawingTools dt) { - if (string.IsNullOrEmpty(this._Mark)) return; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - m_sf.LineAlignment = StringAlignment.Center; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - brush.Color = this._MarkColor; - g.FillRectangle(brush, this._MarkRectangle); //填充背景色 - - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //确定文本绘制所需大小 - var sz = g.MeasureString(this.Mark, this.Font, this._MarkRectangle.Width); - brush.Color = this._ForeColor; - if (sz.Height > this._ItemHeight || sz.Width > this._MarkRectangle.Width) { //如果超过绘图区 则绘制部分 - Rectangle rect = new Rectangle(this._MarkRectangle.Left + 2, this._MarkRectangle.Top + 2, this._MarkRectangle.Width - 20, 16); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this._MarkLines[0], this._Font, brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Far; - rect.Width = this._MarkRectangle.Width - 5; - g.DrawString("+", this._Font, brush, rect, m_sf); // + 表示超过绘图区 - } else { - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this._MarkLines[0].Trim(), this._Font, brush, this._MarkRectangle, m_sf); + if (string.IsNullOrEmpty(this._Mark) || dt.Canvas == null) return; + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._MarkColor), Style = SKPaintStyle.Fill, IsAntialias = false }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + dt.Canvas.DrawRect(this._MarkRectangle.Left, this._MarkRectangle.Top, this._MarkRectangle.Width, this._MarkRectangle.Height, bg); + var fm = text.FontMetrics; + float textHeight = fm.Descent - fm.Ascent; + float textWidth = text.MeasureText(this.Mark ?? string.Empty); + if (textHeight > this._ItemHeight || textWidth > this._MarkRectangle.Width) { + string line = (this._MarkLines != null && this._MarkLines.Length > 0) ? this._MarkLines[0] : string.Empty; + float y = this._MarkRectangle.Top + (this._MarkRectangle.Height - textHeight) / 2f - fm.Ascent; + dt.Canvas.DrawText(line, this._MarkRectangle.Left + 2, y, text); + float plusW = text.MeasureText("+"); + dt.Canvas.DrawText("+", this._MarkRectangle.Right - plusW - 2, y, text); + } else { + string line = (this._MarkLines != null && this._MarkLines.Length > 0) ? this._MarkLines[0].Trim() : string.Empty; + float y = this._MarkRectangle.Top + (this._MarkRectangle.Height - textHeight) / 2f - fm.Ascent; + dt.Canvas.DrawText(line, this._MarkRectangle.Left + 2, y, text); + } } } /// @@ -705,30 +695,32 @@ protected internal virtual void OnDrawMark(DrawingTools dt) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - Pen pen = dt.Pen; - SolidBrush brush = dt.SolidBrush; + if (dt.Canvas == null) return; var t = typeof(object); - if (op.DotColor != Color.Transparent) //设置颜色 - brush.Color = op.DotColor; - else { - if (op.DataType == t) - pen.Color = this.Owner.UnknownTypeColor; - else - brush.Color = this.Owner.TypeColor.ContainsKey(op.DataType) ? this.Owner.TypeColor[op.DataType] : this.Owner.UnknownTypeColor; + SKColor fillColor; + SKColor strokeColor = SkiaDrawingHelper.ToSKColor(this.Owner.UnknownTypeColor); + bool isUnknown = op.DataType == t; + if (op.DotColor != Color.Transparent) { + fillColor = SkiaDrawingHelper.ToSKColor(op.DotColor); + } else { + var c = this.Owner.TypeColor.ContainsKey(op.DataType) ? this.Owner.TypeColor[op.DataType] : this.Owner.UnknownTypeColor; + fillColor = SkiaDrawingHelper.ToSKColor(c); + strokeColor = SkiaDrawingHelper.ToSKColor(this.Owner.UnknownTypeColor); } - if (op.IsSingle) { //单连接 圆形 - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - if (op.DataType == t) { //未知类型绘制 否则填充 - g.DrawEllipse(pen, op.DotRectangle.X, op.DotRectangle.Y, op.DotRectangle.Width - 1, op.DotRectangle.Height - 1); - } else - g.FillEllipse(brush, op.DotRectangle); - } else { //多连接 矩形 - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - if (op.DataType == t) { - g.DrawRectangle(pen, op.DotRectangle.X, op.DotRectangle.Y, op.DotRectangle.Width - 1, op.DotRectangle.Height - 1); - } else - g.FillRectangle(brush, op.DotRectangle); + using (var fill = new SKPaint { Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = strokeColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (op.IsSingle) { + if (isUnknown) { + dt.Canvas.DrawOval(op.DotRectangle.X + op.DotRectangle.Width / 2f, op.DotRectangle.Y + op.DotRectangle.Height / 2f, (op.DotRectangle.Width - 1) / 2f, (op.DotRectangle.Height - 1) / 2f, stroke); + } else { + dt.Canvas.DrawOval(op.DotRectangle.X + op.DotRectangle.Width / 2f, op.DotRectangle.Y + op.DotRectangle.Height / 2f, op.DotRectangle.Width / 2f, op.DotRectangle.Height / 2f, fill); + } + } else { + if (isUnknown) + dt.Canvas.DrawRect(op.DotRectangle.X, op.DotRectangle.Y, op.DotRectangle.Width - 1, op.DotRectangle.Height - 1, stroke); + else + dt.Canvas.DrawRect(op.DotRectangle.X, op.DotRectangle.Y, op.DotRectangle.Width, op.DotRectangle.Height, fill); + } } } /// @@ -737,15 +729,14 @@ protected virtual void OnDrawOptionDot(DrawingTools dt, STNodeOption op) { /// 绘制工具 /// 指定的选项 protected virtual void OnDrawOptionText(DrawingTools dt, STNodeOption op) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - if (op.IsInput) { - m_sf.Alignment = StringAlignment.Near; - } else { - m_sf.Alignment = StringAlignment.Far; - } - brush.Color = op.TextColor; - g.DrawString(op.Text, this.Font, brush, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(op.TextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = op.IsInput ? op.TextRectangle.Left + 2 : op.TextRectangle.Right - text.MeasureText(op.Text) - 2; + canvas.DrawText(op.Text ?? string.Empty, x, y, text); + } + }); } /// /// 当计算Option连线点位置时候发生 @@ -774,7 +765,7 @@ protected virtual Rectangle OnSetOptionTextRectangle(STNodeOption op, Rectangle /// /// 绘图面板 /// 计算出来的大小 - protected virtual Size GetDefaultNodeSize(Graphics g) { + protected virtual Size GetDefaultNodeSize() { int nInputHeight = 0, nOutputHeight = 0; foreach (STNodeOption op in this._InputOptions) nInputHeight += this._ItemHeight; foreach (STNodeOption op in this._OutputOptions) nOutputHeight += this._ItemHeight; @@ -783,16 +774,18 @@ protected virtual Size GetDefaultNodeSize(Graphics g) { SizeF szf_input = SizeF.Empty, szf_output = SizeF.Empty; foreach (STNodeOption v in this._InputOptions) { if (string.IsNullOrEmpty(v.Text)) continue; - SizeF szf = g.MeasureString(v.Text, this._Font); + float w = this.MeasureTextWidth(v.Text); + SizeF szf = new SizeF(w, this._Font.Height); if (szf.Width > szf_input.Width) szf_input = szf; } foreach (STNodeOption v in this._OutputOptions) { if (string.IsNullOrEmpty(v.Text)) continue; - SizeF szf = g.MeasureString(v.Text, this._Font); + float w = this.MeasureTextWidth(v.Text); + SizeF szf = new SizeF(w, this._Font.Height); if (szf.Width > szf_output.Width) szf_output = szf; } int nWidth = (int)(szf_input.Width + szf_output.Width + 25); - if (!string.IsNullOrEmpty(this.Title)) szf_input = g.MeasureString(this.Title, this.Font); + if (!string.IsNullOrEmpty(this.Title)) szf_input = new SizeF(this.MeasureTextWidth(this.Title), this.Font.Height); if (szf_input.Width + 30 > nWidth) nWidth = (int)szf_input.Width + 30; return new Size(nWidth, nHeight); } @@ -803,10 +796,15 @@ protected virtual Size GetDefaultNodeSize(Graphics g) { /// /// 绘图面板 /// 计算后的区域 - protected virtual Rectangle OnBuildMarkRectangle(Graphics g) { + protected virtual Rectangle OnBuildMarkRectangle() { //if (string.IsNullOrEmpty(this._Mark)) return Rectangle.Empty; return new Rectangle(this._Left, this._Top - 30, this._Width, 20); } + private float MeasureTextWidth(string text) { + using (var paint = new SKPaint { TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + return paint.MeasureText(text ?? string.Empty); + } + } /// /// 当需要保存时候 此Node有哪些需要额外保存的数据 /// 注意: 保存时并不会进行序列化 还原时候仅重新通过空参数构造器创建此Node diff --git a/ST.Library.UI/NodeEditor/STNodeControl.cs b/ST.Library.UI/NodeEditor/STNodeControl.cs index 4bd9cca..e84f3cf 100644 --- a/ST.Library.UI/NodeEditor/STNodeControl.cs +++ b/ST.Library.UI/NodeEditor/STNodeControl.cs @@ -4,6 +4,7 @@ using System.Text; using System.Windows.Forms; using System.Drawing; +using SkiaSharp; /* MIT License @@ -195,15 +196,19 @@ public STNodeControl() { } protected internal virtual void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - brush.Color = this._BackColor; - g.FillRectangle(brush, 0, 0, this.Width, this.Height); - if (!string.IsNullOrEmpty(this._Text)) { - brush.Color = this._ForeColor; - g.DrawString(this._Text, this._Font, brush, this.ClientRectangle, m_sf); + if (dt.Canvas != null) { + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) { + dt.Canvas.DrawRect(0, 0, this.Width, this.Height, bg); + } + if (!string.IsNullOrEmpty(this._Text)) { + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ForeColor), TextSize = Math.Max(10f, this._Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float y = (this.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float w = text.MeasureText(this._Text); + float x = (this.Width - w) / 2; + dt.Canvas.DrawText(this._Text, x, y, text); + } + } } if (this.Paint != null) this.Paint(this, new STNodeControlPaintEventArgs(dt)); } diff --git a/ST.Library.UI/NodeEditor/STNodeEditor.cs b/ST.Library.UI/NodeEditor/STNodeEditor.cs index 75bb669..3f0039d 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditor.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditor.cs @@ -11,6 +11,8 @@ using System.ComponentModel; using System.Reflection; using System.IO.Compression; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -44,7 +46,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeEditor : Control + public class STNodeEditor : SKControl { private const UInt32 WM_MOUSEHWHEEL = 0x020E; protected static readonly Type m_type_node = typeof(STNode); @@ -462,6 +464,7 @@ public STNodeEditor() { #region private fields -------------------------------------------------------------------------------------- private DrawingTools m_drawing_tools; + private SKCanvas m_canvas; private NodeFindInfo m_find = new NodeFindInfo(); private MagnetInfo m_mi = new MagnetInfo(); @@ -645,47 +648,74 @@ protected override void WndProc(ref Message m) { } catch { /*add code*/ } } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.Clear(this.BackColor); - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_drawing_tools.Graphics = g; - SolidBrush brush = m_drawing_tools.SolidBrush; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_drawing_tools.Canvas = m_canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + this.RenderEditorToCanvas(m_canvas); + m_canvas = null; + } - if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); + private void RenderEditorToCanvas(SKCanvas canvas) { + if (canvas == null) return; + using (var bitmap = this.RenderEditorToBitmap()) { + canvas.DrawBitmap(bitmap, 0, 0); + } + } - g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); //移动坐标系 - g.ScaleTransform(this._CanvasScale, this._CanvasScale); //缩放绘图表面 + private SKBitmap RenderEditorToBitmap() { + var bitmap = new SKBitmap(Math.Max(this.Width, 1), Math.Max(this.Height, 1), true); + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + this.RenderEditorToCanvasLegacy(canvas); + } + return bitmap; + } - this.OnDrawConnectedLine(m_drawing_tools); - this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); + private void RenderEditorToCanvasLegacy(SKCanvas canvas) { + if (canvas == null) return; + m_canvas = canvas; + m_drawing_tools.Canvas = m_canvas; + if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, this.Width, this.Height); - if (m_ca == CanvasAction.ConnectOption) { //如果正在连线 - m_drawing_tools.Pen.Color = this._HighLineColor; - g.SmoothingMode = SmoothingMode.HighQuality; - if (m_option_down.IsInput) - this.DrawBezier(g, m_drawing_tools.Pen, m_pt_in_canvas, m_pt_dot_down, this._Curvature); - else - this.DrawBezier(g, m_drawing_tools.Pen, m_pt_dot_down, m_pt_in_canvas, this._Curvature); - } - //重置绘图坐标 我认为除了节点以外的其它 修饰相关的绘制不应该在Canvas坐标系中绘制 而应该使用控件的坐标进行绘制 不然会受到缩放比影响 - g.ResetTransform(); + this.RenderLegacyNodeLayer(canvas); switch (m_ca) { - case CanvasAction.MoveNode: //移动过程中 绘制对齐参考线 + case CanvasAction.MoveNode: if (this._ShowMagnet && this._ActiveNode != null) this.OnDrawMagnet(m_drawing_tools, m_mi); break; - case CanvasAction.SelectRectangle: //绘制矩形选取 + case CanvasAction.SelectRectangle: this.OnDrawSelectedRectangle(m_drawing_tools, this.CanvasToControl(m_rect_select)); break; - case CanvasAction.DrawMarkDetails: //绘制标记信息详情 + case CanvasAction.DrawMarkDetails: if (!string.IsNullOrEmpty(m_find.Mark)) this.OnDrawMark(m_drawing_tools); break; } if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, this.Size, m_lst_node_out); - this.OnDrawAlert(g); + this.OnDrawAlert(); + } + + private void RenderLegacyNodeLayer(SKCanvas canvas) { + if (canvas == null) return; + m_drawing_tools.Canvas = canvas; + canvas.Save(); + canvas.Translate(this._CanvasOffsetX, this._CanvasOffsetY); + canvas.Scale(this._CanvasScale, this._CanvasScale); + + this.OnDrawConnectedLine(m_drawing_tools); + this.OnDrawNode(m_drawing_tools, this.ControlToCanvas(this.ClientRectangle)); + + if (m_ca == CanvasAction.ConnectOption) { + using (var high = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HighLineColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2f, IsAntialias = true }) { + if (m_option_down.IsInput) + this.DrawBezier(canvas, high, m_pt_in_canvas, m_pt_dot_down, this._Curvature); + else + this.DrawBezier(canvas, high, m_pt_dot_down, m_pt_in_canvas, this._Curvature); + } + } + canvas.Restore(); } protected override void OnMouseDown(MouseEventArgs e) { @@ -979,21 +1009,19 @@ protected override void OnDragDrop(DragEventArgs drgevent) { /// 需要绘制宽度 /// 需要绘制高度 protected virtual void OnDrawGrid(DrawingTools dt, int nWidth, int nHeight) { - Graphics g = dt.Graphics; - using (Pen p_2 = new Pen(Color.FromArgb(65, this._GridColor))) { - using (Pen p_1 = new Pen(Color.FromArgb(30, this._GridColor))) { - float nIncrement = (20 * this._CanvasScale);             //网格间的间隔 根据比例绘制 - int n = 5 - (int)(this._CanvasOffsetX / nIncrement); - for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), f, 0, f, nHeight); - n = 5 - (int)(this._CanvasOffsetY / nIncrement); - for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) - g.DrawLine((n++ % 5 == 0 ? p_2 : p_1), 0, f, nWidth, f); - //原点两天线 - p_1.Color = Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor); - g.DrawLine(p_1, this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight); - g.DrawLine(p_1, 0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY); - } + if (m_canvas == null) return; + using (var p1 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(30, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var p2 = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(65, this._GridColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + float nIncrement = (20 * this._CanvasScale); + int n = 5 - (int)(this._CanvasOffsetX / nIncrement); + for (float f = this._CanvasOffsetX % nIncrement; f < nWidth; f += nIncrement) + m_canvas.DrawLine(f, 0, f, nHeight, (n++ % 5 == 0 ? p2 : p1)); + n = 5 - (int)(this._CanvasOffsetY / nIncrement); + for (float f = this._CanvasOffsetY % nIncrement; f < nHeight; f += nIncrement) + m_canvas.DrawLine(0, f, nWidth, f, (n++ % 5 == 0 ? p2 : p1)); + p1.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._Nodes.Count == 0 ? 255 : 120, this._GridColor)); + m_canvas.DrawLine(this._CanvasOffsetX, 0, this._CanvasOffsetX, nHeight, p1); + m_canvas.DrawLine(0, this._CanvasOffsetY, nWidth, this._CanvasOffsetY, p1); } } /// @@ -1023,81 +1051,84 @@ protected virtual void OnDrawNodeBorder(DrawingTools dt, STNode node) { else if (node.IsSelected) img_border = m_img_border_selected; else if (this._HoverNode == node) img_border = m_img_border_hover; else img_border = m_img_border; - this.RenderBorder(dt.Graphics, node.Rectangle, img_border); - if (!string.IsNullOrEmpty(node.Mark)) this.RenderBorder(dt.Graphics, node.MarkRectangle, img_border); + this.RenderBorder(m_canvas, node.Rectangle, img_border); + if (!string.IsNullOrEmpty(node.Mark)) this.RenderBorder(m_canvas, node.MarkRectangle, img_border); } /// /// 当绘制已连接路径时候发生 /// /// 绘制工具 protected virtual void OnDrawConnectedLine(DrawingTools dt) { - Graphics g = dt.Graphics; - g.SmoothingMode = SmoothingMode.HighQuality; - m_p_line_hover.Color = Color.FromArgb(50, 0, 0, 0); + if (m_canvas == null) return; var t = typeof(object); - foreach (STNode n in this._Nodes) { - foreach (STNodeOption op in n.OutputOptions) { - if (op == STNodeOption.Empty) continue; - if (op.DotColor != Color.Transparent) //确定线条颜色 - m_p_line.Color = op.DotColor; - else { - if (op.DataType == t) - m_p_line.Color = this._UnknownTypeColor; - else - m_p_line.Color = this._TypeColor.ContainsKey(op.DataType) ? this._TypeColor[op.DataType] : this._UnknownTypeColor;//value can not be null - } - foreach (var v in op.ConnectedOption) { - this.DrawBezier(g, m_p_line_hover, op.DotLeft + op.DotSize, op.DotTop + op.DotSize / 2, - v.DotLeft - 1, v.DotTop + v.DotSize / 2, this._Curvature); - this.DrawBezier(g, m_p_line, op.DotLeft + op.DotSize, op.DotTop + op.DotSize / 2, - v.DotLeft - 1, v.DotTop + v.DotSize / 2, this._Curvature); - if (m_is_buildpath) { //如果当前绘制需要重新建立已连接的路径缓存 - GraphicsPath gp = this.CreateBezierPath(op.DotLeft + op.DotSize, op.DotTop + op.DotSize / 2, + using (var hover = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(50, 0, 0, 0)), Style = SKPaintStyle.Stroke, StrokeWidth = 4f, IsAntialias = true }) + using (var line = new SKPaint { Color = SKColors.Cyan, Style = SKPaintStyle.Stroke, StrokeWidth = 2f, IsAntialias = true }) { + foreach (STNode n in this._Nodes) { + foreach (STNodeOption op in n.OutputOptions) { + if (op == STNodeOption.Empty) continue; + Color lineColor; + if (op.DotColor != Color.Transparent) lineColor = op.DotColor; + else if (op.DataType == t) lineColor = this._UnknownTypeColor; + else lineColor = this._TypeColor.ContainsKey(op.DataType) ? this._TypeColor[op.DataType] : this._UnknownTypeColor; + line.Color = SkiaDrawingHelper.ToSKColor(lineColor); + + foreach (var v in op.ConnectedOption) { + this.DrawBezier(m_canvas, hover, op.DotLeft + op.DotSize, op.DotTop + op.DotSize / 2, v.DotLeft - 1, v.DotTop + v.DotSize / 2, this._Curvature); - m_dic_gp_info.Add(gp, new ConnectionInfo() { Output = op, Input = v }); + this.DrawBezier(m_canvas, line, op.DotLeft + op.DotSize, op.DotTop + op.DotSize / 2, + v.DotLeft - 1, v.DotTop + v.DotSize / 2, this._Curvature); + if (m_is_buildpath) { + GraphicsPath gp = this.CreateBezierPath(op.DotLeft + op.DotSize, op.DotTop + op.DotSize / 2, + v.DotLeft - 1, v.DotTop + v.DotSize / 2, this._Curvature); + m_dic_gp_info.Add(gp, new ConnectionInfo() { Output = op, Input = v }); + } + } + } + } + if (m_gp_hover != null) { + using (var hp = this.ToSKPath(m_gp_hover)) { + if (hp != null) { + hover.Color = SkiaDrawingHelper.ToSKColor(this._HighLineColor); + m_canvas.DrawPath(hp, hover); } } } } - m_p_line_hover.Color = this._HighLineColor; - if (m_gp_hover != null) { //如果当前有被悬停的连接路劲 则高亮绘制 - g.DrawPath(m_p_line_hover, m_gp_hover); - } - m_is_buildpath = false; //重置标志 下次绘制时候 不再重新建立路径缓存 + m_is_buildpath = false; } + /// /// 当绘制 Mark 详情信息时候发生 /// /// 绘制工具 protected virtual void OnDrawMark(DrawingTools dt) { - Graphics g = dt.Graphics; - SizeF sz = g.MeasureString(m_find.Mark, this.Font); //确认文字需要的大小 - Rectangle rect = new Rectangle(m_pt_in_control.X + 15, - m_pt_in_control.Y + 10, - (int)sz.Width + 6, - 4 + (this.Font.Height + 4) * m_find.MarkLines.Length); //sz.Height并没有考虑文字的行距 所以这里高度自己计算 - - if (rect.Right > this.Width) rect.X = this.Width - rect.Width; - if (rect.Bottom > this.Height) rect.Y = this.Height - rect.Height; - if (rect.X < 0) rect.X = 0; - if (rect.Y < 0) rect.Y = 0; - - dt.SolidBrush.Color = this._MarkBackColor; - g.SmoothingMode = SmoothingMode.None; - g.FillRectangle(dt.SolidBrush, rect); //绘制背景区域 - rect.Width--; rect.Height--; - dt.Pen.Color = Color.FromArgb(255, this._MarkBackColor); - g.DrawRectangle(dt.Pen, rect); - dt.SolidBrush.Color = this._MarkForeColor; - - m_sf.LineAlignment = StringAlignment.Center; - //g.SmoothingMode = SmoothingMode.HighQuality; - rect.X += 2; rect.Width -= 3; - rect.Height = this.Font.Height + 4; - int nY = rect.Y + 2; - for (int i = 0; i < m_find.MarkLines.Length; i++) { //绘制文字 - rect.Y = nY + i * (this.Font.Height + 4); - g.DrawString(m_find.MarkLines[i], this.Font, dt.SolidBrush, rect, m_sf); + if (m_canvas == null || string.IsNullOrEmpty(m_find.Mark)) return; + using (var textPaint = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + float textWidth = textPaint.MeasureText(m_find.Mark); + Rectangle rect = new Rectangle(m_pt_in_control.X + 15, + m_pt_in_control.Y + 10, + (int)Math.Ceiling(textWidth) + 6, + 4 + (this.Font.Height + 4) * m_find.MarkLines.Length); + + if (rect.Right > this.Width) rect.X = this.Width - rect.Width; + if (rect.Bottom > this.Height) rect.Y = this.Height - rect.Height; + if (rect.X < 0) rect.X = 0; + if (rect.Y < 0) rect.Y = 0; + + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._MarkBackColor), Style = SKPaintStyle.Fill, IsAntialias = false }) + using (var border = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(255, this._MarkBackColor)), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = false }) + using (var fg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._MarkForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width - 1, rect.Height - 1, border); + + var fm = fg.FontMetrics; + float baseY = rect.Y + 2 - fm.Ascent; + float textX = rect.X + 4; + for (int i = 0; i < m_find.MarkLines.Length; i++) { + float y = baseY + i * (this.Font.Height + 4); + m_canvas.DrawText(m_find.MarkLines[i], textX, y, fg); + } + } } } /// @@ -1106,38 +1137,39 @@ protected virtual void OnDrawMark(DrawingTools dt) { /// 绘制工具 /// 匹配的磁铁信息 protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { - if (this._ActiveNode == null) return; - Graphics g = dt.Graphics; - Pen pen = m_drawing_tools.Pen; - SolidBrush brush = dt.SolidBrush; - pen.Color = this._MagnetColor; - brush.Color = Color.FromArgb(this._MagnetColor.A / 3, this._MagnetColor); - g.SmoothingMode = SmoothingMode.None; - int nL = this._ActiveNode.Left, nMX = this._ActiveNode.Left + this._ActiveNode.Width / 2, nR = this._ActiveNode.Right; - int nT = this._ActiveNode.Top, nMY = this._ActiveNode.Top + this._ActiveNode.Height / 2, nB = this._ActiveNode.Bottom; - if (mi.XMatched) g.DrawLine(pen, this.CanvasToControl(mi.X, true), 0, this.CanvasToControl(mi.X, true), this.Height); - if (mi.YMatched) g.DrawLine(pen, 0, this.CanvasToControl(mi.Y, false), this.Width, this.CanvasToControl(mi.Y, false)); - g.TranslateTransform(this._CanvasOffsetX, this._CanvasOffsetY); //移动坐标系 - g.ScaleTransform(this._CanvasScale, this._CanvasScale); //缩放绘图表面 - if (mi.XMatched) { - //g.DrawLine(pen, this.CanvasToControl(mi.X, true), 0, this.CanvasToControl(mi.X, true), this.Height); - foreach (STNode n in this._Nodes) { - if (n.Left == mi.X || n.Right == mi.X || n.Left + n.Width / 2 == mi.X) { - //g.DrawRectangle(pen, n.Left, n.Top, n.Width - 1, n.Height - 1); - g.FillRectangle(brush, n.Rectangle); + if (m_canvas == null || this._ActiveNode == null) return; + using (var line = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._MagnetColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = false }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this._MagnetColor.A / 3, this._MagnetColor)), Style = SKPaintStyle.Fill, IsAntialias = false }) { + if (mi.XMatched) { + float x = this.CanvasToControl(mi.X, true); + m_canvas.DrawLine(x, 0, x, this.Height, line); + } + if (mi.YMatched) { + float y = this.CanvasToControl(mi.Y, false); + m_canvas.DrawLine(0, y, this.Width, y, line); + } + + m_canvas.Save(); + m_canvas.Translate(this._CanvasOffsetX, this._CanvasOffsetY); + m_canvas.Scale(this._CanvasScale, this._CanvasScale); + + if (mi.XMatched) { + foreach (STNode n in this._Nodes) { + if (n.Left == mi.X || n.Right == mi.X || n.Left + n.Width / 2 == mi.X) { + m_canvas.DrawRect(n.Left, n.Top, n.Width, n.Height, fill); + } } } - } - if (mi.YMatched) { - //g.DrawLine(pen, 0, this.CanvasToControl(mi.Y, false), this.Width, this.CanvasToControl(mi.Y, false)); - foreach (STNode n in this._Nodes) { - if (n.Top == mi.Y || n.Bottom == mi.Y || n.Top + n.Height / 2 == mi.Y) { - //g.DrawRectangle(pen, n.Left, n.Top, n.Width - 1, n.Height - 1); - g.FillRectangle(brush, n.Rectangle); + if (mi.YMatched) { + foreach (STNode n in this._Nodes) { + if (n.Top == mi.Y || n.Bottom == mi.Y || n.Top + n.Height / 2 == mi.Y) { + m_canvas.DrawRect(n.Left, n.Top, n.Width, n.Height, fill); + } } } + + m_canvas.Restore(); } - g.ResetTransform(); } /// /// 绘制选择的矩形区域 @@ -1145,12 +1177,14 @@ protected virtual void OnDrawMagnet(DrawingTools dt, MagnetInfo mi) { /// 绘制工具 /// 位于控件上的矩形区域 protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - dt.Pen.Color = this._SelectedRectangleColor; - g.DrawRectangle(dt.Pen, rectf.Left, rectf.Y, rectf.Width, rectf.Height); - brush.Color = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); - g.FillRectangle(brush, this.CanvasToControl(m_rect_select)); + if (m_canvas == null) return; + var fill = Color.FromArgb(this._SelectedRectangleColor.A / 3, this._SelectedRectangleColor); + Rectangle rect = this.CanvasToControl(m_rect_select); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SelectedRectangleColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(fill), Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rectf.Left, rectf.Top, rectf.Width, rectf.Height, stroke); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + } } /// /// 绘制超出视觉区域的 Node 位置提示信息 @@ -1159,25 +1193,25 @@ protected virtual void OnDrawSelectedRectangle(DrawingTools dt, RectangleF rectf /// 提示框边距 /// 超出视觉区域的 Node 位置信息 protected virtual void OnDrawNodeOutLocation(DrawingTools dt, Size sz, List lstPts) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - brush.Color = this._LocationBackColor; - g.SmoothingMode = SmoothingMode.None; - if (lstPts.Count == this._Nodes.Count && this._Nodes.Count != 0) { //如果超出个数和集合个数一样多 则全部超出 绘制外切矩形 - g.FillRectangle(brush, this.CanvasToControl(this._CanvasValidBounds)); - } - g.FillRectangle(brush, 0, 0, 4, sz.Height); //绘制四边背景 - g.FillRectangle(brush, sz.Width - 4, 0, 4, sz.Height); - g.FillRectangle(brush, 4, 0, sz.Width - 8, 4); - g.FillRectangle(brush, 4, sz.Height - 4, sz.Width - 8, 4); - brush.Color = this._LocationForeColor; - foreach (var v in lstPts) { //绘制点 - var pt = this.CanvasToControl(v); - if (pt.X < 0) pt.X = 0; - if (pt.Y < 0) pt.Y = 0; - if (pt.X > sz.Width) pt.X = sz.Width - 4; - if (pt.Y > sz.Height) pt.Y = sz.Height - 4; - g.FillRectangle(brush, pt.X, pt.Y, 4, 4); + if (m_canvas == null) return; + using (var back = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._LocationBackColor), Style = SKPaintStyle.Fill, IsAntialias = false }) + using (var fore = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._LocationForeColor), Style = SKPaintStyle.Fill, IsAntialias = false }) { + if (lstPts.Count == this._Nodes.Count && this._Nodes.Count != 0) { + Rectangle r = this.CanvasToControl(this._CanvasValidBounds); + m_canvas.DrawRect(r.Left, r.Top, r.Width, r.Height, back); + } + m_canvas.DrawRect(0, 0, 4, sz.Height, back); + m_canvas.DrawRect(sz.Width - 4, 0, 4, sz.Height, back); + m_canvas.DrawRect(4, 0, sz.Width - 8, 4, back); + m_canvas.DrawRect(4, sz.Height - 4, sz.Width - 8, 4, back); + foreach (var v in lstPts) { + var pt = this.CanvasToControl(v); + if (pt.X < 0) pt.X = 0; + if (pt.Y < 0) pt.Y = 0; + if (pt.X > sz.Width) pt.X = sz.Width - 4; + if (pt.Y > sz.Height) pt.Y = sz.Height - 4; + m_canvas.DrawRect(pt.X, pt.Y, 4, 4, fore); + } } } /// @@ -1190,21 +1224,17 @@ protected virtual void OnDrawNodeOutLocation(DrawingTools dt, Size sz, List信息背景色 /// 信息位置 protected virtual void OnDrawAlert(DrawingTools dt, Rectangle rect, string strText, Color foreColor, Color backColor, AlertLocation al) { - if (m_alpha_alert == 0) return; - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; - - g.SmoothingMode = SmoothingMode.None; - brush.Color = backColor; - dt.Pen.Color = brush.Color; - g.FillRectangle(brush, rect); - g.DrawRectangle(dt.Pen, rect.Left, rect.Top, rect.Width - 1, rect.Height - 1); - - brush.Color = foreColor; - m_sf.Alignment = StringAlignment.Center; - m_sf.LineAlignment = StringAlignment.Center; - g.SmoothingMode = SmoothingMode.HighQuality; - g.DrawString(strText, this.Font, brush, rect, m_sf); + if (m_alpha_alert == 0 || m_canvas == null) return; + using (var bg = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(backColor), Style = SKPaintStyle.Fill, IsAntialias = false }) + using (var border = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(backColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = false }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(foreColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); + m_canvas.DrawRect(rect.Left, rect.Top, rect.Width - 1, rect.Height - 1, border); + var fm = text.FontMetrics; + float x = rect.Left + (rect.Width - text.MeasureText(strText)) / 2f; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2f - fm.Ascent; + m_canvas.DrawText(strText, x, y, text); + } } /// /// 获取提示信息需要绘制的矩形区域 @@ -1213,10 +1243,13 @@ protected virtual void OnDrawAlert(DrawingTools dt, Rectangle rect, string strTe /// 需要绘制文本 /// 信息位置 /// 矩形区域 - protected virtual Rectangle GetAlertRectangle(Graphics g, string strText, AlertLocation al) { - SizeF szf = g.MeasureString(m_str_alert, this.Font); - Size sz = new Size((int)Math.Round(szf.Width + 10), (int)Math.Round(szf.Height + 4)); - Rectangle rect = new Rectangle(4, this.Height - sz.Height - 4, sz.Width, sz.Height); + protected virtual Rectangle GetAlertRectangle(string strText, AlertLocation al) { + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = text.FontMetrics; + float w = text.MeasureText(m_str_alert); + float h = fm.Descent - fm.Ascent; + Size sz = new Size((int)Math.Round(w + 10), (int)Math.Round(h + 4)); + Rectangle rect = new Rectangle(4, this.Height - sz.Height - 4, sz.Width, sz.Height); switch (al) { case AlertLocation.Left: @@ -1248,7 +1281,8 @@ protected virtual Rectangle GetAlertRectangle(Graphics g, string strText, AlertL rect.X = this.Width - sz.Width - 4; break; } - return rect; + return rect; + } } #endregion protected @@ -1262,8 +1296,8 @@ internal void BuildLinePath() { this.Invalidate(); } - internal void OnDrawAlert(Graphics g) { - m_rect_alert = this.GetAlertRectangle(g, m_str_alert, m_al); + internal void OnDrawAlert() { + m_rect_alert = this.GetAlertRectangle(m_str_alert, m_al); Color clr_fore = Color.FromArgb((int)((float)m_alpha_alert / 255 * m_forecolor_alert.A), m_forecolor_alert); Color clr_back = Color.FromArgb((int)((float)m_alpha_alert / 255 * m_backcolor_alert.A), m_backcolor_alert); this.OnDrawAlert(m_drawing_tools, m_rect_alert, m_str_alert, clr_fore, clr_back, m_al); @@ -1345,19 +1379,23 @@ private void ShowAlertThread() { } private Image CreateBorderImage(Color clr) { - Image img = new Bitmap(12, 12); - using (Graphics g = Graphics.FromImage(img)) { - g.SmoothingMode = SmoothingMode.HighQuality; - using (GraphicsPath gp = new GraphicsPath()) { - gp.AddEllipse(new Rectangle(0, 0, 11, 11)); - using (PathGradientBrush b = new PathGradientBrush(gp)) { - b.CenterColor = Color.FromArgb(200, clr); - b.SurroundColors = new Color[] { Color.FromArgb(10, clr) }; - g.FillPath(b, gp); - } + using (var bitmap = new SKBitmap(12, 12, true)) + using (var canvas = new SKCanvas(bitmap)) + using (var paint = new SKPaint { IsAntialias = true, Style = SKPaintStyle.Fill }) { + var center = SkiaDrawingHelper.ToSKColor(Color.FromArgb(200, clr)); + var edge = SkiaDrawingHelper.ToSKColor(Color.FromArgb(10, clr)); + using (var shader = SKShader.CreateRadialGradient(new SKPoint(5.5f, 5.5f), 5.5f, + new[] { center, edge }, + new float[] { 0f, 1f }, SKShaderTileMode.Clamp)) { + paint.Shader = shader; + canvas.DrawCircle(5.5f, 5.5f, 5.5f, paint); + } + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new MemoryStream(data.ToArray())) { + return Image.FromStream(ms); } } - return img; } private ConnectionStatus DisConnectionHover() { @@ -1490,18 +1528,19 @@ private MagnetInfo CheckMagnet(STNode node) { return m_mi; } - private void DrawBezier(Graphics g, Pen p, PointF ptStart, PointF ptEnd, float f) { - this.DrawBezier(g, p, ptStart.X, ptStart.Y, ptEnd.X, ptEnd.Y, f); + private void DrawBezier(SKCanvas canvas, SKPaint paint, PointF ptStart, PointF ptEnd, float f) { + this.DrawBezier(canvas, paint, ptStart.X, ptStart.Y, ptEnd.X, ptEnd.Y, f); } - private void DrawBezier(Graphics g, Pen p, float x1, float y1, float x2, float y2, float f) { + private void DrawBezier(SKCanvas canvas, SKPaint paint, float x1, float y1, float x2, float y2, float f) { + if (canvas == null || paint == null) return; float n = (Math.Abs(x1 - x2) * f); if (this._Curvature != 0 && n < 30) n = 30; - g.DrawBezier(p, - x1, y1, - x1 + n, y1, - x2 - n, y2, - x2, y2); + using (var path = new SKPath()) { + path.MoveTo(x1, y1); + path.CubicTo(x1 + n, y1, x2 - n, y2, x2, y2); + canvas.DrawPath(path, paint); + } } private GraphicsPath CreateBezierPath(float x1, float y1, float x2, float y2, float f) { @@ -1517,25 +1556,35 @@ private GraphicsPath CreateBezierPath(float x1, float y1, float x2, float y2, fl return gp; } - private void RenderBorder(Graphics g, Rectangle rect, Image img) { - //填充四个角 - g.DrawImage(img, new Rectangle(rect.X - 5, rect.Y - 5, 5, 5), - new Rectangle(0, 0, 5, 5), GraphicsUnit.Pixel); - g.DrawImage(img, new Rectangle(rect.Right, rect.Y - 5, 5, 5), - new Rectangle(img.Width - 5, 0, 5, 5), GraphicsUnit.Pixel); - g.DrawImage(img, new Rectangle(rect.X - 5, rect.Bottom, 5, 5), - new Rectangle(0, img.Height - 5, 5, 5), GraphicsUnit.Pixel); - g.DrawImage(img, new Rectangle(rect.Right, rect.Bottom, 5, 5), - new Rectangle(img.Width - 5, img.Height - 5, 5, 5), GraphicsUnit.Pixel); - //四边 - g.DrawImage(img, new Rectangle(rect.X - 5, rect.Y, 5, rect.Height), - new Rectangle(0, 5, 5, img.Height - 10), GraphicsUnit.Pixel); - g.DrawImage(img, new Rectangle(rect.X, rect.Y - 5, rect.Width, 5), - new Rectangle(5, 0, img.Width - 10, 5), GraphicsUnit.Pixel); - g.DrawImage(img, new Rectangle(rect.Right, rect.Y, 5, rect.Height), - new Rectangle(img.Width - 5, 5, 5, img.Height - 10), GraphicsUnit.Pixel); - g.DrawImage(img, new Rectangle(rect.X, rect.Bottom, rect.Width, 5), - new Rectangle(5, img.Height - 5, img.Width - 10, 5), GraphicsUnit.Pixel); + private SKPath ToSKPath(GraphicsPath gp) { + if (gp == null) return null; + var points = gp.PathPoints; + if (points == null || points.Length < 2) return null; + var path = new SKPath(); + path.MoveTo(points[0].X, points[0].Y); + int i = 1; + while (i + 2 < points.Length) { + path.CubicTo(points[i].X, points[i].Y, points[i + 1].X, points[i + 1].Y, points[i + 2].X, points[i + 2].Y); + i += 3; + } + return path; + } + + private void RenderBorder(SKCanvas canvas, Rectangle rect, Image img) { + if (canvas == null || img == null) return; + using (var bmp = SkiaDrawingHelper.ToSKBitmap(img)) { + if (bmp == null) return; + //填充四个角 + canvas.DrawBitmap(bmp, new SKRect(0, 0, 5, 5), new SKRect(rect.X - 5, rect.Y - 5, rect.X, rect.Y)); + canvas.DrawBitmap(bmp, new SKRect(img.Width - 5, 0, img.Width, 5), new SKRect(rect.Right, rect.Y - 5, rect.Right + 5, rect.Y)); + canvas.DrawBitmap(bmp, new SKRect(0, img.Height - 5, 5, img.Height), new SKRect(rect.X - 5, rect.Bottom, rect.X, rect.Bottom + 5)); + canvas.DrawBitmap(bmp, new SKRect(img.Width - 5, img.Height - 5, img.Width, img.Height), new SKRect(rect.Right, rect.Bottom, rect.Right + 5, rect.Bottom + 5)); + //四边 + canvas.DrawBitmap(bmp, new SKRect(0, 5, 5, img.Height - 10), new SKRect(rect.X - 5, rect.Y, rect.X, rect.Bottom)); + canvas.DrawBitmap(bmp, new SKRect(5, 0, img.Width - 10, 5), new SKRect(rect.X, rect.Y - 5, rect.Right, rect.Y)); + canvas.DrawBitmap(bmp, new SKRect(img.Width - 5, 5, img.Width, img.Height - 10), new SKRect(rect.Right, rect.Y, rect.Right + 5, rect.Bottom)); + canvas.DrawBitmap(bmp, new SKRect(5, img.Height - 5, img.Width - 10, img.Height), new SKRect(rect.X, rect.Bottom, rect.Right, rect.Bottom + 5)); + } } #endregion private @@ -1786,22 +1835,27 @@ private static bool CanFindNodePath(STNode nodeStart, STNode nodeFind, HashSet图像 public Image GetCanvasImage(Rectangle rect, float fScale) { if (fScale < 0.5) fScale = 0.5f; else if (fScale > 3) fScale = 3; - Image img = new Bitmap((int)(rect.Width * fScale), (int)(rect.Height * fScale)); - using (Graphics g = Graphics.FromImage(img)) { - g.Clear(this.BackColor); - g.ScaleTransform(fScale, fScale); - m_drawing_tools.Graphics = g; + using (var bitmap = new SKBitmap((int)(rect.Width * fScale), (int)(rect.Height * fScale), true)) + using (var canvas = new SKCanvas(bitmap)) { + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas = canvas; + m_drawing_tools.Canvas = canvas; + if (fScale != 1f) canvas.Scale(fScale, fScale); if (this._ShowGrid) this.OnDrawGrid(m_drawing_tools, rect.Width, rect.Height); - g.TranslateTransform(-rect.X, -rect.Y); //移动坐标系 + canvas.Translate(-rect.X, -rect.Y); this.OnDrawNode(m_drawing_tools, rect); this.OnDrawConnectedLine(m_drawing_tools); - - g.ResetTransform(); - - if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, img.Size, m_lst_node_out); + canvas.ResetMatrix(); + + if (this._ShowLocation) this.OnDrawNodeOutLocation(m_drawing_tools, new Size(bitmap.Width, bitmap.Height), m_lst_node_out); + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var ms = new MemoryStream(data.ToArray())) { + m_canvas = null; + return Image.FromStream(ms); + } } - return img; } /// /// 保存画布中的类容到文件中 diff --git a/ST.Library.UI/NodeEditor/STNodeEditorDataType.cs b/ST.Library.UI/NodeEditor/STNodeEditorDataType.cs index d84fa18..35b8156 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorDataType.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorDataType.cs @@ -4,6 +4,7 @@ using System.Text; using System.ComponentModel; using System.Drawing; +using SkiaSharp; namespace ST.Library.UI.NodeEditor { @@ -96,7 +97,7 @@ public enum AlertLocation public struct DrawingTools { - public Graphics Graphics; + public SKCanvas Canvas; public Pen Pen; public SolidBrush SolidBrush; } diff --git a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs index c4a1041..62c91d4 100644 --- a/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs +++ b/ST.Library.UI/NodeEditor/STNodeEditorPannel.cs @@ -5,12 +5,14 @@ using System.Windows.Forms; using System.Drawing; +using SkiaSharp; +using SkiaSharp.Views.Desktop; using System.Runtime.InteropServices; using System.ComponentModel; namespace ST.Library.UI.NodeEditor { - public class STNodeEditorPannel : Control + public class STNodeEditorPannel : SKControl { private bool _LeftLayout = true; /// @@ -123,7 +125,6 @@ public STNodePropertyGrid PropertyGrid { private Point m_pt_down; private bool m_is_mx; private bool m_is_my; - private Pen m_pen; private bool m_nInited; private Dictionary m_dic_status_key = new Dictionary(); @@ -163,7 +164,6 @@ public STNodeEditorPannel() { this.MinimumSize = new Size(250, 250); this.BackColor = Color.FromArgb(255, 34, 34, 34); - m_pen = new Pen(this.BackColor, 3); Type t = typeof(ConnectionStatus); var vv = Enum.GetValues(t); @@ -208,25 +208,27 @@ protected override void SetBoundsCore(int x, int y, int width, int height, Bound base.SetBoundsCore(x, y, width, height, specified); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - m_pen.Width = 3; - m_pen.Color = this._SplitLineColor; - g.DrawLine(m_pen, this._X, 0, this._X, this.Height); - int nX = 0; - if (this._LeftLayout) { - g.DrawLine(m_pen, 0, this._Y, this._X - 1, this._Y); - nX = this._X / 2; - } else { - g.DrawLine(m_pen, this._X + 2, this._Y, this.Width, this._Y); - nX = this._X + (this.Width - this._X) / 2; - } - m_pen.Width = 1; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + var splitColor = SkiaDrawingHelper.ToSKColor(this._SplitLineColor); this._HandleLineColor = Color.Gray; - m_pen.Color = this._HandleLineColor; - g.DrawLine(m_pen, this._X, this._Y - 10, this._X, this._Y + 10); - g.DrawLine(m_pen, nX - 10, this._Y, nX + 10, this._Y); + var handleColor = SkiaDrawingHelper.ToSKColor(this._HandleLineColor); + var canvas = e.Surface.Canvas; + canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + using (var split = new SKPaint { Color = splitColor, StrokeWidth = 3, IsAntialias = true, Style = SKPaintStyle.Stroke }) + using (var handle = new SKPaint { Color = handleColor, StrokeWidth = 1, IsAntialias = true, Style = SKPaintStyle.Stroke }) { + canvas.DrawLine(this._X, 0, this._X, this.Height, split); + int nX; + if (this._LeftLayout) { + canvas.DrawLine(0, this._Y, this._X - 1, this._Y, split); + nX = this._X / 2; + } else { + canvas.DrawLine(this._X + 2, this._Y, this.Width, this._Y, split); + nX = this._X + (this.Width - this._X) / 2; + } + canvas.DrawLine(this._X, this._Y - 10, this._X, this._Y + 10, handle); + canvas.DrawLine(nX - 10, this._Y, nX + 10, this._Y, handle); + } } private void SetLocation() { diff --git a/ST.Library.UI/NodeEditor/STNodeHub.cs b/ST.Library.UI/NodeEditor/STNodeHub.cs index 32bb171..608ebc3 100644 --- a/ST.Library.UI/NodeEditor/STNodeHub.cs +++ b/ST.Library.UI/NodeEditor/STNodeHub.cs @@ -57,9 +57,7 @@ public STNodeHub(bool bSingle, string strTextIn, string strTextOut) { protected override void OnOwnerChanged() { base.OnOwnerChanged(); if (this.Owner == null) return; - using (Graphics g = this.Owner.CreateGraphics()) { - this.Width = base.GetDefaultNodeSize(g).Width; - } + this.Width = base.GetDefaultNodeSize().Width; } private void Addhub() { diff --git a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs index 7151bfd..10bab40 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyAttribute.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Reflection; using System.Windows.Forms; @@ -263,25 +264,31 @@ protected internal virtual void OnSetValueError(Exception ex) { /// /// 绘制工具 protected internal virtual void OnDrawValueRectangle(DrawingTools dt) { - Graphics g = dt.Graphics; - SolidBrush brush = dt.SolidBrush; STNodePropertyGrid ctrl = this.Control; - //STNodePropertyItem item = this._PropertyItem; - brush.Color = ctrl.ItemValueBackColor; - - g.FillRectangle(brush, this.RectangleR); Rectangle rect = this.RectangleR; rect.Width--; rect.Height--; - brush.Color = this.Control.ForeColor; - g.DrawString(this.GetStringFromValue(), ctrl.Font, brush, this.RectangleR, m_sf); - - if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(rect.Right - 13, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 4, rect.Top + rect.Height / 2 - 2), - new Point(rect.Right - 9, rect.Top + rect.Height / 2 + 3) - }); - } + var textValue = this.GetStringFromValue(); + var backColor = SkiaDrawingHelper.ToSKColor(ctrl.ItemValueBackColor); + var textColor = SkiaDrawingHelper.ToSKColor(this.Control.ForeColor); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { + using (var fill = new SKPaint { Color = backColor, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = textColor, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { + canvas.DrawRect(rect.Left, rect.Top, rect.Width + 1, rect.Height + 1, fill); + var metrics = text.FontMetrics; + float textY = rect.Top + (rect.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(textValue ?? string.Empty, rect.Left + 2, textY, text); + if (this.PropertyInfo.PropertyType.IsEnum || this.PropertyInfo.PropertyType == m_t_bool) { + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var path = new SKPath()) { + path.MoveTo(rect.Right - 13, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 4, rect.Top + rect.Height / 2 - 2); + path.LineTo(rect.Right - 9, rect.Top + rect.Height / 2 + 3); + path.Close(); + canvas.DrawPath(path, arrow); + } + } + } + }); } /// /// 当鼠标进入属性值所在区域时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs index 9b07e37..99d29ee 100644 --- a/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs +++ b/ST.Library.UI/NodeEditor/STNodePropertyGrid.cs @@ -7,6 +7,8 @@ using System.Reflection; using System.Windows.Forms; using System.ComponentModel; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -43,7 +45,7 @@ namespace ST.Library.UI.NodeEditor /// /// STNode节点属性编辑器 /// - public class STNodePropertyGrid : Control + public class STNodePropertyGrid : SKControl { #region properties ========== @@ -261,6 +263,7 @@ public bool ReadOnlyModel { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; /// /// 构造一个节点属性编辑器 @@ -325,35 +328,35 @@ private STNodeAttribute GetNodeAttribute(STNode node) { private void SetItemRectangle() { int nw_p = 0, nw_h = 0; - using (Graphics g = this.CreateGraphics()) { + using (var paint = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { foreach (var v in m_lst_item) { - SizeF szf = g.MeasureString(v.Name, this.Font); - if (szf.Width > nw_p) nw_p = (int)Math.Ceiling(szf.Width); + float w = paint.MeasureText(v.Name ?? string.Empty); + if (w > nw_p) nw_p = (int)Math.Ceiling(w); } for (int i = 0; i < m_KeysString.Length - 1; i++) { - SizeF szf = g.MeasureString(m_KeysString[i], this.Font); - if (szf.Width > nw_h) nw_h = (int)Math.Ceiling(szf.Width); + float w = paint.MeasureText(m_KeysString[i] ?? string.Empty); + if (w > nw_h) nw_h = (int)Math.Ceiling(w); } - nw_p += 5; nw_h += 5; - nw_p = Math.Min(nw_p, this.Width >> 1); - m_nInfoLeft = Math.Min(nw_h, this.Width >> 1); - - int nTitleHeight = this._ShowTitle ? m_nTitleHeight : 0; - for (int i = 0; i < m_lst_item.Count; i++) { - STNodePropertyDescriptor item = m_lst_item[i]; - Rectangle rect = new Rectangle(0, i * m_item_height + nTitleHeight, this.Width, m_item_height); - item.Rectangle = rect; - rect.Width = nw_p; - item.RectangleL = rect; - rect.X = rect.Right; - rect.Width = this.Width - rect.Left - 1; - rect.Inflate(-4, -4); - item.RectangleR = rect; - item.OnSetItemLocation(); - } - m_nPropertyVHeight = m_lst_item.Count * m_item_height; - if (this._ShowTitle) m_nPropertyVHeight += m_nTitleHeight; } + nw_p += 5; nw_h += 5; + nw_p = Math.Min(nw_p, this.Width >> 1); + m_nInfoLeft = Math.Min(nw_h, this.Width >> 1); + + int nTitleHeight = this._ShowTitle ? m_nTitleHeight : 0; + for (int i = 0; i < m_lst_item.Count; i++) { + STNodePropertyDescriptor item = m_lst_item[i]; + Rectangle rect = new Rectangle(0, i * m_item_height + nTitleHeight, this.Width, m_item_height); + item.Rectangle = rect; + rect.Width = nw_p; + item.RectangleL = rect; + rect.X = rect.Right; + rect.Width = this.Width - rect.Left - 1; + rect.Inflate(-4, -4); + item.RectangleR = rect; + item.OnSetItemLocation(); + } + m_nPropertyVHeight = m_lst_item.Count * m_item_height; + if (this._ShowTitle) m_nPropertyVHeight += m_nTitleHeight; } #endregion @@ -364,31 +367,19 @@ private void SetItemRectangle() { /// 当控件重绘时候发生 /// /// 事件参数 - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); - Graphics g = e.Graphics; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - m_dt.Graphics = g; - - m_nOffsetY = m_b_current_draw_info ? m_nInfoOffsetY : m_nPropertyOffsetY; - g.TranslateTransform(0, m_nOffsetY); - - if (m_b_current_draw_info) { - m_nVHeight = m_nInfoVHeight; + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + if (this._InfoFirstOnDraw) { this.OnDrawInfo(m_dt); } else { - m_nVHeight = m_nPropertyVHeight; - for (int i = 0; i < m_lst_item.Count; i++) { - this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); - } + for (int i = 0; i < m_lst_item.Count; i++) this.OnDrawPropertyItem(m_dt, m_lst_item[i], i); } - - g.ResetTransform(); - if (this._ShowTitle) this.OnDrawTitle(m_dt); - m_sf.FormatFlags = 0; if (!string.IsNullOrEmpty(m_str_err)) this.OnDrawErrorInfo(m_dt); if (!string.IsNullOrEmpty(m_str_desc)) this.OnDrawDescription(m_dt); + m_canvas = null; } /// /// 当鼠标在控件上移动时候发生 @@ -533,33 +524,29 @@ protected override void OnResize(EventArgs e) { /// 目标属性选项描述器 /// 选项所在索引 protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescriptor item, int nIndex) { - Graphics g = dt.Graphics; - m_brush.Color = (nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, item.Rectangle); - if (item == m_item_hover || item == m_item_selected) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, item.Rectangle); - } - if (m_item_selected == item) { - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height); - if (this._AutoColor && this._STNode != null) - m_brush.Color = this._STNode.TitleColor; - else - m_brush.Color = this._ItemSelectedColor; - g.FillRectangle(m_brush, item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor((nIndex % 2 == 0) ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + if (item == m_item_hover || item == m_item_selected) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(item.Rectangle.Left, item.Rectangle.Top, item.Rectangle.Width, item.Rectangle.Height, fill); + } + if (m_item_selected == item) { + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y, 5, item.Rectangle.Height, fill); + fill.Color = SkiaDrawingHelper.ToSKColor((this._AutoColor && this._STNode != null) ? this._STNode.TitleColor : this._ItemSelectedColor); + m_canvas.DrawRect(item.Rectangle.X, item.Rectangle.Y + 4, 5, item.Rectangle.Height - 8, fill); + } + var fm = text.FontMetrics; + float y = item.RectangleL.Top + (item.RectangleL.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = item.RectangleL.Right - text.MeasureText(item.Name ?? string.Empty) - 2; + m_canvas.DrawText(item.Name ?? string.Empty, x, y, text); } - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this.ForeColor; - g.DrawString(item.Name, this.Font, m_brush, item.RectangleL, m_sf); - item.OnDrawValueRectangle(m_dt); - if (this._ReadOnlyModel) { - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, item.RectangleR); - m_pen.Color = this.ForeColor; - //g.DrawLine(m_pen, - // item.RectangleR.Left - 2, item.RectangleR.Top + item.RectangleR.Height / 2, - // item.RectangleR.Right + 1, item.RectangleR.Top + item.RectangleR.Height / 2); + if (this._ReadOnlyModel && m_canvas != null) { + using (var overlay = new SKPaint { Color = new SKColor(125, 125, 125, 125), Style = SKPaintStyle.Fill, IsAntialias = true }) + m_canvas.DrawRect(item.RectangleR.Left, item.RectangleR.Top, item.RectangleR.Width, item.RectangleR.Height, overlay); } } /// @@ -567,159 +554,79 @@ protected virtual void OnDrawPropertyItem(DrawingTools dt, STNodePropertyDescrip /// /// 绘制工具 protected virtual void OnDrawTitle(DrawingTools dt) { - Graphics g = dt.Graphics; - if (this._AutoColor) - m_brush.Color = this._STNode == null ? this._TitleColor : this._STNode.TitleColor; - else - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, m_rect_title); - m_brush.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_sf.Alignment = StringAlignment.Center; - g.DrawString(this._STNode == null ? this.Text : this._STNode.Title, this.Font, m_brush, m_rect_title, m_sf); - - if (this._ReadOnlyModel) { - m_brush.Color = this.ForeColor; - g.FillRectangle(dt.SolidBrush, 4, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 6, 5, 2, 2); - g.FillRectangle(dt.SolidBrush, 8, 5, 2, 4); - g.FillRectangle(dt.SolidBrush, 3, 9, 8, 6); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true, Style = SKPaintStyle.Fill }) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? (this._STNode == null ? this._TitleColor : this._STNode.TitleColor) : this._TitleColor); + m_canvas.DrawRect(m_rect_title.Left, m_rect_title.Top, m_rect_title.Width, m_rect_title.Height, fill); + text.Color = SkiaDrawingHelper.ToSKColor(this._STNode == null ? this.ForeColor : this._STNode.ForeColor); + var t = this._STNode == null ? this.Text : this._STNode.Title; + var fm = text.FontMetrics; + float y = m_rect_title.Top + (m_rect_title.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + float x = m_rect_title.Left + (m_rect_title.Width - text.MeasureText(t ?? string.Empty)) / 2; + m_canvas.DrawText(t ?? string.Empty, x, y, text); } - //是否绘制面板切换按钮 - if (m_node_attribute == null || m_lst_item.Count == 0) return; - if (m_b_hover_switch) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, m_rect_switch); - } - m_pen.Color = this._STNode == null ? this.ForeColor : this._STNode.ForeColor; - m_brush.Color = m_pen.Color; - int nT1 = m_rect_switch.Top + m_rect_switch.Height / 2 - 2; - int nT2 = m_rect_switch.Top + m_rect_switch.Height / 2 + 1; - g.DrawRectangle(m_pen, m_rect_switch.Left, m_rect_switch.Top, m_rect_switch.Width - 1, m_rect_switch.Height - 1); - - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), new Point(m_rect_switch.Right - 3, nT1), - new Point(m_rect_switch.Left + 3, nT1 - 1), new Point(m_rect_switch.Right - 3, nT1 - 1) - }); - g.DrawLines(m_pen, new Point[]{ - new Point(m_rect_switch.Left + 2, nT2), new Point(m_rect_switch.Right - 3, nT2), - new Point(m_rect_switch.Left + 2, nT2 + 1), new Point(m_rect_switch.Right - 4, nT2 + 1), - }); - - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Left + 2, nT1), - new Point(m_rect_switch.Left + 7, nT1), - new Point(m_rect_switch.Left + 7, m_rect_switch.Top ), - }); - g.FillPolygon(m_brush, new Point[]{ - new Point(m_rect_switch.Right - 2, nT2), - new Point(m_rect_switch.Right - 7, nT2), - new Point(m_rect_switch.Right - 7, m_rect_switch.Bottom - 2 ), - }); } /// /// 当需要绘制属性描述信息时发生 /// /// 绘制工具 protected virtual void OnDrawDescription(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_desc)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_desc, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, this.Height - (int)szf.Height - 4, this.Width, (int)szf.Height + 4); - m_brush.Color = this._DescriptionColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._DescriptionColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_desc, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_desc) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._DescriptionColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_desc, ref bounds); + Rectangle rect_desc = new Rectangle(0, this.Height - (int)Math.Ceiling(bounds.Height) - 8, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_desc, rect_desc.Left + 4, y, text); + } } /// /// 当需要绘制错误信息时发生 /// /// 绘制工具 protected virtual void OnDrawErrorInfo(DrawingTools dt) { - if (string.IsNullOrEmpty(m_str_err)) return; - Graphics g = dt.Graphics; - SizeF szf = g.MeasureString(m_str_err, this.Font, this.Width - 4); - Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)szf.Height + 4); - m_brush.Color = this._ErrorColor; - g.FillRectangle(m_brush, rect_desc); - m_pen.Color = this._ErrorColor; - g.DrawRectangle(m_pen, 0, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1); - rect_desc.Inflate(-4, 0); - m_brush.Color = this.ForeColor; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_str_err, this.Font, m_brush, rect_desc, m_sf); + if (string.IsNullOrEmpty(m_str_err) || m_canvas == null) return; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._ErrorColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + var bounds = new SKRect(); + text.MeasureText(m_str_err, ref bounds); + Rectangle rect_desc = new Rectangle(0, 0, this.Width, (int)Math.Ceiling(bounds.Height) + 8); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width, rect_desc.Height, fill); + m_canvas.DrawRect(rect_desc.Left, rect_desc.Top, rect_desc.Width - 1, rect_desc.Height - 1, stroke); + var fm = text.FontMetrics; + float y = rect_desc.Top + (rect_desc.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(m_str_err, rect_desc.Left + 4, y, text); + } } /// /// 当绘制节点信息时候发生 /// /// 绘制工具 protected virtual void OnDrawInfo(DrawingTools dt) { - if (m_node_attribute == null) return; + if (m_node_attribute == null || m_canvas == null) return; var attr = m_node_attribute; - Graphics g = dt.Graphics; - Color clr_r = Color.FromArgb(this.ForeColor.A / 2, this.ForeColor); - m_sf.Alignment = StringAlignment.Near; - Rectangle rect = new Rectangle(0, this._ShowTitle ? m_nTitleHeight : 0, this.Width, m_item_height); - Rectangle rect_l = new Rectangle(2, rect.Top, m_nInfoLeft - 2, m_item_height); - Rectangle rect_r = new Rectangle(m_nInfoLeft, rect.Top, this.Width - m_nInfoLeft, m_item_height); - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - m_sf.Alignment = StringAlignment.Near; - g.DrawString(m_KeysString[0], this.Font, m_brush, rect_l, m_sf); //author - m_brush.Color = clr_r; - g.DrawString(attr.Author, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_1; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[1], this.Font, m_brush, rect_l, m_sf); //mail - m_brush.Color = clr_r; - g.DrawString(attr.Mail, this.Font, m_brush, rect_r, m_sf); - rect.Y += m_item_height; rect_l.Y += m_item_height; rect_r.Y += m_item_height; - - m_brush.Color = m_clr_item_2; - g.FillRectangle(m_brush, rect); - m_brush.Color = this.ForeColor; - g.DrawString(m_KeysString[2], this.Font, m_brush, rect_l, m_sf); //link_key - m_brush.Color = clr_r; - g.DrawString(attr.Link, this.Font, Brushes.CornflowerBlue, rect_r, m_sf); //link - if (!string.IsNullOrEmpty(attr.Link)) m_rect_link = rect_r; - //fill left - m_brush.Color = Color.FromArgb(40, 125, 125, 125); - g.FillRectangle(m_brush, 0, this._ShowTitle ? m_nTitleHeight : 0, m_nInfoLeft - 1, m_item_height * 3); - - rect.X = 5; rect.Y += m_item_height; - rect.Width = this.Width - 10; - if (!string.IsNullOrEmpty(m_node_attribute.Description)) { - float h = g.MeasureString(m_node_attribute.Description, this.Font, rect.Width).Height; - rect.Height = (int)Math.Ceiling(h / m_item_height) * m_item_height; - m_brush.Color = clr_r; - m_sf.FormatFlags = 0; - g.DrawString(m_node_attribute.Description, this.Font, m_brush, rect, m_sf); - } - m_nInfoVHeight = rect.Bottom; - bool bHasHelp = STNodeAttribute.GetHelpMethod(m_type) != null; - rect.X = 5; rect.Y += rect.Height; - rect.Height = m_item_height; - m_sf.Alignment = StringAlignment.Center; - m_brush.Color = Color.FromArgb(125, 125, 125, 125); - g.FillRectangle(m_brush, rect); - if (bHasHelp) m_brush.Color = Color.CornflowerBlue; - g.DrawString(m_KeysString[3], this.Font, m_brush, rect, m_sf); - if (bHasHelp) m_rect_help = rect; - else { - int w = (int)g.MeasureString(m_KeysString[3], this.Font).Width + 1; - int x = rect.X + (rect.Width - w) / 2, y = rect.Y + rect.Height / 2; - m_pen.Color = m_brush.Color; - g.DrawLine(m_pen, x, y, x + w, y); + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textDim = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(this.ForeColor.A / 2, this.ForeColor)), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) { + int top = this._ShowTitle ? m_nTitleHeight : 0; + int y = top; + void row(SKColor bg,string key,string val,SKPaint vp){ + fill.Color=bg; m_canvas.DrawRect(0,y,this.Width,m_item_height,fill); + var fm=text.FontMetrics; float ty=y+(m_item_height-(fm.Descent-fm.Ascent))/2-fm.Ascent; + m_canvas.DrawText(key,2,ty,text); m_canvas.DrawText(val??string.Empty,m_nInfoLeft,ty,vp); y+=m_item_height; + } + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[0],attr.Author,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_1),m_KeysString[1],attr.Mail,textDim); + row(SkiaDrawingHelper.ToSKColor(m_clr_item_2),m_KeysString[2],attr.Link,new SKPaint{Color=SKColors.CornflowerBlue,TextSize=text.TextSize,IsAntialias=true}); + m_nInfoVHeight = y + m_item_height; } - m_nInfoVHeight = rect.Bottom; } /// /// 当在属性面板鼠标点下时候发生 diff --git a/ST.Library.UI/NodeEditor/STNodeTreeView.cs b/ST.Library.UI/NodeEditor/STNodeTreeView.cs index 6b40ee3..28131ec 100644 --- a/ST.Library.UI/NodeEditor/STNodeTreeView.cs +++ b/ST.Library.UI/NodeEditor/STNodeTreeView.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.ComponentModel; using System.Collections; +using SkiaSharp; +using SkiaSharp.Views.Desktop; /* MIT License @@ -41,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ namespace ST.Library.UI.NodeEditor { - public class STNodeTreeView : Control + public class STNodeTreeView : SKControl { private Color _ItemBackColor = Color.FromArgb(255, 45, 45, 45); /// @@ -195,6 +197,7 @@ public STNodePropertyGrid PropertyGrid { private SolidBrush m_brush; private StringFormat m_sf; private DrawingTools m_dt; + private SKCanvas m_canvas; private Color m_clr_item_1 = Color.FromArgb(10, 0, 0, 0);// Color.FromArgb(255, 40, 40, 40); private Color m_clr_item_2 = Color.FromArgb(10, 255, 255, 255);// Color.FromArgb(255, 50, 50, 50); @@ -366,21 +369,22 @@ protected override void OnResize(EventArgs e) { m_rect_clear = new Rectangle(this.Width - 20, 9, 12, 12); } - protected override void OnPaint(PaintEventArgs e) { - base.OnPaint(e); + protected override void OnPaintSurface(SKPaintSurfaceEventArgs e) { + base.OnPaintSurface(e); m_nOffsetY = string.IsNullOrEmpty(m_str_search) ? m_nSourceOffsetY : m_nSearchOffsetY; - Graphics g = e.Graphics; - m_dt.Graphics = g; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - g.TranslateTransform(0, m_nOffsetY); + m_canvas = e.Surface.Canvas; + m_canvas.Clear(SkiaDrawingHelper.ToSKColor(this.BackColor)); + m_canvas.Save(); + m_canvas.Translate(0, m_nOffsetY); int nCounter = 0; foreach (STNodeTreeCollection v in m_items_draw) nCounter = this.OnStartDrawItem(m_dt, v, nCounter, 0); m_nVHeight = (nCounter + 1) * m_nItemHeight; foreach (STNodeTreeCollection v in m_items_draw) this.OnDrawSwitch(m_dt, v); - g.ResetTransform(); + m_canvas.Restore(); this.OnDrawSearch(m_dt); + m_canvas = null; } protected override void OnMouseMove(MouseEventArgs e) { @@ -478,24 +482,20 @@ protected override void OnMouseWheel(MouseEventArgs e) { /// /// 绘制工具 protected virtual void OnDrawSearch(DrawingTools dt) { - Graphics g = dt.Graphics; - m_brush.Color = this._TitleColor; - g.FillRectangle(m_brush, 0, 0, this.Width, m_nItemHeight); - m_brush.Color = m_tbx.BackColor; - g.FillRectangle(m_brush, 5, 5, this.Width - 10, m_nItemHeight - 10); - m_pen.Color = this.ForeColor; - if (string.IsNullOrEmpty(m_str_search)) { - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 17, 8, 8, 8); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; - g.DrawLine(m_pen, this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9); - } else { - m_pen.Color = this.ForeColor; - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; - g.DrawEllipse(m_pen, this.Width - 20, 9, 10, 10); - g.DrawLine(m_pen, this.Width - 18, 11, this.Width - 12, 17); - g.DrawLine(m_pen, this.Width - 12, 11, this.Width - 18, 17); - g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + if (m_canvas == null) return; + using (var title = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._TitleColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(m_tbx.BackColor), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this.ForeColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(0, 0, this.Width, m_nItemHeight, title); + m_canvas.DrawRect(5, 5, this.Width - 10, m_nItemHeight - 10, box); + if (string.IsNullOrEmpty(m_str_search)) { + m_canvas.DrawOval(new SKRect(this.Width - 17, 8, this.Width - 9, 16), stroke); + m_canvas.DrawLine(this.Width - 13, 17, this.Width - 13, m_nItemHeight - 9, stroke); + } else { + m_canvas.DrawOval(new SKRect(this.Width - 20, 9, this.Width - 10, 19), stroke); + m_canvas.DrawLine(this.Width - 18, 11, this.Width - 12, 17, stroke); + m_canvas.DrawLine(this.Width - 12, 11, this.Width - 18, 17, stroke); + } } } /// @@ -507,7 +507,6 @@ protected virtual void OnDrawSearch(DrawingTools dt) { /// 当前位于第几级子集合 /// 已经绘制个数 protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; Items.DisplayRectangle = new Rectangle(0, m_nItemHeight * (nCounter + 1), this.Width, m_nItemHeight); Items.SwitchRectangle = new Rectangle(5 + nLevel * 10, (nCounter + 1) * m_nItemHeight, 10, m_nItemHeight); if (this._ShowInfoButton && Items.STNodeType != null) @@ -534,23 +533,26 @@ protected virtual int OnStartDrawItem(DrawingTools dt, STNodeTreeCollection Item /// 已经绘制个数的计数器 /// 当前位于第几级子集合 protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, int nCounter, int nLevel) { - Graphics g = dt.Graphics; - m_brush.Color = nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2; - g.FillRectangle(m_brush, items.DisplayRectangle); - if (items == m_item_hover) { - m_brush.Color = this._ItemHoverColor; - g.FillRectangle(m_brush, items.DisplayRectangle); - } - Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); - m_pen.Color = Color.FromArgb(100, 125, 125, 125); - g.DrawLine(m_pen, 9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2); - if (nCounter != 0) { - for (int i = 0; i <= nLevel; i++) { - g.DrawLine(m_pen, 9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1); + if (m_canvas == null) return; + using (var fill = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var line = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + fill.Color = SkiaDrawingHelper.ToSKColor(nCounter % 2 == 0 ? m_clr_item_1 : m_clr_item_2); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); + if (items == m_item_hover) { + fill.Color = SkiaDrawingHelper.ToSKColor(this._ItemHoverColor); + m_canvas.DrawRect(items.DisplayRectangle.Left, items.DisplayRectangle.Top, items.DisplayRectangle.Width, items.DisplayRectangle.Height, fill); } + Rectangle rect = new Rectangle(45 + nLevel * 10, items.SwitchRectangle.Top, this.Width - 45 - nLevel * 10, m_nItemHeight); + line.Color = SkiaDrawingHelper.ToSKColor(Color.FromArgb(100, 125, 125, 125)); + m_canvas.DrawLine(9, items.SwitchRectangle.Top + m_nItemHeight / 2, items.SwitchRectangle.Left + 19, items.SwitchRectangle.Top + m_nItemHeight / 2, line); + if (nCounter != 0) { + for (int i = 0; i <= nLevel; i++) { + m_canvas.DrawLine(9 + i * 10, items.SwitchRectangle.Top - m_nItemHeight / 2, 9 + i * 10, items.SwitchRectangle.Top + m_nItemHeight / 2 - 1, line); + } + } + this.OnDrawItemText(dt, items, rect); + this.OnDrawItemIcon(dt, items, rect); } - this.OnDrawItemText(dt, items, rect); - this.OnDrawItemIcon(dt, items, rect); } /// /// 当绘制树节点展开与关闭开关时候发生 @@ -558,15 +560,15 @@ protected virtual void OnDrawItem(DrawingTools dt, STNodeTreeCollection items, i /// 绘制工具 /// 当前需要绘制的集合 protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.Count != 0) { - m_pen.Color = this._SwitchColor; - m_brush.Color = m_pen.Color; - int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; - g.DrawRectangle(m_pen, items.SwitchRectangle.Left, nT, 8, 8); - g.DrawLine(m_pen, items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4); - if (items.IsOpen) return; - g.DrawLine(m_pen, items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._SwitchColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + int nT = items.SwitchRectangle.Y + m_nItemHeight / 2 - 4; + m_canvas.DrawRect(items.SwitchRectangle.Left, nT, 8, 8, stroke); + m_canvas.DrawLine(items.SwitchRectangle.Left + 1, nT + 4, items.SwitchRectangle.Right - 3, nT + 4, stroke); + if (items.IsOpen) return; + m_canvas.DrawLine(items.SwitchRectangle.Left + 4, nT + 1, items.SwitchRectangle.Left + 4, nT + 7, stroke); + } //if (items.IsOpen) { // //g.FillPolygon(m_brush, new Point[]{ // // new Point(items.DotRectangle.Left + 0, items.DotRectangle.Top + m_nItemHeight / 2 - 2), @@ -594,28 +596,30 @@ protected virtual void OnDrawSwitch(DrawingTools dt, STNodeTreeCollection items) /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; rect.Width -= 20; - m_sf.FormatFlags = StringFormatFlags.NoWrap; - if (!string.IsNullOrEmpty(m_str_search)) { - int nIndex = items.NameLower.IndexOf(m_str_search); - if (nIndex != -1) { - CharacterRange[] chrs = { new CharacterRange(nIndex, m_str_search.Length) };//global - m_sf.SetMeasurableCharacterRanges(chrs); - Region[] regions = g.MeasureCharacterRanges(items.Name, this.Font, rect, m_sf); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Intersect); - m_brush.Color = this._HightLightTextColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - g.SetClip(regions[0], System.Drawing.Drawing2D.CombineMode.Exclude); - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 1 / 2, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); - g.ResetClip(); - return; + using (var textNormal = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var textHi = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._HightLightTextColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + var fm = textNormal.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + string name = items.Name ?? string.Empty; + if (!string.IsNullOrEmpty(m_str_search)) { + int idx = items.NameLower.IndexOf(m_str_search); + if (idx >= 0) { + string pre = name.Substring(0, idx); + string hit = name.Substring(idx, Math.Min(m_str_search.Length, name.Length - idx)); + string suf = name.Substring(idx + hit.Length); + float x = rect.Left; + m_canvas.DrawText(pre, x, y, textNormal); + x += textNormal.MeasureText(pre); + m_canvas.DrawText(hit, x, y, textHi); + x += textHi.MeasureText(hit); + m_canvas.DrawText(suf, x, y, textNormal); + return; + } } + m_canvas.DrawText(name, rect.Left, y, textNormal); } - m_brush.Color = items.STNodeType == null ? Color.FromArgb(this.ForeColor.A * 2 / 3, this.ForeColor) : this.ForeColor; - g.DrawString(items.Name, this.Font, m_brush, rect, m_sf); } /// /// 当绘制树节点图标时候发生 @@ -624,43 +628,52 @@ protected virtual void OnDrawItemText(DrawingTools dt, STNodeTreeCollection item /// 当前需要绘制的集合 /// 文本域所在矩形区域 protected virtual void OnDrawItemIcon(DrawingTools dt, STNodeTreeCollection items, Rectangle rect) { - Graphics g = dt.Graphics; + if (m_canvas == null) return; if (items.STNodeType != null) { - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan; - m_brush.Color = Color.LightGray; - g.DrawRectangle(m_pen, rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.FillRectangle(m_brush, rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - g.FillRectangle(m_brush, rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5); - if (m_item_hover == items && m_bHoverInfo) { - m_brush.Color = this.BackColor; - g.FillRectangle(m_brush, items.InfoRectangle); + using (var stroke = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : Color.DarkCyan), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) + using (var fill = new SKPaint { Color = SKColors.LightGray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + m_canvas.DrawRect(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10, stroke); + m_canvas.DrawRect(rect.Left - 17, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + m_canvas.DrawRect(rect.Left - 6, rect.Top + m_nItemHeight / 2 - 2, 5, 5, fill); + if (m_item_hover == items && m_bHoverInfo) { + fill.Color = SkiaDrawingHelper.ToSKColor(this.BackColor); + m_canvas.DrawRect(items.InfoRectangle.Left, items.InfoRectangle.Top, items.InfoRectangle.Width, items.InfoRectangle.Height, fill); + } + } + using (var info = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true }) { + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6, info); + m_canvas.DrawLine(items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11, info); + m_canvas.DrawLine(items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10, info); + } + using (var box = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor), Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + m_canvas.DrawRect(items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1, box); } - m_pen.Color = this._AutoColor ? items.STNodeTypeColor : this._InfoButtonColor; - m_pen.Width = 2; - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 3, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 3); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 6, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 6); - g.DrawLine(m_pen, items.InfoRectangle.X + 4, items.InfoRectangle.Y + 11, items.InfoRectangle.X + 10, items.InfoRectangle.Y + 11); - g.DrawLine(m_pen, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 7, items.InfoRectangle.X + 7, items.InfoRectangle.Y + 10); - m_pen.Width = 1; - g.DrawRectangle(m_pen, items.InfoRectangle.X, items.InfoRectangle.Y, items.InfoRectangle.Width - 1, items.InfoRectangle.Height - 1); } else { - if (items.IsLibraryRoot) { - Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); - g.DrawRectangle(Pens.Gray, rect_box); - g.DrawLine(Pens.Cyan, rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top); - g.DrawLine(Pens.Cyan, rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2); - g.DrawLine(Pens.Cyan, rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom); - g.DrawLine(Pens.Cyan, rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2); - } else { - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3)); - g.DrawRectangle(Pens.Goldenrod, new Rectangle(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9)); + using (var stroke = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { + if (items.IsLibraryRoot) { + Rectangle rect_box = new Rectangle(rect.Left - 15, rect.Top + m_nItemHeight / 2 - 5, 11, 10); + stroke.Color = SKColors.Gray; + m_canvas.DrawRect(rect_box.Left, rect_box.Top, rect_box.Width, rect_box.Height, stroke); + stroke.Color = SKColors.Cyan; + m_canvas.DrawLine(rect_box.X - 2, rect_box.Top, rect_box.X + 2, rect_box.Top, stroke); + m_canvas.DrawLine(rect_box.X, rect_box.Y - 2, rect_box.X, rect_box.Y + 2, stroke); + m_canvas.DrawLine(rect_box.Right - 2, rect_box.Bottom, rect_box.Right + 2, rect_box.Bottom, stroke); + m_canvas.DrawLine(rect_box.Right, rect_box.Bottom - 2, rect_box.Right, rect_box.Bottom + 2, stroke); + } else { + stroke.Color = SKColors.Goldenrod; + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 6, 8, 3, stroke); + m_canvas.DrawRect(rect.Left - 16, rect.Top + m_nItemHeight / 2 - 3, 13, 9, stroke); + } } if (!this._ShowFolderCount) return; - m_sf.Alignment = StringAlignment.Far; - m_brush.Color = this._FolderCountColor; - rect.X -= 4; - g.DrawString("[" + items.STNodeCount.ToString() + "]", this.Font, m_brush, rect, m_sf); - m_sf.Alignment = StringAlignment.Near; + using (var text = new SKPaint { Color = SkiaDrawingHelper.ToSKColor(this._FolderCountColor), TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + string t = "[" + items.STNodeCount.ToString() + "]"; + float w = text.MeasureText(t); + var fm = text.FontMetrics; + float y = rect.Top + (rect.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; + m_canvas.DrawText(t, rect.Right - w - 4, y, text); + } } } diff --git a/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs new file mode 100644 index 0000000..f5c53d5 --- /dev/null +++ b/ST.Library.UI/NodeEditor/SkiaDrawingHelper.cs @@ -0,0 +1,29 @@ +using System; +using System.Drawing; +using SkiaSharp; + +namespace ST.Library.UI.NodeEditor { + public static class SkiaDrawingHelper { + public static SKColor ToSKColor(Color color) { + return new SKColor(color.R, color.G, color.B, color.A); + } + + public static SKRect ToSKRect(Rectangle rect) { + return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom); + } + + public static SKBitmap ToSKBitmap(Image image) { + if (image == null) return null; + using (var ms = new System.IO.MemoryStream()) { + image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Position = 0; + return SKBitmap.Decode(ms); + } + } + + public static void RenderToCanvas(SKCanvas canvas, Action renderAction) { + if (canvas == null || renderAction == null) return; + renderAction(canvas); + } + } +} diff --git a/ST.Library.UI/ST.Library.UI.csproj b/ST.Library.UI/ST.Library.UI.csproj index 0e038f3..fb6bb9b 100644 --- a/ST.Library.UI/ST.Library.UI.csproj +++ b/ST.Library.UI/ST.Library.UI.csproj @@ -1,90 +1,15 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EFFCC270-4999-4077-A543-56CCCCE92147} - Library - Properties - ST.Library.UI - ST.Library.UI - v4.8 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\ST.Library.UI.XML - true - false - - - - - - - - - - - - - Form - - - Form - - - Component - - - Component - - - - Form - - - - - - - - Component - - - - - - - - Component - - - - - \ No newline at end of file + + + net10.0-windows + true + disable + disable + false + preview + + + + + + + diff --git a/WinNodeEditorDemo/AttrTestNode.cs b/WinNodeEditorDemo/AttrTestNode.cs index b9c7fd2..8613c14 100644 --- a/WinNodeEditorDemo/AttrTestNode.cs +++ b/WinNodeEditorDemo/AttrTestNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Windows.Forms; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..363cf03 100644 --- a/WinNodeEditorDemo/Blender/FrmEnumSelect.cs +++ b/WinNodeEditorDemo/Blender/FrmEnumSelect.cs @@ -1,26 +1,17 @@ -using System; +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; - using System.Drawing; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender { - /// - /// 此类仅演示 作为MixRGB节点的下拉选择框弹出菜单 - /// public class FrmEnumSelect : Form { private Point m_pt; private int m_nWidth; private float m_scale; private List m_lst = new List(); - private StringFormat m_sf; - public Enum Enum { get; set; } - private bool m_bClosed; public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { @@ -31,12 +22,9 @@ public FrmEnumSelect(Enum e, Point pt, int nWidth, float scale) { m_pt = pt; m_scale = scale; m_nWidth = nWidth; - m_sf = new StringFormat(); - m_sf.LineAlignment = StringAlignment.Center; - this.ShowInTaskbar = false; this.BackColor = Color.FromArgb(255, 34, 34, 34); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.FormBorderStyle = FormBorderStyle.None; } protected override void OnLoad(EventArgs e) { @@ -48,27 +36,19 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } } protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); int nIndex = e.Y / (int)(20 * m_scale); if (nIndex >= 0 && nIndex < m_lst.Count) this.Enum = (Enum)m_lst[nIndex]; - this.DialogResult = System.Windows.Forms.DialogResult.OK; + this.DialogResult = DialogResult.OK; m_bClosed = true; } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); if (m_bClosed) return; - //this.DialogResult = System.Windows.Forms.DialogResult.None; this.Close(); } } diff --git a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs index db3bfeb..fdda2e7 100644 --- a/WinNodeEditorDemo/Blender/STNodeCheckBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeCheckBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -35,14 +36,17 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { } protected override void OnPaint(DrawingTools dt) { - //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { + using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 5, 10, 10, gray); + var metrics = textPaint.FontMetrics; + float textY = (20 - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 15, textY, textPaint); + if (this.Checked) canvas.DrawRect(2, 7, 6, 6, black); + } + }); } } } diff --git a/WinNodeEditorDemo/Blender/STNodeProgress.cs b/WinNodeEditorDemo/Blender/STNodeProgress.cs index 5fa5587..5d84a1e 100644 --- a/WinNodeEditorDemo/Blender/STNodeProgress.cs +++ b/WinNodeEditorDemo/Blender/STNodeProgress.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; +using SkiaSharp; using System.Drawing; namespace WinNodeEditorDemo.Blender @@ -32,14 +33,21 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); - + float progress = (float)this._Value / 100; + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { + using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + canvas.DrawRect(0, 0, this.Width * progress, this.Height, fg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Text ?? string.Empty, 2, y, text); + var pct = progress.ToString("F2"); + float tw = text.MeasureText(pct); + canvas.DrawText(pct, this.Width - tw - 2, y, text); + } + }); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { diff --git a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs index 9b36e87..8b48743 100644 --- a/WinNodeEditorDemo/Blender/STNodeSelectBox.cs +++ b/WinNodeEditorDemo/Blender/STNodeSelectBox.cs @@ -5,6 +5,7 @@ using System.Drawing; using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -28,15 +29,22 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { + using (var bg = new SKPaint { Color = new SKColor(0, 0, 0, 80), Style = SKPaintStyle.Fill, IsAntialias = true }) + using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) + using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { + canvas.DrawRect(0, 0, this.Width, this.Height, bg); + var metrics = text.FontMetrics; + float y = (this.Height - (metrics.Descent - metrics.Ascent)) / 2 - metrics.Ascent; + canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(), 2, y, text); + using (var path = new SKPath()) { + path.MoveTo(this.Width - 25, 7); + path.LineTo(this.Width - 15, 7); + path.LineTo(this.Width - 20, 12); + path.Close(); + canvas.DrawPath(path, arrow); + } + } }); } diff --git a/WinNodeEditorDemo/CalcNode.cs b/WinNodeEditorDemo/CalcNode.cs index 01fe541..90c6377 100644 --- a/WinNodeEditorDemo/CalcNode.cs +++ b/WinNodeEditorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToCanvas(e.DrawingTools.Canvas, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToCanvas(e.DrawingTools.Canvas, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..13ed67a 100644 --- a/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageChannelNode.cs @@ -6,6 +6,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; using System.Drawing.Imaging; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs index be7fb01..2a8a441 100644 --- a/WinNodeEditorDemo/ImageNode/ImageInputNode.cs +++ b/WinNodeEditorDemo/ImageNode/ImageInputNode.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Windows.Forms; using System.Reflection; +using SkiaSharp; namespace WinNodeEditorDemo.ImageNode { @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs index 188be18..9023def 100644 --- a/WinNodeEditorDemo/NumberNode/NumberAddNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs index 335babe..23a9f9d 100644 --- a/WinNodeEditorDemo/NumberNode/NumberInputNode.cs +++ b/WinNodeEditorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WinNodeEditorDemo/ToolStripRendererEx.cs b/WinNodeEditorDemo/ToolStripRendererEx.cs index 64943d8..0a76663 100644 --- a/WinNodeEditorDemo/ToolStripRendererEx.cs +++ b/WinNodeEditorDemo/ToolStripRendererEx.cs @@ -4,6 +4,8 @@ using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; +using ST.Library.UI.NodeEditor; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -23,27 +25,15 @@ protected override void InitializeItem(ToolStripItem item) { } protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { - using (SolidBrush sb = new SolidBrush(Color.FromArgb(34, 34, 34))) { - e.Graphics.FillRectangle(sb, e.AffectedBounds); - } base.OnRenderToolStripBackground(e); } protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { - e.Graphics.DrawRectangle(Pens.Black, e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1); base.OnRenderToolStripBorder(e); } - //protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) { - // using (SolidBrush sb = new SolidBrush(Color.FromArgb(50, 50, 50))) { - // e.Graphics.FillRectangle(sb, e.AffectedBounds); - // } - // base.OnRenderImageMargin(e); - //} - protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) { e.TextColor = e.Item.Selected ? Color.White : Color.LightGray; - e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; e.TextRectangle = new Rectangle(e.TextRectangle.Left, e.TextRectangle.Top, e.TextRectangle.Width, 30); base.OnRenderItemText(e); } @@ -54,27 +44,12 @@ protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e) { } protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { - Point ptEnd = new Point(e.Item.ContentRectangle.X + e.Item.Width / 2, e.Item.ContentRectangle.Y); - using (LinearGradientBrush lgb = new LinearGradientBrush(e.Item.ContentRectangle.Location, ptEnd, Color.Transparent, Color.Gray)) { - lgb.WrapMode = WrapMode.TileFlipX; - using (Pen p = new Pen(lgb)) { - e.Graphics.DrawLine(p, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); - } - } - //e.Graphics.DrawLine(Pens.Gray, e.Item.ContentRectangle.Location, new Point(e.Item.ContentRectangle.Right, ptEnd.Y)); base.OnRenderSeparator(e); } protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { - if (e.Item.Selected) - e.Graphics.FillRectangle(m_brush, e.Item.ContentRectangle); - else - base.OnRenderMenuItemBackground(e); + base.OnRenderMenuItemBackground(e); } - //protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e) { - // //base.OnRenderItemImage(e); - // e.Graphics.DrawImage(e.Image, e.ImageRectangle.X, e.ImageRectangle.Y, 17, 17); - //} } } diff --git a/WinNodeEditorDemo/WinNodeEditorDemo.csproj b/WinNodeEditorDemo/WinNodeEditorDemo.csproj index 69ea974..cd5bb2c 100644 --- a/WinNodeEditorDemo/WinNodeEditorDemo.csproj +++ b/WinNodeEditorDemo/WinNodeEditorDemo.csproj @@ -1,116 +1,16 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {4E1829B5-2160-48F5-ABD6-11914A6A25DD} WinExe - Properties - WinNodeEditorDemo - WinNodeEditorDemo - v4.8 - 512 - + net10.0-windows + true + disable + disable + false + preview - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - Form - - - - - - - - Form - - - Form1.cs - - - - - - - - - - - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + - - {EFFCC270-4999-4077-A543-56CCCCE92147} - ST.Library.UI - + + - - - - \ No newline at end of file + diff --git a/WpfNodeEdittorDemo/AttrTestNode.cs b/WpfNodeEdittorDemo/AttrTestNode.cs index b9c7fd2..b9b9737 100644 --- a/WpfNodeEdittorDemo/AttrTestNode.cs +++ b/WpfNodeEdittorDemo/AttrTestNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo @@ -87,9 +88,8 @@ protected override object GetValueFromString(string strText) { //绘制属性窗口值区域时候调用 protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt);//先采用默认的绘制 并再绘制颜色预览 - dt.SolidBrush.Color = (Color)this.GetValue(null); - dt.Graphics.FillRectangle(dt.SolidBrush, m_rect);//填充颜色 - dt.Graphics.DrawRectangle(Pens.Black, m_rect); //绘制边框 + var color = SkiaDrawingHelper.ToSKColor((Color)this.GetValue(null)); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var fill = new SKPaint { Color = color, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var stroke = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true }) { canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, fill); canvas.DrawRect(m_rect.Left, m_rect.Top, m_rect.Width, m_rect.Height, stroke);} }); } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs index 3c8e87f..87a4ac9 100644 --- a/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs +++ b/WpfNodeEdittorDemo/Blender/FrmEnumSelect.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; namespace WinNodeEditorDemo.Blender @@ -48,13 +49,6 @@ protected override void OnLoad(EventArgs e) { protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); - Graphics g = e.Graphics; - g.ScaleTransform(m_scale, m_scale); - Rectangle rect = new Rectangle(0, 0, this.Width, 20); - foreach (var v in m_lst) { - g.DrawString(v.ToString(), this.Font, Brushes.White, rect, m_sf); - rect.Y += rect.Height; - } } protected override void OnMouseClick(MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs index db3bfeb..c7bf278 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeCheckBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -36,13 +37,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnPaint(DrawingTools dt) { //base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, 0, 5, 10, 10); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.LightGray, new Rectangle(15, 0, this.Width - 20, 20), m_sf); - if (this.Checked) { - g.FillRectangle(Brushes.Black, 2, 7, 6, 6); - } + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var gray = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var black = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var textPaint = new SKPaint { Color = SKColors.LightGray, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,5,10,10,gray); var fm=textPaint.FontMetrics; float y=(20-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,15,y,textPaint); if(this.Checked) canvas.DrawRect(2,7,6,6,black);} }); } } } diff --git a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs index 5fa5587..fa917ff 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeProgress.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeProgress.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.Blender { @@ -32,13 +33,7 @@ protected virtual void OnValueChanged(EventArgs e) { protected override void OnPaint(DrawingTools dt) { base.OnPaint(dt); - Graphics g = dt.Graphics; - g.FillRectangle(Brushes.Gray, this.ClientRectangle); - g.FillRectangle(Brushes.CornflowerBlue, 0, 0, (int)((float)this._Value / 100 * this.Width), this.Height); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Text, this.Font, Brushes.White, this.ClientRectangle, m_sf); - m_sf.Alignment = StringAlignment.Far; - g.DrawString(((float)this._Value / 100).ToString("F2"), this.Font, Brushes.White, this.ClientRectangle, m_sf); + float progress=(float)this._Value/100; SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var fg = new SKPaint { Color = SKColors.CornflowerBlue, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); canvas.DrawRect(0,0,this.Width*progress,this.Height,fg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Text ?? string.Empty,2,y,text); var pct=progress.ToString("F2"); canvas.DrawText(pct,this.Width-text.MeasureText(pct)-2,y,text);} }); } diff --git a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs index 9b36e87..5111567 100644 --- a/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs +++ b/WpfNodeEdittorDemo/Blender/STNodeSelectBox.cs @@ -4,6 +4,7 @@ using System.Text; using System.Drawing; +using SkiaSharp; using ST.Library.UI.NodeEditor; namespace WinNodeEditorDemo.Blender @@ -28,16 +29,7 @@ protected virtual void OnValueChanged(EventArgs e) { } protected override void OnPaint(DrawingTools dt) { - Graphics g = dt.Graphics; - dt.SolidBrush.Color = Color.FromArgb(80, 0, 0, 0); - g.FillRectangle(dt.SolidBrush, this.ClientRectangle); - m_sf.Alignment = StringAlignment.Near; - g.DrawString(this.Enum.ToString(), this.Font, Brushes.White, this.ClientRectangle, m_sf); - g.FillPolygon(Brushes.Gray, new Point[]{ - new Point(this.Right - 25, 7), - new Point(this.Right - 15, 7), - new Point(this.Right - 20, 12) - }); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var bg = new SKPaint { Color = new SKColor(0,0,0,80), Style = SKPaintStyle.Fill, IsAntialias = true }) using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) using (var arrow = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(0,0,this.Width,this.Height,bg); var fm=text.FontMetrics; float y=(this.Height-(fm.Descent-fm.Ascent))/2-fm.Ascent; canvas.DrawText(this.Enum == null ? string.Empty : this.Enum.ToString(),2,y,text); using (var path = new SKPath()) { path.MoveTo(this.Width-25,7); path.LineTo(this.Width-15,7); path.LineTo(this.Width-20,12); path.Close(); canvas.DrawPath(path,arrow);} } }); } protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { diff --git a/WpfNodeEdittorDemo/CalcNode.cs b/WpfNodeEdittorDemo/CalcNode.cs index 01fe541..90c6377 100644 --- a/WpfNodeEdittorDemo/CalcNode.cs +++ b/WpfNodeEdittorDemo/CalcNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo { @@ -33,8 +34,7 @@ protected override void OnCreate() { ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Far; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("0", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToCanvas(e.DrawingTools.Canvas, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("0"); canvas.DrawText("0", c.Width - w - 2, y, text); } }); }; string[] strs = { //按钮文本 @@ -58,8 +58,7 @@ protected override void OnCreate() { if (i == 8) ctrl.Paint += (s, e) => { m_sf.Alignment = StringAlignment.Center; STNodeControl c = s as STNodeControl; - Graphics g = e.DrawingTools.Graphics; - g.DrawString("_", ctrl.Font, Brushes.White, c.ClientRectangle, m_sf); + SkiaDrawingHelper.RenderToCanvas(e.DrawingTools.Canvas, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, ctrl.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = (c.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float w = text.MeasureText("_"); canvas.DrawText("_", (c.Width - w) / 2, y, text); } }); }; ctrl.MouseClick += (s, e) => System.Windows.Forms.MessageBox.Show(((STNodeControl)s).Text); } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs index 15fbbea..97caf8e 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageChannelNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Drawing.Imaging; namespace WinNodeEditorDemo.ImageNode @@ -78,10 +79,8 @@ void m_op_img_in_DataTransfer(object sender, STNodeOptionEventArgs e) { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 120, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } } diff --git a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs index be7fb01..f75edaf 100644 --- a/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs +++ b/WpfNodeEdittorDemo/ImageNode/ImageInputNode.cs @@ -4,6 +4,7 @@ using System.Text; using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; using System.Windows.Forms; using System.Reflection; @@ -37,10 +38,8 @@ protected override void OnCreate() { protected override void OnDrawBody(DrawingTools dt) { base.OnDrawBody(dt); - Graphics g = dt.Graphics; Rectangle rect = new Rectangle(this.Left + 10, this.Top + 30, 140, 80); - g.FillRectangle(Brushes.Gray, rect); - if (m_img_draw != null) g.DrawImage(m_img_draw, rect); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) { canvas.DrawRect(rect.Left, rect.Top, rect.Width, rect.Height, bg); if (m_img_draw != null) { using (var bmp = SkiaDrawingHelper.ToSKBitmap(m_img_draw)) { if (bmp != null) canvas.DrawBitmap(bmp, new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom)); } } } }); } } /// @@ -77,8 +76,7 @@ protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { protected override void OnDrawValueRectangle(DrawingTools dt) { base.OnDrawValueRectangle(dt); //在STNodePropertyGrid绘制此属性区域时候将"打开"按钮绘制上去 - dt.Graphics.FillRectangle(Brushes.Gray, m_rect_open); - dt.Graphics.DrawString("+", this.Control.Font, Brushes.White, m_rect_open, m_sf); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var bg = new SKPaint { Color = SKColors.Gray, Style = SKPaintStyle.Fill, IsAntialias = true }) using (var tx = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Control.Font.Size), IsAntialias = true }) { canvas.DrawRect(m_rect_open.Left, m_rect_open.Top, m_rect_open.Width, m_rect_open.Height, bg); var fm = tx.FontMetrics; float y = m_rect_open.Top + (m_rect_open.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_rect_open.Left + (m_rect_open.Width - tx.MeasureText("+")) / 2; canvas.DrawText("+", x, y, tx);} }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs index 188be18..9023def 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberAddNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -67,7 +68,7 @@ protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { m_sf.Alignment = StringAlignment.Far; strText = (m_nNum1 + m_nNum2).ToString(); } - dt.Graphics.DrawString(strText, this.Font, Brushes.White, op.TextRectangle, m_sf); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = m_sf.Alignment == StringAlignment.Far ? op.TextRectangle.Right - text.MeasureText(strText) - 2 : op.TextRectangle.Left + 2; canvas.DrawText(strText, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs index 335babe..23a9f9d 100644 --- a/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs +++ b/WpfNodeEdittorDemo/NumberNode/NumberInputNode.cs @@ -5,6 +5,7 @@ using ST.Library.UI.NodeEditor; using System.Drawing; +using SkiaSharp; namespace WinNodeEditorDemo.NumberNode { @@ -46,7 +47,8 @@ protected override void OnCreate() { /// 需要绘制的选项 protected override void OnDrawOptionText(DrawingTools dt, STNodeOption op) { base.OnDrawOptionText(dt, op); - dt.Graphics.DrawString(this._Number.ToString(), this.Font, Brushes.White, op.TextRectangle, m_sf); + var txt = this._Number.ToString(); + SkiaDrawingHelper.RenderToCanvas(dt.Canvas, canvas => { using (var text = new SKPaint { Color = SKColors.White, TextSize = Math.Max(10f, this.Font.Size), IsAntialias = true }) { var fm = text.FontMetrics; float y = op.TextRectangle.Top + (op.TextRectangle.Height - (fm.Descent - fm.Ascent)) / 2 - fm.Ascent; float x = op.TextRectangle.Right - text.MeasureText(txt) - 2; canvas.DrawText(txt, x, y, text); } }); } } } diff --git a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj index bddd856..39c7fa8 100644 --- a/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj +++ b/WpfNodeEdittorDemo/WpfNodeEdittorDemo.csproj @@ -11,6 +11,7 @@ +