新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 七段数码显示的数字时钟【附源码】 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 6032 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 七段数码显示的数字时钟【附源码】 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 七段数码显示的数字时钟【附源码】

    摘要
    绝大多数的电子产品都使用了七段数码显示,如果软件也能模拟出这种效果该有多好?在本文之前,VC知识库在线杂志曾有两篇文章介绍过如何实现这种效果,有一篇的实现方法较为简单,但绘出的数字不够逼真,而另一篇实现的效果虽然逼真,但必须依赖位图资源,并且无法设置前景色和背景色等。笔者经过仔细的研究与试验,终于找到了较好的解决办法。本文将详细讲述七段数码显示的数字时钟的实现。
    关键字 七段数码显示 数字时钟
    实现原理
    我们知道,时钟的显示由时、分、秒及冒号组成,因此我们可以用以下函数来实现:DrawHour,DrawMinute,DrawSecond和Draw2Dot。由于时、分、秒都由两个数字组成(小于10的前面加0),因此可以再把问题分解,用DrawSingleNunber来画单个数字。单个数字又该怎么画呢?下面看七段数码的组成,我们用1到7的标号来表示每一段。

    由于每个数字都是由这七段拼凑而成,因此我们可以在DrawSingleNumber函数中用switch语句,根据不同的数字去画不同的段,接下来的工作就是如何去画这七段了,每一段都是一个具有颜色填充的多边形。

    void CDigitalClock::DrawSingleNumber(int nNum,int nLeft)
    {
     switch (nNum)
     {
     case 0:
      DrawSection1(nLeft);
      DrawSection2(nLeft);
      DrawSection3(nLeft);
      DrawSection4(nLeft);
      DrawSection5(nLeft);
      DrawSection6(nLeft);
      break;
     case 1:  
      DrawSection2(nLeft);
      DrawSection3(nLeft);  
      break;
     case 2:
      DrawSection1(nLeft);
      DrawSection2(nLeft);
      DrawSection4(nLeft);
      DrawSection5(nLeft);
      DrawSection7(nLeft);
      break;
     case 3:
      DrawSection1(nLeft);
      DrawSection2(nLeft);
      DrawSection3(nLeft);
      DrawSection4(nLeft);  
      DrawSection7(nLeft);
      break;
     case 4:  
      DrawSection2(nLeft);
      DrawSection3(nLeft);  
      DrawSection6(nLeft);
      DrawSection7(nLeft);
      break;
     case 5:
      DrawSection1(nLeft);
      DrawSection3(nLeft);
      DrawSection4(nLeft);
      DrawSection6(nLeft);
      DrawSection7(nLeft);
      break;
     case 6:
      DrawSection1(nLeft);
      DrawSection3(nLeft);
      DrawSection4(nLeft);
      DrawSection5(nLeft);
      DrawSection6(nLeft);
      DrawSection7(nLeft);
      break;
     case 7:
      DrawSection1(nLeft);
      DrawSection2(nLeft);
      DrawSection3(nLeft);  
      break;
     case 8:
      DrawSection1(nLeft);
      DrawSection2(nLeft);
      DrawSection3(nLeft);
      DrawSection4(nLeft);
      DrawSection5(nLeft);
      DrawSection6(nLeft);
      DrawSection7(nLeft);
      break;
     case 9:
      DrawSection1(nLeft);
      DrawSection3(nLeft);
      DrawSection4(nLeft);
      DrawSection2(nLeft);
      DrawSection6(nLeft);
      DrawSection7(nLeft);
      break;
     default:
      ;
     }
    }

    要画出逼真的效果来,必须精确或基本精确去计算出多边形的每个顶点的坐标,然后用作图函数MoveTo和LineTo去画线条,画线前,可以构造一个画笔,用指定的颜色去画。把几个边的线条画好后,发现还需要进行填充,因此再去构造一个区域,使用画刷进行填充。这样一来,不仅画出了立体效果,还可以设置不同的背景色和前景色。以下代码展示了第一段的绘制过程
    void CDigitalClock::DrawSection1(int nLeft)
    {
     if (m_memDC.m_hDC!=NULL)
     {
      CPoint point[4];
      point[0].x=nLeft+(int)(0.1*m_nWidth);
      point[0].y=m_nYmargin;

      point[1].x=nLeft+(int)(0.9*m_nWidth);
      point[1].y=m_nYmargin;

      point[2].x=nLeft+(int)(0.7*m_nWidth);
      point[2].y=(int)(0.2*m_nWidth)+m_nYmargin;

      point[3].x=nLeft+(int)(0.3*m_nWidth);
      point[3].y=(int)(0.2*m_nWidth)+m_nYmargin;

      CBrush br(m_crText);
      CRgn rgn;
      rgn.CreatePolygonRgn(point,4,ALTERNATE);
      m_memDC.FillRgn(&rgn,&br);

      br.DeleteObject();
      rgn.DeleteObject();
      
      m_memDC.MoveTo(point[0]);
      m_memDC.LineTo(point[1]);
      
      m_memDC.MoveTo(point[1]);
      m_memDC.LineTo(point[2]);
      
      m_memDC.MoveTo(point[2]);
      m_memDC.LineTo(point[3]);
      
      m_memDC.MoveTo(point[3]);
      m_memDC.LineTo(point[0]);   
     } 
    }

    实现了这些基本元素“段”,就可以画单个数字了,进而可以在不同的位置画出时、分、秒。冒号由一个专门的函数Draw2Dot来实现。
    void CDigitalClock::Draw2Dot(int nLeft)
    {
     if (m_memDC.m_hDC!=NULL)
     {
      CBrush br(m_crText);    

      CRect rect;
      rect.SetRect(nLeft+(int)(0.3*m_nWidth),(int)(0.4*m_nWidth)+m_nYmargin,
       nLeft+(int)(0.6*m_nWidth),(int)(0.7*m_nWidth)+m_nYmargin);
      m_memDC.Ellipse(rect);
      CRgn rgn1;
      rgn1.CreateEllipticRgn(rect.left,rect.top,rect.right,rect.bottom);
      m_memDC.FillRgn(&rgn1,&br);

      rect.OffsetRect(0,(int)(0.8*m_nWidth)+m_nYmargin);
      m_memDC.Ellipse(rect);
      CRgn rgn2;
      rgn2.CreateEllipticRgn(rect.left,rect.top,rect.right,rect.bottom);
      m_memDC.FillRgn(&rgn2,&br);

      br.DeleteObject();
      rgn1.DeleteObject();
      rgn2.DeleteObject();
     }
    }

    结语
    要实现七段数码显示的效果,关键在于计算各个顶点的坐标,经过调试发现,将一个数字的宽度调整为高度的一半时可达到最好的显示效果。最初设计这个类时,我是在OnPaint里面调用自定义绘图函数DrawHour、DrawMinute、DrawSecond以及Draw2Dot,结果发现绘出的时钟有明显闪烁,后来采用双缓冲绘图的办法消除了这一现象。
    本文实现的数字时钟从CStatic派生,使用时,只需在界面上放置一个静态文本控件,然后关联一个CDigitalClock的控件变量即可。示例代码在VC6.0+Windows XP下编译通过。


    [此贴子已经被作者于2008-7-17 15:53:42编辑过]

       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/7/16 9:06:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/7/29 9:42:15

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms