我希望我的表格在06:00,12:00和24:00结束时关闭.但在关闭之前,我想显示一个进度条,显示表单关闭前剩余的时间(当进度条达到100%时 - 表单关闭).我怎样才能做到这一点?
编辑:我这样做:
procedure TMainForm.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
AdvOfficeStatusBar1.Panels[4].Progress.Position := AdvOfficeStatusBar1.Panels[4].Progress.Position +1;
if AdvOfficeStatusBar1.Panels[4].Progress.Position = 100 then begin
MainForm.Close;
end;
Timer1.Enabled := True;
end;
Run Code Online (Sandbox Code Playgroud)
所以我需要的可能是另一个计时器,它可以检测当天的时间并在指定的时间点击进度条(Timer1.Enabled:= True;).你如何在代码中检测到合适的时间?
我建议你调查Waitable计时器.这些可以设置为在特定时间段(如常规TTimer)之后或在一天中的指定时间触发,这正是您在这种情况下所需的.
在您的表单创建/显示事件中,创建一个等待计时器并将其设置为您希望"触发"的所需时间(它将只是您的候选关闭时间之一,即下一个在当前时间之后发生) .在你的情况下,我相信你提到在倒闭时间前90秒开始倒计时,所以这是你的等待计时器的"到期时间"(下一个T - 90秒).
您设置的截止时间必须在FILETIME中指定,并且必须是UTC,而不是本地时间.这很繁琐,但并不是特别困难.
计算下一个自动关闭时间,减去90秒.然后将DateTimeToSystemTime(localTDateTime,localSYSTEMTIME)用于SYSTEMTIME表示形式的结果TDateTime值,然后您可以将其传递给TzSpecificLocalTimeToSystemTime()以转换为UTC SYSTEMTIME.
从那里,你只需再转换你的UTC SYSTEMTIME到FILETIME(SystemTimeToFileTime()在SysUtils单元).
回调proc是第一类proc,而不是form方法,并且必须符合预期的回调签名.
回调proc将在一个单独的线程中调用,因此启动倒计时器的回调实现必须是线程安全的.实现这一目标的最简单方法是利用消息队列并简单地将消息发送(或发布)到表单,然后通过启动倒数计时器来响应.为了确保使用正确的窗口句柄,可以将其传递给回调过程.由于HWND适合指针,因此可以通过类型转换直接传递指针中的HWND.
你的回调过程看起来像这样:
procedure TimerCallbackProc(aData: Pointer; aTimerLo, aTimerHi: DWORD);
begin
PostMessage(HWND(aData), MM_STARTCOUNTDOWNTIMER, 0, 0);
end;
Run Code Online (Sandbox Code Playgroud)
其中MM_STARTCOUNTDOWNTIMER是一个基于WM_USER的私有消息,表单处理该消息以启动倒计时器:
注意: 您的表单必须在计时器被"解雇"之前或之后取消时取消回调计时器.
把所有这些放在一起,你应该得到类似的东西:
const
MM_STARTCOUNTDOWNTIMER = WM_USER + 1;
type
TMyForm = class(TForm)
fCloseCountdownTimer: TTimer;
fCloseTimer: HANDLE;
..
procedure MMStartCountdownTimer(var aMessage: TMessage); message MM_STARTCOUNTDOWNTIMER;
end;
procedure TMyForm.FormCreate(Sender: TObject);
begin
..
..
fCloseTimer := CreateWaitableTimer( .. );
SetWaitableTimer( fCloseTimer, dueTime, 0, TimerCallbackproc, Pointer(Handle), TRUE );
end;
procedure TMyForm.FormClose(Sender: TObject);
begin
CancelWaitableTimer( fCloseTimer );
end;
procedure TMyForm.MMStartCountdownTimer(var aMessage: TMessage);
begin
fCloseCountdownTimer.Enabled := TRUE;
end;
Run Code Online (Sandbox Code Playgroud)
注意:上面代码中对SetWaitableTimer()的调用中的最后一个TRUE参数确保如果系统在计时器触发时暂停,则系统将唤醒以处理计时器.如果这不是您想要的,那么只需传递FALSE,并且计时器不会唤醒睡眠系统(但是如果在系统处于睡眠状态时已经过去了,您的表单将不会自动关闭).
有关更多更具体的细节,我建议您参考Microsoft的Waitable Timer API文档
| 归档时间: |
|
| 查看次数: |
754 次 |
| 最近记录: |