在.NET开发领域,用户界面的直观性和功能性是至关重要的。本文将介绍一个.NET用户控件,它是一个图形滑尺,用于线性地表示数据。这个控件由一个静态指针(类似于指针)和一个可移动的线性刻度组成。静态指针指向移动刻度的当前位置,并通过刻度上的图形位置显示输入值。滑尺是无限的,可以在某一时刻表示一个无限大的值(类型为double)。
在CodeProject上,已经有许多非常有用且外观精美的仪器可供使用。想再添加一个到这个链条中。这个项目是用C#开发的,使用SharpDevelop和.NET 2.0,以及GDI+。
滑尺继承自System.Windows.Forms.UserControl,重写了OnPaint方法,并添加了一些新属性:
在代码中,使用了父控件的以下属性:
滑尺由四层组成:
完整的逻辑放在OnPaint方法中。有一个小的不变部分,对于纯粹主义者来说,被封闭在一个签名区域内,可以移动到OnPaint之外。其他一切都在几个简单的步骤中完成:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Draw simple text, don't waste time with luxury render:
e.Graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
#region Can be moved outside OnPaint ...
// Calculate help variables
int W = this.ClientRectangle.Width;
int H = this.ClientRectangle.Height;
int Wm = W / 2;
int Hm = H / 2;
// Calculate distances between ticks
double largeTicksDistance = scaleRange / largeTicksCount;
double smallTicksDistance = largeTicksDistance / (smallTicksCount + 1);
// Calculate number of pixel between small ticks
float smallTicksPixels = (float)(W / scaleRange * smallTicksDistance);
#endregion Can be moved outside OnPaint
// Calculate first large tick value and position
double tickValue = Math.Floor((curValue - scaleRange / 2) / largeTicksDistance) * largeTicksDistance;
float tickPosition = (float)Math.Floor(Wm - W / scaleRange * (curValue - tickValue));
// Create drawing resources
Pen pen = new Pen(ForeColor);
Brush brush = new SolidBrush(ForeColor);
// For all large ticks
for (int L = 0; L <= largeTicksCount; L++)
{
// Draw large tick
e.Graphics.DrawLine(pen, tickPosition - 0, 0, tickPosition - 0, 15);
e.Graphics.DrawLine(pen, tickPosition - 1, 0, tickPosition - 1, 15);
// Draw large tick numerical value
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
e.Graphics.DrawString(Math.Round(tickValue, 2).ToString(), Font, brush, new PointF(tickPosition, Hm), sf);
// For all small ticks
for (int S = 1; S <= smallTicksCount; S++)
{
// Update tick value and position
tickValue += smallTicksDistance;
tickPosition += smallTicksPixels;
// Draw small tick
e.Graphics.DrawLine(pen, tickPosition, 0, tickPosition, 10);
}
// Update tick value and position
tickValue += smallTicksDistance;
tickPosition += smallTicksPixels;
}
// Dispose drawing resources
brush.Dispose();
pen.Dispose();
if (ShadowEnabled)
{
LinearGradientBrush LGBrush = null;
// Draw left side shadow
LGBrush = new LinearGradientBrush(new Rectangle(0, 0, Wm, H), Color.FromArgb(255, ShadowColor), Color.FromArgb(0, BackColor), 0, true);
e.Graphics.FillRectangle(LGBrush, new Rectangle(0, 0, Wm, H));
// Draw right side shadow
LGBrush = new LinearGradientBrush(new Rectangle(Wm + 1, 0, Wm, H), Color.FromArgb(255, ShadowColor), Color.FromArgb(0, BackColor), 180, true);
e.Graphics.FillRectangle(LGBrush, new Rectangle(Wm + 1, 0, Wm, H));
LGBrush.Dispose();
}
// Draw scale needle
e.Graphics.DrawLine(new Pen(NeedleColor), Wm - 0, 0, Wm - 0, H);
e.Graphics.DrawLine(new Pen(NeedleColor), Wm - 1, 0, Wm - 1, H);
}
这个控件有一组良好的默认属性值,因此一旦包含在解决方案中,就可以简单地从工具调色板中选择,拖放到表单中,并立即使用。否则,只有少数其他列出的属性需要配置。只需要一行代码就可以让它工作:
slidingScale1.Value = your value here!
包含的归档文件包含组件的完整源代码和编译的二进制文件,以及一个简单的测试应用程序。
有很多方法可以改进这个控件。这里有一些想法,如果有人想这样做:
这些是一些其他期望的特性:
这是控件的初步版本,还有许多特性需要实现。会尽快覆盖这些。