首页 > 编程语言 >C#自定义控件—流动管道

C#自定义控件—流动管道

时间:2024-09-02 23:03:32浏览次数:8  
标签:控件 自定义 C# Height break Rectangle path new rectangle

C#用户控件之流动管道

如何绘制一个动态的流动管道(FlowPipe)?

分两步绘制

  1. 定义属性;
  2. 画布重绘;

主要技能:

  • 管道的绘制(渐变色矩形)
  /// <summary>
  /// 画渐变色矩形的方法
  /// </summary>
  /// <param name="g">画布</param>
  /// <param name="brush">画刷</param>
  /// <param name="pen">笔</param>
  /// <param name="rectangle">矩形</param>
  private void PaintRectangle(Graphics g, Brush brush, Pen pen, Rectangle rectangle)
  {
      //填充矩形
      g.FillRectangle(brush, rectangle);

      switch (this.pipeStyle)
      {
          case PipeStyle.Horizontal:
              g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X + rectangle.Width, rectangle.Y);
              g.DrawLine(pen, rectangle.X, rectangle.Y + rectangle.Height - 1, rectangle.X + rectangle.Width, rectangle.Height);
              break;
          case PipeStyle.Vertical:
              g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Y + rectangle.Height);
              g.DrawLine(pen, rectangle.X + rectangle.Width - 1, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Height);
              break;
          default:
              break;
      }
  }
  • 管道的绘制(渐变色半圆)
/// <summary>
/// 画渐变色半圆的方法
/// </summary>
/// <param name="g">画布</param>
/// <param name="colorBlend"></param>
/// <param name="p"></param>
/// <param name="rect"></param>
/// <param name="startAngle"></param>
/// <param name="sweepAngle"></param>
private void PaintEllipse(Graphics g, ColorBlend colorBlend, Pen p, Rectangle rect, float startAngle, float sweepAngle)
{
    //第一步:创建GPI路径
    GraphicsPath path = new GraphicsPath();
    path.AddEllipse(rect);

    //第二步:渐变色填充
    PathGradientBrush brush = new PathGradientBrush(path);
    brush.CenterPoint = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
    brush.InterpolationColors = colorBlend;

    //第三步:绘制管道
    g.FillPie(brush, rect, startAngle, sweepAngle);

    //第四步:绘制边线
    g.DrawArc(p, rect, startAngle, sweepAngle);
}
  • 流动条的绘制(用笔的虚线)
//画虚线,关键用笔和路径来画
Pen pen = new Pen(this.flowColor, this.flowWidth);
pen.DashStyle = DashStyle.Custom;
pen.DashPattern = new float[]
{
    flowLength,flowLengthGap
};
pen.DashOffset = this.startOffset;
g.DrawPath(pen, path);

 //流动条路径
 GraphicsPath path = new GraphicsPath();

 //虚线路径—左边、中间、右边
 switch (this.pipeTurnLeft)
 {
     case PipeTurn.Up:
         path.AddArc(new Rectangle(this.Height / 2, this.Height / 2 * (-1) -1, this.Height, this.Height), 181.0f, -91.0f);
         break;
     case PipeTurn.Down:
         path.AddArc(new Rectangle(this.Height / 2, this.Height / 2, this.Height, this.Height), 180.0f, 90.0f);
         break;
     default:
         path.AddLine(-1, this.Height / 2, this.Height+1, this.Height / 2);
         break;
 }
  • 关键理解:绘制的椭圆、线(Rectangle)<x,y【圆切矩形相对于控件原点<左上角>的坐标】,宽,高,开始角度,扫描角度>理解了就好画了
    path.AddArc(new Rectangle(this.Height / 2, this.Height / 2, this.Height, this.Height), 180.0f, 90.0f);
    path.AddLine(-1, this.Height / 2, this.Height+1, this.Height / 2);

  • 可以流动的关键要素

     //流动条流动速度(刷新速度)
     this.myTimer = new Timer();
     myTimer.Interval = 50;
     this.myTimer.Tick += MyTimer_Tick; ;

 }

 #region 定时循环
 private void MyTimer_Tick(object sender, EventArgs e)
 {
     this.startOffset = this.startOffset - this.moveSpeed;

     if (this.startOffset > this.flowLength + this.flowLengthGap || this.startOffset < (this.flowLength + this.flowLengthGap) * (-1))
     { this.startOffset = 0; }
     this.Invalidate();
 }

 #endregion

1.定义属性

  • 管道的(两端转向、样式、边沿颜色、中间颜色、激活)
  • 流动条的(速度、长度、宽度、间隙、颜色)
//属性示例:按照示例添加以上各种属性
private float moveSpeed = 0.3f;
[Browsable(true)]
[Category("布局_G")]
[Description("流动条速度,负数为反向")]  //属性说明
public float MoveSpeed
{
    get { return moveSpeed; }
    set
    {
        this.moveSpeed = value;
        this.Invalidate();  //重绘
    }
}

2.画布重绘

【管道分为左、中、右三部分。先画管道(矩形):左、中、右;再画流动条(虚线):左、中、右】
//矩形画刷
LinearGradientBrush linearGradientBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, this.Height), pipeColorEdge, pipeColorEdge);
linearGradientBrush.InterpolationColors = colorBlend;

//绘制左部分
switch (this.pipeTurnLeft)
{
    case PipeTurn.Up:
        this.PaintEllipse(g, colorBlend, p, new Rectangle(0, this.Height * (-1)-1, this.Height * 2, this.Height * 2), 90.0f, 90.0f);
        break;
    case PipeTurn.Down:
        this.PaintEllipse(g, colorBlend, p, new Rectangle(0, 0, this.Height * 2, this.Height * 2), 180.0f, 90.0f);
        break;
    default:
        this.PaintRectangle(g, linearGradientBrush, p, new Rectangle(-1, 0, this.Height+1, this.Height));
        break;
}

//绘制右部分
switch (this.pipeTurnRight)
{
    case PipeTurn.Up:
        this.PaintEllipse(g, colorBlend, p, new Rectangle(this.Width - this.Height * 2, this.Height * (-1)-1, this.Height * 2, this.Height * 2), 0.0f, 90.0f);
        break;
    case PipeTurn.Down:
        this.PaintEllipse(g, colorBlend, p, new Rectangle(this.Width - this.Height * 2, 0, this.Height * 2, this.Height * 2), 270.0f, 90.0f);
        break;
    default:
        this.PaintRectangle(g, linearGradientBrush, p, new Rectangle(this.Width - this.Height, 0, this.Height, this.Height));
        break;
}

//绘制中间
if (this.Width > this.Height * 2)
{
    this.PaintRectangle(g, linearGradientBrush, p, new Rectangle(this.Height - 1, 0, this.Width - this.Height * 2 + 2, this.Height));
}
//流动条路径
GraphicsPath path = new GraphicsPath();

//虚线路径—左边
switch (this.pipeTurnLeft)
{
    case PipeTurn.Up:
        path.AddArc(new Rectangle(this.Height / 2, this.Height / 2 * (-1) -1, this.Height, this.Height), 181.0f, -91.0f);
        break;
    case PipeTurn.Down:
        path.AddArc(new Rectangle(this.Height / 2, this.Height / 2, this.Height, this.Height), 180.0f, 90.0f);
        break;
    default:
        path.AddLine(-1, this.Height / 2, this.Height+1, this.Height / 2);
        break;
}

//虚线路径—中间
if (this.Width > this.Height * 2)
{
    path.AddLine(this.Height, this.Height / 2, this.Width - this.Height -1, this.Height / 2);
}

//虚线路径—右边
switch (this.pipeTurnRight)
{
    case PipeTurn.Up:
        path.AddArc(new Rectangle(this.Width - 1 - this.Height * 3 / 2, -this.Height / 2-1 , this.Height, this.Height), 88f, -91.0f);
        break;
    case PipeTurn.Down:
        path.AddArc(new Rectangle(this.Width - 1 - this.Height * 3 / 2, this.Height / 2, this.Height, this.Height), 270.0f, 90.0f);
        break;
    default:
        path.AddLine(this.Width - this.Height, this.Height / 2, this.Width , this.Height / 2);
        break;
}

//画虚线,关键用笔和路径来
Pen pen = new Pen(this.flowColor, this.flowWidth);
pen.DashStyle = DashStyle.Custom;
pen.DashPattern = new float[]
{
    flowLength,flowLengthGap
};
pen.DashOffset = this.startOffset;
g.DrawPath(pen, path);

格式都是一样的,掌握关键代码,肝就对了。

End

标签:控件,自定义,C#,Height,break,Rectangle,path,new,rectangle
From: https://www.cnblogs.com/guoenshuo/p/18391637

