{******************************************************************************} { CnPack For Delphi/C++Builder } { 中国人自己的开放源码第三方开发包 } { (C)Copyright 2001-2016 CnPack 开发组 } { ------------------------------------ } { } { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 } { 改和重新发布这一程序。 } { } { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 } { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 } { } { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 } { 还没有,可访问我们的网站: } { } { 网站地址:http://www.cnpack.org } { 电子邮件:master@cnpack.org } { } {******************************************************************************} unit CnCodeDemo; {* |
================================================================================ * 软件名称:CnPack组件包 * 单元名称:组件代码规范示例单元 * 单元作者:周劲羽 (zjy@cnpack.org) * 开发平台:PWin98SE + Delphi 5.0 * 兼容测试:PWin9X/2000/XP + Delphi 5/6 * 本 地 化:该单元中的字符串均符合本地化处理方式 * 单元标识:$Id: Delphi单元规范格式.pas,v 1.8 2009/02/25 12:32:57 liuxiao Exp $ * 备 注:- 此单元仅仅只作为 CnPack 的代码规范示例单元,供阅读与对比用,不参与 * 实际的编译与调试。 * - 本例中的TCnTimer采用单独的线程进行定时控制,精度比TTimer要高,相应 * 地也占用较多的CPU资源。 * 修改记录:2009.02.18 V1.1 * 更改单元说明 * 2002.04.18 V1.0 * 创建单元 ================================================================================ |} interface {$I CnPack.inc} uses Windows, Classes, SysUtils, ExtCtrls, CnClasses, CnConsts, CnCompConsts; type //============================================================================== // 高精度定时器组件定时线程 //============================================================================== { TCnTimerThread } TCnTimer = class; TCnTimerThread = class(TThread) private FOwner: TCnTimer; FInterval: Word; FStop: THandle; protected constructor Create(CreateSuspended: Boolean); virtual; procedure Execute; override; end; //============================================================================== // 高精度定时器组件 //============================================================================== { TCnTimer } TTimerQuality = (tqHighest, tqHigh, tqLow); {* 高精度定时器定时精度类型 |
tqHighest - 最高精度,采用高优先级的线程定时
tqHigh - 高精度,采用普通优先级的线程定时
tqLow - 低精度,内部使用TTimer进行定时
|}
TCnTimer = class(TCnComponent)
{* 高精度定时器组件,使用单独的线程进行定时控制,使用方法与TTimer一样,
仅增加了一个Quality属性控制定时精度}
private
FOnTimer: TNotifyEvent;
FQuality: TTimerQuality;
FEnabled: Boolean;
FInterval: Word;
FTimerThread: TCnTimerThread;
FTimer: TTimer;
FLastTick: Cardinal;
FLastCountTick: Cardinal;
FActualInterval: Integer;
FActualRate: Integer;
FCount: Integer;
procedure DoTimer;
procedure OnTimerTimer(Sender: TObject);
procedure CreateTimer;
procedure CreateTimerThread;
procedure FreeTimer;
procedure FreeTimerThread;
procedure SetEnabled(Value: Boolean);
procedure SetInterval(Value: Word);
procedure SetQuality(const Value: TTimerQuality);
protected
function GetAuthor: string; override;
function GetComment: string; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property ActualInterval: Integer read FActualInterval;
{* 实际的定时间隔,单位为毫秒}
property ActualRate: Integer read FActualRate;
{* 实际的定时速度,单位为次每秒}
published
property Enabled: Boolean read FEnabled write SetEnabled;
{* 是否允许定时事件}
property Interval: Word read FInterval write SetInterval default 1000;
{* 定时间隔,单位为毫秒}
property Quality: TTimerQuality read FQuality write SetQuality default tqLow;
{* 定时精度,如果Interval小于55(Win9X)或10(WinNT),建议设为高精度以上}
property OnTimer: TNotifyEvent read FOnTimer write FOnTimer;
{* 定时器事件}
end;
implementation
//==============================================================================
// 高精度定时器组件定时线程
//==============================================================================
{ TCnTimerThread }
// 初始化线程
constructor TCnTimerThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FStop := CreateEvent(nil, False, False, nil); // 创建退出用事件
end;
// 线程主体
procedure TCnTimerThread.Execute;
begin
repeat // 等待退出事件置位或 FInterval 毫秒后超时退出
if WaitForSingleObject(FStop, FInterval) = WAIT_TIMEOUT then
Synchronize(FOwner.DoTimer); // 同步方式产生定时事件
until Terminated;
CloseHandle(FStop); // 释放事件句柄
end;
{ TCnTimer }
//==============================================================================
// 高精度定时器组件
//==============================================================================
// 组件初始化
constructor TCnTimer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FEnabled := False;
FInterval := 1000;
FQuality := tqLow;
FTimer := nil;
FTimerThread := nil;
CreateTimer;
end;
// 释放
destructor TCnTimer.Destroy;
begin
FreeTimer;
FreeTimerThread;
inherited Destroy;
end;
//------------------------------------------------------------------------------
// 事件产生
//------------------------------------------------------------------------------
// 产生定时事件
procedure TCnTimer.DoTimer;
var
Tick: Cardinal;
begin
Tick := GetTickCount;
if (FLastTick = 0) and (FLastCountTick = 0) then
begin
FLastTick := Tick;
FLastCountTick := Tick;
end
else
begin
FActualInterval := Tick - FLastTick;
FLastTick := Tick;
if Tick - FLastCountTick >= 1000 then
begin
FActualRate := FCount;
FLastCountTick := Tick;
FCount := 0;
end else
Inc(FCount);
end;
begin
if Assigned(FOnTimer) then
FOnTimer(Self);
end;
end;
//------------------------------------------------------------------------------
// 内部定时器创建释放
//------------------------------------------------------------------------------
// 内部Timer事件
procedure TCnTimer.OnTimerTimer(Sender: TObject);
begin
DoTimer;
end;
// 创建内部Timer定时器(低精度)
procedure TCnTimer.CreateTimer;
begin
if not Assigned(FTimer) then
begin
FTimer := TTimer.Create(Self);
FTimer.OnTimer := OnTimerTimer;
FTimer.Interval := FInterval;
FTimer.Enabled := FEnabled;
end;
end;
// 创建定时器线程(高精度)
procedure TCnTimer.CreateTimerThread;
begin
if not Assigned(FTimerThread) then
begin
FTimerThread := TCnTimerThread.Create(True);
FTimerThread.FOwner := Self;
FTimerThread.FreeOnTerminate := False;
FTimerThread.Priority := tpNormal;
FTimerThread.FInterval := FInterval;
if FEnabled then
begin
if FInterval > 0 then
begin
SetEvent(FTimerThread.FStop);
FTimerThread.Resume;
end;
end
else
FTimerThread.Suspend;
end;
end;
// 释放内部定时器(低精度)
procedure TCnTimer.FreeTimer;
begin
if Assigned(FTimer) then
begin
FTimer.Free;
FTimer := nil;
end;
end;
// 释放定时器线程(高精度)
procedure TCnTimer.FreeTimerThread;
begin
if Assigned(FTimerThread) then
begin
FTimerThread.Terminate;
SetEvent(FTimerThread.FStop);
if FTimerThread.Suspended then FTimerThread.Resume;
FTimerThread.WaitFor;
FTimerThread.Free;
FTimerThread := nil;
end;
end;
//------------------------------------------------------------------------------
// 属性读写方法
//------------------------------------------------------------------------------
// 设置定时精度
procedure TCnTimer.SetQuality(const Value: TTimerQuality);
begin
if FQuality <> Value then
begin
FQuality := Value;
case FQuality of
tqHighest, tqHigh:
begin
FreeTimer;
CreateTimerThread;
if Value = tqHighest then
FTimerThread.Priority := tpHigher
else
FTimerThread.Priority := tpNormal;
end;
tqLow:
begin
FreeTimerThread;
CreateTimer;
end;
end;
end;
end;
// 设置是否允许定时
procedure TCnTimer.SetEnabled(Value: Boolean);
begin
if Value <> FEnabled then
begin
FEnabled := Value;
if FQuality = tqLow then
FTimer.Enabled := FEnabled
else
begin
if FEnabled then
begin
if FTimerThread.FInterval > 0 then
begin
SetEvent(FTimerThread.FStop);
FTimerThread.Resume;
end;
end
else
FTimerThread.Suspend;
end;
end;
end;
// 设置定时间隔
procedure TCnTimer.SetInterval(Value: Word);
begin
if Value <> FInterval then
begin
FInterval := Value;
Enabled := False;
if FQuality = tqLow then
FTimer.Interval := FInterval
else
FTimerThread.FInterval := FInterval;
Enabled := True;
end;
end;
// 取组件作者
function TCnTimer.GetAuthor: string;
begin
Result := SCnPack_Zjy;
end;
// 取组件注释
function TCnTimer.GetComment: string;
begin
Result := SCnTimerComment;
end;
end.