七段数码管显示控件的制作与应用

 




七段数码管在工业控制中有着很广泛的应用,例如用来显示温度、数量、重量、日期、时间,还可以用来显示比赛的比分等,具有显示醒目、直观的优点。笔者采用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环境下调试通过。

本文作者 烟台鲁宝钢管有限责任公司 马近科 

你可能感兴趣的:(编程技术)