信息发布软件,b2b软件,广告发布软件

标题: Delphi程序开发自己的第一个桌面是地种程序 [打印本页]

作者: 群发软件    时间: 2017-8-3 15:20
标题: Delphi程序开发自己的第一个桌面是地种程序
本帖最后由 群发软件 于 2017-8-3 15:24 编辑

  最近在学习Delphi,以不同的实现方式来体现学习的过程,刚开始直接在窗体上绘制时钟,完成使用定时器后,又用线程实现时钟的走动(见第一个、第二个程序)。接着以封装成组件类,方便下次使用,也分别用定时器和线程实现(见第三个、第四个程序)。最后,以GDI+绘制时钟,效果比GDI好很多,也利用到双缓冲机制和定时器(见第五个程序)。

时钟[定时器控制]

时钟[线程控制]

时钟[定时器组件]  需要先安装“时钟/Source/Clock.pas”组件,再打开工程。

时钟[多线程组件]  需要先安装“时钟/Source/Clock.pas”组件,再打开工程。

时钟[GDI+和定时器]  需要有IGDI+环境(见文章Delphi 7下IGDIPlus库的使用),再安装“时钟/Source/Clock.pas”组件,接着再打开工程。


delphi写时钟,delphi模拟时钟,delphi桌面时钟源码

   制作石英钟 (0 folders, 12 files, 26.51 KB, 26.51 KB in total.)

   Exa22.dcu 9.21 KB

   Exa22.dfm 799 bytes

   Exa22.pas 4.79 KB

   Exa22_pro.bdsproj 8.05 KB

   Exa22_pro.bdsproj.local 463 bytes

   Exa22_pro.cfg 428 bytes

   Exa22_pro.dpr 233 bytes

   Exa22_pro.identcache 160 bytes

   Exa22_pro.res 876 bytes

Delphi程序开发自己的第一个桌面是地种程序 b2b软件


在Windows中的很多场合下编程(例如工业控制、游戏)中需要比较精确的记时器,本文讨论的是在Delphi下实现记时器的若干方法以及它们的精度控制问题。

在Delphi中最常用的是Timer控件,它的设置和使用都非常方便,理论上它的记时精度可以达到1ms(毫秒)。但是众所周知的,实际上Timer在记时间隔小于50ms之下是精度是十分差的。它只适用于对于精度要求不太高的场合。

        这里作者要介绍的是两种利用Windows API函数实现精确记时的方法。第一中方法是利用高性能频率记数(作者本人的称呼)法。利用这种方法要使用两个API函数QueryPerformanceFrequency和QueryPerformanceCounter。QueryPerformanceFrequency函数获得高性能频率记数器的震荡频率。

调用该函数后,函数会将系统频率记数器的震荡频率(每毫秒)保存到一个LargeInteger中。不过利用该函数在几台机器上做过试验,结果都是1193180。读者朋友可以在自己的机器上试一下

QueryPerformanceCounter函数获得系统频率记数器的震荡次数,结果也保存到一个Largenteger中。

很显然,如果在计时中首先使用QueryPerformanceFrequency获得高性能频率记数器每毫秒的震荡次数,然后在计时开始时使用QueryPerformanceCounter函数获得当前系统频率记数器的震荡次数。在计时结束时再调用QueryPerformanceCounter函数获得系统频率记数器的震荡次数。将两者相减,再将结果除以频率记数器每毫秒的震荡次数,就可以获得某一事件经过的准确时间。(次数除以频率等于时间)

另外的一种精确记时器的功能是利用多媒体记时器函数(这也是作者的定义,因为这个系列的函数是在Winmm.dll中定义并且是为媒体播放服务的)。

实现多媒体记时器首先要使用timeSetEvent函数建立计时事件。该函数在Delphi中的mmsystem.pas中有定义,定义如下:

function timeSetEvent(uDelay, uResolution: UINT;

   lpFunction: TFNTimeCallBack; dwUser: DWord; uFlags: UINT): MMRESULT; stdcall

函数定义中参数uDelay定义延迟时间,以毫秒为单位,该参数相当于Timer控件的Interval属性。参数uResolution定义记时精度,如果要求尽可能高的精度,要将该参数设置为0;参数lpFunction定义了timeSetEvent函数的回调函数。该函数相当于一个定时中断处理函数,每当经过一个uDelay长度的时间间隔,该函数就会被调用,编程者可以在该函数中加入相应的处理语句。参数dwUser定义用户自定义的回调值,该值将传递给回调函数。参数uFlags定义定时类型,如果要不间断的记时,该值应设置为1。

如果函数调用成功,在系统中建立了一个多媒体记时器对象,每当经过一个uDelay时间后lpFunction指定的函数都会被调用。同时函数返回一个对象标识,如果不再需要记时器则必须要使用timeKillEvent函数删除记时器对象。

XML:namespace prefix = o ns = "urn:schemas-microsoft-comfficeffice" />

由于Windows是一个多任务的操作系统,因此基于API调用的记时器的精度都会受到其它很多因素的干扰。到底这两中记时器的精度如何,我们来使用以下的程序进行验证:

设置三种记时器(Timer控件、高性能频率记数、多媒体记时器)。将它们的定时间隔设置为10毫秒,让它们不停工作直到达到一个比较长的时间(比如60秒),这样记时器的误差会被累计下来,然后同实际经过的时间相比较,就可以得到它们的精度。

下面是具体的检测程序。

unit Unit1;interfaceuses   Windows, Messages, SysUtils, Classes, GraphiCS, Controls, Forms, Dialogs,   StdCtrls, ExtCtrls,mmSystem;type   TForm1 = class(TForm)     Edit1: TEdit;     Edit2: TEdit;     Edit3: TEdit;     Button1: TButton;     Button2: TButton;     Timer1: TTimer;     procedure FormCreate(Sender: TObject);     procedure Button1Click(Sender: TObject);     procedure Timer1Timer(Sender: TObject);     procedure Button2Click(Sender: TObject);   private     { Private declarations }   public     { Public declarations }   end;var   Form1: TForm1;   actTime1,actTime2:Cardinal;   smmCount,sTimerCount,sPCount:Single;   hTimeID:Integer;   iTen:Integer;   proTimeCallBack:TFNTimeCallBack;procedure TimeProc(uTimerID, uMessage: UINT;      dwUser, dw1, dw2: DWord) stdcall;procedure proEndCount;implementation{$R *.DFM}//timeSetEvent的回调函数procedure proEndCount;begin   actTime2:=GetTickCount-actTime1;   Form1.Button2.Enabled :=False;   Form1.Button1.Enabled :=TRue;   Form1.Timer1.Enabled :=False;   smmCount:=60;   sTimerCount:=60;   spCount:=-1;   timeKillEvent(hTimeID);end;procedure TimeProc(uTimerID, uMessage: UINT;     dwUser, dw1, dw2: DWord) stdcall;begin   Form1.Edit2.Text:=FloatToStr(smmCount);   smmCount:=smmCount-0.01;end;procedure TForm1.FormCreate(Sender: TObject);begin   Button1.Caption :='开始倒计时';   Button2.Caption :='结束倒计时';   Button2.Enabled :=False;   Button1.Enabled :=True;   Timer1.Enabled :=False;   smmCount:=60;   sTimerCount:=60;   sPCount:=60;end;procedure TForm1.Button1Click(Sender: TObject);var   lgTick1,lgTick2,lgPer:TLargeInteger;   fTemp:Single;begin   Button2.Enabled :=True;   Button1.Enabled :=False;   Timer1.Enabled :=True;   Timer1.Interval :=10;   proTimeCallback:=TimeProc;   //timeSetEvent hTimeID:=timeSetEvent(10,0,proTimeCallback,1,1);   actTime1:=GetTickCount;   //获得系统的高性能频率计数器在一秒内的震动次数
QueryPerformanceFrequency(lgPer);   fTemp:=lgPer/1000;   iTen:=Trunc(fTemp*10);   QueryPerformanceCounter(lgTick1);   lgTick2:=lgTick1;   sPCount:=60;   while sPCount>0 do begin     QueryPerformanceCounter(lgTick2);     //如果时钟震动次数超过10毫秒的次数则刷新Edit3的显示     If lgTick2 - lgTick1 > iTen Then begin             lgTick1 := lgTick2;             sPCount := sPCount - 0.01;             Edit3.Text := FloatToStr(sPCount);             Application.ProcessMessages;     end;   end;end;procedure TForm1.Timer1Timer(Sender: TObject);begin   Edit1.Text := FloatToStr(sTimerCount);   sTimerCount:=sTimerCount-0.01;end;procedure TForm1.Button2Click(Sender: TObject);begin   proEndCount;   //显示从开始记数到记数实际经过的时间   ShowMessage('实际经过时间'+IntToStr(actTime2)+'毫秒');end;end.

        运行程序,点击“开始倒记时”按钮,程序开始60秒倒记时,由于上面的程序只涉及了记时器程序的原理而没有将错误处理加入其中,所以不要等60秒倒记时结束。点击“结束倒记时”按钮可以结束倒记时。这时在弹出对话框中会显示实际经过的时间(单位为毫秒),将三个文本框内的时间乘以1000再加上实际经过的时间,越接近60000,则记时精度越高。

