在上面例子中, 每點一次鼠標, 那個回調函數才執行一次; 作為定時器, 如果想讓它每秒執行一次怎麼弄?
但每一次執行那個 APC 函數, 都得有 SleepEx(當然不止它)給送進去, 那這樣得反復調用 SleepEx 才可以.
怎麼調用, 用循環嗎? 別說網上能找到的例子我沒見到不用循環的(太笨了), 就在那個 APC 函數裡調用不就完了.
當然這時一般要設時間間隔的, 下面我們將設間隔為 1000(1秒).
但接著問題又來了, 譬如把代碼修改成:
var
hTimer: THandle;
procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWord;
dwTimerHighValue: DWord); stdcall;
begin
Form1.Text := IntToStr(StrToIntDef(Form1.Text, 0) + 1);
SleepEx(INFINITE, True); {這裡再次調用 SleepEx}
end;
procedure TForm1.Button1Click(Sender: TObject);
var
DueTime: Int64;
begin
hTimer := CreateWaitableTimer(nil, True, nil);
DueTime := 0;
{下面的參數 1000 表示間隔 1秒}
if SetWaitableTimer(hTimer, DueTime, 1000, @TimerAPCProc, nil, False) then
begin
SleepEx(INFINITE, True);
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(hTimer);
end;
任務能完成, 但窗體"死"了... 怎麼辦? 嘿, 現在學的不是多線程嗎?
下面例子中, 同時使用了 CancelWaitableTimer 來取消定時器, 很好理解;效果圖:
代碼文件:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
hTimer: THandle;
{APC 函數}
procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWord;
dwTimerHighValue: DWord); stdcall;
begin
Form1.Text := IntToStr(StrToIntDef(Form1.Text, 0) + 1);
SleepEx(INFINITE, True);
end;
{線程入口函數}
function MyThreadFun(p: Pointer): Integer; stdcall;
var
DueTime: Int64;
begin
DueTime := 0;
{SetWaitableTimer 必須與 SleepEx 在同一線程}
if SetWaitableTimer(hTimer, DueTime, 1000, @TimerAPCProc, nil, False) then
begin
SleepEx(INFINITE, True);
end;
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ID: DWord;
begin
{建立 WaitableTimer 對象}
if hTimer = 0 then hTimer := CreateWaitableTimer(nil, True, nil);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ID); {建立線程}
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
CancelWaitableTimer(hTimer); {取消定時器}
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(hTimer);
end;
end.