30外部事件

外部事件

Revit API提供了一个外部事件框架,以适应非模态对话框的使用。它是为异步处理量身定制的,其操作类似于具有默认频率的Idling事件。

要使用外部事件框架实现无模式对话框,请执行以下步骤:

  1. 通过从IExternalEventException接口派生来实现外部事件处理程序
  2. 使用静态ExternalEvent.Create()方法创建ExternalEvent
  3. 当需要执行Revit操作的无模式对话框中发生事件时,调用ExternalEvent.Raise()
  4. 当存在可用的空闲时间周期时,Revit将调用IExternalEvents.Execute()方法的实现。

IExternalEventHandler

这是要为外部事件实现的接口。实现此接口的类的实例注册到Revit中,每次引发相应的外部事件时,都会调用此接口的Execute方法。

IExternalEventHandler 只有两个方法要实现,Execute()方法和GetName(),后者应该返回事件的名称。下面是一个基本的实现,它将在引发事件时显示TaskDialog。

**代码区域:实现IExternalEventHandler **

public class ExternalEventExample : IExternalEventHandler
{
    public void Execute(UIApplication app)
    {
        TaskDialog.Show("External Event", "Click Close to close.");
    }

    public string GetName()
    {
        return "External Event Example";
    }
}

外部事件

ExternalEvent类用于创建ExternalEvent。此类的实例将在事件创建时返回给外部事件的所有者。事件的所有者将使用此实例来通知Revit应调用该事件。Revit将定期检查是否有任何事件已发出信号(引发),并将执行通过调用事件各自处理程序上的Execute方法引发的所有事件。

下面的示例演示IExternalApplication的实现,该IExternalApplication具有从ExternalCommand(显示在代码区域的末尾)调用的ShowForm()方法。ShowForm()方法从上面的例子中创建了一个外部事件处理程序的新实例,创建了一个新的ExternalEvent,然后显示无模式对话框,该对话框稍后将使用传入的ExternalEvent对象来引发事件。

代码区域:创建外部事件

public class ExternalEventExampleApp : IExternalApplication
{
    // class instance
    public static ExternalEventExampleApp thisApp = null;
    // ModelessForm instance
    private ExternalEventExampleDialog m_MyForm;

    public Result OnShutdown(UIControlledApplication application)
    {
        if (m_MyForm != null && m_MyForm.Visible)
        {
            m_MyForm.Close();
        }

        return Result.Succeeded;
    }

    public Result OnStartup(UIControlledApplication application)
    {
        m_MyForm = null;   // no dialog needed yet; the command will bring it
        thisApp = this;  // static access to this application instance

        return Result.Succeeded;
    }

    //   The external command invokes this on the end-user's request
    public void ShowForm(UIApplication uiapp)
    {
        // If we do not have a dialog yet, create and show it
        if (m_MyForm == null || m_MyForm.IsDisposed)
        {
            // A new handler to handle request posting by the dialog
            ExternalEventExample handler = new ExternalEventExample();

            // External Event for the dialog to use (to post requests)
            ExternalEvent exEvent = ExternalEvent.Create(handler);

            // We give the objects to the new dialog;
            // The dialog becomes the owner responsible for disposing them, eventually.
            m_MyForm = new ExternalEventExampleDialog(exEvent, handler);
            m_MyForm.Show();
        }
    }
}

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class Command : IExternalCommand
{
    public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        try
        {
            ExternalEventExampleApp.thisApp.ShowForm(commandData.Application);
            return Result.Succeeded;
        }
        catch (Exception ex)
        {
            message = ex.Message;
            return Result.Failed;
        }
    }
}

一旦显示非模态对话框,用户就可以与之交互。对话框中的操作可能需要触发Revit中的某些操作。发生这种情况时,将调用ExternalEvent.Raise()方法。下面的示例是一个简单的无模式对话框的代码,该对话框有两个按钮:一个用于引发事件,另一个用于关闭对话框。

代码区域:引发事件

public partial class ExternalEventExampleDialog : Form
{
    private ExternalEvent m_ExEvent;
    private ExternalEventExample m_Handler;

    public ExternalEventExampleDialog(ExternalEvent exEvent, ExternalEventExample handler)
    {
        InitializeComponent();
        m_ExEvent = exEvent;
        m_Handler = handler;
    }

    protected override void OnFormClosed(FormClosedEventArgs e)
    {
        // we own both the event and the handler
        // we should dispose it before we are closed
        m_ExEvent.Dispose();
        m_ExEvent = null;
        m_Handler = null;

        // do not forget to call the base class
        base.OnFormClosed(e);
    }

    private void closeButton_Click(object sender, EventArgs e)
    {
        Close();
    }

    private void showMessageButton_Click(object sender, EventArgs e)
    {
        m_ExEvent.Raise();
    }
}

调用ExternalEvent.Raise()方法时,Revit将等待可用的Idling计时器,然后调用IExternalEventEvent.Execute()方法。在这个简单的例子中,它将显示一个TaskDialog,文本为“Click Close to close.”“,如上面第一个代码区域所示。

有关使用外部事件框架的更复杂示例,请参见SDK中ModelessDialog\ModelessForm_ExternalEvent文件夹下的示例代码。它使用一个带有许多按钮的非模态对话框,IExternalEventEvent实现有一个公共属性来跟踪按下了哪个按钮,因此它可以在Execute()方法中打开该值。

注:翻译自Revit API Developers Guide

posted @ 2024-11-29 15:59  funtim  阅读(82)  评论(0)    收藏  举报