一个简单Led控件

Led控件,可能是非常经典和常用的了,但是很遗憾的是,这个名称至少涵盖了三种控件:
1.是7段式的有发光二极管构成的Led,通常用来显示数字。
2.是指示灯,通常用来闪烁,指示电源,等状态。
3.是由发光二极管阵列组成的模拟显示屏,这种led屏有较高的分辨率,所以可以显示中文内容和一定容量的界面。

这篇文章里面说的是1.其中2这种在codeproject上面有很多例子,我曾经改写其中的例子成为在移动设备上使用。

今天我用c#写了这样一个Led控件。我也曾经下载过,可惜好像没有什么源码,想来这个东西应该没太复杂,所以干脆自己也写个玩玩。记得当年本科时候我就写过单片机程序,控制led数码管,实现了时间调节时闪烁,“霓虹灯”屏保等效果,大大出乎了老师的预期。我想作为一个控件,这个东西的主要功能是为了模拟现实中的用户界面,或者让它更美观,更有趣味一些。而如果只是为了显示一些信息,显然有太多其他的更方便的选择了。所以我用较短的时间实现了一个功能比较简陋的但是能用的控件。

它的运行效果如下:我想这个没什么可说的。


笔画变细以后是这样的:


这里我加载了6个控件,一个定时器,用来实时的显示系统时间。
对于这个控件我想了一下,也许可以使用图片资源来做,比较方便,但我还是把它做成了矢量型的,这样,把一个led中所有笔画(我称为section,段)采用一个六边形模拟,我需要随时能够计算出所有笔画的坐标,这样一个led具有6个点*7段=42个点,这样会占用300多bytes左右。如果显示的数字不多,还是可以不去在乎这点内存的。这就是矢量图的特点,如果你想表现的更细腻,显然会极大加大计算量,脑子也会累的。

然后我用下面的函数计算出七段的坐标:
/**/ /// <summary>
/// 重新计算段的坐标!!!(这种方法得出的图形将是矢量的,不受缩放影响)
/// </summary>

private   void  ComputeSections( int  ledwidth, int  ledheight)
{
    
//计算出控件中心点的坐标
    int cx=ledwidth/2;
    
int cy=ledheight/2;

    
int t1=this.m_SectionThick*3/4;    //大斜坡长
    int t2=this.m_SectionThick/4;    //小斜坡长
    int t3=this.m_SectionThick/2;    //中斜坡长
    
//段的一半长度!
    int hw=cx-this.m_SectionThick-2;    //half width of section 距离边缘2像素
    int hh=cy-this.m_SectionThick-2;    //half height of section
    Section[] s=this.m_Sections;

    
//第0段(最底下一横)
    s[0].P[0].X=cx-hw-this.m_SectionThick/4;
    s[
0].P[0].Y=cy+hh+this.m_SectionThick/4;
    s[
0].P[1].X=s[0].P[0].X-t2;
    s[
0].P[1].Y=s[0].P[0].Y-t2;
    s[
0].P[2].X=s[0].P[1].X+t1;
    s[
0].P[2].Y=s[0].P[1].Y-t1;

    
//第1段(它是中间的一横,因为和其他任何段都没对称关系,只能手写!)
    s[1].P[0].X=cx-hw+this.m_SectionThick*3/16;
    s[
1].P[0].Y=cy+t3;
    s[
1].P[1].X=s[1].P[0].X-t3;
    s[
1].P[1].Y=s[1].P[0].Y-t3;
    s[
1].P[2].X=s[1].P[0].X;
    s[
1].P[2].Y=cy-t3;

    
//第2段(最上面一横,与第0段按y轴对称)
    for(int i=0;i<3;i++)
    
{
        s[
2].P[i].X=s[0].P[2-i].X;
        s[
2].P[i].Y=ledheight-s[0].P[2-i].Y;
    }

    
//循环为0,1,2三个水平段的p[3],p[4],p[5]赋值,注意这几个值可以根据钱三个点求出
    for(int i=0;i<3;i++)
    
{
        
for(int j=3;j<6;j++)
        
{
            s[i].P[j].X
=ledwidth-s[i].P[5-j].X;
            s[i].P[j].Y
=s[i].P[5-j].Y;
        }

    }

    
//到这里我们已经计算好了0,1,2段的全部坐标,下面开始计算3~6段,他们具有相互对称的关系!
    
    
//第3段(左上的竖)(注意本身自己也不具备对称关系,6个点都要手写)
    s[3].P[0].X=cx-hw+this.m_SectionThick/5;
    s[
3].P[0].Y=cy-this.m_SectionThick*3/5;
    s[
3].P[1].X=s[3].P[0].X-t3;
    s[
3].P[1].Y=s[3].P[0].Y+t3;
    s[
3].P[2].X=s[3].P[1].X-t3;
    s[
3].P[2].Y=s[3].P[1].Y-t3;
    s[
3].P[3].X=s[3].P[2].X;
    s[
3].P[3].Y=s[3].P[0].Y-hh+this.m_SectionThick;
    s[
3].P[4].X=s[3].P[3].X+t2;
    s[
3].P[4].Y=s[3].P[3].Y-t2;
    s[
3].P[5].X=s[3].P[4].X+t1;
    s[
3].P[5].Y=s[3].P[4].Y+t1;

    
//计算4,5,6段的点坐标(4和3段x对称,5和3是y对称,6和3是原点对称)
    for(int i=0;i<6;i++)
    
{
        
int m=(8-i)%6;
        s[
4].P[i].X=ledwidth-s[3].P[m].X;
        s[
4].P[i].Y=s[3].P[m].Y;

        s[
5].P[i].X=s[3].P[m].X;
        s[
5].P[i].Y=ledheight-s[3].P[m].Y;

        s[
6].P[i].X=ledwidth-s[3].P[i].X;
        s[
6].P[i].Y=ledheight-s[3].P[i].Y;
    }

}


