应用程序名称:ModelessForm_ExternalEvent

Revit 平台:所有版本

Revit 版本:2013.0

首次发布于:2013.0

编程语言:C#

技能级别:中级

类别:基础

类型:ExternalCommand ExternalApplication

主题:显示无模式窗体(外部事件)

摘要:

该示例演示如何利用外部事件对象从外部无模式对话框与 Revit API 进行通信。

类:

Autodesk.Revit.DB;

Autodesk.Revit.UI;

Autodesk.Revit.UI.Events;

项目文件:

Command.cs

包含从接口 IExternalCommand 继承并实现 Execute 方法的 Command 类。

 

Application.cs

包含从接口 IExternalApplication 继承并实现其方法的 Command 类。

 

Request.cs

包含当前请求的变量绑定的类。

 

RequestHandler.cs

带有执行对话框用户发出的请求的方法的类。

 

ModelessForm.cs

我们无模式对话框的类。

描述:

该示例演示如何利用外部事件对象从外部无模式对话框与 Revit API 进行通信。

说明:

1. 启动 Revit 并创建一个新文档。

2. 创建几堵墙,并在其上添加一些门——保留在平面图视图中。

3. 启动 AddIn 命令——“显示无模式窗体(外部事件)”。

4. 当对话框出现时,选择一些门。

5. 使用无模式对话框中的命令按钮操纵门。

源代码

完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码

Application.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.

//
// AUTODESK PROVIDES THIS PROGRAM 'AS IS' AND WITH ALL ITS FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable. 

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;

using Autodesk;
using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.ApplicationServices;

namespace Revit.SDK.Samples.ModelessForm_ExternalEvent.CS
{
    /// <summary>
    /// Implements the Revit add-in interface IExternalApplication
    /// </summary>
    public class Application : IExternalApplication
    {
        // class instance
        internal static Application thisApp = null;
        // ModelessForm instance
        private ModelessForm m_MyForm;

        #region IExternalApplication Members
        /// <summary>
        /// Implements the OnShutdown event
        /// </summary>
        /// <param name="application"></param>
        /// <returns></returns>
        public Result OnShutdown(UIControlledApplication application)
        {
            if (m_MyForm != null && m_MyForm.Visible)
            {
                m_MyForm.Close();
            }

            return Result.Succeeded;
        }

        /// <summary>
        /// Implements the OnStartup event
        /// </summary>
        /// <param name="application"></param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        ///   This method creates and shows a modeless dialog, unless it already exists.
        /// </summary>
        /// <remarks>
        ///   The external command invokes this on the end-user's request
        /// </remarks>
        /// 
        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
                RequestHandler handler = new RequestHandler();

                // 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 fore disposing them, eventually.
                m_MyForm = new ModelessForm(exEvent, handler);
                m_MyForm.Show();
            }
        }


        /// <summary>
        ///   Waking up the dialog from its waiting state.
        /// </summary>
        /// 
        public void WakeFormUp()
        {
            if (m_MyForm != null)
            {
                m_MyForm.WakeUp();
            }
        }
        #endregion
    }
}

Request.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Threading;

namespace Revit.SDK.Samples.ModelessForm_ExternalEvent.CS
{
   /// <summary>
   ///   A list of requests the dialog has available
   /// </summary>
   /// 
   public enum RequestId : int
   {
       /// <summary>
       /// None
       /// </summary>
       None = 0,
       /// <summary>
       /// "Delete" request
       /// </summary>
       Delete = 1,
       /// <summary>
       /// "FlipLeftRight" request
       /// </summary>
       FlipLeftRight = 2,
       /// <summary>
       /// "FlipInOut" request
       /// </summary>
       FlipInOut = 3,
       /// <summary>
       /// "MakeRight" request
       /// </summary>
       MakeRight = 4,
       /// <summary>
       /// "MakeLeft" request
       /// </summary>
       MakeLeft = 5,
       /// <summary>
       /// "TurnOut" request
       /// </summary>
       TurnOut = 6,
       /// <summary>
       /// "TurnIn" request
       /// </summary>
       TurnIn = 7,
       /// <summary>
       /// "Rotate" request
       /// </summary>
       Rotate = 8
   }

   /// <summary>
   ///   A class around a variable holding the current request.
   /// </summary>
   /// <remarks>
   ///   Access to it is made thread-safe, even though we don't necessarily
   ///   need it if we always disable the dialog between individual requests.
   /// </remarks>
   /// 
   public class Request
   {
      // Storing the value as a plain Int makes using the interlocking mechanism simpler
      private int m_request = (int)RequestId.None;

