标题:
C#示波器控件 ScopeV1.0
[打印本页]
作者:
liuda
时间:
2015-1-23 03:10
标题:
C#示波器控件 ScopeV1.0
C#示波器控件 ScopeV1.0
// C#示波器控件 ScopeV1.0 测试版仅供参考
// C# 2008
// author: dzrjojo
// date: 2010.07.28
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Dongzr.WindPowerTool
{
public partial class Scope : UserControl
{
public const int INTERVAL = 1000; // 采样时间间隔1000ms
public const int MAX_CURVE_NUM = 10; // 示波器显示最大曲线数为10
private const int SCOPE_WIDTH = 500; // 示波器宽度
private const int SCOPE_HEIGHT = 500; // 示波器高度
private const int SCOPE_FRAME = 25; // 示波器边框宽度
private const int DATA_LENGTH = SCOPE_WIDTH; // 示波器最大采样点数设为示波器宽度
private Curve[] curve;
// private ReaderWriterLock datas_lock; // 单线程不需要读写锁
private Brush brush;
private Font font;
private Pen white_dash_pen;
private bool hold;
private Bitmap bitmap;
public Scope()
{
InitializeComponent();
}
// 添加曲线
public bool CreateCurve(int id,Color color,string unit)
{
bool re = false;
if (id >= 0 && id < MAX_CURVE_NUM)
{
// datas_lock.AcquireWriterLock(-1);
if (this.curve[id] == null)
{
this.curve[id] = new Curve();
}
if (this.curve[id].show == false)
{
this.curve[id].Init(true, color, DATA_LENGTH, INTERVAL, unit);
re = true;
}
// datas_lock.ReleaseWriterLock();
}
return re;
}
// 删除曲线
public void RemoveCurve(int id)
{
// datas_lock.AcquireWriterLock(-1);
if (this.curve[id] != null)
{
if (this.curve[id].show == true)
{
this.curve[id].show = false;
}
}
// datas_lock.ReleaseWriterLock();
this.Invalidate();
}
// 添加单点数据
public void AddData(int id,float f)
{
if (this.hold == false)
{
// datas_lock.AcquireWriterLock(-1);
if (this.curve[id] != null)
{
if (this.curve[id].show == true)
{
for (int i = Curve.points - 1; i > 0; i--)
{
if (this.curve[id].counter == 0)
{
this.curve[id].data_raw[i].X = 0;
}
else
{
this.curve[id].data_raw[i].X = this.curve[id].data_raw[i - 1].X + 1;
}
this.curve[id].data_raw[i].Y = this.curve[id].data_raw[i - 1].Y;
}
this.curve[id].data_raw[0].X = 0;
this.curve[id].data_raw[0].Y = f;
if (this.curve[id].counter < Curve.points)
{
this.curve[id].counter++;
}
}
}
// datas_lock.ReleaseWriterLock();
this.Invalidate();
}
}
// 暂停波形
public bool Hold
{
set
{
this.hold = value;
}
}
// 设置曲线参数
private void SetCurveOffsetX(int id, int offset_x) // 暂时禁止X轴偏置设置,其原点在右,向左为正方向
{
if (this.curve[id] != null)
{
Curve.offset_x = offset_x;
this.Invalidate();
}
}
public void SetCurveOffsetY(int id, int offset_y)
{
if (this.curve[id] != null)
{
this.curve[id].offset_y = offset_y;
this.Invalidate();
}
}
public void SetCurveZoomX(int id, float zoom_x)
{
if (this.curve[id] != null)
{
if (zoom_x >= 1.0f) // 限制X轴缩放比例 >=1
{
Curve.zoom_x = zoom_x;
this.Invalidate();
}
}
}
public void SetCurveZoomY(int id, float zoom_y)
{
if (this.curve[id] != null)
{
this.curve[id].zoom_y = zoom_y;
}
}
// 示波器初始化
private void Scope_Load(object sender, EventArgs e)
{
// datas_lock = new ReaderWriterLock();
curve = new Curve[MAX_CURVE_NUM];
Curve.InitStatic(DATA_LENGTH, INTERVAL, 0, 1.0f);
brush = new SolidBrush(Color.Yellow);
font = new Font("SimSun", 10, System.Drawing.FontStyle.Regular);
white_dash_pen = new Pen(Color.White, 1);
white_dash_pen.DashStyle = DashStyle.Dot;
hold = false;
}
// size改变时刷新
private void Scope_Resize(object sender, EventArgs e)
{
this.Invalidate();
}
// 右键菜单about
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Scope V1.0\r\n\r\nCopyRight dongzr 2010-2012", "About...");
}
// 绘图,双缓冲在Scope属性里设置
private void Scope_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.HighSpeed;
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
g.Clear(Color.DarkGray);
g.ScaleTransform(-(float)this.Width / (SCOPE_WIDTH + SCOPE_FRAME*2),
-(float)this.Height / (SCOPE_HEIGHT + SCOPE_FRAME*2) ); // 缩放,并使XY轴反向
g.TranslateTransform(-(SCOPE_WIDTH + SCOPE_FRAME) , - (SCOPE_HEIGHT/2 + SCOPE_FRAME)); // 新的坐标原点,位于波形显示区的右侧中点
// 示波器显示范围指示
g.SetClip(new Rectangle(0, SCOPE_HEIGHT / 2 + 5, SCOPE_WIDTH, SCOPE_FRAME - 10));
g.Clear(Color.Black);
g.DrawRectangle(Pens.YellowGreen, new Rectangle(0, SCOPE_HEIGHT / 2 + 10, (int)(SCOPE_WIDTH / Curve.zoom_x), SCOPE_FRAME - 20));
// 绘制零点指示标志
g.SetClip(new Rectangle(SCOPE_WIDTH + 5, -SCOPE_HEIGHT / 2, SCOPE_FRAME - 10, SCOPE_HEIGHT));
g.Clear(Color.Black);
for (int ls = 0; ls < MAX_CURVE_NUM; ls++)
{
if (this.curve[ls] != null)
{
if (this.curve[ls].show == true)
{
g.DrawLine(this.curve[ls].pen, SCOPE_WIDTH + 5, this.curve[ls].offset_y, SCOPE_WIDTH + 15, this.curve[ls].offset_y + 3);
g.DrawLine(this.curve[ls].pen, SCOPE_WIDTH + 5, this.curve[ls].offset_y, SCOPE_WIDTH + SCOPE_FRAME - 5, this.curve[ls].offset_y);
g.DrawLine(this.curve[ls].pen, SCOPE_WIDTH + 5, this.curve[ls].offset_y, SCOPE_WIDTH + 15, this.curve[ls].offset_y - 3);
}
}
}
// 设置作图区域为波形显示区,大小为SCOPE_WIDTH*SCOPE_HEIGHT
g.SetClip(new Rectangle(0, -SCOPE_HEIGHT / 2, SCOPE_WIDTH, SCOPE_HEIGHT));
g.Clear(Color.Black);
// 绘制坐标网格
for (int step = SCOPE_WIDTH / 50,i = 0; i <= 50; i++)
{
if (i % 5 == 0)
{
g.DrawLine(white_dash_pen, i * step, -SCOPE_HEIGHT / 2, i * step, SCOPE_HEIGHT / 2);
}
else
{
g.DrawLine(white_dash_pen, i * step, -SCOPE_HEIGHT / 2, i * step, -SCOPE_HEIGHT / 2 + step / 2);
// g.DrawLine(white_dash_pen, i * step, -step / 4, i * step, step / 4);
g.DrawLine(white_dash_pen, i * step, SCOPE_HEIGHT / 2, i * step, SCOPE_HEIGHT / 2 - step / 2);
}
}
for (int step = SCOPE_HEIGHT / 50, i = -25; i <= 25; i++)
{
if (i % 5 == 0)
{
g.DrawLine(white_dash_pen, SCOPE_WIDTH, i * step, 0, i * step);
}
else
{
g.DrawLine(white_dash_pen, SCOPE_WIDTH, i * step, SCOPE_WIDTH - step / 2, i * step);
// g.DrawLine(white_dash_pen, SCOPE_WIDTH / 2 + step / 4, i * step, SCOPE_WIDTH / 2 - step / 4, i * step);
g.DrawLine(white_dash_pen, step / 2, i * step, 0, i * step);
}
}
// 绘制data
// datas_lock.AcquireWriterLock(-1);
for (int ls = 0; ls < MAX_CURVE_NUM; ls++)
{
if (this.curve[ls] != null)
{
if (this.curve[ls].show == true)
{
// data变换
for (int i = 0; i < Curve.points; i++)
{
this.curve[ls].data_show[i].X = this.curve[ls].data_raw[i].X * Curve.zoom_x + Curve.offset_x;
this.curve[ls].data_show[i].Y = this.curve[ls].data_raw[i].Y * this.curve[ls].zoom_y + this.curve[ls].offset_y;
}
// 显示
g.DrawLines(this.curve[ls].pen, this.curve[ls].data_show);
}
}
}
// datas_lock.ReleaseWriterLock();
// 绘制单位坐标
g.ScaleTransform(-1, -1);
g.SetClip(new Rectangle(-SCOPE_WIDTH, SCOPE_HEIGHT / 2 + 5, SCOPE_WIDTH, SCOPE_FRAME - 10));
g.Clear(Color.Black);
g.DrawString("10 9 8 7 6 5 4 3 2 1 0", font, brush, -SCOPE_WIDTH, SCOPE_HEIGHT / 2 + 5);
g.RotateTransform(-90);
g.SetClip(new Rectangle(-SCOPE_HEIGHT / 2 , 5, SCOPE_HEIGHT, SCOPE_FRAME - 10));
g.Clear(Color.Black);
g.DrawString("-5 -4 -3 -2 -1 0 1 2 3 4 5", font, brush, -SCOPE_HEIGHT / 2, 5);
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
bool isSave = true;
SaveFileDialog saveImageDialog = new SaveFileDialog();
saveImageDialog.Title = "Save Scope image";
saveImageDialog.Filter = @".bmp|*.bmp";
if (saveImageDialog.ShowDialog() == DialogResult.OK)
{
string fileName = saveImageDialog.FileName.ToString();
if (fileName != "" && fileName != null)
{
System.Drawing.Imaging.ImageFormat imgformat = null;
imgformat = System.Drawing.Imaging.ImageFormat.Bmp;
if (isSave)
{
try
{
bitmap = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
this.DrawToBitmap(bitmap, this.ClientRectangle);
bitmap.Save(fileName, imgformat);
MessageBox.Show("图片已经成功保存!");
}
catch
{
MessageBox.Show("保存失败!");
}
finally
{
bitmap.Dispose();
}
}
}
}
}
}
internal class Curve
{
public bool show; // 是否显示
public PointF[] data_raw; // 数据原始值
public PointF[] data_show; // 数据显示值
public Pen pen; // 画笔
public static int points; // 采样点数
public string unit; // 数据的单位
public static int interval; // 采样点的时间间隔,单位ms
public static int offset_x; // 横轴偏置
public int offset_y; // 纵轴偏置
public static float zoom_x; // 横轴缩放比例
public float zoom_y; // 纵轴缩放比例
public int counter;
public Curve()
{
this.show = false;
}
public static void InitStatic(int points, int interval, int offset_x, float zoom_x)
{
Curve.points = points;
Curve.interval = interval;
Curve.offset_x = offset_x;
Curve.zoom_x = zoom_x;
}
public void Init(bool show, Color color, int points, int interval, string unit)
{
this.show = show;
this.unit = unit;
this.pen = new Pen(color, 1);
this.data_raw = new PointF[Curve.points];
this.data_show = new PointF[Curve.points];
this.offset_y = 0;
this.zoom_y = 1.0f;
this.counter = 0;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
this.scope1.CreateCurve(0, Color.Yellow, "");
this.scope1.SetCurveZoomY(0,100);
this.scope1.CreateCurve(1, Color.Cyan, "");
for(int i = 0;i<500;i++)
{
this.scope1.AddData(0,sin(3.14* i / 100));
this.scope1.AddData(1,cos(3.14* i / 100));
}
this.scope1.RemoveCurve(1);
复制代码
作者:
12345678901
时间:
2015-10-25 02:28
这个怎么用啊?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1