承接上节,从本节开始持续更新后续代码功能,由于更新内容比较随机,详细介绍见代码备注
更新内容:
1. 绘图曲线函数
2.缓存数组与数据处理数组
3.画面刷新
4.外部输入接口
代码如下:
FormScope.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinForms_Start1
{
public partial class FormScope : Form
{
const int dataCountMax = 10001;
bool scopeRun;
//缓存数据
public static volatile Queue<int> quedata1 = new Queue<int>(dataCountMax);//通道1数据
//public static volatile Queue<int> quedata2 = new Queue<int>(10001);
//public static volatile Queue<int> quedata3 = new Queue<int>(10001);
//public static volatile Queue<int> quedata4 = new Queue<int>(10001);
//示波器显示数组
int[] arrScope1 = new int[dataCountMax];
//int[] arrScope2 = new int[10001];
//int[] arrScope3 = new int[10001];
//int[] arrScope4 = new int[10001];
//显示数据个数
int dataCount;
//示波器参数
PointF startPoint; //绘图原点
PointF originPoint; //示波器框的原点
float Slength_X, Slength_Y;
private Pen TablePen = new Pen(Color.FromArgb(0x3c, 0x3c, 0x3c));//线条画笔,灰色
private Pen RedPen = new Pen(Color.FromArgb(0xff, 0x00, 0x00), 1f);//波形1线条颜色,红色
float DrawStepX;//x轴分辨率
float DrawStepY;//y轴分辨率
//屏幕刷新定时器
Timer timRefresh = new Timer();
public FormScope()
{
InitializeComponent();
ScopeInit();
for (int i = 0; i < dataCountMax; i++) //必须提前填满,不然容易出BUG
{
quedata1.Enqueue(0);
//ComDataDef.queCube2.Enqueue(0);
//ComDataDef.queCube3.Enqueue(0);
//ComDataDef.queCube4.Enqueue(0);
}
}
/// <summary>
/// 示波器初始化函数
/// </summary>
private void ScopeInit()
{
scopeRun = true;
startPoint.X = 30;
startPoint.Y = 500;
originPoint = ConvertPoint(startPoint, 10, 50);//示波器原点坐标
Slength_X = 600;
Slength_Y = 400;
dataCount = 100;//该值需要小于dataCountMax
DrawStepX = Slength_X/ dataCount;//根据显示数据自适应
DrawStepY = 1f;
timRefresh.Tick += new EventHandler(this.timRefresh_Tick);
timRefresh.Interval = 50; //定时器刷新屏幕
timRefresh.Start();
SetStyle(ControlStyles.DoubleBuffer, true); // 设置双缓冲,防止图像抖动
SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 忽略系统消息,防止图像闪烁
Invalidate();//刷新显示
}
private void timRefresh_Tick(object sender, EventArgs e) //屏幕刷新定时器
{
//防止部分数据未及时更新出bug
originPoint = ConvertPoint(startPoint, 10, 50);//示波器原点坐标
DrawStepX = Slength_X / (float)dataCount;
//数据处理
if (scopeRun)
{
QueToArray(quedata1, arrScope1);
}
Invalidate();//刷新显示
}
//private void QueToArray(Queue<int> que, int[] arr, ComboBox cmb) //把缓存通道数据放进数组
private void QueToArray(Queue<int> que, int[] arr)
{
int i = 0;
foreach (int num in que)
{
arr[i] = num;
i++;
}
}
private void Form_Paint(object sender, PaintEventArgs e)画图函数
{
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
e.Graphics.FillRectangle(Brushes.Black, e.Graphics.ClipBounds); //默认黑色
//画示波器框线 (颜色,起点坐标,终点坐标)
//横轴
e.Graphics.DrawLine(TablePen, originPoint, ConvertPoint(originPoint, Slength_X, 0));
e.Graphics.DrawLine(TablePen, ConvertPoint(originPoint,0,Slength_Y), ConvertPoint(originPoint, Slength_X, Slength_Y));
//纵轴
e.Graphics.DrawLine(TablePen, originPoint, ConvertPoint(originPoint, 0, Slength_Y));
e.Graphics.DrawLine(TablePen, ConvertPoint(originPoint, Slength_X, 0), ConvertPoint(originPoint, Slength_X, Slength_Y));
//刻度轴
//坐标参数
//波形显示,(输入数组,显示个数,偏移量,初始点)
ShowWaveLine(arrScope1, dataCount, 0 ,originPoint, DrawStepX, DrawStepY, e, RedPen);
}
private void ShowWaveLine(int[] arr,int datacount,int databackcount ,PointF p, float drawstepX, float drawstepY, PaintEventArgs e, Pen pen ) //数组,初始坐标,线条,触发事件
{
int count = dataCountMax - datacount - databackcount;
if (count < 0)
{
count = 0;
}
float p1_x;
float p1_y;
float p2_x;
float p2_y;
for (int i = 0; i < dataCountMax - databackcount -count; i++)
{
//当前坐标
p1_x = p.X + i * drawstepX;
p1_y = p.Y - arr[i+count-1] * drawstepY;
//计算下一个坐标
p2_x = p.X + (i+1) * drawstepX;
p2_y = p.Y - arr[(i+ count)] * drawstepY;
//防止过界
if (p1_y < originPoint.Y - Slength_Y)
{
p1_y = originPoint.Y - Slength_Y;
}
else if(p1_y > originPoint.Y)
{
p1_y = originPoint.Y;
}
if (p2_y < originPoint.Y - Slength_Y)
{
p2_y = originPoint.Y - Slength_Y;
}
else if (p2_y > originPoint.Y)
{
p2_y = originPoint.Y;
}
e.Graphics.DrawLine(pen, p1_x, p1_y, p2_x, p2_y);
}
}
/// <summary>
/// 坐标转换函数
/// </summary>
/// <param name="point"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns>新坐标值</returns>
///
PointF ConvertPoint(PointF point, float x, float y)
{
PointF p = point;
p.X += x;
p.Y -= y;
return p;
}
//参数输入接口
public void DataInput(int data)
{
quedata1.Dequeue();
quedata1.Enqueue(data);
}
}
}
设计文件
namespace WinForms_Start1
{
partial class FormScope
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FormScope
//
this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 24F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1774, 1129);
this.Name = "FormScope";
this.Text = "示波器";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form_Paint);
this.ResumeLayout(false);
}
#endregion
}
}
最后在主窗口里持续添加数据
效果如下: