冰
冰冷的雨
Unregistered / Unconfirmed
GUEST, unregistred user!
1、怎么把TWaitableTimer的Self传给TimerAPCProc?这种做法对吗:SetWaitableTimer(FHandle, DueTime, 1000, @TimerAPCProc,[red] Pointer(self), [/red]False)procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD; dwTimerHighValue: DWORD); stdcall;var WT :TWaitableTimer;begin [red]WT := TWaitableTimer(lpArgToCompletionRoutine^);[/red]红色的部分传递Self。2、程序运行到下述红色语句时出错:Project Projcet1.exe raised exception class EAccessViolation with message 'Access violation at address 004A6E40 inmodule 'Project1.exe', Write of address 004A68CC'.procedure TWaitableTimer.SetElapsedTime(const Value: TDateTime);begin gLock.Enter; try [red]FElapsedTime := Value;[/red] finally gLock.Leave; end;end;3、当剩余时间为0时,如何终止定时器?这样处理行吗?procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD; dwTimerHighValue: DWORD); stdcall;var WT :TWaitableTimer;begin WT := TWaitableTimer(lpArgToCompletionRoutine^); with WT do begin [red]if FRemainingTime>0 then …… else CancelTimer;[/red] end; SleepEx(INFINITE, True);end;源程序如下:unit WaitTimer;interfaceuses SysUtils, Classes, Windows, SyncObjs, StdCtrls;type TWaitableTimer = class(TThread) private FHandle: THandle; FStartTime: TDateTime; FShowRT: Boolean; FETParent: TStaticText; FTotalTimes: TDateTime; FElapsedTime: TDateTime; FRemainingTime: TDateTime; FRTParent: TStaticText; procedure SetHandle; procedure SetShowRT(const Value: Boolean); procedure SetStartTime; procedure SetETParent(const Value: TStaticText); function GetShowRT: Boolean; procedure SetTimer(const ETSender,RTSender: TObject); procedure SetRTParent(const Value: TStaticText); procedure SetRTCaption(const Value: string); public constructor Create(const ETSender,RTSender: TObject; const AName: String = ''); destructor Destroy(); override; procedure Execute; override; function CancelTimer: Boolean; function Time2String(aTime: TDateTime): string; procedure SetTotalTimes(const Value: TDateTime); procedure SetElapsedTime(const Value: TDateTime); procedure SetRemainingTime(const Value: TDateTime); function GetTotalTimes: TDateTime; Protected property Handle: THandle read FHandle; property StartTime: TDateTime read FStartTime; property TotalTimes: TDateTime read GetTotalTimes write SetTotalTimes; property ElapsedTime: TDateTime read FElapsedTime write SetElapsedTime; property RemainingTime: TDateTime read FRemainingTime write SetRemainingTime; property ETParent: TStaticText read FETParent write SetETParent; property RTParent: TStaticText read FRTParent write SetRTParent; property ShowRT: Boolean read GetShowRT write SetShowRT; end;implementation{ TWaitableTimer }var gLock: TCriticalSection;procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD;dwTimerHighValue: DWORD); stdcall;var WT :TWaitableTimer;begin WT := TWaitableTimer(lpArgToCompletionRoutine^); with WT do begin if FRemainingTime>0 then begin SetElapsedTime(Now - StartTime); FETParent.Caption := Time2String(FElapsedTime); if GetShowRT then begin SetRemainingTime(GetTotalTimes - FElapsedTime); SetRTCaption(Time2String(FRemainingTime)); end; end else CancelTimer; end; SleepEx(INFINITE, True);end;function TWaitableTimer.CancelTimer: Boolean;begin Result := CancelWaitableTimer(FHandle);end;constructor TWaitableTimer.Create(const ETSender, RTSender: TObject; const AName: String);begin gLock := TCriticalSection.Create; SetTimer(ETSender,RTSender); inherited Create(False);end;destructor TWaitableTimer.Destroy;begin CloseHandle(FHandle); gLock.Destroy; inherited;end;procedure TWaitableTimer.Execute;var DueTime: int64;begin inherited; DueTime := 0; if SetWaitableTimer( FHandle, DueTime, 1000, @TimerAPCProc, Pointer(self),False ) then begin SleepEx(INFINITE, True); end;end;function TWaitableTimer.GetShowRT: Boolean;begin result := False; gLock.Enter; try result := FShowRT; finally gLock.Leave; end;end;function TWaitableTimer.GetTotalTimes: TDateTime;begin result := 0; gLock.Enter; try result := FTotalTimes; finally gLock.Leave; end;end;procedure TWaitableTimer.SetElapsedTime(const Value: TDateTime);begin gLock.Enter; try FElapsedTime := Value; finally gLock.Leave; end;end;procedure TWaitableTimer.SetHandle;begin if FHandle = 0 then FHandle := CreateWaitableTimer(nil, True, nil);end;procedure TWaitableTimer.SetRemainingTime(const Value: TDateTime);begin gLock.Enter; try FRemainingTime := Value; finally gLock.Leave; end;end;procedure TWaitableTimer.SetRTCaption(const Value: string);begin if ShowRT then RTParent.Caption := Value else RTParent.Caption := '计算中……';end;procedure TWaitableTimer.SetRTParent(const Value: TStaticText);begin FRTParent := Value;end;procedure TWaitableTimer.SetShowRT(const Value: Boolean);begin gLock.Enter; try FShowRT := Value; finally gLock.Leave; end;end;procedure TWaitableTimer.SetStartTime;begin FStartTime := Now;end;procedure TWaitableTimer.SetTimer(const ETSender, RTSender: TObject);begin SetHandle; SetStartTime; SetTotalTimes(0); SetElapsedTime(0); SetRemainingTime(0); if ETSender is TStaticText then SetETParent(TStaticText(ETSender)); if RTSender is TStaticText then SetRTParent(TStaticText(RTSender)); SetRTCaption(''); SetShowRT(False);end;procedure TWaitableTimer.SetETParent(const Value: TStaticText);begin FETParent := Value;end;procedure TWaitableTimer.SetTotalTimes(const Value: TDateTime);begin gLock.Enter; try FTotalTimes := Value; if FTotalTimes<>0 then SetShowRT(True); finally gLock.Leave; end;end;function TWaitableTimer.Time2String(aTime: TDateTime): string;begin DateTimeToString(result,'hh:nn:ss',aTime);end;end.调用如下:unit Unit3;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, WaitTimer;type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; StaticText1: TStaticText; StaticText2: TStaticText; Label1: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);var WT: TWaitableTimer; i: integer; t1,t2: Int64;begin randomize; WT := TWaitableTimer.Create(StaticText1,StaticText2); t1 := GetTickCount; for I := 0 to 1000 do begin Label1.Caption := inttostr(i); Application.ProcessMessages; Sleep(random(10)); t2 := (GetTickCount - t1) * (1000 - i); WT.SetTotalTimes(t2); end; WT.Free;end;end.