      /// <summary>
      ///   Take - The Idling handler calls this to obtain the latest request. 
      /// </summary>
      /// <remarks>
      ///   This is not a getter! It takes the request and replaces it
      ///   with 'None' to indicate that the request has been "passed on".
      /// </remarks>
      /// 
      public RequestId Take()
      {
         return (RequestId)Interlocked.Exchange(ref m_request, (int)RequestId.None);
      }

      /// <summary>
      ///   Make - The Dialog calls this when the user presses a command button there. 
      /// </summary>
      /// <remarks>
      ///   It replaces any older request previously made.
      /// </remarks>
      /// 
      public void Make(RequestId request)
      {
         Interlocked.Exchange(ref m_request, (int)request);
      }
   }
}

RequestHandler.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;

using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace Revit.SDK.Samples.ModelessForm_ExternalEvent.CS
{
    /// <summary>
    ///   A class with methods to execute requests made by the dialog user.
    /// </summary>
    /// 
    public class RequestHandler : IExternalEventHandler
    {
        // A trivial delegate, but handy
        private delegate void DoorOperation(FamilyInstance e);

        // The value of the latest request made by the modeless form 
        private Request m_request = new Request();

        /// <summary>
        /// A public property to access the current request value
        /// </summary>
        public Request Request
        {
            get { return m_request; }
        }

        /// <summary>
        ///   A method to identify this External Event Handler
        /// </summary>
        public String GetName()
        {
            return "R2014 External Event Sample";
        }


        /// <summary>
        ///   The top method of the event handler.
        /// </summary>
        /// <remarks>
        ///   This is called by Revit after the corresponding
        ///   external event was raised (by the modeless form)
        ///   and Revit reached the time at which it could call
        ///   the event's handler (i.e. this object)
        /// </remarks>
        /// 
        public void Execute(UIApplication uiapp)
        {
            try
            {
                switch (Request.Take())
                {
                    case RequestId.None:
                        {
                            return;  // no request at this time -> we can leave immediately
                        }
                    case RequestId.Delete:
                        {
                            ModifySelectedDoors(uiapp, "Delete doors", e => e.Document.Delete(e.Id));
                            break;
                        }
                    case RequestId.FlipLeftRight:
                        {
                            ModifySelectedDoors(uiapp, "Flip door Hand", e => e.flipHand());
                            break;
                        }
                    case RequestId.FlipInOut:
                        {
                            ModifySelectedDoors(uiapp, "Flip door Facing", e => e.flipFacing());
                            break;
                        }
                    case RequestId.MakeLeft:
                        {
                            ModifySelectedDoors(uiapp, "Make door Left", MakeLeft);
                            break;
                        }
                    case RequestId.MakeRight:
                        {
                            ModifySelectedDoors(uiapp, "Make door Right", MakeRight);
                            break;
                        }
                    case RequestId.TurnOut:
                        {
                            ModifySelectedDoors(uiapp, "Place door Out", TurnOut);
                            break;
                        }
                    case RequestId.TurnIn:
                        {
                            ModifySelectedDoors(uiapp, "Place door In", TurnIn);
                            break;
                        }
                    case RequestId.Rotate:
                        {
                            ModifySelectedDoors(uiapp, "Rotate door", FlipHandAndFace);
                            break;
                        }
                    default:
                        {
                            // some kind of a warning here should
                            // notify us about an unexpected request 
                            break;
                        }
                }
            }
            finally
            {
                Application.thisApp.WakeFormUp();
            }

            return;
        }


        /// <summary>
        ///   The main door-modification subroutine - called from every request 
        /// </summary>
        /// <remarks>
        ///   It searches the current selection for all doors
        ///   and if it finds any it applies the requested operation to them
        /// </remarks>
        /// <param name="uiapp">The Revit application object</param>
        /// <param name="text">Caption of the transaction for the operation.</param>
        /// <param name="operation">A delegate to perform the operation on an instance of a door.</param>
        /// 
        private void ModifySelectedDoors(UIApplication uiapp, String text, DoorOperation operation)
        {
            UIDocument uidoc = uiapp.ActiveUIDocument;

            // check if there is anything selected in the active document

            if ((uidoc != null) && (uidoc.Selection != null))
            {
                ICollection<ElementId> selElements = uidoc.Selection.GetElementIds();
                if (selElements.Count > 0)
                {
                    // Filter out all doors from the current selection

                    FilteredElementCollector collector = new FilteredElementCollector(uidoc.Document, selElements);
                    ICollection<Element> doorset = collector.OfCategory(BuiltInCategory.OST_Doors).ToElements();

                    if (doorset != null)
                    {
                        // Since we'll modify the document, we need a transaction
                        // It's best if a transaction is scoped by a 'using' block
                        using (Transaction trans = new Transaction(uidoc.Document))
                        {
                            // The name of the transaction was given as an argument

                            if (trans.Start(text) == TransactionStatus.Started)
                            {
                                // apply the requested operation to every door

                                foreach (FamilyInstance door in doorset)
                                {
                                    operation(door);
                                }

                                trans.Commit();
                            }
                        }
                    }
                }
            }
        }


        //////////////////////////////////////////////////////////////////////////
        //
        // Helpers - simple delegates operating upon an instance of a door

        private void FlipHandAndFace(FamilyInstance e)
        {
            e.flipFacing(); e.flipHand();
        }

        // Note: The door orientation [left/right] is according the common
        // conventions used by the building industry in the Czech Republic.
        // If the convention is different in your county (like in the U.S),
        // swap the code of the MakeRight and MakeLeft methods.

        private static void MakeLeft(FamilyInstance e)
        {
            if (e.FacingFlipped ^ e.HandFlipped) e.flipHand();
        }

        private void MakeRight(FamilyInstance e)
        {
            if (!(e.FacingFlipped ^ e.HandFlipped)) e.flipHand();
        }

        // Note: The In|Out orientation depends on the position of the
        // wall the door is in; therefore it does not necessary indicates
        // the door is facing Inside, or Outside, respectively.
        // The presented implementation is good enough to demonstrate
        // how to flip a door, but the actual algorithm will likely
        // have to be changes in a read-world application.

        private void TurnIn(FamilyInstance e)
        {
            if (!e.FacingFlipped) e.flipFacing();
        }

        private void TurnOut(FamilyInstance e)
        {
            if (e.FacingFlipped) e.flipFacing();
        }

    }  // class

}  // namespace