下面是在我的机器上的执行结果。

XML:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />ASPectratio="t">2000/temp/msoclip1/01/clip_image001.jpg" o:title="精确记时器">

        从上面的结果看,由Delphi的Timer控件建立的记时器的精度十分差,无法在实际中使用,而利用高性能频率记数法和多媒体计数器法的误差都在1%以下。考虑到程序中在文本框中显示时间对程序所造成的影响,这个误差在应用中是完全可以忽略的。

另外在运行程序时作者还发现一个问题,如果在倒记时时拖动窗口,文本框中的显示都会停止,而当停止窗口拖放后,多媒体记时器显示会跳过这段时间记时,而其它两种记时器显示倒记时却还是从原来的时间倒数。这说明多媒体记时器是在独立的线程中运行的,不会受到程序的影响。

综合上面的介绍和范例,我们可以看到,如果要建立高精度的记时器,使用多媒体记时器是比较好的选择。而高性能频率记数法比较适合计算某个耗时十分短的过程所消耗的时间(例如分析程序中某个被多次调用的程序段执行时间以优化程序),因为毕竟高性能频率记数的理论可以达到微秒级别。Timer控件虽然精度比上面两者差很多,但是它使用方便,在要求不高的场合它还是最佳选择。




作者: chenzhanhua    时间: 2017-8-4 21:16
意思,出差一直没顾上。微信平台开发找你们做绝对是正确的选择。服务是值得肯定的,售后也非常到位,技术支持很强大,重点是热心.不厌其烦。不像有些玩技术的那个清高啊,那个沟通难度啊真不是一般的高。
作者: 阿拉丁    时间: 2017-8-5 22:48
欢迎前来参观本店百德家具广场
作者: a5206662    时间: 2017-8-7 00:57
功能蛮齐全的,价格698也不高,找了好几间就觉得这家性价比最高了。客服的态度也不错,说以后还能继续提供技术支持。总之整体而言挺满意~
作者: java12005    时间: 2017-8-11 01:20
,制作完美。
作者: nble002    时间: 2017-8-12 06:51
和5号笨蛋服务不错,好评!!
作者: ufo50200    时间: 2017-8-13 08:23
很好独特运行速度也很快卖家很专业
作者: ctbvip    时间: 2017-8-15 00:20
好,速度快,下次碰到问题还来找您!
作者: ufo50200    时间: 2017-8-18 06:16
非常好,很耐心,很专业的团队,希望下次继续合作!
作者: cjagl520    时间: 2017-8-18 12:06
的很好,对我一个菜鸟很用心的指导!老板还说了,以后不懂的,都可以找他解决!全部五星!嘿嘿~~~
作者: 都敏俊系    时间: 2017-8-19 02:45
很快,服务周到
作者: 小痞子    时间: 2017-8-19 12:03
值得好评,大爱
作者: 1124789174    时间: 2017-8-20 18:59
量非常好,与卖家描述的完全一致,非常满意卖家的服务太棒了,考虑非常周到
作者: niubttt    时间: 2017-8-22 20:32
任了,就像巴黎欧莱雅,你值得拥有
作者: chenzhanhua    时间: 2017-8-23 03:06
谢卖家。三两下就解决了问题
作者: xiaozhu168    时间: 2017-8-26 22:27
诚信的店铺,完全为客户考虑,我购买了PC端和电脑端模板,店家都很热心的帮忙解决问题店家基本都在线,很是尽职尽责,服务无忧,售后无忧,我是新店家,她帮了我很多。真心感谢!
作者: meili1    时间: 2017-8-26 22:28
客服姐姐晨曦都值得表扬,加班加点很敬业修改了10几次,都依依解决。最后都非常满意,现在像这种有问题能随时改正
作者: pwl2015    时间: 2017-8-30 23:23
很好用,店家手把手教真好
作者: xubaojin    时间: 2017-8-31 05:20
的细心指导和安装,服务热情周到,很好很成功的一次网购,我还会再来的!




欢迎光临 信息发布软件,b2b软件,广告发布软件 (http://postbbs.com/) Powered by Discuz! X3.2