【问题标题】:Delphi: refer to control from thread in frameDelphi:从框架中的线程引用控制
【发布时间】:2011-10-20 07:35:22
【问题描述】:

有一个FRAME(不是表格)和一个线程。如何从线程中引用Frame的控件?例如,我想禁用线程中的按钮。但是我没有指向按钮的指针,框架中没有全局变量。

谢谢!

【问题讨论】:

  • 您的操作方式与不使用线程的方式完全相同,只是您将处理 ListView 控件的所有内容放在一个不带任何参数的方法中,并从您的线程中调用它,如 Synchronize(MethodName )。
  • 如果使用 PostMessage 如何设置帧的句柄?谢谢!
  • 创建线程时,在线程对象中创建一个属性并设置MyThread.NotificationHandle := MyForm.Handle;
  • @Warren P,感谢您的帮助,+1!!!我知道表格句柄。框架的把手呢?这是我想知道的。
  • 您是否尝试过查看 Frame 是否具有称为 Handle 的属性?加油 MaxFax,别偷懒!

标签: delphi pointers tframe refer


【解决方案1】:

实际上,您根本不应该调用任何方法或修改 VCL 控件的任何属性,或任何对用户可见的内容(应用程序的用户界面,这意味着 VCL 控件通常在 Delphi 中,无论是在框架中还是不是)直接来自后台线程。

但是,您可以使用PostMessageTThread.SynchronizeTThread.Queue 向主线程发送事件或通知。

与其在线程对象中引用框架或控件,不如将包含框架或其他控件的表单句柄传递给线程,并使用用户消息 ( WM_USER+10001) 点赞this.

我更喜欢 PostMessage 而不是 TTHread.Synchronize 或 Queue,因为它非常简单而且效果很好。由于它与 Win32 API 相关联,因此它并不是一种跨平台友好的技术。

你应该像这样调用同步:

  TMyThread = class(TThread)
  private
    FFrame: TFrame;
    ...
  public
    constructor Create(AFrame: TFrame); 
    ...
  end;

  constructor TMyThread.Create(AFrame: TFrame);
  begin
    FFrame := AFrame;
    inherited Create;
  end;

  // do not call directly, only using Synchronize
  procedure TMyThread.AMethodWithNoParameters; 
  begin
     FFrame.Button1.Enabled := not FBusy;
  end;

  procedure TMyThread.DoWork; // called from Execute.
  begin
    FBusy := true; 
    Synchronize(AMethodWithNoParameters);
    Sleep(100); //dummy;
    FBusy := false; 
    Synchronize(AMethodWithNoParameters);
  end;

【讨论】:

  • 非常感谢!!!我使用 TThread.Synchronize。如何使用 Synchronize 执行 Button1.Enable:=False?如何引用按钮?
  • @maxfax 只需向线程公开那些需要公开的 UI 部分。
  • @David Heffernan,谢谢和 +1!怎么样?我找不到关于控件的确切信息。
  • 我真正需要的是设置列表视图的项目/子项目的文本。
  • @Warren P - 我希望你不介意我添加了一个传入 Frame 实例的构造函数示例。
【解决方案2】:

正如非常正确地指出的那样,您不能在后台线程中调用任何可视组件的任何成员。

要从线程代码中禁用按钮,您必须引用按钮或引用可以分配线程对象的事件 - 然后您可以在排队或同步过程中触发线程,就像这样:-

    type
      test=class(tthread)
         ondisablebutton:tnotifyevent;

{...}

然后,在你用 tthread.synchronize 封装的过程中,你可以调用事件,不要忘记测试它是否被分配......

procedure test.synchronisedprocedure;
begin
  if assigned(ondisablebutton) then
    ondisablebuttone(self);
end;

当您创建您设计的线程对象时,您必须将 ondisablebutton 分配给包含按钮的表单过程,如下所示:-

procedure form1.threadwantstodisablebutton(sender:tobject);
begin
  button1.enabled:=false;
end;

你的线程创建需要额外的一行:-

  mythread:=test.create;
  test.ondisablebutton:=form1.threadwantstodisablebutton;

像这样,显然您必须有权访问您定义和创建线程的 form1(或包含按钮的表单),这不一定是好的设计,但它可以工作。

【讨论】:

    猜你喜欢
    • 2010-10-14
    • 2011-04-05
    • 2016-10-27
    • 2013-06-11
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    • 2015-09-02
    相关资源
    最近更新 更多