65.9K
CodeProject 正在变化。 阅读更多。
Home

SimpleLine 线条和框图控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.42/5 (20投票s)

2005年5月9日

CPOL

2分钟阅读

viewsIcon

83424

downloadIcon

1259

支持渐变的线条和容器框控件。

Sample Image - SimpleLine.jpg

引言

有没有其他人也好奇为什么 Microsoft 没有在 .NET 中包含一个“简单”的线条/形状控件?每次我想在屏幕上画一条线时,都不得不编写 GDI+,这让我很厌烦。

概述

这是我提交的第一篇文章,所以请大家包涵一下格式。 我认为我有很多东西可以提供给 CodeProject 社区,但我想从一些简单的东西开始。

首先,我想声明这个控件是在我自己的时间开发的。 如果这是我受雇做的事情,我可能会在代码中添加一些更好的注释,并且控件中不会有任何“陷阱”。

话虽如此,这个项目包含三个控件

SimpleLine

simple line 控件可以作为线条或方框使用。 如果它是一条线,它可以是水平或垂直的。 它还可以处理渐变,作为线条或方框(见上图)。

以下是一些可以通过设计器属性框以及在运行时设置的属性

/// <summary>
/// Enum indicating horizontal or vertical gradient draw
/// </summary>
[Category("Custom")]
public GradientDirection GradientAngle

/// <summary>
/// For lines, this will scale the line
/// to fit right-to-left, or top-to-bottom
/// </summary>
[Category("Custom")]
public bool FitToParent

/// <summary>
/// If set to true, gradient will draw
/// with FillColor and Gradient color
/// </summary>
[Category("Custom")]
public bool UseGradient

/// <summary>
/// Enum indicating horizontal line, vertical line, or Box
/// </summary>
[Category("Custom")]
public LineStyle Style

要绘制实际的线条(或方框),调用 DrawLine() 方法

