VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)
首页 - 经验之谈 - 七段数码管显示控件的制作与应用
发表评论(0)作者:马近科, 平台:VB6.0+Win98, 阅读:12221, 日期:2001-02-15
七段数码管显示控件的制作与应用

烟台鲁宝钢管有限责任公司 马近科

--------------------------------------------------------------------------------


七段数码管在工业控制中有着很广泛的应用,例如用来显示温度、数量、重量、日期、时间,还可以用来显示比赛的比分等,具有显示醒目、直观的优点。笔者采用VC++6.0开发了七段数码管显示控件,用在支持ActiveX技术的软件系统中(如VB,VC,EXCEL等),取得了很好的效果。本文分为两部分,第一部分介绍如何用VC++开发七段数码管显示控件,第二部分用VB建立一个数字时钟,用例子来说明如何在VB6.0中使用该控件。
一、七段数码管显示控件的制作
1、原理:首先将数码管分为七段,如下图所示:



根据数码(0,1,2,3,4,5,6,7,8,9)来决定七段中的某一段或某几段进行绘制,例如如果数码为0,则显示0、1、2、3、4、5段;数码为1,则显示1、2段,依次类推。
2、运行AppWizard来生成SevenSegNum工程。通过从File菜单选择New,然后在Project选项卡上选定MFC ActiveX ControlWizard .命名工程名为SevenSegNum,接受其他默认设置。
3、使用ClassWizard(快捷键Ctrl+W)在CSevenSegNumCtrl类中重载OnDraw函数。在SevenSegNumCtrl.CPP文件中编辑如下所示代码:
void CSevenSegNumCtrl::OnDraw( CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
//共七段,每段分为7个点,画7个封闭的多边形,表示7段的每一段
POINT p0[7],p1[7],p2[7],p3[7],p4[7],p5[7],p6[7];
int iLineWidth;//段的宽度
int iUnit=3;//将段的宽度分为3份,决定每段的起始和终止部分的斜线夹角
//取控件宽度和高度数值小的数值来决定段宽
if(rcBounds.Height() < rcBounds.Width()){
iLineWidth=rcBounds.Height()/10; //缺省段宽为控件宽度或高度的1/10
}
else{
iLineWidth=rcBounds.Width()/10;
}
//第零个段
p0[0].x=iLineWidth/iUnit;
p0[0].y=iLineWidth/iUnit;
p0[1].x=iLineWidth/iUnit*(iUnit-1);
p0[1].y=rcBounds.top;
p0[2].x=rcBounds.right - iLineWidth/iUnit*(iUnit-1);
p0[2].y=rcBounds.top;
p0[3].x=rcBounds.right - iLineWidth/iUnit;
p0[3].y=iLineWidth/iUnit;
p0[4].x=rcBounds.right - iLineWidth;
p0[4].y=iLineWidth;
p0[5].x=iLineWidth;
p0[5].y=iLineWidth;
p0[6].x=iLineWidth/iUnit;
p0[6].y=iLineWidth/iUnit;
//第一个段
p1[0].x=rcBounds.right - iLineWidth/iUnit;
p1[0].y=iLineWidth/iUnit*2;
p1[1].x=rcBounds.right ;
p1[1].y=iLineWidth/iUnit*3 ;
p1[2].x=rcBounds.right;
p1[2].y=rcBounds.Height()/2 - iLineWidth/iUnit ;
p1[3].x=rcBounds.right - iLineWidth/iUnit;
p1[3].y=rcBounds.Height()/2;
p1[4].x=rcBounds.right - iLineWidth;
p1[4].y=rcBounds.Height()/2 - iLineWidth/iUnit*(iUnit-1);
p1[5].x=rcBounds.right - iLineWidth;
p1[5].y=iLineWidth/iUnit*(iUnit+1);
p1[6].x=rcBounds.right - iLineWidth/iUnit;
p1[6].y=iLineWidth/iUnit*2;
//第二个段
p2[0].x=rcBounds.right - iLineWidth/iUnit;
p2[0].y=rcBounds.Height()/2;
p2[1].x=rcBounds.right ;
p2[1].y=rcBounds.Height()/2 + iLineWidth/iUnit ;
p2[2].x=rcBounds.right;
p2[2].y=rcBounds.Height() - iLineWidth/iUnit*3 ;
p2[3].x=rcBounds.right - iLineWidth/iUnit;
p2[3].y=rcBounds.Height() - iLineWidth/iUnit*2;
p2[4].x=rcBounds.right - iLineWidth;
p2[4].y=rcBounds.Height() - iLineWidth/iUnit*(iUnit+1);
p2[5].x=rcBounds.right - iLineWidth;
p2[5].y=rcBounds.Height()/2 + iLineWidth/iUnit*(iUnit-1);
p2[6].x=rcBounds.right - iLineWidth/iUnit;
p2[6].y=rcBounds.Height()/2;
//第三个段
p3[0].x=iLineWidth/iUnit;
p3[0].y=rcBounds.Height()- iLineWidth/iUnit;
p3[1].x=iLineWidth/iUnit*(iUnit-1);
p3[1].y=rcBounds.bottom;
p3[2].x=rcBounds.right - iLineWidth/iUnit*(iUnit-1);
p3[2].y=rcBounds.bottom;
p3[3].x=rcBounds.right - iLineWidth/iUnit;
p3[3].y=rcBounds.bottom -iLineWidth/iUnit;
p3[4].x=rcBounds.right - iLineWidth;
p3[4].y=rcBounds.Height() -iLineWidth;
p3[5].x=iLineWidth;
p3[5].y=rcBounds.Height()-iLineWidth;
p3[6].x=iLineWidth/iUnit;
p3[6].y=rcBounds.Height() - iLineWidth/iUnit;
//第四个段
p4[0].x=iLineWidth/iUnit;
p4[0].y=rcBounds.Height()/2;
p4[1].x=rcBounds.left ;
p4[1].y=rcBounds.Height()/2 + iLineWidth/iUnit ;
p4[2].x=rcBounds.left;
p4[2].y=rcBounds.Height() - iLineWidth/iUnit*3 ;
p4[3].x=iLineWidth/iUnit;
p4[3].y=rcBounds.Height() - iLineWidth/iUnit*2;
p4[4].x=iLineWidth;
p4[4].y=rcBounds.Height() - iLineWidth/iUnit*(iUnit+1);
p4[5].x=iLineWidth;
p4[5].y=rcBounds.Height()/2 + iLineWidth/iUnit*(iUnit-1);
p4[6].x=iLineWidth/iUnit;
p4[6].y=rcBounds.Height()/2;
//第五个段
p5[0].x=iLineWidth/iUnit;
p5[0].y=iLineWidth/iUnit*2;
p5[1].x=rcBounds.left ;
p5[1].y=iLineWidth/iUnit*3 ;
p5[2].x=rcBounds.left;
p5[2].y=rcBounds.Height()/2 - iLineWidth/iUnit ;
p5[3].x=iLineWidth/iUnit;
p5[3].y=rcBounds.Height()/2;
p5[4].x=iLineWidth;
p5[4].y=rcBounds.Height()/2 - iLineWidth/iUnit*(iUnit-1);
p5[5].x=iLineWidth;
p5[5].y=iLineWidth/iUnit*(iUnit+1);
p5[6].x=iLineWidth/iUnit;
p5[6].y=iLineWidth/iUnit*2;
//第六个段
p6[0].x=iLineWidth/iUnit*2;
p6[0].y=rcBounds.Height()/2;
p6[1].x=iLineWidth/iUnit*(iUnit+1);
p6[1].y=rcBounds.Height()/2 - iLineWidth/2 ;
p6[2].x=rcBounds.right - iLineWidth/iUnit*(iUnit+1);
p6[2].y=rcBounds.Height()/2 - iLineWidth/2 ;
p6[3].x=rcBounds.right - iLineWidth/iUnit*2;
p6[3].y=rcBounds.Height()/2;
p6[4].x=rcBounds.right - iLineWidth/iUnit*(iUnit+1);
p6[4].y=rcBounds.Height()/2 + iLineWidth/2 ;
p6[5].x=iLineWidth/iUnit*(iUnit+1);
p6[5].y=rcBounds.Height()/2 + iLineWidth/2 ;
p6[6].x=iLineWidth/iUnit*2;
p6[6].y=rcBounds.Height()/2;
//产生封闭多边形的内部颜色画刷(分为要显示的段的颜色画刷,不需显示的段的颜色画刷),控件的背景颜色画刷
CBrush brRgn,brRect,brBackRgn;
brRgn.CreateSolidBrush(lForeColor1);
brRect.CreateSolidBrush(lBackColor);
brBackRgn.CreateSolidBrush(lForeColor2);
//填充控件背景
pdc->FillRect(rcBounds,&brRect);
//根据上面的7个数组,产生7个区域,绘制7个段
CRgn rgn0,rgn1,rgn2,rgn3,rgn4,rgn5,rgn6;
rgn0.CreatePolygonRgn(p0,7,ALTERNATE);
rgn1.CreatePolygonRgn(p1,7,ALTERNATE);
rgn2.CreatePolygonRgn(p2,7,ALTERNATE);
rgn3.CreatePolygonRgn(p3,7,ALTERNATE);
rgn4.CreatePolygonRgn(p4,7,ALTERNATE);
rgn5.CreatePolygonRgn(p5,7,ALTERNATE);
rgn6.CreatePolygonRgn(p6,7,ALTERNATE);
//根据数码的不同,决定显示的段
switch(chVal){
case 0:
pdc->FillRgn(&rgn0,&brRgn), pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brRgn);
pdc->FillRgn(&rgn4,&brRgn), pdc->FillRgn(&rgn5,&brRgn);
pdc->FillRgn(&rgn6,&brBackRgn);
break;
case 1:
pdc->FillRgn(&rgn0,&brBackRgn), pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brBackRgn);
pdc->FillRgn(&rgn4,&brBackRgn),pdc->FillRgn(&rgn5,&brBackRgn);
pdc->FillRgn(&rgn6,&brBackRgn);
break;
case 2:
pdc->FillRgn(&rgn0,&brRgn), pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brBackRgn),pdc->FillRgn(&rgn3,&brRgn);
pdc->FillRgn(&rgn4,&brRgn), pdc->FillRgn(&rgn5,&brBackRgn);
pdc->FillRgn(&rgn6,&brRgn);
break;
case 3:
pdc->FillRgn(&rgn0,&brRgn), pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brRgn);
pdc->FillRgn(&rgn4,&brBackRgn),pdc->FillRgn(&rgn5,&brBackRgn);
pdc->FillRgn(&rgn6,&brRgn);
break;
case 4:
pdc->FillRgn(&rgn0,&brBackRgn),pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brBackRgn);
pdc->FillRgn(&rgn4,&brBackRgn),pdc->FillRgn(&rgn5,&brRgn);
pdc->FillRgn(&rgn6,&brRgn);
break;
case 5:
pdc->FillRgn(&rgn0,&brRgn),pdc->FillRgn(&rgn1,&brBackRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brRgn);
pdc->FillRgn(&rgn4,&brBackRgn),pdc->FillRgn(&rgn5,&brRgn);
pdc->FillRgn(&rgn6,&brRgn);
break;
case 6:
pdc->FillRgn(&rgn0,&brRgn), pdc->FillRgn(&rgn1,&brBackRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brRgn);
pdc->FillRgn(&rgn4,&brRgn),pdc->FillRgn(&rgn5,&brRgn);
pdc->FillRgn(&rgn6,&brRgn);
break;
case 7:
pdc->FillRgn(&rgn0,&brRgn), pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brBackRgn);
pdc->FillRgn(&rgn4,&brBackRgn), pdc->FillRgn(&rgn5,&brBackRgn);
pdc->FillRgn(&rgn6,&brBackRgn);
break;
case 8:
pdc->FillRgn(&rgn0,&brRgn),pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brRgn);
pdc->FillRgn(&rgn4,&brRgn), pdc->FillRgn(&rgn5,&brRgn);
pdc->FillRgn(&rgn6,&brRgn);
break;
case 9:
pdc->FillRgn(&rgn0,&brRgn), pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brRgn);
pdc->FillRgn(&rgn4,&brBackRgn), pdc->FillRgn(&rgn5,&brRgn);
pdc->FillRgn(&rgn6,&brRgn);
break;
default:
pdc->FillRgn(&rgn0,&brRgn), pdc->FillRgn(&rgn1,&brRgn);
pdc->FillRgn(&rgn2,&brRgn), pdc->FillRgn(&rgn3,&brRgn);
pdc->FillRgn(&rgn4,&brRgn), pdc->FillRgn(&rgn5,&brRgn);
pdc->FillRgn(&rgn6,&brRgn);
break;
}
}
4、增加四个私有变量到CSevenSegNumCtrl类。在SevenSegNumCtrl.h中增加如下所示的变量。
private:
long lBackColor;
long lForeColor2;
long lForeColor1;
short chVal;
5、增加函数。用快捷键Ctrl+W 打开ClassWizard,选择Automation选项卡,在Class name编辑框选择CSevenSegNumCtrl类,单击Add Method按钮,弹出Add Method对话框,在External name编辑框内输入SetValue,在Return type编辑框内选择void类型,在Parameter list列表中增加参数chValue,类型为short,按OK按钮返回MFC ClassWizard选项卡,单击Edit code按钮,在void CSevenSegNumCtrl::SetValue(short chValue) 函数中输入如下代码:
void CSevenSegNumCtrl::SetValue(short chValue)
{
chVal=chValue;
//刷新控件
CRect rc;
GetClientRect(&rc);
InvalidateRect(rc,TRUE);  
}
类似上面步骤,添加如下三个函数。
void CSevenSegNumCtrl::SetBackColor(long Backcolor)  
{
lBackColor=Backcolor;
CRect rc;
GetClientRect(&rc);
InvalidateRect(rc,TRUE);  
}
void CSevenSegNumCtrl::SetForeColor1(long ForeColor1)  
{
lForeColor1=ForeColor1;
CRect rc;
GetClientRect(&rc);
InvalidateRect(rc,TRUE);  
}
void CSevenSegNumCtrl::SetForeColor2(long ForeColor2)  
{
lForeColor2=ForeColor2;
CRect rc;
GetClientRect(&rc);
InvalidateRect(rc,TRUE);  
}
6、添加如下代码到CsevenSegNumCtrl类的构造函数中,用以初始化变量,如下所示:
CSevenSegNumCtrl::CSevenSegNumCtrl()
{
InitializeIIDs(&IID_DSevenSegNum, &IID_DSevenSegNumEvents);
chVal=48; //初始显示为0
lForeColor1=RGB(255,0,0); //数码颜色
lForeColor2=RGB(166,154,151); //不显示的段的颜色
lBackColor=RGB(192,192,192); //控件背景
}
7、编译该工程,名为SevenSegNum Control的控件已经加入注册表,可以被支持ActiveX技术的软件使用了。
到现在为止,七段数码管显示控件开发完毕,该控件可以自由拉伸缩放,可以设置控件的背景色、需要显示的段的颜色、不需要显示的段的颜色等功能。

