野比的示波器案例(Winfrom用户控件)
使用该用户控件做的效果图,如果数据正确,可实现 波形、直线、等等效果图。。。。。。
对于本程序的认识还是不够深彻。如果有其他方法或算法,欢迎讨论下。将我所能理解的代码都再次标识了一番。
--------------------------------------------------------------------------------------------------using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace PowerTest
{
public partial class StatusChart : UserControl
{
#region ** 私有成员:属性 **
/// <summary>
/// 波形所容纳的最大值
/// </summary>
private int range = 100;
/// <summary>
/// 定时器间隔
/// </summary>
private int interval = 1;
/// <summary>
/// Chart 值数组
/// </summary>
private int[] val;
/// <summary>
/// 当前值
/// </summary>
private int currentValue = 0;
/// <summary>
/// W:画布宽度 ,H:画布高度
/// </summary>
private int w, h;
/// <summary>
/// 定时器
/// </summary>
private Timer tmrRefresh;
/// <summary>
/// 私有成员:绘图 绘图方式
/// </summary>
private ChartMode chartMode = ChartMode.Waveform;
/// <summary>
/// 平移偏移量
/// </summary>
private int iOffset = 0;
/// <summary>
/// 网格是否平移
/// </summary>
private bool gridShiftting = true;
/// <summary>
/// 网格平移间距
/// </summary>
private int gridShifttingIncrement = 1;
/// <summary>
/// 网格宽度
/// </summary>
private int gridWidth = 10;
/// <summary>
/// 网格高度
/// </summary>
private int gridHeight = 10;
/// <summary>
/// 绘制网格画笔
/// </summary>
private Pen penChart = new Pen(Color.Lime, 2);
/// <summary>
/// 绘制曲线画笔
/// </summary>
private Pen penGrid = new Pen(Color.Green);
/// <summary>
/// 魔版
/// </summary>
private Graphics graph;
#endregion
#region ** 私有方法:绘制图形 **
/// <summary>
/// 根据画布大小绘制所需求大小的网格
/// </summary>
/// <param name="g">魔板</param>
/// <param name="offset">网格每次平移变量</param>
private void DrawGrids(ref Graphics g, int offset)
{
//网格数(不计边缘)
float div;
float pos = 0F;
//先画 垂直 方向
//可以少画一根线无所谓,看各自需求 画多少条线(画布大小除以网格的宽度)
div = (float)w / (float)gridWidth + 1;
//循环画横线
for (int i = 0; i < (int)div; i++)
{
pos += gridWidth;
g.DrawLine(penGrid, pos - offset, 0, pos - offset, h);
}
//画 水平 方向 画多少条线(画布大小除以网格的高度)
div = (float)h / (float)gridHeight + 1;
pos = 0F;
//循环画竖线
for (int i = 0; i < (int)div; i++)
{
g.DrawLine(penGrid, 0, pos, w, pos);
pos += gridHeight;
}
}
/// <summary>(难点)
/// 根据数据绘制示波数据线
/// </summary>
/// <param name="g">魔板</param>
/// <param name="p">画笔</param>
/// <param name="val">数据数组</param>
private void DrawChart(ref Graphics g, Pen p, ref int[] val)
{
//从 0 到 w 绘制
int len = w;
//根据绘制方式(多重阴影与单线)
if (chartMode == StatusChart.ChartMode.Histogram)
{
//绘制的是数据A点与画布高度之间的连线
//绘制第一个数据,一直到,倒数第二个数据
for (int i = 0; i < len; i++)
{
//第一个点(i,画布高度减去第i个数据),第二个点(i,画布高度)
g.DrawLine(p, i, h - val[i], i, h);
}
//第一个点(画布宽度,画布宽度减去最后一个数据),第二个点(画布宽度,画布高度)
g.DrawLine(p, len, h - val[len - 1], len, h);
}
else
{
len--;
//绘制的是一条数据A点与数据B点的连线
//绘制第一个数据,一直到,倒数第二个数据之间每一个点的连线
for (int i = 0; i < len; i++)
{
//两点决定1向量
//第一个点(i,画布高度减去第i个数据),第二个点(i+1,画布高度减去第i+1个数据)
g.DrawLine(p, i, h - val[i], i + 1, h - val[i + 1]);
}
len++;
//绘制倒数第二个与最后一个数据之间的连线(绘制最后两个点之间的连线)
//第一个点(画布宽度-1,画布宽度减去倒数第二个数据),第二个点(画布宽度,画布宽带减去倒数第一个数据)
g.DrawLine(p, len - 1, h - val[len - 2], len, h - val[len - 1]);
}
}
/// <summary>
/// 私有方法:重写方法系统 OnLoad 方法 (窗体加载事件)
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
//base.OnLoad(e);
//打开双缓冲(双缓存),防止闪烁
DoubleBuffered = true;
h = base.ClientSize.Height - 1;
w = base.ClientSize.Width - 1;
val = new int[w];
//创建一个 Timer 控件
tmrRefresh = new Timer();
//设置Timer时间
tmrRefresh.Interval = interval;
//开始Timer
tmrRefresh.Enabled = true;
//绑定事件
tmrRefresh.Tick += new EventHandler(tmrRefresh_Tick);
}
/// <summary>
/// 重写改变窗体大小事件
/// </summary>
/// <param name="e"></param>
protected override void OnResize(EventArgs e)
{
h = base.ClientSize.Height;
w = base.ClientSize.Width;
Array.Resize(ref val, w);
//使控件的整个图面无效并导致重绘控件。(导致OnPaint事件的发生)
Invalidate();
}
/// <summary>
/// 控件重写,重新绘制事件(由系统控制,每秒不知道重绘N次)
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
//base.OnPaint(e);
graph = e.Graphics;
DrawGrids(ref graph, iOffset);
DrawChart(ref graph, penChart, ref val);
}
/// <summary>
/// 定时器更新(由tmrRefresh定时器绑定的方法)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tmrRefresh_Tick(object sender, EventArgs e)
{
//(难点)
//更新网格偏移
//只有启用了网格移动才处理
if (gridShiftting)
{
iOffset += gridShifttingIncrement;
iOffset %= gridWidth;
}
//更新图形(整体左移)
//必须在这里而不能在画图的同时移动,
//若在画图中移动,则当画面被遮挡(OnPaint)事件不发生时无法更新
int len = w;
//不断的将数组中的第i个位置的数据移动到第i-1的位置。
for (int i = 0; i < len; i++)
{
//判断数组越界
if (i < len - 1)
{
val[i] = val[i + 1];
}
else
{
val[len - 1] = currentValue;
//break;
}
}
//val[len] = currentValue;
//使控件的整个图面无效并导致重绘控件。(导致OnPaint事件的发生)
Invalidate();
}
#endregion
#region ** 公共成员:设置绘制方式(多重阴影与单线) **
/// <summary>
/// 波形图显示方式枚举。
/// </summary>
public enum ChartMode
{
/// <summary>
/// 直方图
/// </summary>
Histogram = 0, //直方图
/// <summary>
/// 波形图
/// </summary>
Waveform //波形图
}
#endregion
#region ** 公共属性 **
//指定一个属性或事件是否应显示在“属性”窗口中。
[Browsable(true)]
/// <summary>
/// 当前值(给的数据,外面用一个Timer来每多少毫秒给一次数据,对外的Timer要与本StatusChart用户控件中的Timer时间同步)。
/// </summary>
[Category("内容"), Description("当前值。"), DefaultValue(0)]
public int Value
{
get
{
return currentValue;
}
set
{
//约束 value
if (value > range)
{
value = range;
}
if (value < 0)
{
value = 0;
}
//根据 Range 属性修正 value
//尽量减小误差
value = (int)((float)value / (float)range * (float)h);
currentValue = value;
}
}
/// <summary>
/// 数据值范围。绘图时将根据此值缩放 Value 值。
/// </summary>
[Category("内容"), Description("数据值范围。绘图时将根据此值缩放 Value 值。"), DefaultValue(100)]
public int Range
{
get
{
return range;
}
set
{
range = value;
}
}
/// <summary>
/// 波形图刷新间隔。
/// </summary>
[Category("内容"), Description("波形图刷新间隔。"), DefaultValue(500)]
public int Interval
{
get
{
return interval;
}
set
{
interval = value;
if (tmrRefresh != null)
{
tmrRefresh.Interval = interval;
}
}
}
/// <summary>
/// 指示波形是否继续更新。
/// </summary>
[Category("内容"), Description("指示波形是否继续更新。"), DefaultValue(true)]
public new bool Enabled
{
get
{
if (tmrRefresh != null)
{
return tmrRefresh.Enabled;
}
else
{
return false;
}
}
set
{
if (tmrRefresh != null)
{
tmrRefresh.Enabled = value;
}
}
}
/// <summary>
/// 显示方式。
/// </summary>
[Category("外观"), Description("波形显示方式。"), DefaultValue(typeof(StatusChart.ChartMode), "Histogram")]
public ChartMode Mode
{
get
{
return chartMode;
}
set
{
chartMode = value;
}
}
/// <summary>
/// 网格每次更新时向左平移的距离。
/// </summary>
[Category("外观"), Description("网格每次更新时向左平移的距离。"), DefaultValue(1)]
public int ShifttingIncrement
{
get
{
return gridShifttingIncrement;
}
set
{
gridShifttingIncrement = value;
if (gridShifttingIncrement < 0)
{
gridShifttingIncrement = 0;
}
}
}
/// <summary>
/// 指示网格是否每次更新时向左平移。
/// </summary>
[Category("外观"), Description("指示网格是否每次更新时向左平移。"), DefaultValue(true)]
public bool GridShiftting
{
get
{
return gridShiftting;
}
set
{
gridShiftting = value;
}
}
/// <summary>
/// 网格宽度。
/// </summary>
[Category("外观"), Description("网格宽度。"), DefaultValue(10)]
public int GridWidth
{
get
{
return gridWidth;
}
set
{
gridWidth = value;
Invalidate();
}
}
/// <summary>
/// 网格高度。
/// </summary>
[Category("外观"), Description("网格高度。"), DefaultValue(10)]
public int GridHeight
{
get
{
return gridHeight;
}
set
{
gridHeight = value;
Invalidate();
}
}
/// <summary>
/// 网格颜色。
/// </summary>
[Category("外观"), Description("网格颜色。"), DefaultValue(typeof(Color), "Green")]
public Color GridColor
{
get
{
return penGrid.Color;
}
set
{
penGrid.Color = value;
}
}
/// <summary>
/// 波形颜色。
/// </summary>
[Category("外观"), Description("波形颜色。"), DefaultValue(typeof(Color), "Lime")]
public override Color ForeColor
{
get
{
return penChart.Color;
}
set
{
penChart.Color = value;
}
}
#endregion
#region ** 公共方法 **
/// <summary>
/// 启动计时器更新。返回执行情况。
/// </summary>
/// <returns>执行情况。true 成功;false 失败。</returns>
public bool Start()
{
try
{
if (tmrRefresh != null)
{
tmrRefresh.Enabled = true;
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
/// <summary>
/// 停止计时器更新。返回执行情况。
/// </summary>
/// <returns>执行情况。true 成功;false 失败。</returns>
public bool Stop()
{
try
{
if (tmrRefresh != null)
{
tmrRefresh.Enabled = false;
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
/// <summary>
/// 清除历史状态记录。
/// </summary>
public void Clear()
{
if (val != null)
{
//没用
//val.Initialize();
Array.Resize(ref val, 0);
Array.Resize(ref val, w);
currentValue = 0;
}
}
/// <summary>
/// 控制计时器更新。返回执行情况。
/// </summary>
/// <returns>执行情况。true 成功;false 失败。</returns>
public void StopTrim(bool bol)
{
tmrRefresh.Enabled = bol;
}
#endregion
}
}
--------------------------------------------------------------------------------------------------使用该用户控件做的效果图,如果数据正确,可实现波形、直线、等等效果图 。。。。。。
----------------------对于本程序的认识还是不够深彻。如果有其他方法或算法,欢迎讨论下。将我所能理解的代码都再次标识了一番。
http://yunpan.cn/Q7YT8FGMMgn5x 提取码 6cc8
http://yunpan.cn/Q7YTkEHm24cJD 提取码 3cb8
DotNetBar9.2.0.0破解版,去除了AdvTree的Trial信息:
http://yunpan.cn/Q7YTGgegJS9LW 提取码 8143
野比的示波器案例(Winfrom用户控件)的更多相关文章
- winfrom获取用户控件里的控件对象
如何获取用户控件里的控件对象呢,其实思路也是很简单的, 比如有一个panel 用户控件 里面有许多的其他控件. 那么要找出一个Label控件怎么找呢,好的.现在我们就开始 首先,一个foreach循环 ...
- winfrom进程、线程、用户控件
一.进程 一个进程就是一个程序,利用进程可以在一个程序中打开另一个程序. 1.开启某个进程Process.Start("文件缩写名"); 注意:Process要解析命名空间. 2. ...
- 【demo练习四】:WPF用户控件案例
首先,新建vs中“用户控件(WPF)”,右键项目名 =>"添加"按钮 => 选择“新建项”. 然后选择“用户控件(WPF)” => 起名字 => 点击“添加 ...
- 【2017-05-04】winfrom进程、线程、用户控件
一.进程 一个进程就是一个程序,利用进程可以在一个程序中打开另一个程序. 1.开启某个进程Process.Start("文件缩写名"); 注意:Process要解析命名空间. 2. ...
- .Net用户控件
用户控件用户控件是个什么东西?自定义的反复重用的控件集合 好处?1.代码重用2.结构良好3.分工开发4.局部缓存 难点:一.交换信息: 注意信息的交换只在相邻层之间进行交换,如果是嵌套交换信息除Ses ...
- 在VisualStudio 工具箱中隐藏用户控件
当我们创建一个用户控件后,VisualStudio会自动将其添加到工具箱中,本来这是一个比较贴心的设计.但是,有的时候,我们并不想将用户控件放到工具箱中. 例如:在WPF中,为了避免一个页面的控件过多 ...
- 【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
前言: Wpf开发过程中,最经常使用的功能之一,就是用户控件(UserControl)了.用户控件可以用于开发用户自己的控件进行使用,甚至可以用于打造一套属于自己的UI框架.依赖属性(Dependen ...
- C# 自定义控件VS用户控件
1 自定义控件与用户控件区别 WinForm中, 用户控件(User Control):继承自 UserControl,主要用于开发 Container 控件,Container控件可以添加其他Con ...
- .net 用户控件ascx.cs注册js脚本代码无效果
在.net web项目中碰到一个比较奇怪的问题,网上没找到解决方案,先自己mark一下 问题描述: 添加一个用户控件ascx,在后端.cs添加js注册脚本,执行后没有弹出框 注册脚本为: this.P ...
随机推荐
- Quartz.Net 作业调度后台管理系统,基于Extjs
Quartz.Net是一个开源的.非常灵活的作业调度框架,具体使用方法和教程:http://www.cnblogs.com/shanyou/archive/2007/08/25/quartznettu ...
- 通过PowerShell获取Windows系统密码Hash
当你拿到了系统控制权之后如何才能更长的时间内控制已经拿到这台机器呢?作为白帽子,已经在对手防线上撕开一个口子,如果你需要进一步扩大战果,你首先需要做的就是潜伏下来,收集更多的信息便于你判断,便于有更大 ...
- GNU风格 ARM汇编语法指南
汇编源程序一般用于系统最基本的初始化:初始化堆栈指针.设置页表.操作 ARM的协处理器等.这些初始化工作完成后就可以跳转到C代码main函数中执行. 1. GNU汇编语言语句格式 任何Linux汇编 ...
- [初读笔记] Cloud Migration Research: A Systematic Review (TCC, 2013)
Pooyan Jamshidi, Aakash Ahmad, Claus Pahl, "Cloud Migration Research: A Systematic Review," ...
- iOS 7新功能例子
参考https://github.com/shu223/iOS7-Sampler Code examples for the new functions of iOS 7. Contents Dyna ...
- S5PV210之Sate210-F DIY硬件,移植uboot,kernel,android 活动现在已经进入实施阶段吗,欢迎广大网友参与 !
大家一起来diy 超低价四核的exynos4412或者Cortex A8S5pv210开源开发板 商业版Sate210已经完成了好久了.Sate4412 也已经出来.但是这两个接口非常全,主要是针对企 ...
- SNF开发平台WinForm之十-Excel导入-SNF快速开发平台3.3-Spring.Net.Framework
7.1运行效果: 2.Excel导入开发实现 2.1. 创建窗体,修改命名空间 新增的窗体命名“FrmImport表名”,这个导入窗口比较其它窗口会特殊一些,需要继承BaseFormImport父级窗 ...
- Eclipse卸载插件
Eclipse卸载插件 ### 本人Eclipse版本为:Eclipse Mars 1. 选择: Help -> Install New Software , 如下图:2. 点击 what is ...
- NGUI 动态添加控件
本文链接地址: Unity3D NGUI动态创建按钮 本例仅以熟悉NGUI组件功能为目的,想快捷简便的创建按钮或其它游戏物体请参考 “Unity3D 动态实例化Prefab” 以动态创建服务器列表为例 ...
- 搭建windows下filezilla FTP服务器
FTP服务器必不可少,鉴于serv-u越来越冗余繁多的设置,个人还是比较喜欢简单.干净,满足需求即可的东东,所以选择filezilla.更主要的原因是ta是开元免费使用的,虽然免费,功能却齐全,我发现 ...