外部イベント

外部イベント

Revit API にはモードレス ダイアログの使用に適応するための、外部イベント フレームワークが用意されています。これは非同期の処理用に作成されたもので、既定の頻度による Idling イベントと同様に動作します。

外部イベント フレームワークを使用してモードレス ダイアログを実装するには、次の手順を実行します。

  1. IExternalEventHandler インタフェースから派生させて、外部イベント ハンドラを実装します
  2. 静的 ExternalEvent.Create()メソッドを使用して ExternalEvent を作成します
  3. Revit の操作が必要なモードレス ダイアログでイベントが発生した後、ExternalEvent.Raise()を呼び出します
  4. 使用可能な Idling 時間サイクルがある場合、Revit は IExternalEventHandler.Execute()メソッドの実装を呼び出します。

IExternalEventHandler

これは、外部イベントに対して実装するインタフェースです。このインタフェースを実装するクラスのインスタンスは 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 を作成するには、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()メソッドでその値がオンに切り替わるようになっています。