Delphi - TTimer的源码

技术交流,DH讲解.

我之前用一个线程实现了Timer的功能,现在我们来看看Delphi自带的Timer怎么实现的?
其实,不看代码也大致知道怎么的?
1 SetTimer 和 KillTimer 2个API来控制Timer的启动和关闭
2 响应WM_Timer消息执行用户事件.
由于Timer是一个不可视控件,应该从TComponent继承,但是TComponent不具备处理消息的能力,也就是我们需要手动创建窗体过程然后分配给它.
好说了这么多,看代码:

  TTimer = class(TComponent)
  private
    //间隔时间
    FInterval: Cardinal;
    //接收消息的句柄
    FWindowHandle: HWND;
    //用户事件
    FOnTimer: TNotifyEvent;
    FEnabled: Boolean;
    //当属性设置后,更新计时器
    //kill掉已有的,然后创建新的
    procedure UpdateTimer;
    //Setter
    procedure SetEnabled(Value: Boolean);
    procedure SetInterval(Value: Cardinal);
    procedure SetOnTimer(Value: TNotifyEvent);
    //窗体过程
    procedure WndProc(var Msg: TMessage);
  protected
    procedure Timer; dynamic;
{$IF DEFINED(CLR)}
  strict protected
    procedure Finalize; override;
{$IFEND}
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Enabled: Boolean read FEnabled write SetEnabled default True;
    property Interval: Cardinal read FInterval write SetInterval default 1000;
    property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
  end;
我们就看关键的方法UpdateTimer和WndProc窗体过程.
procedure TTimer.UpdateTimer;
begin
  if FWindowHandle <> 0 then
    KillTimer(FWindowHandle, 1);

  if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
  begin
    if FWindowHandle = 0 then    //分配句柄处理消息
      FWindowHandle := AllocateHWnd(WndProc);
    if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
      raise EOutOfResources.Create(SNoTimers);
  end
  else
  if FWindowHandle <> 0 then
  begin
    DeallocateHWnd(FWindowHandle);  //取消句柄处理消息
    FWindowHandle := 0;
  end;
end;
窗体过程都干了什么呢?
procedure TTimer.WndProc(var Msg: TMessage);
begin
  with Msg do
    if Msg = WM_TIMER then
      try
        Timer;
      except
        Application.HandleException(Self);
      end
    else//其他消息,采用默认的windows处理方式
      Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
end;
这个有个timer方法,干什么的呢?对了,就是执行用户事件的.
procedure TTimer.Timer;
begin
  if Assigned(FOnTimer) then FOnTimer(Self);
end;

也很简单嘛,主要让大家看看控件怎么编写的.

我是DH

posted @ 2010-03-03 15:23  HuangJacky  阅读(3005)  评论(0编辑  收藏  举报
AdminLogin