外部事件Revit API提供了一个外部事件框架,以适应非模态对话框的使用。它是为异步处理量身定制的,其操作类似于具有默认频率的Idling事件。
要使用外部事件框架实现无模式对话框,请执行以下步骤:
通过从IExternalEventException接口派生来实现外部事件处理程序
使用静态ExternalEvent.Create()方法创建ExternalEvent
当需要执行Revit操作的无模式对话框中发生事件时,调用ExternalEvent.Raise()
当存在可用的空闲时间周期时,Revit将调用IExternalEvents.Execute()方法的实现。
IExternalEventHandler这是要为外部事件实现的接口。实现此接口的类的实例注册到Revit中,每次引发相应的外部事件时,都会调用此接口的Execute方法。
IExternalEventHandler 只有两个方法要实现,Execute()方法和GetName(),后者应该返回事件的名称。下面是一个基本的实现,它将在引发事件时显示TaskDialog。
**代码区域:实现IExternalEventHandler **
123456789101112public 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对象来引发事件。
代码区域:创建外部事件
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162public 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()方法。下面的示例是一个简单的无模式对话框的代码,该对话框有两个按钮:一个用于引发事件,另一个用于关闭对话框。
代码区域:引发事件
12345678910111213141516171819202122232425262728293031323334public 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