Revit API にはモードレス ダイアログの使用に適応するための、外部イベント フレームワークが用意されています。これは非同期の処理用に作成されたもので、既定の頻度による Idling イベントと同様に動作します。
外部イベント フレームワークを使用してモードレス ダイアログを実装するには、次の手順を実行します。
これは、外部イベントに対して実装するインタフェースです。このインタフェースを実装するクラスのインスタンスは Revit に登録され、対応する外部イベントが発生するたびに、このインタフェースの Execute メソッドが呼び出されます。
IExternalEventHandler が実装するメソッドは Execute()メソッドと GetName()メソッドの 2 つであり、後者はイベントの名前を返します。次は、イベントの発生時に 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 メソッドを呼び出して、発生したすべてのイベントを実行します。
次の例は、ExternalCommand(コード領域の最後に表示)から呼び出されるメソッド ShowForm()を持つ IExternalApplication の実装を表しています。上記の例では、ShowForm()メソッドは外部イベント ハンドラの新しいインスタンスを作成して、新しい ExternalEvent を作成し、その後にモードレス ダイアログ ボックスを表示します。後ほどモードレス ダイアログ ボックスは 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()メソッドが呼び出されます。次は、2 つのボタン(イベントを発生させるボタンとダイアログを閉じるボタン)のある簡単なモードレス ダイアログのコード例です。
コード領域: イベントを発生 |
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 時間サイクルを待ち、その後 IExternalEventHandler.Execute()メソッドを呼び出します。この簡単な例では、上記の最初のコード領域にあるように、テキスト「Click Close to close.」が記載された TaskDialog が表示されます。
外部イベント フレームワークを使用したより複雑な例については、ModelessDialog¥ModelessForm_ExternalEvent フォルダ内の SDK にあるサンプル コードを参照してください。これは多数のボタンのあるモードレス ダイアログを使用しており、IExternalEventHandler の実装には押されたボタンを追跡するためのパブリック プロパティがあり、Execute()メソッドでその値がオンに切り替わるようになっています。