public void DrawLine()
{
  if (this.Parent == null) { return ; }
  //we don't want the control to draw on itself at design time

  if (this.Style == LineStyle.None)
  //default to Horizontal line, when placed on a parent
  {
    _lineStyle = LineStyle.Horizontal ;
    _lineWidth = 1 ;
    this.Left = (Parent.Width /2) - this.Width / 2 ;
    this.Top = Parent.Height / 2 ;
  }
  Graphics g = this.CreateGraphics() ; //create the graphics object
  g.Clear(Parent.BackColor) ;
  Pen pn ;
  if (this.Style == LineStyle.Vertical || this.Style == LineStyle.Horizontal)
    pn = new Pen( LineColor,LineWidth * 2);
  else
    pn = new Pen( LineColor,LineWidth);

  Point pt1 = new Point( 0, 0 );
  Point pt2 ;
  if (this.Style == LineStyle.Horizontal)
  {
    if (FitToParent == true)
    {
      this.Left = 0 ;
      this.Width = Parent.ClientRectangle.Width ;
    }
    this.Height = LineWidth ;
    if (this.Height < 1) { this.Height = 1 ; }
    pt2 = new Point( Width , 0 );
    if (UseGradient == false)
    {
      g.DrawLine( pn, pt1, pt2 );
    }
    else
    {
      Rectangle rect = new Rectangle(new Point(0,0), 
        new Size(this.ClientRectangle.Width,LineWidth)) ;
      if (FillColor == Color.Transparent)
      {FillColor = Parent.BackColor ; }
      {
        LinearGradientBrush lgb = new 
          LinearGradientBrush(rect,FillColor,Gradient,0,false) ;
        g.FillRectangle(lgb,0,0,this.Width,LineWidth) ;
      }
    }
  }
  else if (this.Style == LineStyle.Vertical)
  {
    if (FitToParent == true)
    {
      this.Top = 0 ;
      this.Height = Parent.Height ;
    }
    this.Width = LineWidth ;
    if (this.Width < 1) { this.Width = 1 ; }
    pt2 = new Point( 0, Height ) ;
    if (UseGradient == false)
    {
      g.DrawLine( pn, pt1, pt2 );
    }
    else
    {
      Rectangle rect = new Rectangle(new Point(0,0), 
                       new Size(LineWidth,this.Height)) ;
      if (FillColor == Color.Transparent)
      {FillColor = Parent.BackColor ; }
      {
        LinearGradientBrush lgb = new 
          LinearGradientBrush(rect,FillColor,Gradient,90,false) ;
        g.FillRectangle(lgb,0,0,LineWidth,this.Height) ;
      }
    }
  }
  else if (this.Style == LineStyle.Box )
  {
    if (FitToParent == true)
    {
      this.Top = 0 ;
      this.Left = 0 ;
      this.Width = Parent.Width;
      this.Height = Parent.Height ;
    }
    Rectangle rect = new Rectangle(new Point(0,0), 
                     new Size(this.Width,this.Height)) ;
    if (FillColor == Color.Transparent)
    {FillColor = Parent.BackColor ; }
    if (UseGradient)
    {
      LinearGradientBrush lgb = new LinearGradientBrush(rect, 
       FillColor,Gradient,
       GradientAngle==GradientDirection.Horizontal ? 0 : 90,false) ;
      g.FillRectangle(lgb,0,0,this.Width - LineWidth, 
                           this.Height - LineWidth) ;
    }
    else
    {
      SolidBrush sb = new SolidBrush(FillColor) ;
      g.FillRectangle(sb,0,0,this.Width - LineWidth,this.Height - LineWidth) ;
    }
    decimal mod = Decimal.Remainder((decimal)LineWidth,(decimal)2) ;
    int offset = 0 ;
    if (mod != 0 && LineWidth !=1) { offset = 1 ; }
    rect.Offset(LineWidth/2,LineWidth/2) ;
    rect.Height = rect.Height - LineWidth + offset -1 ;
    rect.Width = rect.Width - LineWidth + offset -1 ;
    if (LineWidth > 0) {g.DrawRectangle(pn,rect) ;}
  }
  g.Dispose() ;
}

SimpleBox

SimpleBox 控件“看起来”像 SimpleLine 控件(在 “Box” 模式下运行)。 主要区别在于:SimpleBox 是一个容器控件。 换句话说,它的行为类似于 Panel

要使用户控件成为容器控件,您只需将以下属性添加到类中

[Designer("System.Windows.Forms.Design.ParentControlDesigner, 
                              System.Design", typeof(IDesigner))]

TransparentLabel

我必须将这个控件的功劳归于 Kenneth Hadden。 我在上一份工作中与 Ken 共事了大约一年,他主动将此控件添加到 SimpleLine 项目中。 尽管 .NET 允许您将“透明”指定为各种控件(例如 .NET Label 控件)的背景,但这并不是真正的透明。 如果放置在渐变控件上,它会准确地显示渐变,但是如果在渐变和 Label 之间有另一个控件,您将看不到它。

用法

要使用这些控件,请打开我包含的解决方案。 编译,并在必要时将三个 SimpleLine 控件添加到您的工具箱。 将其中一个控件放在窗体或用户控件上,并设置相应的属性。

这些控件的属性非常简单明了。 如果要显示渐变,请确保将 “UseGradient” 属性更改为 true

祝你好运。 值得一提的是,我正在几个生产应用程序中使用这些控件。 代码并不完美,但我还没有遇到任何问题。

... 并且最后

如果您喜欢这个控件,请投票。 如果您不喜欢它,请通过 paul@blurious.com 给我的发送电子邮件,并在您投票之前给我机会修复或解释。

更新

  • 05-10-05
    • 添加了来自 Eric Woodruff 的代码,以允许 SimpleBox 在设计时绘制。
    • 添加了一些代码片段来说明控件如何运作。
© . All rights reserved.