0

在我的 C# 项目中,我使用以下代码在其自己的类之外访问我的表单。

public static FormMain singletonInstance { get; private set; }

    public static void PFA(Action<FormMain> action) //PFA = PerForm Action
    {
        var form = FormMain.singletonInstance;
        if (form != null)
        {

            form.PerformAction(action);
        }
    }

    public void PerformAction(Action<FormMain> action)
    {
        if (InvokeRequired)
            Invoke(action, this);
        else
            action(this);
    }

“FormMain”中的构造函数是:

    public FormMain()
    {
        InitializeComponent();
        singletonInstance = this;
    }

我不知道如何在Delphi中做到这一点。

问题(Delphi):当我在其类之外调用时,如何更改表单上的某些内容(例如 Edit1.Text)?

提前致谢!

4

1 回答 1

8

Invoke()动作的需要与调用代码在其类内部或外部无关,有必要确保仅在创建控件的线程的上下文中调用对控件进行操作的方法。控件有线程亲和性,与 C# 或 .NET 无关,它是 Windows 工作方式固有的。控件/窗口的消息只能在创建它的线程中处理。这也适用于 Delphi,而且整个 VCL 也不是线程安全的。

Delphi VCL最接近Invoke()的是Synchronize()方法。它在辅助线程中用于调度要在主 VCL 线程的上下文中执行的代码,用户界面线程需要在其中创建所有 VCL 控件,因此在其中处理这些控件的所有 Windows 消息,并且是唯一一个真正安全的调用任何控制方法。

Delphi 程序不会自行创建任何辅助线程,您必须自己创建。但除非你这样做,否则一切都发生在主线程上下文中,无需调用Synchronize()。您可以简单地调用您需要调用的方法。

继续您的示例:您为编辑控件设置新文本,如下所示:

Form1.Edit1.Text := 'foo bar baz';

这假设包含TForm1该类的单元包含一个变量Form1,它通常会这样做。这类似于 C# 代码中的单例。它之所以有效,是因为拖放到表单上的所有控件都将具有公共可见性。

题外话

请注意,虽然这是相当常见的代码,但它违反了Demeter 法则。更改表单中的控件将需要随后更改以这种方式访问​​它们的所有代码。但这完全是另一个讨论。

于 2009-06-27T17:44:00.393 回答