您现在的位置:首页 >> VCL >> VCL >> 内容

关于Delphi中的TTimer组件使用

时间:2011/9/3 16:26:08 点击:

  核心提示:如果使用传统的SDK开发方式,那么,创建和销毁一个定时器有两个API可以使用:UINT_PTR SetTimer( HWND hWnd, // handle to window, 用来接收WM_TIM...
如果使用传统的SDK开发方式,那么,创建和销毁一个定时器有两个API可以使用:
UINT_PTR SetTimer(
  HWND hWnd,              // handle to window, 用来接收WM_TIMER消息的窗体句柄
  UINT_PTR nIDEvent,      // timer identifier, 定时器的ID
  UINT uElapse,           // time-out value, 定时器的超时值
  TIMERPROC lpTimerFunc   // timer procedure,定时器的处理函数
);

BOOL KillTimer(
  HWND hWnd,          // handle to window,窗体句柄
  UINT_PTR uIDEvent   // timer identifier,定时器的标示
);

       但是,这种方式的定时并不能达到很精确的定时。因为当有到达了设置的时间时,windows仅仅是将一条WM_TIMER消息放入应用程序的消息队列,如果应用程序没有及时的处理,定时将可能更长。需要注意的是:WM_TIMER消息在应用程序的队列中不会同时出现两次,如果上次的WM_TIMER没有被处理,windows会将其合并成一条新的消息。

       再看看Delphi中TTimer组件的继承关系:
      TObject
       |
       |-- TPersist
         |
         |-- TComponent
           |
           |-- TTimer

   进入TTimer的实现单元,我们可以看到,在TTimer中,有一个窗体句柄:FWindowHandle: HWND;
   在TTimer的Create时:
       FWindowHandle := Classes.AllocateHWnd(WndProc);
    AllocateHWnd过程创建了一个类名为TPutilWindow的窗口:

  UtilWindowClass: TWndClass = (
    style: 0;
    lpfnWndProc: @DefWindowProc;
    cbClsExtra: 0;
    cbWndExtra: 0;
    hInstance: 0;
    hIcon: 0;
    hCursor: 0;
    hbrBackground: 0;
    lpszMenuName: nil;
    lpszClassName: 'TPUtilWindow');

  Result := CreateWindowEx(WS_EX_TOOLWINDOW, UtilWindowClass.lpszClassName,
                            '', WS_POPUP {!0}, 0, 0, 0, 0, 0, 0, HInstance, nil);
然后设置窗体过程为WndProc.
     使用Spy++察看,果然可以看到一个大小为0的窗体。不仅仅在TTimer中使用了该类窗体,而且,所有的弹出菜单(TPopupMenu)的管理窗体都是TPutilWindow。

再看看TTimer的窗口回调函数:WndProc中只处理了WM_TIMER:
procedure TTimer.WndProc(var Msg: TMessage);
begin
  with Msg do
    if Msg = WM_TIMER then
      try
        Timer;
      except
        Application.HandleException(Self);
      end
    else
      Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
end;

Timer为动态方法(dynamic):
procedure TTimer.Timer;
begin
  //如果用户自定义了FOnTimer事件,则调用该事件
  if Assigned(FOnTimer) then FOnTimer(Self);
end;

在设置Interval的中,调用UpdateTimer:
该方法调用Windows API SetTimer设置一个定时器:
procedure TTimer.UpdateTimer;
begin
  //如果已经存在,则销毁之前的timer
  KillTimer(FWindowHandle, 1);
  //重新设置Timer
  if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
    if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
      raise EOutOfResources.Create(SNoTimers);
end;

作者:网络 来源:转载
共有评论 1相关评论
发表我的评论
  • 大名:
  • 内容:
本类推荐
  • 没有
本类固顶
  • 没有
  • 盒子文章(www.2ccc.com) © 2020 版权所有 All Rights Reserved.
  • 沪ICP备05001939号