相关文章

  • 亲测好用,ChatGPT 3.5/4.0新手使用手册~ 【2024年9月 更新】
    都知道ChatGPT很强大,聊聊天、写论文、搞翻译、写代码、写文案、审合同等等,无所不能~那么到底怎么使用呢?其实很简单了,国内AI产品发展也很快,很多都很好用了~我一直在用,建议收藏下来~  有最先进、最新的GPT模型,还有很多其他效率工具都是在各自领域,绝对领先地位的产品~①......
  • 亲测好用,ChatGPT 3.5/4.0新手使用手册~ 【2024年9月 更新】
    都知道ChatGPT很强大,聊聊天、写论文、搞翻译、写代码、写文案、审合同等等,无所不能~那么到底怎么使用呢?其实很简单了,国内AI产品发展也很快,很多都很好用了~我一直在用,建议收藏下来~  有最先进、最新的GPT模型,还有很多其他效率工具都是在各自领域,绝对领先地位的产品~①......
  • 吐血整理 ChatGPT 3.5/4.0 新手使用手册~ 【2024.09.03 更新】
     以前我也是通过官网使用,但是经常被封号,就非常不方便,后来有朋友推荐国内工具,用了一阵之后,发现:稳定方便,用着也挺好的。最新的GPT-4o、4omini,可搭配使用~1、 最新模型科普:现在人工智能很强大,聊聊天、写论文、搞翻译、写代码、写文案、审合同、情感陪伴等,真是无所不能~......
  • 科普文:软件架构Elasticsearch系列之【2024年8月30日 Shay:Elasticsearch is Open Sourc
     2021年1月,当时Elastic公司决定把Elasticsearch和Kibana的许可证从Apache2.0变更为ElasticLicense2.0(ELv2)和ServerSidePublicLicense(SSPL)双许可。尽管这两个许可证也允许源代码公开,但它们并不符合开源倡议组织(OSI)的开源定义。应对质疑:“本就是一个错误,现......
  • CSS瀑布流实现
    文章目录前言前置知识React中实现代码实现Vue中实现代码实现前言瀑布流是一种CSS布局技术,它允许不同高度的元素在页面上以美观的方式排列,同时保持行与列间的间距一致。前置知识使用multi-column实现多列布局column-count:设置布局显示的列数。column-gap......
  • 对Xcode Tools实现机制的一点思考
    场景在编译wine前,执行.configure检查依赖项是否都满足条件,发现bison的版本较低。检查发现存在一个/usr/bin/bison,但是从未安装过这一命令,所以考虑到是XTools中携带的,检查后发现确实如此然后就又一次引发了我对于XTool的疑问,/usr/bin/下和XTools中包含的相同可执行程序,不是以软连......
  • Java LeetCode练习
        LeetCodeExercise        807.保持城市天际线    题解:贪心        从左侧和右侧看,城市天际线等于矩阵grid的每一行的建筑物高度最大值;从顶部和底部看,城市天际线等于矩阵grid的每一列的建筑物高度最大值。只要不改变每一行和每一列......
  • Codeforces Round 970 div3
    CodeforcesRound970div3错过的一场比赛,第二天早晨VP,题目的通过率还挺奇怪A.Sakurako'sExamhttps://codeforces.com/contest/2008/problem/A题意:有a个1和b个2的数组,在1和2前面增添加减号,判断是否能让结果为0思路:1个2需要2个1进行填补,不如先让2自己进行消去,如......
  • 高通xbl创建protocol驱动,abl调用xbl中的驱动
    UEFI有关的文件格式介绍:fdf:flashdefinitionfile,描述flash分区地址范围dec:packagedeclarationfile,定义了不同模块的GUID信息dsc:descriptionfile,主要包含需要用到的所有inf文件inf:单个模块的编译信息,类似makefileefi:最终编译生成的UEFI可执行文件一、xbl创建protocol驱......
  • Jenkins - 在Rocky Linux系统下安装Jenkins和配置Agent节点
    安装Jenkins主节点下载和安装JenkinsLTS版本本机信息[root@localhost~]#cat/etc/system-releaseRockyLinuxrelease9.4(BlueOnyx)[root@localhost~]#[root@localhost~]#uname-aLinuxlocalhost.localdomain5.14.0-427.33.1.el9_4.x86_64#1SMPPREEMPT_DYNA......