Проблема :
При обрезке области текущей графики ( Graphics.SetClip метод) результирующий чертеж теряет качество, поскольку эффект сглаживания, генерируемый Graphics.SmoothingMode = SmoothingMode.AntiAlias
, теряется.
Возможное решение состоит в том, чтобы избежать ограничения области, определенной GraphicsPath
, используемой для проектирования дуг (метод GraphicsPath.AddPie ); это, однако, оставляет линии пирога видимыми, ставя под угрозу форму.
Другое решение - нарисовать многоточие в центре дуг, используя фоновый цвет холста. Поскольку дуги нарисованы с использованием двух прямоугольников, мы можем использовать внутренний прямоугольник, раздувая его (метод Rectangle.Inflate ) по мере необходимости (часть - Pen.Width / 2
- размера пера, используемого для контура, обычно ).
Это позволяет удалить артефакты, сгенерированные формами GraphicsPath
, и нарисовать некоторый другой графический контент в центре фигур.
Например, используя разные кисти:
LinearGradientBrush HatchBrush TextureBrush
Конечно, есть и другие методы для достижения того же результата. Мы могли бы нарисовать дуги, используя метод GraphicsPath.AddArc , извлечь или рассчитать первую и последнюю точки дуг и использовать их для рисования двух линий ( GraphicsPath.AddLine ), которые закроются фигуры.
Но, поскольку мы хотим рисовать различные графические объекты в центре дуг, эти объекты в любом случае будут покрывать центральную область.
Как использовать этот код :
- В форме добавьте TrackBar (здесь он называется
tbarSpeed
)
- Добавьте панель (называемую
Canvas
), с размером (200, 200)
. Используйте предоставленный здесь элемент управления Custom Panel, который добавляет немного ControlStyles
в свой конструктор. Это позволит избежать мерцания и артефактов
- Подключите трекбар
tbarSpeed_Scroll
и событие Panel 1066 *Canvas_Paint
.
using System.Drawing;
using System.Drawing.Drawing2D;
float GaugeValue = 88.0f;
float GaugeSweepAngle = 270.0f;
float GaugeStartAngle = 135.0F;
private void Canvas_Paint(object sender, PaintEventArgs e)
{
Control canvas = sender as Control;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle outerRectangle = new Rectangle(10, 10, 180, 180);
Rectangle innerRectangle = new Rectangle(30, 30, 140, 140);
Rectangle blendRectangle = new Rectangle(10, 10, 180, 160);
PointF innerCenter = new PointF(outerRectangle.Left + (outerRectangle.Width / 2),
outerRectangle.Top + (outerRectangle.Height / 2));
float gaugeLength = (outerRectangle.Width / 2) - 2;
using (GraphicsPath path = new GraphicsPath())
{
path.AddPie(outerRectangle, GaugeStartAngle, GaugeSweepAngle);
path.AddPie(innerRectangle, GaugeStartAngle, GaugeSweepAngle);
innerRectangle.Inflate(-1, -1);
using (Pen pen = new Pen(Color.White, 3f))
using (SolidBrush backgroundbrush = new SolidBrush(canvas.BackColor))
using (LinearGradientBrush gradientBrush = new LinearGradientBrush(blendRectangle,
Color.Green, Color.Red, LinearGradientMode.ForwardDiagonal))
{
Blend blend = new Blend()
{
Factors = new[] { 0.0f, 0.0f, 0.1f, 0.3f, 0.7f, 1.0f },
Positions = new[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f }
};
gradientBrush.Blend = blend;
e.Graphics.FillPath(gradientBrush, path);
e.Graphics.DrawPath(pen, path);
e.Graphics.FillEllipse(backgroundbrush, innerRectangle);
using (StringFormat format = new StringFormat())
{
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
innerRectangle.Location = new Point(innerRectangle.X, innerRectangle.Y + canvas.Font.Height);
e.Graphics.DrawString(GaugeValue.ToString() + "%", canvas.Font, Brushes.White, innerRectangle, format);
}
using (Matrix matrix = new Matrix())
{
matrix.RotateAt(GaugeStartAngle + 90 + (GaugeValue * (GaugeSweepAngle / 100)), innerCenter);
e.Graphics.Transform = matrix;
e.Graphics.DrawLine(pen, innerCenter, new PointF(innerCenter.X, innerCenter.Y - gaugeLength));
e.Graphics.ResetTransform();
}
}
}
}
private void tbarSpeed_Scroll(object sender, EventArgs e)
{
GaugeValue = tbarSpeed.Value;
Canvas.Invalidate();
}
Настраиваемая панель управления :
using System.ComponentModel;
using System.Windows.Forms;
[DesignerCategory("code")]
public class DrawingPanel : Panel
{
public DrawingPanel()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer, true);
this.UpdateStyles();
}
}
Пример кода на PasteBin