创建线程类时,添加一个变量来存储面板id:
type
TMyThread = class(TThread)
public
PanelId: integer;
constructor Create(APanelId: integer);
end;
constructor TMyThread.Create(APanelId: integer);
begin
inherited Create({CreateSuspended=}true);
PanelId := APanelId;
Suspended := false;
end;
为每个线程创建一个面板并将其标签值设置为此 Id:
for i := 1 to MaxThreads do begin
threads[i] := TMyThread.Create(i);
panels[i] := TPanel.Create(Self);
panels[i].Tag := i;
end;
当您的线程需要更新面板上的数据时,它应该向主窗体发送一条特殊定义的消息:
const
WM_CONNECTED = WM_USER + 1;
WM_DISCONNECTED = WM_USER + 2;
在此消息的 wParam 中,您传递 PanelId:
procedure TMyThread.Connected;
begin
PostMessage(MainForm.Handle, WM_CONNECTED, PanelId, 0);
end;
在 MainForm 中,您捕获此消息,找到面板并更新它:
TMainForm = class(TForm)
{....}
protected
procedure WmConnected(var msg: TMessage); message WM_CONNECTED;
end;
{...}
procedure TMainForm.WmConnected(var msg: TMessage);
begin
panels[msg.wParam].Color := clGreen;
end;
与 WmDisconnected 相同。
这里重要的是,您不能也不应该尝试从主线程以外的线程更新可视组件。如果需要更新用户控件,则应将消息发布到主窗体并创建处理程序,如本例所示。然后,这些处理程序将从主线程自动调用。