我的应用程序有一些任务需要在后台运行。我使用任务计划程序在需要任务时运行应用程序,并在任务完成后自行关闭。到目前为止,一切都很好。
任务可能要花一些时间才能完成,因此我在任务开始和结束时都会向操作中心发送通知。对于第一个,我没有问题,但是在第二个通知中,我想在用户单击日志文件时打开一个日志文件。
操作中心显示两个通知,但是单击通知时日志文件不会打开。我猜是因为该应用程序已经关闭。
到目前为止,我尝试了以下方法。
uses
System.SysUtils, System.Classes, System.Notification,
System.Generics.Collections;
type
TActionCenter = class(TDataModule)
NotificationCenter: TNotificationCenter;
procedure NotificationCenterReceiveLocalNotification(Sender: TObject;
ANotification: TNotification);
strict private
FNotifications: TDictionary<string, TOnReceiveLocalNotification>;
public
class procedure AppRegister(const ACompanyName: string);
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
procedure SendNotification(const ATitle, AMessage: string); overload;
procedure SendNotification(const ATitle, AMessage: string; AOnClick: TOnReceiveLocalNotification); overload;
end;
var
_ActionCenter: TActionCenter;
...
uses
System.Hash, System.Win.Registry, Winapi.Windows;
procedure TActionCenter.AfterConstruction;
begin
inherited;
FNotifications := TDictionary<string, TOnReceiveLocalNotification>.Create;
end;
class procedure TActionCenter.AppRegister(const ACompanyName: string);
const
ActionCenterKey = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\';
var
ApplicationKey: string;
Registry: TRegistry;
begin
ApplicationKey := ACompanyName + '.DesktopToasts.' + THashBobJenkins.GetHashString(ParamStr(0));
Registry := TRegistry.Create;
try
Registry.RootKey := HKEY_CURRENT_USER;
if not Registry.KeyExists(ActionCenterKey + ApplicationKey) then
begin
Registry.Access := KEY_WRITE;
if Registry.OpenKey(ActionCenterKey + ApplicationKey, True) then
Registry.WriteInteger('ShowInActionCenter', 1);
end;
finally
Registry.Free;
end;
end;
procedure TActionCenter.BeforeDestruction;
begin
inherited;
FNotifications.Free;
end;
procedure TActionCenter.NotificationCenterReceiveLocalNotification(
Sender: TObject; ANotification: TNotification);
var
Pair: TPair<string, TOnReceiveLocalNotification>;
begin
Pair := FNotifications.ExtractPair(ANotification.Name);
if Assigned(Pair.Value) then
Pair.Value(Sender, ANotification);
end;
procedure TActionCenter.SendNotification(const ATitle, AMessage: string);
begin
SendNotification(ATitle, AMessage, nil);
end;
procedure TActionCenter.SendNotification(const ATitle, AMessage: string;
AOnClick: TOnReceiveLocalNotification);
var
Notification: TNotification;
begin
Notification := NotificationCenter.CreateNotification;
try
Notification.Name := TGUID.NewGuid.ToString;
Notification.Title := ATitle;
Notification.AlertBody := AMessage;
FNotifications.Add(Notification.Name, AOnClick);
NotificationCenter.PresentNotification(Notification);
finally
Notification.Free;
end;
end;
initialization
TActionCenter.AppRegister('MyCompanyName');
_ActionCenter := TActionCenter.Create(nil);
finalization
_ActionCenter.Free;
...
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, ActionCenter.Classes;
type
TMain = class(TForm)
Send: TButton;
procedure SendClick(Sender: TObject);
strict private
procedure NotificationClick1(ASender: TObject; ANotification: TNotification);
procedure NotificationClick2(ASender: TObject; ANotification: TNotification);
procedure NotificationClick3(ASender: TObject; ANotification: TNotification);
procedure OpenLog(FileName: TFileName);
end;
....
uses
Winapi.ShellAPI;
procedure TMain.NotificationClick1(ASender: TObject; ANotification: TNotification);
begin
OpenLog('C:\First.txt');
end;
procedure TMain.NotificationClick2(ASender: TObject; ANotification: TNotification);
begin
OpenLog('C:\Second.txt');
end;
procedure TMain.NotificationClick3(ASender: TObject; ANotification: TNotification);
begin
OpenLog('C:\Third.txt');
end;
procedure TMain.OpenLog(FileName: TFileName);
var
Handle: THandle;
begin
Handle := GetStdHandle(STD_INPUT_HANDLE);
ShellExecute(Handle, nil, PChar(FileName), nil, nil, SW_SHOWNORMAL);
end;
有没有办法做到这一点?即使在应用关闭后,OnReceiveLocalNotification事件是否仍然有效?
答案 0 :(得分:0)
我解决了用TTrayIcon和OnBaloonClick替换TNotificationCenter和OnReceiveLocalNotification的问题。似乎TTrayIcon通知使应用程序运行了几秒钟。这不是完美的解决方案,但到目前为止已经足够。