注册 登录
编程论坛 C# 论坛

[控件设计]Nobi's StatusChart - 野比的状态波形图控件 从构思到实现

野比 发布于 2008-04-22 14:01, 16152 次点击
Nobi's StatusChart - 野比的状态波形图控件
从构思到实现

野比 著

源程序下载:
Demo
只有本站会员才能查看附件,请 登录

控件
只有本站会员才能查看附件,请 登录


背景

目前比较流行的 WinForm 程序设计都会提供形象的可视化数据流动记录功能,如 FlashGet 及其衍生软件的悬浮窗网速监视图,Windows 任务管理器的 CPU、内存使用图等。
只有本站会员才能查看附件,请 登录
只有本站会员才能查看附件,请 登录


构思

为了在我们自己的程序中实现这种效果,就需要研究、分析它们的原理,掌握其规律,然后加以实现。很明显,从软件可重用性以及各种随之而来的好处考虑,我们要求将这个“波形显示”效果做成一个控件(Control)。

分析

还是以 FlashGet 的悬浮窗和 Windows 任务管理器作为研究对象。仔细观察它们的工作方式,发现它们有以下的共同点:

而通过深入研究,发现二者不同点如下:


设计

通过分析,可以决定如下:凡是二者共同点,加以重点实现;凡二者不同之处,通过设置属性(Property)进行更改。最后绘制时,基于所设置的属性,使用共同方法加以实现。
因此自定义属性如下:

控件因为要定时更新,因此具有一个内部的 Timer 对其进行定时,其 Interval 由控件的 Interval 属性指定。
对于此自定义控件,需要每次更新时在其 OnPaint() 事件中对整个控件进行绘制。绘制顺序为:背景 - 网格 - 波形,如此保证所有部分均正确画出且无遮挡。
从波形看,很明显,我们需要一个长度至少等于波形控件宽度的数组来存放每时刻波形的值,因此可以确定这个数组是和控件绘图画布宽度一致的。

算法

绘图最重要的是算法部分,如何计算如网格位置,如何将图形整体平移,如何设置波形值是本控件的重点和难点部分。
计算网格位置,以上面的 ShifttingIncrement 为 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;
            
pos = 0F;
            
for (int i = 0; i < (int)div; i++)
            
{
               
pos += gridHeight;
               
g.DrawLine(penGrid, 0, pos, w, pos);
            
}

对于波形,传入其波形值数组作为参数
            //从 0 到 w 绘制
            int len = w;
            
//根据绘制方式
            if (chartMode == StatusChart.ChartMode.Histogram)
            
{
               
for (int i = 0; i < len; i++)
               
{
                    
g.DrawLine(p, i, h - val[i], i, h);
               
}
               
g.DrawLine(p, len, h - val[len - 1], len, h);
            
}
            
else
            
{
               
len--;
               
for (int i = 0; i < len; i++)
               
{
                    
g.DrawLine(p, i, h - val[i], i + 1, h - val[i + 1]);
               
}
               
len++;
               
g.DrawLine(p, len - 1, h - val[len - 2], len, h - val[len - 1]);
            
}


如何平移,是一个难点,需要在内部定时器的 Tick() 事件中加以处理
            //更新网格偏移
            //只有启用了网格移动才处理
            if (gridShiftting)
            
{
               
iOffset += gridShifttingIncrement;
               
iOffset %= gridWidth;
            
}
            
//更新图形(整体左移)
            //必须在这里而不能在画图的同时移动,
            //若在画图中移动,则当画面被遮挡(OnPaint)事件不发生时无法更新
            int len = w;
            
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;
            Invalidate();

最后引发控件的 Invalidate() 方法使控件重绘自身。

效果

最后的控件运行效果如下图所示:
只有本站会员才能查看附件,请 登录


总结

通过设计并实现 StatusChart 控件,我们研究了波形状态监控的相关现象和原理,复习并使用了控件的设计生成,最后使用 GDI+ 技术对其进行了实现。

