D5pro:当我的应用运行一段时间后,我想在任务栏中更改应用程序图标。我有一个带有两个图标的TImageList,0和1,我发现这不会强制编译时错误,但不会更改任务栏上的图标。
date2=2/2/2
我尝试了ImageList1.GetIcon(0, Application.Icon);
// Do stuff for ten minutes here
//...
// and to put it back when finished
ImageList1.GetIcon(1, Application.Icon);
,但没有任何区别,原来的图标仍在显示。
答案 0 :(得分:1)
更改图标的基本机制是正确的。您的问题是您在主线程中所做的工作是阻止您的进程适当地响应图标的更改,即更新任务栏上图标的显示。
处理此问题的一种方法是将工作放在后台线程中并修改您的应用程序,使其遵循以下过程:
通过将工作放在后台线程中,您的主线程可以自由响应必要的消息以更新图标以响应对其所做的更改。
此实现演示了该原则。首先是一个非常简单的线程类,模拟2秒的工作":
type
TWork = class(TThread)
constructor Create(aOnTerminate: TNotifyEvent); reintroduce;
procedure Execute; override;
end;
constructor TWork.Create(aOnTerminate: TNotifyEvent);
begin
OnTerminate := aOnTerminate;
FreeOnTerminate := TRUE;
inherited Create(FALSE);
end;
procedure TWork.Execute;
begin
Sleep(2000);
end;
这是一个简单的"火灾和忘记"线。它将运行,执行其工作然后自我毁灭。这是在自定义构造函数中设置的,它接受一个事件处理程序作为线程的 OnTerminate 处理程序安装,然后再调用继承的构造函数来初始化和启动线程。
线程的执行方法在完成之前等待2秒。退出执行方法,然后触发 OnTerminate 事件。
然后,应用程序代码只需将图标更改为运行状态,并创建此工作线程的实例以执行实际工作。将应用程序图标恢复到就绪状态的代码进入回调事件,以便在工作完成后调用:
type
TForm1 = class(TForm)
ImageList1: TImageList;
btnDoWork: TButton;
procedure btnDoWorkClick(Sender: TObject);
private
{ Private declarations }
public
procedure OnComplete(Sender: TObject);
end;
procedure TForm1.btnDoWorkClick(Sender: TObject);
begin
ImageList1.GetIcon(0, Application.Icon);
TWork.Create(OnComplete);
end;
procedure TForm1.OnComplete(Sender: TObject);
begin
ImageList1.GetIcon(1, Application.Icon);
end;
注意:这是为了证明所涉及的原则。它不是一个完整而强大的解决方案。
通过将工作放在后台线程中,如果所执行的工作不完全是自包含的,则可能会出现需要解决的其他复杂情况。例如,线程可能不适合在完成时释放自身,并且可能需要同步技术来确保线程安全访问工作与代码的其他部分之间共享的任何数据和/或以其他方式更新UI如果在线程执行的工作中需要的话。
但它确实展示了您当前问题的解决方案。