技术交流,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;
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;
procedure TTimer.Timer; begin if Assigned(FOnTimer) then FOnTimer(Self); end;
也很简单嘛,主要让大家看看控件怎么编写的.
我是DH