二、七段数码管显示控件应用举例
下面用VB6.0(英文版)开发一个数字时钟的例子,来说明该控件的使用方法。
1、新建一个Standard Exe工程,通过从Project菜单选择Components(或Ctrl+T),在Components对话框已经注册的控件列表中找到SevenSegNum ActiveX Control Module项,单击该项左边的方框,选择该控件,按确定退出。这时可以看到在左边的Toolbox中七段数码管控件。将该控件放置到窗体上。
2、参照步骤1,再加入5个七段数码管控件,调整这6个控件的大小、位置等。
3、设置窗体的Caption属性为“数字时钟”
4、向窗体添加4个Shape控件,这4个控件的Shape属性均为3(3-Circle),BackStyle属性均为1(1-opaque),BackColor属性均为红色(&H000000FF&),BorderColor属性设置为与窗体的背景色相同,调整这4个Shape控件的大小,使之与七段数码管控件以及窗体比较协调。
5、在窗体上放置一个Timer控件,Timer控件的Interval属性等于1000(即每秒显示1次)
6、双击Timer控件,输入如下代码:
Private Sub Timer1_Timer()
Dim s As Variant
s = Time
注释:设置控件的背景色
SevenSegNum1.SetBackColor RGB(192, 192, 192)
SevenSegNum2.SetBackColor RGB(192, 192, 192)
SevenSegNum3.SetBackColor RGB(192, 192, 192)
SevenSegNum4.SetBackColor RGB(192, 192, 192)
SevenSegNum5.SetBackColor RGB(192, 192, 192)
SevenSegNum6.SetBackColor RGB(192, 192, 192)
注释:设置控件显示段的颜色
SevenSegNum1.SetForeColor1 RGB(255, 0, 0)
SevenSegNum2.SetForeColor1 RGB(255, 0, 0)
SevenSegNum3.SetForeColor1 RGB(255, 0, 0)
SevenSegNum4.SetForeColor1 RGB(255, 0, 0)
SevenSegNum5.SetForeColor1 RGB(255, 0, 0)
SevenSegNum6.SetForeColor1 RGB(255, 0, 0)
注释:设置控件不显示段的颜色
SevenSegNum1.SetForeColor2 RGB(188, 188, 188)
SevenSegNum2.SetForeColor2 RGB(188, 188, 188)
SevenSegNum3.SetForeColor2 RGB(188, 188, 188)
SevenSegNum4.SetForeColor2 RGB(188, 188, 188)
SevenSegNum5.SetForeColor2 RGB(188, 188, 188)
SevenSegNum6.SetForeColor2 RGB(188, 188, 188)
注释:设置控件显示的数码
SevenSegNum1.SetValue int(Mid(s, 1, 1))
SevenSegNum2.SetValue int(Mid(s, 2, 1))
SevenSegNum3.SetValue int(Mid(s, 4, 1))
SevenSegNum4.SetValue int(Mid(s, 5, 1))
SevenSegNum5.SetValue int(Mid(s, 7, 1))
SevenSegNum6.SetValue int(Mid(s, 8, 1))
End Sub
按F5运行,一个数字时钟就制作完毕。如下图所示:



程序在PIII500,128M内存,Win98,VB6.0 VC6.0环境下调试通过。