声明

本控件仅供,学习交流,请勿用于商业用途或其他一切正式场合。
作者野比拒绝对因擅用本控件所造成的一切法律或社会的不良后果负责。
For evaluation ONLY, NOT for commercial use!

如果你的程序用到了本控件或其部分思路,请发一份给我,让我也能分享到你的成就!

[[it] 本帖最后由 野比 于 2009-3-17 22:38 编辑 [/it]]
38 回复
#2
mylbs2008-04-22 17:17
支持 下来好好研究研究
#3
shezhenhui19892008-04-23 13:26
支持支持啊
#4
cxwl3sxl2008-05-04 16:49
能不能把你的demo分享一哈呢@!你的控件思路我晓得也明白,想要的是你的图片上那个demo程序,有项目文件最好!想研究研究~谢谢,cxwl3sxl@
#5
野比2008-05-05 02:31
嗯…我想说的是 如果你看得够仔细的话,你可以在文章的最开始找到 Demo 下载连接。我很少用邮箱,所以原谅我不会给你发邮件。
欢迎你和我交流研究心得
#6
dptan0012008-10-21 20:50
好的,顶
回去研究,研究。
#7
sinsfk2008-10-26 19:51
受教了,正在研究这部分内容....
#8
zhouxicheng2010-04-20 15:04
谢谢了,我找了有几个月了,一直在找这个
#9
snakelee1232010-07-02 15:22
请问 为什么我的VS2008英文版 不能看你的DOEM呢? 大概会是什么问题呢
#10
beifang19862010-07-03 09:17
好东西,谢谢楼主
#11
mj200611162010-08-01 10:08
楼主牛人呀!
#12
lopopoo2010-12-02 23:04
很不错的帖子,谢谢分享!
#13
sping9092011-08-17 22:46
很好的东西,可是vS2008不能看啊
#14
polar20112011-08-19 14:04
牛人真多
#15
scort2012-06-07 13:21
下载研究下,正想做个类似示波器的小工具,显示串口发上来的波形数据
#16
lin_xx2012-08-24 14:07
相当不错
#17
l090461622012-09-11 20:38
谢谢楼主分享!!!!!!!!!!
#18
rphoho2012-11-11 22:10
正需要。。。学习学习。。
#19
lj_a_b2012-11-27 10:57
下载了,谢谢分享
#20
transport1982012-12-08 20:59
lz这个东西很好啊,下来学习学习
#21
haliven2013-08-31 08:54
这个牛气!
#22
liujin9512015-02-12 23:11
为啥不搞个坐标显示呢
#23
ymxmy2015-07-16 18:03
好东西,谢谢楼主
#24
pjj5064066192015-08-09 13:03
支持楼主,学习学习
#25
yyphzc2015-09-22 14:28
受教了,正在研究这部分内容...
#26
H1M1ssAl1ce2015-12-04 10:47
支持···
#27
wdw摩羯2016-03-02 18:12
支持支持!很实用的东西
#28
lzp00372016-10-21 15:18
#29
etalk2016-10-28 16:18
bu cuo ,hengh
#30
peter21082016-12-08 13:12
谢谢分享!!!
#31
njusttian2017-01-09 18:42
16年新手看还是觉得思路清晰,赞一个
#32
隐居象牙塔2017-03-28 20:11
迫切需要学习这一方面的知识,希望这个有用,感谢分享!
#33
隐居象牙塔2017-03-28 20:11
迫切需要学习这一方面的知识,希望这个有用,感谢分享!
#34
cuisanquan2017-11-29 13:59
学习学习
#35
visitant2018-06-12 21:44
感谢分享!
#36
迪拜2018-08-25 22:13
感谢分享,好人一生平安。
#37
Su6318478292019-06-25 13:51
怎么添加刻度?左边是固定的数值,下边是时间轴
#38
fu7409710252019-07-25 22:12
#39
ukyoken2019-09-22 17:21
最近需要做预测及生成图形的工作,正好需要这个
1