上面的代码可能是这个控件里唯一复杂的工作。。。。这是一个很劳累的工作,可是我暂时没想到更好的办法让它更加简化。段的编号顺序是:0底部横,1中部横,2顶部横,3左上竖,4右上竖,5左下竖,6右下竖,7小数点(我暂时没有绘制它)。

显示时,使用一个byte来控制,其所在位为1时,相应的section被点亮,否则为熄灭。
因此,几个基本数字的编码如下:
( byte ) 0x7d , // 0
( byte ) 0x50 , // 1
( byte ) 0x37 , // 2
( byte ) 0x57 , // 3
( byte ) 0x5a , // 4
( byte ) 0x4f , // 5
( byte ) 0x6f , // 6
( byte ) 0x54 , // 7
( byte ) 0x7f , // 8
( byte ) 0x5f , // 9
( byte ) 0x02 , // -

最后,当我们显示时:
// 绘制七段,section是一个struct,包含一个point数组
for ( int  i = 0 ;i < this .m_Sections.Length;i ++ )
   {
    
if((this.m_DisplayCode & (1<<i))!=0)
         {
               
this.m_Brush.Color=this.ForeColor;    
               g.FillPolygon( this.m_Brush,
this.m_Sections[i].P);
    }

    
else
         
{
                
this.m_Brush.Color=this.m_OffColor;
                g.FillPolygon(
this.m_Brush, this.m_Sections[i].P); 
       }

}

对外部可以提供一个简单的属性,displaynumber来获取和设置显示的数字,允许0~9.
也允许外部设置笔画宽度,这样上面的sections坐标需要重新计算,并更新到显示。但是这个属性不能设置的过大,否则坐标值相互超越则显示会出错。

最后我想了一下,目前它的灵活性被我怀疑,加载了6个一摸一样的led控件也让我感到使得代码很笨拙。它现在的功能比较简陋,它可以继续扩展,使他将来能够同时容纳多个显示位。

在最后我提供这个控件以及示例的完整代码下载地址:(当然,它目前还不成熟,在结构和接口上有进一步的进化空间)

http://files.cnblogs.com/hoodlum1980/LedTest_ByHoodlum.rar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值