ModelessForm.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
namespace Revit.SDK.Samples.ModelessForm_ExternalEvent.CS
{
   partial class ModelessForm
   {
      /// <summary>
      /// Required designer variable.
      /// </summary>
      private System.ComponentModel.IContainer components = null;

      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
      protected override void Dispose(bool disposing)
      {
         if (disposing && (components != null))
         {
            components.Dispose();
         }
         base.Dispose(disposing);
      }

      #region Windows Form Designer generated code

      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {
         this.btnExit = new System.Windows.Forms.Button();
         this.btnDeleted = new System.Windows.Forms.Button();
         this.btnFlipUpDown = new System.Windows.Forms.Button();
         this.btnFlipLeftRight = new System.Windows.Forms.Button();
         this.btnFlipLeft = new System.Windows.Forms.Button();
         this.btnFlipRight = new System.Windows.Forms.Button();
         this.btnFlipUp = new System.Windows.Forms.Button();
         this.btnFlipDown = new System.Windows.Forms.Button();
         this.btnRotate = new System.Windows.Forms.Button();
         this.SuspendLayout();
         // 
         // btnExit
         // 
         this.btnExit.Location = new System.Drawing.Point(66, 146);
         this.btnExit.Name = "btnExit";
         this.btnExit.Size = new System.Drawing.Size(89, 23);
         this.btnExit.TabIndex = 0;
         this.btnExit.Text = "Exit";
         this.btnExit.UseVisualStyleBackColor = true;
         this.btnExit.Click += new System.EventHandler(this.btnExit_Click);
         // 
         // btnDeleted
         // 
         this.btnDeleted.Location = new System.Drawing.Point(115, 102);
         this.btnDeleted.Name = "btnDeleted";
         this.btnDeleted.Size = new System.Drawing.Size(89, 24);
         this.btnDeleted.TabIndex = 8;
         this.btnDeleted.Text = "Delete";
         this.btnDeleted.UseVisualStyleBackColor = true;
         this.btnDeleted.Click += new System.EventHandler(this.btnDelete_Click);
         // 
         // btnFlipUpDown
         // 
         this.btnFlipUpDown.Location = new System.Drawing.Point(115, 12);
         this.btnFlipUpDown.Name = "btnFlipUpDown";
         this.btnFlipUpDown.Size = new System.Drawing.Size(89, 24);
         this.btnFlipUpDown.TabIndex = 2;
         this.btnFlipUpDown.Text = "In / Out";
         this.btnFlipUpDown.UseVisualStyleBackColor = true;
         this.btnFlipUpDown.Click += new System.EventHandler(this.btnFlipInOut_Click);
         // 
         // btnFlipLeftRight
         // 
         this.btnFlipLeftRight.Location = new System.Drawing.Point(12, 12);
         this.btnFlipLeftRight.Name = "btnFlipLeftRight";
         this.btnFlipLeftRight.Size = new System.Drawing.Size(89, 24);
         this.btnFlipLeftRight.TabIndex = 1;
         this.btnFlipLeftRight.Text = "Left / Right";
         this.btnFlipLeftRight.UseVisualStyleBackColor = true;
         this.btnFlipLeftRight.Click += new System.EventHandler(this.btnFlipLeftRight_Click);
         // 
         // btnFlipLeft
         // 
         this.btnFlipLeft.Location = new System.Drawing.Point(12, 42);
         this.btnFlipLeft.Name = "btnFlipLeft";
         this.btnFlipLeft.Size = new System.Drawing.Size(89, 24);
         this.btnFlipLeft.TabIndex = 3;
         this.btnFlipLeft.Text = "Left";
         this.btnFlipLeft.UseVisualStyleBackColor = true;
         this.btnFlipLeft.Click += new System.EventHandler(this.btnFlipLeft_Click);
         // 
         // btnFlipRight
         // 
         this.btnFlipRight.Location = new System.Drawing.Point(12, 72);
         this.btnFlipRight.Name = "btnFlipRight";
         this.btnFlipRight.Size = new System.Drawing.Size(89, 24);
         this.btnFlipRight.TabIndex = 5;
         this.btnFlipRight.Text = "Right";
         this.btnFlipRight.UseVisualStyleBackColor = true;
         this.btnFlipRight.Click += new System.EventHandler(this.btnFlipRight_Click);
         // 
         // btnFlipUp
         // 
         this.btnFlipUp.Location = new System.Drawing.Point(115, 42);
         this.btnFlipUp.Name = "btnFlipUp";
         this.btnFlipUp.Size = new System.Drawing.Size(89, 24);
         this.btnFlipUp.TabIndex = 4;
         this.btnFlipUp.Text = "Out";
         this.btnFlipUp.UseVisualStyleBackColor = true;
         this.btnFlipUp.Click += new System.EventHandler(this.btnFlipOut_Click);
         // 
         // btnFlipDown
         // 
         this.btnFlipDown.Location = new System.Drawing.Point(115, 72);
         this.btnFlipDown.Name = "btnFlipDown";
         this.btnFlipDown.Size = new System.Drawing.Size(89, 24);
         this.btnFlipDown.TabIndex = 6;
         this.btnFlipDown.Text = "In";
         this.btnFlipDown.UseVisualStyleBackColor = true;
         this.btnFlipDown.Click += new System.EventHandler(this.btnFlipIn_Click);
         // 
         // btnRotate
         // 
         this.btnRotate.Location = new System.Drawing.Point(12, 102);
         this.btnRotate.Name = "btnRotate";
         this.btnRotate.Size = new System.Drawing.Size(89, 24);
         this.btnRotate.TabIndex = 7;
         this.btnRotate.Text = "Rotate";
         this.btnRotate.UseVisualStyleBackColor = true;
         this.btnRotate.Click += new System.EventHandler(this.btnRotate_Click);
         // 
         // ModelessForm
         // 
         this.AcceptButton = this.btnExit;
         this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
         this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
         this.ClientSize = new System.Drawing.Size(216, 184);
         this.Controls.Add(this.btnRotate);
         this.Controls.Add(this.btnFlipRight);
         this.Controls.Add(this.btnFlipLeft);
         this.Controls.Add(this.btnFlipLeftRight);
         this.Controls.Add(this.btnFlipDown);
         this.Controls.Add(this.btnFlipUp);
         this.Controls.Add(this.btnFlipUpDown);
         this.Controls.Add(this.btnDeleted);
         this.Controls.Add(this.btnExit);
         this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
         this.MaximizeBox = false;
         this.MinimizeBox = false;
         this.Name = "ModelessForm";
         this.Opacity = 0.75D;
         this.ShowInTaskbar = false;
         this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
         this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
         this.Text = "Door Operator (External Event)";
         this.TopMost = true;
         this.ResumeLayout(false);

      }

      #endregion

      private System.Windows.Forms.Button btnExit;
      private System.Windows.Forms.Button btnDeleted;
      private System.Windows.Forms.Button btnFlipUpDown;
      private System.Windows.Forms.Button btnFlipLeftRight;
      private System.Windows.Forms.Button btnFlipLeft;
      private System.Windows.Forms.Button btnFlipRight;
      private System.Windows.Forms.Button btnFlipUp;
      private System.Windows.Forms.Button btnFlipDown;
      private System.Windows.Forms.Button btnRotate;
   }
}