更改图标的基本机制是正确的。您的问题是您在主线程中执行的工作会阻止您的进程正确响应图标更改,即更新任务栏上图标的显示。
一个对付这种方式是将工作在后台线程并修改应用程序,使其遵循以下流程:
- 更改图标“忙碌”状态。
- 创建线程来执行工作
- 更改图标返回到“就绪”状态,当工作完成
通过将工作在后台线程主线程仍然可以自由地到必要的消息作出响应,更新图标以响应对其所做的更改。
该实现演示了原理。首先一个非常简单的线程类,模拟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;
这是一个简单的“发射后不管”的线程。它会运行,执行它的工作,然后自我毁灭。这是在自定义构造函数中设置的,该构造函数在调用继承构造函数以初始化和启动线程之前接受要作为线程处理程序安装的事件处理程序。
执行线程的方法只需等待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时可能不合适如果在线程执行工作期间需要的话。
但它确实证明了解决您目前的问题。
问题中的代码无法编译。请显示[mcve]。 –