diff --git a/DotNet.Exchange.Revit/DotNet.Exchange.Revit.csproj b/DotNet.Exchange.Revit/DotNet.Exchange.Revit.csproj
new file mode 100644
index 0000000..86da647
--- /dev/null
+++ b/DotNet.Exchange.Revit/DotNet.Exchange.Revit.csproj
@@ -0,0 +1,69 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}
+ Library
+ Properties
+ DotNet.Exchange.Revit
+ DotNet.Exchange.Revit
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPI.dll
+ False
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Exchange.Revit/Export/ExportFactory.cs b/DotNet.Exchange.Revit/Export/ExportFactory.cs
new file mode 100644
index 0000000..924365b
--- /dev/null
+++ b/DotNet.Exchange.Revit/Export/ExportFactory.cs
@@ -0,0 +1,342 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Exchange.Revit.Export
+{
+ public class ExportFactory
+ {
+ #region fields
+ private uint m_ExportLevel;
+ private Document m_Document;
+ private IExportElement m_ExportHandle;
+ #endregion
+
+ #region properties
+ ///
+ /// 导出等级.
+ /// 1 - 10;默认等级为5.
+ ///
+ public uint ExportLevel
+ {
+ get
+ {
+ return m_ExportLevel;
+ }
+ set
+ {
+ m_ExportLevel = value;
+ }
+ }
+ #endregion
+
+ #region ctors
+ public ExportFactory(Document doc, IExportElement exportHandle)
+ {
+ if (exportHandle == null || doc == null)
+ throw new NullReferenceException("exportHandle or doc parameter is null reference !!");
+
+ m_ExportLevel = 5;
+ m_Document = doc;
+ m_ExportHandle = exportHandle;
+ }
+ #endregion
+
+ #region methods
+ ///
+ /// 导出指定的元素
+ ///
+ /// The elem array.
+ public void Export(params Element[] elemArray)
+ {
+ for (int i = 0; i < elemArray.Length; i++)
+ {
+ this.ElementExport(elemArray[i]);
+ }
+ }
+
+ ///
+ /// 导出当前文档的所有元素.
+ ///
+ public void Export()
+ {
+ var view3d = new FilteredElementCollector(m_Document)
+ .OfClass(typeof(View3D)).FirstOrDefault(m => (m as View3D).Origin != null);
+
+ if (view3d == null)
+ throw new NullReferenceException();
+
+ var elems = new FilteredElementCollector(m_Document, view3d.Id).WhereElementIsNotElementType();
+
+ var eum = elems.GetElementIterator();
+ while (eum.MoveNext())
+ {
+ this.ElementExport(eum.Current);
+ }
+ }
+
+ ///
+ /// 异步导出指定元素.
+ ///
+ public void AsynchExport(params Element[] elemArray)
+ {
+ Task.Run(() => this.Export(elemArray));
+ }
+
+ ///
+ /// 异步导出当前文档所有元素.
+ ///
+ public void AsynchExport()
+ {
+ Task.Run(() => this.Export());
+ }
+
+ #endregion
+
+ #region privates
+
+ ///
+ /// Elements the export.
+ ///
+ private bool ElementExport(Element elem)
+ {
+ if (!m_ExportHandle.OnElementStart(elem))
+ {
+ return false;
+ }
+
+ var transform = default(Transform);
+ if (elem is Instance)
+ {
+ transform = (elem as Instance).GetTransform();
+ }
+
+
+ var objects = this.GetGeometryObject(elem);
+ if (objects.Count == 0)
+ {
+ return false;
+ }
+
+ while (objects.Count > 0)
+ {
+ var obj = objects.Pop();
+
+ var node = new GeometryObjectNode(obj);
+ if (!m_ExportHandle.OnGeometryObjectStart(node))
+ {
+ return false;
+ }
+
+ if (obj.GetType().Equals(typeof(Solid)))
+ {
+ var solid = obj as Solid;
+
+ var faces = solid.Faces;
+
+ var eum = faces.GetEnumerator();
+ while (eum.MoveNext())
+ {
+ var face = (Face)eum.Current;
+
+ // not handle....
+ m_ExportHandle.OnMaterial(face.MaterialElementId);
+
+ var polygonMeshNode = this.FaceConvert(face, transform);
+
+ m_ExportHandle.OnPolygonMesh(polygonMeshNode);
+ }
+
+ }
+ m_ExportHandle.OnGeometryObjectEnd(node);
+ }
+
+ m_ExportHandle.OnElementEnd(elem);
+ return true;
+ }
+
+
+ ///
+ /// Faces the convert.
+ ///
+ private PolygonMeshNode FaceConvert(Face face, Transform transform)
+ {
+ var result = new PolygonMeshNode();
+
+ var mesh = face.Triangulate(m_ExportLevel * 0.1);
+ var temps = new Dictionary();
+
+ // resolve triangle face..
+ for (int i = 0; i < mesh.NumTriangles; i++)
+ {
+ var triangle = mesh.get_Triangle(i);
+
+ var pt1 = triangle.get_Vertex(0);
+ var pt2 = triangle.get_Vertex(1);
+ var pt3 = triangle.get_Vertex(2);
+
+ var pi1 = (int)triangle.get_Index(0);
+ var pi2 = (int)triangle.get_Index(1);
+ var pi3 = (int)triangle.get_Index(2);
+
+ if (!temps.ContainsKey(pi1))
+ {
+ temps.Add(pi1, pt1);
+ }
+
+ if (!temps.ContainsKey(pi2))
+ {
+ temps.Add(pi2, pt2);
+ }
+
+ if (!temps.ContainsKey(pi3))
+ {
+ temps.Add(pi3, pt3);
+ }
+
+ result.TriangleFaces.Add(new TriangleFaceNode(pi1, pi2, pi3));
+ }
+
+ var eum = temps.OrderBy(m => m.Key).GetEnumerator();
+ while (eum.MoveNext())
+ {
+ result.Points.Add(eum.Current.Value);
+ }
+
+
+ // resolve point and uv..
+ foreach (EdgeArray edgeArray in face.EdgeLoops)
+ {
+ foreach (Edge item in edgeArray)
+ {
+ result.AddUV(item.EvaluateOnFace(0, face));
+ result.AddUV(item.EvaluateOnFace(1, face));
+ }
+ }
+
+ // resolve normal..
+
+ if (face.GetType().Equals(typeof(PlanarFace)))
+ {
+ var planarFace = face as PlanarFace;
+ result.AddNormal(planarFace.FaceNormal);
+ }
+ else
+ {
+ foreach (var item in result.TriangleFaces)
+ {
+ var normal = this.GetNormal(result.Points[item.V1], result.Points[item.V2], result.Points[item.V3]);
+ result.AddNormal(normal);
+ }
+ }
+
+ if (transform != null)
+ {
+ for (int i = 0; i < result.Points.Count; i++)
+ {
+ result.Points[i] = transform.OfPoint(result.Points[i]);
+ }
+
+ for (int i = 0; i < result.Normals.Count; i++)
+ {
+ result.Normals[i] = transform.OfVector(result.Normals[i]);
+ }
+ }
+ return result;
+ }
+
+ public Autodesk.Revit.DB.Plane ToPlane(XYZ point, XYZ other)
+ {
+ var v = other - point;
+ var angle = v.AngleTo(XYZ.BasisX);
+ var norm = v.CrossProduct(XYZ.BasisX).Normalize();
+
+ if (Math.Abs(angle - 0) < 1e-4)
+ {
+ angle = v.AngleTo(XYZ.BasisY);
+ norm = v.CrossProduct(XYZ.BasisY).Normalize();
+ }
+
+ if (Math.Abs(angle - 0) < 1e-4)
+ {
+ angle = v.AngleTo(XYZ.BasisZ);
+ norm = v.CrossProduct(XYZ.BasisZ).Normalize();
+ }
+ return new Autodesk.Revit.DB.Plane(norm, point);
+ }
+
+ ///
+ /// Gets the normal.
+ ///
+ private XYZ GetNormal(XYZ p1, XYZ p2, XYZ p3)
+ {
+ var v1 = p2 - p1;
+ var v2 = p3 - p1;
+ return v1.CrossProduct(v2).Normalize();
+ }
+
+ ///
+ /// Gets the geometry object.
+ ///
+ private Stack GetGeometryObject(Element elem)
+ {
+ var geometryElement = default(GeometryElement);
+
+ if (elem is FamilyInstance)
+ {
+ geometryElement = (elem as FamilyInstance).GetOriginalGeometry(new Options() { DetailLevel = ViewDetailLevel.Fine});
+ }
+ else
+ {
+ geometryElement = elem.get_Geometry(new Options() { DetailLevel = ViewDetailLevel.Fine, ComputeReferences = true });
+ }
+
+ var objects = new List();
+ this.RecursionObject(geometryElement, ref objects);
+
+ return new Stack(objects);
+ }
+
+ ///
+ /// Recursions the object.
+ ///
+ private void RecursionObject(GeometryElement geometryElement, ref List geometryObjects)
+ {
+ if (geometryElement == null)
+ return;
+
+ var eum = geometryElement.GetEnumerator();
+ while (eum.MoveNext())
+ {
+ var current = eum.Current;
+ var type = current.GetType();
+
+ if (type.Equals(typeof(GeometryInstance)))
+ {
+ this.RecursionObject((current as GeometryInstance).SymbolGeometry, ref geometryObjects);
+ }
+ else if (type.Equals(typeof(GeometryElement)))
+ {
+ this.RecursionObject(current as GeometryElement, ref geometryObjects);
+ }
+ else
+ {
+ if (type.Equals(typeof(Solid)))
+ {
+ var solid = current as Solid;
+ if (solid.Edges.Size == 0 || solid.Faces.Size == 0)
+ {
+ continue;
+ }
+ }
+ geometryObjects.Add(current);
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/DotNet.Exchange.Revit/Export/GeometryObjectNode.cs b/DotNet.Exchange.Revit/Export/GeometryObjectNode.cs
new file mode 100644
index 0000000..89850da
--- /dev/null
+++ b/DotNet.Exchange.Revit/Export/GeometryObjectNode.cs
@@ -0,0 +1,19 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Exchange.Revit.Export
+{
+ public class GeometryObjectNode
+ {
+ public GeometryObject GeometryObject { get; private set; }
+
+ public GeometryObjectNode(GeometryObject geometryObject)
+ {
+ this.GeometryObject = geometryObject;
+ }
+ }
+}
diff --git a/DotNet.Exchange.Revit/Export/IExportElement.cs b/DotNet.Exchange.Revit/Export/IExportElement.cs
new file mode 100644
index 0000000..7839a25
--- /dev/null
+++ b/DotNet.Exchange.Revit/Export/IExportElement.cs
@@ -0,0 +1,47 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Exchange.Revit.Export
+{
+ ///
+ /// IExportElement
+ ///
+ public interface IExportElement
+ {
+ ///
+ /// 元素开始进行导出时执行.
+ /// 如果返回结果为true,则开始进行此元素导出,否则放弃此元素导出.
+ ///
+ bool OnElementStart(Element elem);
+
+ ///
+ /// 当元素内的GeometryObject进行导出时执行.
+ /// 如果返回结果为true,则开始进行此GeometryObject导出,否则放弃此元素导出.
+ ///
+ bool OnGeometryObjectStart(GeometryObjectNode geometryObject);
+
+ ///
+ /// 开始检索多边形的材质.
+ ///
+ void OnMaterial(ElementId materialId);
+
+ ///
+ /// 开始检索Solid内的多边形拓扑节点.
+ ///
+ void OnPolygonMesh(PolygonMeshNode polygonMesh);
+
+ ///
+ /// 当元素内的GeometryObject导出结束时执行.
+ ///
+ void OnGeometryObjectEnd(GeometryObjectNode geometryObject);
+
+ ///
+ /// 当元素导出结束时开始执行.
+ ///
+ void OnElementEnd(Element elem);
+ }
+}
diff --git a/DotNet.Exchange.Revit/Export/PolygonMeshNode.cs b/DotNet.Exchange.Revit/Export/PolygonMeshNode.cs
new file mode 100644
index 0000000..54a3d6b
--- /dev/null
+++ b/DotNet.Exchange.Revit/Export/PolygonMeshNode.cs
@@ -0,0 +1,52 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Exchange.Revit.Export
+{
+ public class PolygonMeshNode
+ {
+ public PolygonMeshNode()
+ {
+ this.Points = new List();
+ this.TriangleFaces = new List();
+ this.Normals = new List();
+ this.UVs = new List();
+ }
+
+ public List Points { get; private set; }
+ public List TriangleFaces { get; private set; }
+ public List Normals { get; private set; }
+ public List UVs { get; private set; }
+
+ internal void AddPoint(XYZ point)
+ {
+ var flag = this.Points.FirstOrDefault(m => m.IsAlmostEqualTo(point, 1e-6));
+ if (flag == null)
+ {
+ this.Points.Add(point);
+ }
+ }
+
+ internal void AddUV(UV uv)
+ {
+ var flag = this.UVs.FirstOrDefault(m => m.IsAlmostEqualTo(uv, 1e-6));
+ if (flag == null)
+ {
+ this.UVs.Add(uv);
+ }
+ }
+
+ internal void AddNormal(XYZ normal)
+ {
+ var flag = this.Normals.FirstOrDefault(m => m.IsAlmostEqualTo(normal, 1e-6));
+ if (flag == null)
+ {
+ this.Normals.Add(normal);
+ }
+ }
+ }
+}
diff --git a/DotNet.Exchange.Revit/Export/TriangleFaceNode.cs b/DotNet.Exchange.Revit/Export/TriangleFaceNode.cs
new file mode 100644
index 0000000..1f21364
--- /dev/null
+++ b/DotNet.Exchange.Revit/Export/TriangleFaceNode.cs
@@ -0,0 +1,23 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Exchange.Revit.Export
+{
+ public sealed class TriangleFaceNode
+ {
+ internal TriangleFaceNode(int v1, int v2, int v3)
+ {
+ this.V1 = (int)v1;
+ this.V2 = (int)v2;
+ this.V3 = (int)v3;
+ }
+
+ public int V1 { get; private set; }
+ public int V2 { get; private set; }
+ public int V3 { get; private set; }
+ }
+}
diff --git a/DotNet.Exchange.Revit/ExportElment.cs b/DotNet.Exchange.Revit/ExportElment.cs
new file mode 100644
index 0000000..996d2ca
--- /dev/null
+++ b/DotNet.Exchange.Revit/ExportElment.cs
@@ -0,0 +1,51 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Exchange.Revit.Export
+{
+ ///
+ /// 自定义测试导出类.
+ ///
+ ///
+ public class ExportElment : IExportElement
+ {
+ // 临时测试
+
+ public HashSet PolygonMeshNodes = new HashSet();
+
+ bool IExportElement.OnElementStart(Autodesk.Revit.DB.Element elem)
+ {
+
+ return true;
+ }
+
+ bool IExportElement.OnGeometryObjectStart(GeometryObjectNode solid)
+ {
+ return true;
+ }
+
+ void IExportElement.OnMaterial(Autodesk.Revit.DB.ElementId materialId)
+ {
+
+ }
+
+ void IExportElement.OnPolygonMesh(PolygonMeshNode polygonMesh)
+ {
+ PolygonMeshNodes.Add(polygonMesh);
+ }
+
+ void IExportElement.OnGeometryObjectEnd(GeometryObjectNode solid)
+ {
+
+ }
+
+ void IExportElement.OnElementEnd(Autodesk.Revit.DB.Element elem)
+ {
+
+ }
+ }
+}
diff --git a/DotNet.Exchange.Revit/Properties/AssemblyInfo.cs b/DotNet.Exchange.Revit/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..114c358
--- /dev/null
+++ b/DotNet.Exchange.Revit/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNet.Exchange.Revit")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Exchange.Revit")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ec829d77-42ee-431c-8606-4c23ab9123fd")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Exchange.Revit/Test.cs b/DotNet.Exchange.Revit/Test.cs
new file mode 100644
index 0000000..9f549be
--- /dev/null
+++ b/DotNet.Exchange.Revit/Test.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.Attributes;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.Utility;
+using System.Diagnostics;
+using Autodesk.Revit.ApplicationServices;
+using DotNet.Exchange.Revit.Export;
+
+namespace DotNet.Exchange.Revit
+{
+ ///
+ /// 自定义导出测试代码。
+ /// 备注:自定义导出未经过长时间测试,在此开源是提供一个思路和方法,如果有遇到问题,可联系本人进行讨论.
+ ///
+ ///
+ [Transaction(TransactionMode.Manual)]
+ public class Test : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ var uiDoc = commandData.Application.ActiveUIDocument;
+
+ var doc = uiDoc.Document;
+
+ var refer = uiDoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
+
+ var elem = doc.GetElement(refer);
+
+
+ var export = new ExportElment();
+ var exportFactory = new ExportFactory(doc, export);
+ exportFactory.ExportLevel = 3;
+ exportFactory.Export(elem);
+
+ // 绘制测试,因绘制线速度较慢,所以当需要绘制测试时,请测试少量模型
+
+ doc.Invoke(m =>
+ {
+ foreach (var polygonMesh in export.PolygonMeshNodes)
+ {
+ foreach (var triangleFaces in polygonMesh.TriangleFaces)
+ {
+ var p1 = polygonMesh.Points[triangleFaces.V1];
+ var p2 = polygonMesh.Points[triangleFaces.V2];
+ var p3 = polygonMesh.Points[triangleFaces.V3];
+
+ CreateModelLine(doc, p1, p2);
+ CreateModelLine(doc, p2, p3);
+ CreateModelLine(doc, p3, p1);
+ }
+ }
+ });
+ return Result.Succeeded;
+ }
+
+ private void CreateModelLine(Document doc, XYZ p1, XYZ p2)
+ {
+ using (var line = Line.CreateBound(p1, p2))
+ {
+ using (var skPlane = SketchPlane.Create(doc, this.ToPlane(p1, p2)))
+ {
+ if (doc.IsFamilyDocument)
+ {
+ doc.FamilyCreate.NewModelCurve(line, skPlane);
+ }
+ else
+ {
+ doc.Create.NewModelCurve(line, skPlane);
+ }
+ }
+ }
+ }
+
+ private Autodesk.Revit.DB.Plane ToPlane(XYZ point, XYZ other)
+ {
+ var v = other - point;
+ var angle = v.AngleTo(XYZ.BasisX);
+ var norm = v.CrossProduct(XYZ.BasisX).Normalize();
+
+ if (Math.Abs(angle - 0) < 1e-4)
+ {
+ angle = v.AngleTo(XYZ.BasisY);
+ norm = v.CrossProduct(XYZ.BasisY).Normalize();
+ }
+
+ if (Math.Abs(angle - 0) < 1e-4)
+ {
+ angle = v.AngleTo(XYZ.BasisZ);
+ norm = v.CrossProduct(XYZ.BasisZ).Normalize();
+ }
+ return new Autodesk.Revit.DB.Plane(norm, point);
+ }
+ }
+
+ public static class DocumentExtension
+ {
+ ///
+ /// 使用委托启动事务.事务内自动进行事务启动,提交、回滚等处理。
+ ///
+ /// The document.
+ /// The action.
+ /// The name.
+ public static void Invoke(this Document doc, Action action, string name = "default")
+ {
+ using (var tr = new Transaction(doc, name))
+ {
+ tr.Start();
+
+ action(tr);
+
+ var status = tr.GetStatus();
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ break;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return;
+ default:
+ return;
+ }
+ }
+ }
+ }
+}
+
diff --git a/DotNet.Revit.ExternalEvent/CmdExternalEvent.cs b/DotNet.Revit.ExternalEvent/CmdExternalEvent.cs
new file mode 100644
index 0000000..2d0cede
--- /dev/null
+++ b/DotNet.Revit.ExternalEvent/CmdExternalEvent.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.Attributes;
+using DotNet.Revit.ExternalEvent;
+using System.Windows.Interop;
+using Autodesk.Windows;
+
+namespace DotNet.Revit.ExternalEvent
+{
+ [Transaction(TransactionMode.Manual)]
+ public class CmdExternalEvent : IExternalCommand
+ {
+ private static CmdExternalEvent m_Instance;
+ private ExternalEventHelper m_ExternalEventHelper;
+
+ public static CmdExternalEvent Instance
+ {
+ get { return m_Instance; }
+ }
+
+ public ExternalEventHelper ExternalEventHelper
+ {
+ get { return m_ExternalEventHelper; }
+ }
+
+
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ m_Instance = this;
+ m_ExternalEventHelper = new ExternalEventHelper(commandData.Application);
+
+
+ var main = new MainWinodow();
+ var mainHelper = new WindowInteropHelper(main);
+ mainHelper.Owner = ComponentManager.ApplicationWindow;
+ main.Show();
+
+ return Result.Succeeded;
+ }
+
+ }
+
+}
diff --git a/DotNet.Revit.ExternalEvent/DocumentExtension.cs b/DotNet.Revit.ExternalEvent/DocumentExtension.cs
new file mode 100644
index 0000000..105b170
--- /dev/null
+++ b/DotNet.Revit.ExternalEvent/DocumentExtension.cs
@@ -0,0 +1,24 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Revit.ExternalEvent
+{
+ public static class DocumentExtension
+ {
+ public static void Invoke(this Document doc, Action action, string name = "INVOKE")
+ {
+ using (var tr = new Transaction(doc, name))
+ {
+ tr.Start();
+ action(tr);
+
+ if (tr.GetStatus() == TransactionStatus.Started)
+ tr.Commit();
+ }
+ }
+ }
+}
diff --git a/DotNet.Revit.ExternalEvent/DotNet.Revit.ExternalEvent.csproj b/DotNet.Revit.ExternalEvent/DotNet.Revit.ExternalEvent.csproj
new file mode 100644
index 0000000..6429655
--- /dev/null
+++ b/DotNet.Revit.ExternalEvent/DotNet.Revit.ExternalEvent.csproj
@@ -0,0 +1,80 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}
+ Library
+ Properties
+ DotNet.Revit.ExternalEvent
+ DotNet.Revit.ExternalEvent
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\AdWindows.dll
+ False
+
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPI.dll
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPIUI.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MainWinodow.xaml
+
+
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.ExternalEvent/ExternalEventHelper.cs b/DotNet.Revit.ExternalEvent/ExternalEventHelper.cs
new file mode 100644
index 0000000..50e9d1e
--- /dev/null
+++ b/DotNet.Revit.ExternalEvent/ExternalEventHelper.cs
@@ -0,0 +1,124 @@
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Revit.ExternalEvent
+{
+ ///
+ /// 外部事件的封装.
+ ///
+ public class ExternalEventHelper
+ {
+ private readonly ExternalEventHandlerCommon externalEventHandlerCommon;
+
+ private readonly Autodesk.Revit.UI.ExternalEvent externalEvent;
+
+ ///
+ /// 外部事件刚刚开始并且准备执行时触发.
+ ///
+ public event EventHandler Started;
+
+ ///
+ /// 外部事件结束时触发.
+ ///
+ public event EventHandler End;
+
+ public ExternalEventHelper(UIApplication uiApp)
+ {
+ this.externalEventHandlerCommon = new ExternalEventHandlerCommon();
+ this.externalEvent = Autodesk.Revit.UI.ExternalEvent.Create(this.externalEventHandlerCommon);
+
+ this.externalEventHandlerCommon.Started += externalEventCommon_Started;
+ this.externalEventHandlerCommon.End += externalEventCommon_End;
+ }
+
+ public ExternalEventHelper(UIControlledApplication uiControlApp)
+ {
+ this.externalEventHandlerCommon = new ExternalEventHandlerCommon();
+ this.externalEvent = Autodesk.Revit.UI.ExternalEvent.Create(this.externalEventHandlerCommon);
+
+ this.externalEventHandlerCommon.Started += externalEventCommon_Started;
+ this.externalEventHandlerCommon.End += externalEventCommon_End;
+ }
+
+ public void Invoke(Action action, string name = "")
+ {
+ var nf = string.IsNullOrWhiteSpace(name) ? Guid.NewGuid().ToString() : name;
+ this.externalEventHandlerCommon.Actions.Enqueue(new KeyValuePair>(nf, action));
+ this.externalEvent.Raise();
+ }
+
+ private void externalEventCommon_End(object sender, ExternalEventArg e)
+ {
+ if (this.End != null)
+ this.End(this, e);
+ }
+
+ private void externalEventCommon_Started(object sender, ExternalEventArg e)
+ {
+ if (this.Started != null)
+ this.Started(this, e);
+ }
+
+ class ExternalEventHandlerCommon : IExternalEventHandler
+ {
+ internal Queue>> Actions { get; set; }
+
+ public event EventHandler Started;
+ public event EventHandler End;
+
+ internal ExternalEventHandlerCommon()
+ {
+ this.Actions = new Queue>>();
+ }
+
+ public void Execute(UIApplication app)
+ {
+ while (this.Actions.Count > 0)
+ {
+ var first = this.Actions.Dequeue();
+
+ if (string.IsNullOrWhiteSpace(first.Key) || first.Value == null)
+ continue;
+
+ try
+ {
+ if (this.Started != null)
+ this.Started(this, new ExternalEventArg(app, first.Key));
+
+ first.Value(app);
+ }
+ finally
+ {
+ this.End(this, new ExternalEventArg(app, first.Key));
+ }
+ }
+ }
+
+ public string GetName()
+ {
+ return "";
+ }
+ }
+ }
+
+ ///
+ /// 外部事件参数.
+ ///
+ ///
+ public class ExternalEventArg : EventArgs
+ {
+ public ExternalEventArg(UIApplication app, string name)
+ {
+ this.App = app;
+ this.Name = name;
+ }
+
+ public UIApplication App { get; private set; }
+
+ public string Name { get; private set; }
+ }
+}
diff --git a/DotNet.Revit.ExternalEvent/MainWinodow.xaml b/DotNet.Revit.ExternalEvent/MainWinodow.xaml
new file mode 100644
index 0000000..f9ddc29
--- /dev/null
+++ b/DotNet.Revit.ExternalEvent/MainWinodow.xaml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/DotNet.Revit.ExternalEvent/MainWinodow.xaml.cs b/DotNet.Revit.ExternalEvent/MainWinodow.xaml.cs
new file mode 100644
index 0000000..3fa1a81
--- /dev/null
+++ b/DotNet.Revit.ExternalEvent/MainWinodow.xaml.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using DotNet.Revit.ExternalEvent;
+using Autodesk.Revit.UI.Selection;
+
+namespace DotNet.Revit.ExternalEvent
+{
+ ///
+ /// Interaction logic for MainWinodow.xaml
+ ///
+ public partial class MainWinodow : Window
+ {
+ public MainWinodow()
+ {
+ InitializeComponent();
+ }
+
+ private void Button_Click(object sender, RoutedEventArgs e)
+ {
+ // 连续调用外部事件...
+
+ var helper = CmdExternalEvent.Instance.ExternalEventHelper;
+
+ helper.Invoke(m =>
+ {
+ var uiDoc = m.ActiveUIDocument;
+ var doc = uiDoc.Document;
+
+ var ids = uiDoc.Selection.GetElementIds();
+ if (ids.Count > 0)
+ {
+ doc.Invoke(x =>
+ {
+ doc.Delete(ids);
+ });
+ }
+
+ });
+
+ helper.Invoke(m =>
+ {
+ var uiDoc = m.ActiveUIDocument;
+ var doc = uiDoc.Document;
+ try
+ {
+ var refer = uiDoc.Selection.PickObject(ObjectType.Element);
+ doc.Invoke(x =>
+ {
+ doc.Delete(refer.ElementId);
+ });
+ }
+ catch (Exception ex)
+ {
+
+ }
+ });
+ }
+
+ private void Button_Click_1(object sender, RoutedEventArgs e)
+ {
+
+ }
+ }
+}
diff --git a/DotNet.Revit.ExternalEvent/Properties/AssemblyInfo.cs b/DotNet.Revit.ExternalEvent/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..06a0836
--- /dev/null
+++ b/DotNet.Revit.ExternalEvent/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNet.Revit.ExternalEvent")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.ExternalEvent")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("912969b4-7586-4f87-9d7d-69f0e3b38c83")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Revit.GeometryObject/CmdGeometryObject.cs b/DotNet.Revit.GeometryObject/CmdGeometryObject.cs
new file mode 100644
index 0000000..e98e870
--- /dev/null
+++ b/DotNet.Revit.GeometryObject/CmdGeometryObject.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.Attributes;
+using Autodesk.Revit.UI.Selection;
+using DotNet.Revit;
+
+namespace DotNet.Revit.GeometryObject
+{
+
+ [Transaction(TransactionMode.Manual)]
+ public class CmdGeometryObject : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ var uiDoc = commandData.Application.ActiveUIDocument;
+ var doc = uiDoc.Document;
+
+ try
+ {
+ // 选取一个门
+ var refer = uiDoc.Selection.PickObject(ObjectType.Element,
+ new SelectionFilterCommon(m => m.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Doors));
+
+ var elem = doc.GetElement(refer);
+ var geomObjects = elem.GetGeometryObjects(new Options() { IncludeNonVisibleObjects = true });
+
+ // 获取门的所有有效Solid
+
+ var solids = geomObjects.OfType();
+ }
+ catch
+ {
+ return Result.Failed;
+ }
+ return Result.Succeeded;
+ }
+ }
+
+ ///
+ /// 通用元素交互选择过滤器.
+ ///
+ ///
+ public class SelectionFilterCommon : ISelectionFilter
+ {
+ private readonly Func m_Func;
+
+ private readonly Func m_Func2;
+
+ public SelectionFilterCommon(Func match, Func func2)
+ {
+ m_Func = match;
+
+ m_Func2 = func2;
+ }
+
+ public SelectionFilterCommon(Func match)
+ : this(match, null)
+ {
+
+ }
+
+ public bool AllowElement(Element elem)
+ {
+ return m_Func == null ? true : m_Func(elem);
+ }
+
+ public bool AllowReference(Reference reference, XYZ position)
+ {
+ return m_Func2 == null ? true : m_Func2(reference, position);
+ }
+ }
+}
diff --git a/DotNet.Revit.GeometryObject/DotNet.Revit.GeometryObject.csproj b/DotNet.Revit.GeometryObject/DotNet.Revit.GeometryObject.csproj
new file mode 100644
index 0000000..e0d45c4
--- /dev/null
+++ b/DotNet.Revit.GeometryObject/DotNet.Revit.GeometryObject.csproj
@@ -0,0 +1,61 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}
+ Library
+ Properties
+ DotNet.Revit.GeometryObject
+ DotNet.Revit.GeometryObject
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPI.dll
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPIUI.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.GeometryObject/GeometryObjectHelper.cs b/DotNet.Revit.GeometryObject/GeometryObjectHelper.cs
new file mode 100644
index 0000000..38b0a6b
--- /dev/null
+++ b/DotNet.Revit.GeometryObject/GeometryObjectHelper.cs
@@ -0,0 +1,74 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Revit
+{
+ public static class GeometryObjectHelper
+ {
+ ///
+ /// 获取元素的所有GeomObjects
+ ///
+ /// The elem.
+ /// The options.
+ ///
+
+ public static List GetGeometryObjects(this Element elem, Options options = default(Options))
+ {
+ var result = new List();
+
+ options = options ?? new Options();
+
+ GeometryObjectHelper.RecursionObject(elem.get_Geometry(options), ref result);
+
+ return result;
+ }
+
+ ///
+ /// 递归遍历所有GeometryObject.
+ ///
+ /// 初始GeometryElement.
+ /// 递归结果.
+
+ private static void RecursionObject(this GeometryElement geometryElement, ref List geometryObjects)
+ {
+ if (geometryElement == null)
+ {
+ return;
+ }
+
+ var eum = geometryElement.GetEnumerator();
+
+ while (eum.MoveNext())
+ {
+ var current = eum.Current;
+
+ switch (current)
+ {
+ case GeometryInstance instance:
+ instance.SymbolGeometry.RecursionObject(ref geometryObjects);
+ break;
+
+ case GeometryElement elemlemt:
+ elemlemt.RecursionObject(ref geometryObjects);
+ break;
+
+ case Solid solid:
+ if (solid.Edges.Size == 0 || solid.Faces.Size == 0)
+ {
+ continue;
+ }
+ geometryObjects.Add(current);
+ break;
+
+ default:
+ geometryObjects.Add(current);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/DotNet.Revit.GeometryObject/Properties/AssemblyInfo.cs b/DotNet.Revit.GeometryObject/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..20dfeb6
--- /dev/null
+++ b/DotNet.Revit.GeometryObject/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNet.Revit.GeometryObject")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.GeometryObject")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("9d5b8f0e-fe57-472e-ae69-189201cde20b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Revit.Hook/Achieve/GlobalMouseHook.cs b/DotNet.Revit.Hook/Achieve/GlobalMouseHook.cs
new file mode 100644
index 0000000..a36865a
--- /dev/null
+++ b/DotNet.Revit.Hook/Achieve/GlobalMouseHook.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DotNet.Revit.Hook.Achieve
+{
+ ///
+ /// 全局鼠标钩子
+ ///
+ ///
+ public class GlobalMouseHook : MouseHookBase
+ {
+ public GlobalMouseHook(IntPtr processId)
+ : base(processId)
+ {
+
+ }
+ }
+}
diff --git a/DotNet.Revit.Hook/Achieve/HookBase.cs b/DotNet.Revit.Hook/Achieve/HookBase.cs
new file mode 100644
index 0000000..12238cf
--- /dev/null
+++ b/DotNet.Revit.Hook/Achieve/HookBase.cs
@@ -0,0 +1,98 @@
+using DotNet.Revit.Hook.DataStructure;
+using DotNet.Revit.Hook.Helper;
+using DotNet.Revit.Hook.Interface;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DotNet.Revit.Hook.Achieve
+{
+ public abstract class HookBase : IHook
+ {
+ private static Dictionary m_Hooks;
+ private IntPtr m_ProcessId;
+ private int m_ThreadId;
+ private HookType m_HookType;
+ private HookProc m_HookProc;
+
+ protected internal int m_HookId;
+
+ static HookBase()
+ {
+ m_Hooks = new Dictionary();
+ }
+
+ private HookBase(HookType hookType)
+ {
+ m_HookType = hookType;
+ m_HookProc = HookProc;
+ }
+
+ protected HookBase(IntPtr processId, HookType hookType)
+ : this(hookType)
+ {
+ m_ProcessId = processId;
+ if (m_ProcessId == IntPtr.Zero)
+ {
+ m_ProcessId = HookHelper.GetCurrentProcessId();
+ }
+ }
+
+ protected HookBase(int threadId, HookType hookType)
+ : this(hookType)
+ {
+ m_ThreadId = threadId;
+ if (m_ThreadId == 0)
+ {
+ m_ThreadId = HookHelper.GetCurrentThreadId();
+ }
+ }
+
+ public void Install()
+ {
+ if (m_ThreadId != 0)
+ {
+ m_HookId = HookHelper.SetWindowsHookEx(m_HookType, m_HookProc, IntPtr.Zero, m_ThreadId);
+ }
+ else
+ {
+ if (m_ProcessId == IntPtr.Zero)
+ {
+ return;
+ }
+ m_HookId = HookHelper.SetWindowsHookEx(m_HookType, m_HookProc, m_ProcessId, 0);
+ }
+
+ if (m_HookId == 0)
+ {
+ return;
+ }
+
+ if (!m_Hooks.ContainsKey(m_HookId))
+ {
+ m_Hooks.Add(m_HookId, this);
+ }
+ }
+
+ public void Uninstall()
+ {
+ if (m_HookId == 0)
+ {
+ return;
+ }
+
+ var flag = HookHelper.UnhookWindowsHookEx(m_HookId);
+ if (flag)
+ {
+ if (m_Hooks.Remove(m_HookId))
+ {
+ m_HookId = 0;
+ }
+ }
+ }
+
+ protected abstract int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
+ }
+
+}
diff --git a/DotNet.Revit.Hook/Achieve/MouseHook.cs b/DotNet.Revit.Hook/Achieve/MouseHook.cs
new file mode 100644
index 0000000..9bed18e
--- /dev/null
+++ b/DotNet.Revit.Hook/Achieve/MouseHook.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DotNet.Revit.Hook.Achieve
+{
+ ///
+ /// 线程鼠标Hook.
+ ///
+ ///
+ public class MouseHook : MouseHookBase
+ {
+ public MouseHook(int threadId = 0)
+ : base(threadId)
+ {
+
+ }
+ }
+
+}
diff --git a/DotNet.Revit.Hook/Achieve/MouseHookBase.cs b/DotNet.Revit.Hook/Achieve/MouseHookBase.cs
new file mode 100644
index 0000000..d175436
--- /dev/null
+++ b/DotNet.Revit.Hook/Achieve/MouseHookBase.cs
@@ -0,0 +1,145 @@
+using DotNet.Revit.Hook.DataStructure;
+using DotNet.Revit.Hook.Helper;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace DotNet.Revit.Hook.Achieve
+{
+ public abstract class MouseHookBase : HookBase
+ {
+ protected MouseHookBase(IntPtr processId)
+ : base(processId, HookType.WH_MOUSE_LL)
+ {
+
+ }
+
+ protected MouseHookBase(int threadId)
+ : base(threadId, HookType.WH_MOUSE)
+ {
+
+ }
+
+ ///
+ /// 鼠标双击
+ ///
+ public event HookHandler MouseDoubleClick;
+
+ ///
+ /// 鼠标移动
+ ///
+ public event HookHandler MouseMove;
+
+ ///
+ /// 鼠标按下
+ ///
+ public event HookHandler MouseDown;
+
+ ///
+ /// 鼠标弹起
+ ///
+ public event HookHandler MouseUp;
+
+ protected override int HookProc(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ if (nCode < 0)
+ {
+ return HookHelper.CallNextHookEx(m_HookId, nCode, wParam, lParam);
+ }
+
+ var mouseMsg = (MouseMessage)wParam.ToInt32();
+ var mouseHookStruct = lParam.ToStruct();
+
+ var button = this.GetMouseButtons(mouseMsg);
+
+ switch (mouseMsg)
+ {
+ case MouseMessage.WM_LBUTTONDOWN:
+ case MouseMessage.WM_RBUTTONDOWN:
+ case MouseMessage.WM_MBUTTONDOWN:
+
+ return this.OnRaiseMouseDown(button, 1, mouseHookStruct.pt.X, mouseHookStruct.pt.Y, mouseHookStruct.mouseData);
+
+ case MouseMessage.WM_LBUTTONUP:
+ case MouseMessage.WM_MBUTTONUP:
+ case MouseMessage.WM_RBUTTONUP:
+
+ return this.OnRaiseMouseUp(button, 1, mouseHookStruct.pt.X, mouseHookStruct.pt.Y, mouseHookStruct.mouseData);
+
+ case MouseMessage.WM_LBUTTONDBLCLK:
+ case MouseMessage.WM_RBUTTONDBLCLK:
+ case MouseMessage.WM_MBUTTONDBLCLK:
+
+ return this.OnRaiseMouseDoubleClick(button, 2, mouseHookStruct.pt.X, mouseHookStruct.pt.Y, mouseHookStruct.mouseData);
+
+ case MouseMessage.WM_MOUSEMOVE:
+
+ return this.OnRaiseMouseMove(MouseButtons.None, 0, mouseHookStruct.pt.X, mouseHookStruct.pt.Y, mouseHookStruct.mouseData);
+ default:
+ return HookHelper.CallNextHookEx(m_HookId, nCode, wParam, lParam);
+ }
+ }
+
+ private MouseButtons GetMouseButtons(MouseMessage mouseMsg)
+ {
+ MouseButtons result = MouseButtons.None;
+ switch (mouseMsg)
+ {
+ case MouseMessage.WM_LBUTTONDBLCLK:
+ case MouseMessage.WM_LBUTTONDOWN:
+ case MouseMessage.WM_LBUTTONUP:
+ result = MouseButtons.Left;
+ break;
+ case MouseMessage.WM_MBUTTONDBLCLK:
+ case MouseMessage.WM_MBUTTONDOWN:
+ case MouseMessage.WM_MBUTTONUP:
+ result = MouseButtons.Middle;
+ break;
+ case MouseMessage.WM_RBUTTONDBLCLK:
+ case MouseMessage.WM_RBUTTONDOWN:
+ case MouseMessage.WM_RBUTTONUP:
+ result = MouseButtons.Right;
+ break;
+ }
+ return result;
+ }
+
+ private int OnRaiseMouseDoubleClick(MouseButtons button, int clicks, int x, int y, int delta)
+ {
+ if (this.MouseDoubleClick != null)
+ {
+ return this.MouseDoubleClick(this, new MouseEventArgs(button, clicks, x, y, delta));
+ }
+ return 0;
+ }
+
+ private int OnRaiseMouseDown(MouseButtons button, int clicks, int x, int y, int delta)
+ {
+ if (this.MouseDown != null)
+ {
+ return this.MouseDown(this, new MouseEventArgs(button, clicks, x, y, delta));
+ }
+ return 0;
+ }
+
+ private int OnRaiseMouseUp(MouseButtons button, int clicks, int x, int y, int delta)
+ {
+ if (this.MouseUp != null)
+ {
+ return this.MouseUp(this, new MouseEventArgs(button, clicks, x, y, delta));
+ }
+ return 0;
+ }
+
+ private int OnRaiseMouseMove(MouseButtons button, int clicks, int x, int y, int delta)
+ {
+ if (this.MouseMove != null)
+ {
+ return this.MouseMove(this, new MouseEventArgs(button, clicks, x, y, delta));
+ }
+ return 0;
+ }
+ }
+}
diff --git a/DotNet.Revit.Hook/CommandTest.cs b/DotNet.Revit.Hook/CommandTest.cs
new file mode 100644
index 0000000..3086ce2
--- /dev/null
+++ b/DotNet.Revit.Hook/CommandTest.cs
@@ -0,0 +1,42 @@
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.Attributes;
+
+namespace DotNet.Revit.Hook
+{
+ ///
+ /// 鼠标双击元素拦截事件.
+ ///
+ ///
+ [Transaction(TransactionMode.Manual)]
+ public class MouseHookTest : IExternalCommand
+ {
+ Result IExternalCommand.Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ if (ElementMonitor.Instance == null)
+ {
+ ElementMonitor.Register(commandData.Application);
+ }
+
+ ElementMonitor.Instance.DoubleClickElement += OnRaiseDoubleClickElement;
+
+ return Result.Succeeded;
+ }
+
+ private int OnRaiseDoubleClickElement(object sender, DoubleClickElementEventArgs e)
+ {
+ if (e.Element == null)
+ {
+ return 0;
+ }
+
+ System.Windows.Forms.MessageBox.Show(string.Format("双击击元素Id: {0}", e.Element.Id));
+
+ return 1;
+ }
+ }
+}
diff --git a/DotNet.Revit.Hook/DataStructure/HookType.cs b/DotNet.Revit.Hook/DataStructure/HookType.cs
new file mode 100644
index 0000000..71f5b72
--- /dev/null
+++ b/DotNet.Revit.Hook/DataStructure/HookType.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DotNet.Revit.Hook.DataStructure
+{
+ public enum HookType : int
+ {
+ WH_MSGFILTER = -1,
+ WH_JOURNALRECORD = 0,
+ WH_JOURNALPLAYBACK = 1,
+ WH_KEYBOARD = 2,
+ WH_GETMESSAGE = 3,
+ WH_CALLWNDPROC = 4,
+ WH_CBT = 5,
+ WH_SYSMSGFILTER = 6,
+ WH_MOUSE = 7,
+ WH_HARDWARE = 8,
+ WH_DEBUG = 9,
+ WH_SHELL = 10,
+ WH_FOREGROUNDIDLE = 11,
+ WH_CALLWNDPROCRET = 12,
+ WH_KEYBOARD_LL = 13,
+ WH_MOUSE_LL = 14,
+ }
+}
diff --git a/DotNet.Revit.Hook/DataStructure/MOUSEHOOKSTRUCT.cs b/DotNet.Revit.Hook/DataStructure/MOUSEHOOKSTRUCT.cs
new file mode 100644
index 0000000..f20c558
--- /dev/null
+++ b/DotNet.Revit.Hook/DataStructure/MOUSEHOOKSTRUCT.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace DotNet.Revit.Hook.DataStructure
+{
+ ///
+ /// 全局鼠标消息结构体
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ struct MOUSEHOOKSTRUCT
+ {
+ ///
+ /// 屏幕坐标
+ ///
+ public POINT pt;
+
+ ///
+ /// 如果消息是WM_MOUSEWHEEL,则此成员的高位字是wheel delta。保留低位字。正值表示车轮向前旋转,远离用户; 负值表示车轮向后旋转,朝向用户。
+ /// XBUTTON1 == 0x0001 如果按下或释放第一个X按钮。
+ /// XBUTTON2 == 0x0002 如果按下或释放第一个X按钮。
+ ///
+ public int mouseData;
+
+ public int flags;
+
+ public uint wHitTestCode;
+
+ public uint dwExtraInfo;
+ }
+}
diff --git a/DotNet.Revit.Hook/DataStructure/MouseMessage.cs b/DotNet.Revit.Hook/DataStructure/MouseMessage.cs
new file mode 100644
index 0000000..d1302f2
--- /dev/null
+++ b/DotNet.Revit.Hook/DataStructure/MouseMessage.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DotNet.Revit.Hook.DataStructure
+{
+ [Flags]
+ public enum MouseMessage
+ {
+ ///
+ /// 鼠标左键按下
+ ///
+ WM_LBUTTONDOWN = 0x0201,
+
+ ///
+ /// 鼠标左键双击
+ ///
+ WM_LBUTTONDBLCLK = 0x0203,
+
+ ///
+ /// 鼠标左键弹起
+ ///
+ WM_LBUTTONUP = 0x0202,
+
+ ///
+ /// 鼠标右键单击
+ ///
+ WM_RBUTTONDOWN = 0x0204,
+
+ ///
+ /// 鼠标右键双击
+ ///
+ WM_RBUTTONDBLCLK = 0x0206,
+
+ ///
+ /// 鼠标右键弹起
+ ///
+ WM_RBUTTONUP = 0x0205,
+
+ ///
+ /// 鼠标中键双击
+ ///
+ WM_MBUTTONDBLCLK = 0x0209,
+ ///
+ /// 鼠标中键单击
+ ///
+ WM_MBUTTONDOWN = 0x0207,
+ ///
+ /// 鼠标中键弹起
+ ///
+ WM_MBUTTONUP = 0x0208,
+
+ ///
+ /// 鼠标侧键双击时触发.
+ ///
+ WM_XBUTTONDBLCLK = 0x020D,
+
+ ///
+ /// 鼠标侧键单击时触发
+ ///
+ WM_XBUTTONDOWN = 0x020B,
+
+ ///
+ /// 鼠标侧键弹起时触发.
+ ///
+ WM_XBUTTONUP = 0x020C,
+
+ ///
+ /// 鼠标移动
+ ///
+ WM_MOUSEMOVE = 0x0200,
+
+ ///
+ /// 鼠标滚动
+ ///
+ WM_MOUSEWHEEL = 0x020A,
+
+ ///
+ /// 鼠标滚动
+ ///
+ WM_MOUSEHWHEEL = 0x020E,
+
+ ///
+ /// 正在失去鼠标捕获的窗口.
+ ///
+ WM_CAPTURECHANGED = 0x0215,
+
+ ///
+ /// 当鼠标在非激活窗体按下时.
+ ///
+ WM_MOUSEACTIVATE = 0x0021,
+
+ ///
+ /// 当光标悬停在窗口的客户端区域上达到在先前调用TrackMouseEvent中指定的时间段时,发布到窗口。
+ ///
+ WM_MOUSEHOVER = 0x02A1,
+ }
+}
diff --git a/DotNet.Revit.Hook/DataStructure/POINT.cs b/DotNet.Revit.Hook/DataStructure/POINT.cs
new file mode 100644
index 0000000..104929b
--- /dev/null
+++ b/DotNet.Revit.Hook/DataStructure/POINT.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace DotNet.Revit.Hook.DataStructure
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct POINT
+ {
+ public int X;
+ public int Y;
+ }
+}
diff --git a/DotNet.Revit.Hook/DotNet.Revit.Hook.csproj b/DotNet.Revit.Hook/DotNet.Revit.Hook.csproj
new file mode 100644
index 0000000..4b1ae2c
--- /dev/null
+++ b/DotNet.Revit.Hook/DotNet.Revit.Hook.csproj
@@ -0,0 +1,71 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}
+ Library
+ Properties
+ DotNet.Revit.Hook
+ DotNet.Revit.Hook
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPI.dll
+ False
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.Hook/DoubleClickElementEventArgs.cs b/DotNet.Revit.Hook/DoubleClickElementEventArgs.cs
new file mode 100644
index 0000000..bb01150
--- /dev/null
+++ b/DotNet.Revit.Hook/DoubleClickElementEventArgs.cs
@@ -0,0 +1,15 @@
+using Autodesk.Revit.DB;
+using System;
+
+namespace DotNet.Revit.Hook
+{
+ public class DoubleClickElementEventArgs : EventArgs
+ {
+ public DoubleClickElementEventArgs(Element elem)
+ {
+ this.Element = elem;
+ }
+
+ public Element Element { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/DotNet.Revit.Hook/ElementMonitor.cs b/DotNet.Revit.Hook/ElementMonitor.cs
new file mode 100644
index 0000000..9dc4e99
--- /dev/null
+++ b/DotNet.Revit.Hook/ElementMonitor.cs
@@ -0,0 +1,139 @@
+using Autodesk.Revit.UI;
+using DotNet.Revit.Hook.Achieve;
+using DotNet.Revit.Hook.Helper;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace DotNet.Revit.Hook
+{
+ ///
+ /// 元素监控.
+ ///
+ public class ElementMonitor
+ {
+ private static ElementMonitor m_Instance;
+ private MouseHook m_MouseHook;
+ private bool m_IsMonitor;
+ private UIApplication m_UIApplication;
+
+ private ElementMonitor(UIApplication uiApp)
+ {
+ m_Instance = this;
+ m_UIApplication = uiApp;
+
+ m_MouseHook = new MouseHook();
+ m_MouseHook.Install();
+
+ m_MouseHook.MouseDoubleClick += OnRaiseMouseDoubleClick;
+ }
+
+ ///
+ /// 静态实例,可在入口类判断此实例是否为null,防止重复注册.
+ ///
+ public static ElementMonitor Instance
+ {
+ get
+ {
+ return m_Instance;
+ }
+ }
+
+ ///
+ /// 是否监控.
+ ///
+ public bool IsMonitor
+ {
+ get
+ {
+ return m_IsMonitor;
+ }
+
+ set
+ {
+ m_IsMonitor = value;
+ }
+ }
+
+ ///
+ /// 当鼠标双击元素时触发此事件.
+ ///
+ public event HookHandler DoubleClickElement;
+
+ ///
+ /// 注册元素监控,并指定是否立即监控.
+ ///
+ public static void Register(UIApplication uiApp)
+ {
+ if (uiApp == null)
+ {
+ throw new ArgumentNullException(nameof(uiApp));
+ }
+
+ new ElementMonitor(uiApp)
+ {
+ m_IsMonitor = true
+ };
+ }
+
+ ///
+ /// 注册元素监控,并指定是否立即监控.
+ ///
+ public static void Register(UIControlledApplication uiControllApp)
+ {
+ if (uiControllApp == null)
+ {
+ throw new ArgumentNullException(nameof(uiControllApp));
+ }
+
+ var flag = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod;
+
+ var uiApp = (UIApplication)uiControllApp.GetType().InvokeMember("getUIApplication", flag, Type.DefaultBinder, uiControllApp, null);
+
+ Register(uiApp);
+ }
+
+
+ ///
+ /// 返回1,则拦截鼠标消息,返回0则传递给真正消息接收者.
+ ///
+ private int OnRaiseMouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
+ {
+ if (this.DoubleClickElement == null)
+ {
+ return 0;
+ }
+
+ if (!m_IsMonitor || e.Button != MouseButtons.Left || e.Clicks != 2)
+ {
+ return 0;
+ }
+
+ var uiDoc = m_UIApplication.ActiveUIDocument;
+
+ if (uiDoc == null)
+ {
+ return 0;
+ }
+
+ var elemIds = uiDoc.Selection.GetElementIds();
+
+ if (elemIds.Count == 1)
+ {
+ var elem = uiDoc.Document.GetElement(elemIds.First());
+
+ if (elem == null)
+ {
+ return 0;
+ }
+
+ return this.DoubleClickElement(this, new DoubleClickElementEventArgs(elem));
+ }
+
+ return 0;
+ }
+ }
+
+}
diff --git a/DotNet.Revit.Hook/Helper/HookHelper.cs b/DotNet.Revit.Hook/Helper/HookHelper.cs
new file mode 100644
index 0000000..2cd9df6
--- /dev/null
+++ b/DotNet.Revit.Hook/Helper/HookHelper.cs
@@ -0,0 +1,56 @@
+using DotNet.Revit.Hook.DataStructure;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace DotNet.Revit.Hook.Helper
+{
+ static class HookHelper
+ {
+ [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int GetCurrentThreadId();
+
+ [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, int dwThreadId);
+
+ [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int CallNextHookEx(int idHook, int code, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern bool UnhookWindowsHookEx(int idHook);
+
+ [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr GetModuleHandle(string lpModuleName);
+
+ [DllImport("kernel32", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr GetCurrentProcessId();
+
+ [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int GetKeyboardState(byte[] pbKeyState);
+
+ [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
+
+ public static int HiWord(IntPtr dword)
+ {
+ return dword.ToInt32() >> 16 & 65535;
+ }
+
+ public static int LoWord(IntPtr dword)
+ {
+ return dword.ToInt32() & 65535;
+ }
+
+ public static T ToStruct(this IntPtr lParam) where T : struct
+ {
+ return (T)Marshal.PtrToStructure(lParam, typeof(T));
+ }
+ }
+
+
+ public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
+
+ public delegate int HookHandler(object sender, TEvent e) where TEvent : EventArgs;
+}
diff --git a/DotNet.Revit.Hook/Interface/IHook.cs b/DotNet.Revit.Hook/Interface/IHook.cs
new file mode 100644
index 0000000..3fe661b
--- /dev/null
+++ b/DotNet.Revit.Hook/Interface/IHook.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DotNet.Revit.Hook.Interface
+{
+ ///
+ /// IHook
+ ///
+ public interface IHook
+ {
+ ///
+ /// Installs this Hook.
+ ///
+ void Install();
+
+ ///
+ /// Uninstalls this Hook.
+ ///
+ void Uninstall();
+ }
+}
diff --git a/DotNet.Revit.Hook/Properties/AssemblyInfo.cs b/DotNet.Revit.Hook/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e6e9501
--- /dev/null
+++ b/DotNet.Revit.Hook/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("DotNet.Revit.Hook")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.Hook")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("957a91dd-d04d-4811-82b7-7350a444cb12")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Revit.InvokeCommand/CmdInvoke.cs b/DotNet.Revit.InvokeCommand/CmdInvoke.cs
new file mode 100644
index 0000000..6bfb6c2
--- /dev/null
+++ b/DotNet.Revit.InvokeCommand/CmdInvoke.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.Attributes;
+using System.Diagnostics;
+using Autodesk.Windows;
+
+namespace DotNet.Revit.InvokeCommand
+{
+ [Transaction(TransactionMode.Manual)]
+ public class CmdInvoke : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ // 调用Look up Snoop Db
+ // Look up Snoop Db 命令Id通过下方执行下方命令CmdInvokeTest,控制台输出查询。
+
+ InvokeHelper.Invoke("CustomCtrl_%CustomCtrl_%CustomCtrl_%Add-Ins%Revit Lookup%Options%Snoop Db..");
+
+
+ /* 调用右键菜单 - 区域放大
+ 右键菜单的 命令Id 可在Revit日志内进行查询..*/
+
+ InvokeHelper.Invoke("ID_ZOOM_IN");
+
+ return Result.Succeeded;
+ }
+ }
+
+ [Transaction(TransactionMode.Manual)]
+ public class CmdInvokeTest : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ // 当命令控件点击执行后触发事件...
+
+ ComponentManager.ItemExecuted += ComponentManager_ItemExecuted;
+
+ return Result.Succeeded;
+ }
+
+ void ComponentManager_ItemExecuted(object sender, Autodesk.Internal.Windows.RibbonItemExecutedEventArgs e)
+ {
+ if (e.Item == null)
+ return;
+
+ // 获取命令Id
+ var id = UIFramework.ControlHelper.GetCommandId(e.Item);
+
+ Debug.WriteLine(string.Format("Text: {0} ID: {1}", e.Item.Text, id));
+ }
+ }
+}
diff --git a/DotNet.Revit.InvokeCommand/DotNet.Revit.InvokeCommand.csproj b/DotNet.Revit.InvokeCommand/DotNet.Revit.InvokeCommand.csproj
new file mode 100644
index 0000000..09404e5
--- /dev/null
+++ b/DotNet.Revit.InvokeCommand/DotNet.Revit.InvokeCommand.csproj
@@ -0,0 +1,80 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}
+ Library
+ Properties
+ DotNet.Revit.InvokeCommand
+ DotNet.Revit.InvokeCommand
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\AdWindows.dll
+ False
+
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPI.dll
+ False
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\UIFramework.dll
+ False
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\UIFrameworkServices.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.InvokeCommand/InvokeHelper.cs b/DotNet.Revit.InvokeCommand/InvokeHelper.cs
new file mode 100644
index 0000000..3e7e684
--- /dev/null
+++ b/DotNet.Revit.InvokeCommand/InvokeHelper.cs
@@ -0,0 +1,40 @@
+using Autodesk.Windows;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using UIFramework;
+using UIFrameworkServices;
+
+namespace DotNet.Revit.InvokeCommand
+{
+ public static class InvokeHelper
+ {
+ ///
+ /// 指定一个命令Id,调用命令.
+ ///
+ /// 命令控件的Id值
+ ///
+ public static bool Invoke(string cmdId)
+ {
+ if (ExternalCommandHelper.CanExecute(cmdId))
+ {
+ ExternalCommandHelper.executeExternalCommand(cmdId);
+ return true;
+ }
+ else if (CommandHandlerService.canExecute(cmdId))
+ {
+ CommandHandlerService.invokeCommandHandler(cmdId);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ }
+}
diff --git a/DotNet.Revit.InvokeCommand/Properties/AssemblyInfo.cs b/DotNet.Revit.InvokeCommand/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c94b444
--- /dev/null
+++ b/DotNet.Revit.InvokeCommand/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNet.Revit.InvokeCommand")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.InvokeCommand")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e719e43a-c846-4d27-a870-d984878f9615")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Revit.NET/App.config b/DotNet.Revit.NET/App.config
new file mode 100644
index 0000000..4bfa005
--- /dev/null
+++ b/DotNet.Revit.NET/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/DotNet.Revit.NET/DotNet.Revit.NET.csproj b/DotNet.Revit.NET/DotNet.Revit.NET.csproj
new file mode 100644
index 0000000..e7ed069
--- /dev/null
+++ b/DotNet.Revit.NET/DotNet.Revit.NET.csproj
@@ -0,0 +1,100 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}
+ Exe
+ Properties
+ DotNet.Revit.NET
+ DotNet.Revit.NET
+ v4.8
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+
+
+
+ x64
+ true
+ full
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+ Usingdll\RevitAddInUtility.dll
+
+
+ E:\Program Files\Autodesk\Revit 2016\RevitAPI.dll
+ False
+
+
+ E:\Program Files\Autodesk\Revit 2016\RevitNET.dll
+ False
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.NET/Program.cs b/DotNet.Revit.NET/Program.cs
new file mode 100644
index 0000000..f1d2153
--- /dev/null
+++ b/DotNet.Revit.NET/Program.cs
@@ -0,0 +1,338 @@
+using Autodesk.Revit;
+using Autodesk.Revit.ApplicationServices;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.Utility;
+using Autodesk.RevitAddIns;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Revit.NET
+{
+ public class Program
+ {
+ static readonly string WorkPath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
+
+ static Program()
+ {
+ RevitCoreContext.Instance.Run();
+ }
+
+ ///
+ /// Revit 内核必须加 STAThread 标签
+ ///
+ ///
+
+ [STAThread]
+ static void Main(string[] args)
+ {
+ var app = RevitCoreContext.Instance.Application;
+
+ // Todo ...
+
+ var projectrTemplate = app.DefaultProjectTemplate;
+
+ if (!File.Exists(projectrTemplate))
+ {
+ throw new FileNotFoundException("默认项目路径不存在 , 请指定 !");
+ }
+
+ var document = app.NewProjectDocument(projectrTemplate);
+
+ if (document == null)
+ {
+ throw new InvalidOperationException();
+ }
+
+ // create wall demo ...
+
+ var p1 = XYZ.Zero;
+
+ var p2 = p1 + XYZ.BasisX * 10;
+
+ var p3 = p2 + XYZ.BasisY * 10;
+
+ var p4 = p1 + XYZ.BasisY * 10;
+
+ var points = new XYZ[] { p1, p2, p3, p4 };
+
+ document.Invoke(m =>
+ {
+ var level0 = document.QueryByType().OfType().FirstOrDefault(x => Math.Abs(x.Elevation - 0.0) <= 1e-7);
+
+ if (level0 == null)
+ {
+ level0 = Level.Create(document, 0);
+
+ document.Regenerate();
+ }
+
+ for (int i = 0; i < points.Length; i++)
+ {
+ var a = points[i];
+
+ var b = i == points.Length - 1 ? points[0] : points[i + 1];
+
+ Wall.Create(document, Line.CreateBound(a, b), level0.Id, false);
+ }
+ });
+
+ document.SaveAs(Path.Combine(WorkPath, "demowall.rvt"), new SaveAsOptions() { OverwriteExistingFile = true });
+
+ RevitCoreContext.Instance.Stop();
+ }
+ }
+
+ public class RevitCoreContext
+ {
+ // 此路径为动态反射搜索路径 、 此路径可为任意路径(只要路径下有RevitNET 所需依赖项即可,完整依赖项可在 Naviswork 2016 下面找到)
+
+ static readonly string[] Searchs = RevitProductUtility.GetAllInstalledRevitProducts().Select(x => x.InstallLocation).ToArray();
+
+ static readonly object lockobj = new object();
+
+ static RevitCoreContext _instance;
+
+ private Product _product;
+
+ public Application Application { get => _product.Application; }
+
+ public static RevitCoreContext Instance
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ lock (lockobj)
+ {
+ if (_instance == null)
+ {
+ _instance = new RevitCoreContext();
+ }
+ }
+ }
+
+ return _instance;
+ }
+ }
+
+ static RevitCoreContext()
+ {
+ AddEnvironmentPaths(Searchs);
+
+ AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
+ }
+
+ public void Run()
+ {
+ _product = Product.GetInstalledProduct();
+
+ var clientId = new ClientApplicationId(Guid.NewGuid(), "DotNet", "BIMAPI");
+
+ // I am authorized by Autodesk to use this UI-less functionality. 必须是此字符串。 Autodesk 规定的.
+
+ _product.Init(clientId, "I am authorized by Autodesk to use this UI-less functionality.");
+ }
+
+ public void Stop()
+ {
+ _product?.Exit();
+ }
+
+ static void AddEnvironmentPaths(params string[] paths)
+ {
+ var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty };
+
+ var newPath = string.Join(System.IO.Path.PathSeparator.ToString(), path.Concat(paths));
+
+ Environment.SetEnvironmentVariable("PATH", newPath);
+ }
+
+ private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
+ {
+ var assemblyName = new AssemblyName(args.Name);
+
+ foreach (var item in Searchs)
+ {
+ var file = string.Format("{0}.dll", System.IO.Path.Combine(item, assemblyName.Name));
+
+ if (File.Exists(file))
+ {
+ return Assembly.LoadFile(file);
+ }
+ }
+
+ return args.RequestingAssembly;
+ }
+ }
+
+ public static class DocumentExtension
+ {
+ public static void Invoke(this Document doc, Action action, string name = "default")
+ {
+ using (var tr = new Transaction(doc, name))
+ {
+ tr.Start();
+
+ action(tr);
+
+ var status = tr.GetStatus();
+
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ return;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return;
+ default:
+ return;
+ }
+ }
+ }
+
+ public static TResult Invoke(this Document doc, Func func, string name = "default")
+ {
+ using (var tr = new Transaction(doc, name))
+ {
+ tr.Start();
+
+ var result = func(tr);
+
+ var status = tr.GetStatus();
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return result;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ return result;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return result;
+ default:
+ return result;
+ }
+ }
+ }
+
+ public static void InvokeSub(this Document doc, Action action)
+ {
+ using (var tr = new SubTransaction(doc))
+ {
+ tr.Start();
+
+ action(tr);
+
+ var status = tr.GetStatus();
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ break;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return;
+ default:
+ return;
+ }
+ }
+ }
+
+
+ public static TResult InvokeSub(this Document doc, Func func)
+ {
+ using (var tr = new SubTransaction(doc))
+ {
+ tr.Start();
+
+ var result = func(tr);
+
+ var status = tr.GetStatus();
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return result;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ return result;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return result;
+ default:
+ return result;
+ }
+ }
+ }
+
+ public static void InvokeGroup(this Document doc, Action action, string name = "default")
+ {
+ using (var tr = new TransactionGroup(doc, name))
+ {
+ tr.Start();
+
+ action(tr);
+
+ var status = tr.GetStatus();
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ break;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return;
+ default:
+ return;
+ }
+ }
+ }
+
+ public static TResult InvokeGroup(this Document doc, Func func, string name = "default")
+ {
+ using (var tr = new TransactionGroup(doc, name))
+ {
+ tr.Start();
+
+ var result = func(tr);
+
+ var status = tr.GetStatus();
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return result;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ return result;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return result;
+ default:
+ return result;
+ }
+ }
+ }
+
+ public static FilteredElementCollector QueryByType(this Document doc) where T : Element
+ {
+ return new FilteredElementCollector(doc).OfClass(typeof(T));
+ }
+ }
+}
diff --git a/DotNet.Revit.NET/Properties/AssemblyInfo.cs b/DotNet.Revit.NET/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ef44d38
--- /dev/null
+++ b/DotNet.Revit.NET/Properties/AssemblyInfo.cs
@@ -0,0 +1,44 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNet.Revit.NET")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.NET")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Revit.NET/Properties/Resources.Designer.cs b/DotNet.Revit.NET/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..0581e50
--- /dev/null
+++ b/DotNet.Revit.NET/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace DotNet.Revit.NET.Properties {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNet.Revit.NET.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/DotNet.Revit.NET/Properties/Resources.resx b/DotNet.Revit.NET/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/DotNet.Revit.NET/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.NET/Properties/Settings.Designer.cs b/DotNet.Revit.NET/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..ab8496e
--- /dev/null
+++ b/DotNet.Revit.NET/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace DotNet.Revit.NET.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/DotNet.Revit.NET/Properties/Settings.settings b/DotNet.Revit.NET/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/DotNet.Revit.NET/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.NET/Usingdll/RevitAddInUtility.dll b/DotNet.Revit.NET/Usingdll/RevitAddInUtility.dll
new file mode 100644
index 0000000..27b3f09
Binary files /dev/null and b/DotNet.Revit.NET/Usingdll/RevitAddInUtility.dll differ
diff --git a/DotNet.Revit.Ribbon/App.config b/DotNet.Revit.Ribbon/App.config
new file mode 100644
index 0000000..4bfa005
--- /dev/null
+++ b/DotNet.Revit.Ribbon/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/DotNet.Revit.Ribbon/App.xaml b/DotNet.Revit.Ribbon/App.xaml
new file mode 100644
index 0000000..90411b5
--- /dev/null
+++ b/DotNet.Revit.Ribbon/App.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/DotNet.Revit.Ribbon/App.xaml.cs b/DotNet.Revit.Ribbon/App.xaml.cs
new file mode 100644
index 0000000..9049f9e
--- /dev/null
+++ b/DotNet.Revit.Ribbon/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace DotNet.Revit.Ribbon
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/DotNet.Revit.Ribbon/DotNet.Revit.Ribbon.csproj b/DotNet.Revit.Ribbon/DotNet.Revit.Ribbon.csproj
new file mode 100644
index 0000000..c081775
--- /dev/null
+++ b/DotNet.Revit.Ribbon/DotNet.Revit.Ribbon.csproj
@@ -0,0 +1,119 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}
+ WinExe
+ Properties
+ DotNet.Revit.Ribbon
+ DotNet.Revit.Ribbon
+ v4.8
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\AdWindows.dll
+
+
+ D:\Program Files\Autodesk\Revit 2016\ManagedMC3.dll
+
+
+ False
+ D:\Program Files\Autodesk\Revit 2016\Microsoft.Expression.Interactions.dll
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.Ribbon/MainWindow.xaml b/DotNet.Revit.Ribbon/MainWindow.xaml
new file mode 100644
index 0000000..687853d
--- /dev/null
+++ b/DotNet.Revit.Ribbon/MainWindow.xaml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DotNet.Revit.Ribbon/MainWindow.xaml.cs b/DotNet.Revit.Ribbon/MainWindow.xaml.cs
new file mode 100644
index 0000000..7f04051
--- /dev/null
+++ b/DotNet.Revit.Ribbon/MainWindow.xaml.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using RS = DotNet.Revit.Ribbon.Properties.Resources;
+
+namespace DotNet.Revit.Ribbon
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ [DllImport("gdi32.dll")]
+ private static extern bool DeleteObject(IntPtr hObject);
+
+ public MainWindow()
+ {
+ InitializeComponent();
+
+ // 设置大图标
+ this.ID_DoNet.LargeImage = this.ConvertTo(RS.Github32);
+ this.ID_Revit.LargeImage = this.ConvertTo(RS.Github32);
+ this.ID_GitHub.LargeImage = this.ConvertTo(RS.Github32);
+ this.ID_GitHubChild.LargeImage = this.ConvertTo(RS.Github32);
+
+ // 绑定命令
+ this.ID_DoNet.CommandHandler = new CmdCommand();
+ this.ID_Revit.CommandHandler = new CmdCommand();
+ this.ID_GitHub.CommandHandler = new CmdCommand();
+ this.ID_GitHubChild.CommandHandler = new CmdCommand();
+ }
+
+ private BitmapSource ConvertTo(Icon icon)
+ {
+ var hIcon = icon.Handle;
+ try
+ {
+ var source = Imaging.CreateBitmapSourceFromHIcon(
+ hIcon,
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+ return source;
+ }
+ finally
+ {
+ DeleteObject(hIcon);
+ }
+ }
+ }
+
+ public class CmdCommand : ICommand
+ {
+ public bool CanExecute(object parameter)
+ {
+ return true;
+ }
+
+ public event EventHandler CanExecuteChanged;
+
+ public void Execute(object parameter)
+ {
+ var item = parameter as Autodesk.Windows.RibbonItem;
+ MessageBox.Show(string.Format("This is {0} command test !!", item.Text));
+ }
+ }
+}
diff --git a/DotNet.Revit.Ribbon/Properties/AssemblyInfo.cs b/DotNet.Revit.Ribbon/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..3adf0bb
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNet.Revit.Ribbon")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.Ribbon")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Revit.Ribbon/Properties/Resources.Designer.cs b/DotNet.Revit.Ribbon/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..9d2781e
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/Resources.Designer.cs
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace DotNet.Revit.Ribbon.Properties {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNet.Revit.Ribbon.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
+ ///
+ internal static System.Drawing.Icon Github32 {
+ get {
+ object obj = ResourceManager.GetObject("Github32", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+ }
+}
diff --git a/DotNet.Revit.Ribbon/Properties/Resources.resx b/DotNet.Revit.Ribbon/Properties/Resources.resx
new file mode 100644
index 0000000..24d3004
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/Resources.resx
@@ -0,0 +1,197 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnksoAZ5LKAGeSygBnksoAZpDIAGyY0gltmdIcbJjRMGqW
+ zz9plc1LaZXNS2qWz0BsmNEwbZnTHGyY0gllkMgAZ5LKAGeSygBnksoAZ5LKAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ5LKAGeSygBnksoAapbPAWuX0RhplM1AYYrAalZ9
+ sY1NcqSoSWyduUdqmsFHaprCSWyduU1ypKhVfLCOYIrAammUzUFrl9AZapbOAmeSygBnksoAZ5LKAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ5LKAGeSygBnksoAaZTNAGuWzxNok8tJWYG2hkhs
+ nbxBZJPiQ2aV9ktwof5Qdqn/Unis/1F2qf9Qdaf/THCh/kVol/ZCZJPiSGydvFmBtoZok8tKa5bPFGmU
+ zQBnksoAZ5LKAGeSygAAAAAAAAAAAAAAAAAAAAAAAAAAAGeSygBnksoAZ5LKAGiTywFqls8rX4i+dEhs
+ nbxCZJPuTXKk/1Z+tP9chLr/Z5LL/2aSzP9kj8r/YozF/2aQyP9nksr/ZY/G/1yEuf9NcqX/Q2WU70hs
+ nbxfiL51apbPLGiTywFnksoAZ5LKAGeSygAAAAAAAAAAAAAAAAAAAAAAZ5LKAGeSygBolMwDaZXNOld+
+ so9CZJPcSGye/1qDuv9lkMn/YIrE/16Gvf9mkcr/ZpHL/2SOyP9hi8X/ZI7F/2eSyv9nksr/aJLK/2aR
+ yf9iisD/THCi/0Jkk91XfrKQaZXNO2iUzANnksoAZ5LKAAAAAAAAAAAAAAAAAGeSygBnksoAaJPLAWmV
+ zTtUeq6ZQWOS6lN6rv9ficL/X4rD/2WQyf9ficP/XYa9/2aRyf9mkcv/Y47I/2GMxf9jjMT/Z5LK/2eS
+ yv9oksr/ZpDI/2mUzP9nkcn/VXyv/0FjkutUeq2aaZXNPGiTywJnksoAZ5LKAAAAAABnksoAZ5LKAGmU
+ zQBqls8sV36ykEFjkupZgbf/ZZDL/2CKxP9gisT/ZZDJ/2CJw/9dhr3/ZZDI/2aRy/9jjsj/YYzG/2GK
+ wv9nkcn/Z5LK/2mTyv9mkcj/aJPL/2iTyv9nksv/WIC0/0FjkutWfbGRapbOLWmVzQBnksoAZ5LKAGeS
+ ygBnkssAa5bPFF+IvnZCZJPdWIC1/2qW0P9lkMr/YIrD/2CKxP9lkMn/YIrD/12Fvf9lkMf/aZPM/2eQ
+ x/9njsT/Z47D/2uUy/9nksr/aZPK/2eRyP9ok8r/aJPK/2eSyv9ok8v/V32w/0Fjk95eh713a5bPFWeS
+ ywBnksoAZ5LKAGqWzwJnk8tLSGucvVB2qP9tm9T/aZbQ/2WQyv9gisP/YIrE/2WQyf9gisP/XIS8/1V5
+ r/9EYpj/OVWK/zhSh/9BW47/XXur/3CWyf9ok8v/aJLJ/2iSyv9ok8r/Z5LK/2iTy/9nkcj/SGyd/0dr
+ nL9nkspNapbPAmeSygBnksoAa5fQGliAtIhEZ5bwapbO/2+d1/9pltD/ZZDK/2CKw/9gi8X/ZJDJ/2CK
+ xP9Jbab/JkF4/yE7dP8kQHn/JUF6/yA6cv8jPXT/VXKi/26XzP9nksn/Z5LJ/2iTy/9nksr/aZTL/2WQ
+ yP9agrf/Q2aV8Vh/tIprl9AbZ5LKAGONxABplMxDR2ubvlV8r/9zotz/bpzW/2mWz/9lkMr/YIrE/2GL
+ xf9kkMn/X4nD/zVUjP8fOXD/PVqQ/1mAuf9Ygbv/QmSe/yA7cv80ToP/bZPG/2aQx/9kjsb/aZTL/2eS
+ yv9plMv/ZI7G/2SOxf9Rdqj/R2ubwGiUzEVfiL0AbJjSC1+Iv25DZZXlZ5PK/3Oi3f9unNb/aZbP/2WQ
+ yv9gisT/YYzF/2SQyf9gisP/NlaO/x44b/9HY5b/bpPG/2eOxf9OcKj/Ijxz/y5Jf/9njcH/aJLJ/2GL
+ wv9pk8v/aJLK/2qUy/9hi8P/Zo/G/1+HvP9CZJPmX4i+b2yZ0gxtmdIfVHuukUltnfhwn9j/c6Lc/26c
+ 1v9plc//ZZDK/2CKxP9hjMb/ZJDJ/2CKxP9Oc6z/KEV8/yQ/d/80ToP/NVCF/ydBd/8gOnH/PFyT/2eQ
+ x/9plMv/YozD/2eSyf9qlMv/aZPL/12Hvv9mkMf/ZpDH/0ZpmfhUeq6TbZnSIGuX0DRMcKKsUniq/3Oj
+ 3f9zotz/bpzW/2mVz/9lkMr/YIrE/2KNx/9lkMn/YIrD/12Gv/9Ncaj/JkF6/yA7c/8mQnr/ME6H/0Fj
+ m/9gicH/Z5LK/2mUy/9mkMf/ZZDI/2iTy/9lkMj/WoS7/2mTyv9nksr/TXKj/0twoa5rl9A1apXORkdr
+ m75Zgrb/dKPd/3Oi3P9unNb/aZbP/2WQyv9gisT/Yo3G/2SQyf9gicP/XYa//0Jkm/8gO3P/MEuC/1qA
+ t/9dh8H/X4jA/2eSyf9nksr/aJPL/2mUy/9mkcn/Z5LK/2CKwf9eiL//apTL/2iTy/9Teav/R2qbv2mV
+ zUholMxURWmZxlyFuv90o97/c6Lc/26c1v9plc//ZZDK/2CKxP9ijcf/ZZDJ/2CKw/9dhr//SW2k/yI9
+ dv8vSX//X32v/2iLv/9ji8L/ZpDI/2eSyv9oksr/a5XM/2aRyf9kj8b/XYe9/2WQyP9qlMv/aJPL/1V7
+ r/9FaJjIaJPLWGiUzFVFaJnGXIW6/3Sj3v9zotz/bpzW/2mVz/9lkMr/YIrE/2OOyP9kkMn/YIrD/1yE
+ vf9GaZ7/JUB4/yA6cv8jPHT/NE2C/2F/rv9rlcr/Z5LK/2eSyv9qlcz/Z5LJ/2GMw/9eib//Z5LK/2mU
+ y/9ok8v/VXuv/0VomMhok8tZaZXOSEdqm79agrf/dKPd/3Oi3P9unNb/aZXP/2WQyv9gisT/Y47I/2WQ
+ yf9gisT/TnOs/yVBeP8kPnf/M1KK/zBOh/8fOXL/MUt+/22Qwf9ok8v/Z5LK/2qUy/9ok8r/Yo3E/2OO
+ xf9pk8v/aZPL/2iTy/9Ueaz/R2qawGmVzUprl9A2S3ChrlN5rP90o93/c6Lc/26c1v9plc//ZZDK/2CK
+ xP9jjsj/ZZDJ/2GLxP89Xpb/Hzlx/zlUiv9kjMT/XIW//y1Kgv8hOnH/W3qs/2qUzP9nksr/aZPL/2mU
+ y/9mkcn/Z5LK/2qUy/9ok8r/Z5PL/05ypP9Lb6Gwa5fQN22Z0iFTea2USm6f+XGf2f9zotz/bpzW/2mV
+ z/9lkMr/YIvE/2SPyf9lkMn/YYvE/zpbk/8eOXD/PlqO/2+Vyv9gisP/L02F/yA6cf9Wdaf/bJbN/2eS
+ yv9ok8r/apTL/2eSyv9nksr/apTL/2eSyv9mkMf/R2qa+VN5rJZtmdIibJnSDV6HvXFDZpXnaZXM/3Oi
+ 3P9unNb/aZXP/2WQyv9hi8T/ZI/J/2WQyf9hi8X/SGyl/yE7c/8oQnn/T2ud/0Zkmf8kPnb/ITty/ztW
+ iv9tkcT/Z5LL/2eSyv9qlcv/Z5LK/2mTy/9plMv/Z5LL/1+Ivf9CZJPoXoe9c2yZ0g2Bs/EAaJPLSEZq
+ msNXf7P/c6Ld/26c1v9plc//ZZDK/2GLxP9kj8n/ZZDK/2CKxP9bg7r/PmCY/yI+d/8fOXH/Hzlx/yM+
+ df8lQXn/KUR7/2aKvf9ok8v/Z5LK/2mUy/9qlMv/apTL/2eSyv9nksv/UXap/0ZpmsRok8tJc6HcAGeS
+ ygBrl9AeVn2xjkVpmPNsmdH/b53X/2mVz/9lkMr/YYvF/2SPyf9lkMn/YIrE/12Gvf9kj8f/Unmz/0Fk
+ nv9CZZ7/UHWs/1qCuf9Rdq7/ZIzD/2eSy/9nksr/aJLK/2qUy/9ok8r/Z5LL/2KLwf9DZZTzVn2xkGuX
+ 0B9nksoAZ5LKAGqWzwNnkclSRmmaxFR6rf9unNb/aZXP/2WQyv9hi8X/ZJDK/2WQyf9gisP/XYa9/2aS
+ yv9nk8z/ZZDK/2ONx/9jjcP/aJPL/2iTy/9nksr/Z5LK/2eSyv9nksr/Z5LK/2eSyv9nksr/TnOl/0Zp
+ mcVmkclTapbPA2eSygBnksoAZ5PLAGuXzxhchbp9QmSU41yFu/9qltD/ZZDK/2GLxf9kkMn/ZZDJ/2CK
+ w/9ehr3/Z5LL/2aRy/9kj8j/YozE/2SNxP9nksr/Z5LK/2eSyv9nksr/Z5LK/2eSyv9nksr/aJPL/1h/
+ s/9BY5LkXIS6f2uXzxlnk8sAZ5LKAGeSygBnksoAapXOAGqVzjNUeq6YQmWU71yFvP9mkcv/YYvF/2WQ
+ yv9lkMn/YIrD/16Hvf9nk8z/ZpHL/2SPyf9hi8P/ZY/G/2eSyv9nksr/Z5LK/2eSyv9nksr/Z5LK/2iT
+ y/9bg7j/QmST8FN6rZlqlc40apbOAGeSygBnksoAAAAAAGeSygBnksoAaZTMA2iUzENRdqmiQmSU8Fd+
+ tP9hi8X/ZZHL/2WQyf9gisP/X4i+/2eTzP9mkcv/ZI/J/2GLwv9mkcj/Z5LK/2eSyv9nksr/Z5LK/2eS
+ y/9nksr/WH+0/0Jkk/BQdqmiaJTMRGmUzANnksoAZ5LKAAAAAAAAAAAAAAAAAGeSygBnkssAaZTNBWiU
+ zENTeq2ZQWOS5ExwpP9hi8P/ZZDK/2CKxP9fiL7/aJPN/2aRy/9kj8j/YozC/2eRyf9nksr/Z5LK/2eT
+ y/9ok8v/YozD/090pv9BY5LlU3qtmmiUzERplc0FZ5PLAGeSygAAAAAAAAAAAAAAAAAAAAAAZ5LKAGeS
+ ygBnk8sAaZTMA2qVzjRchLp/RmmZxkNmlvRQdqn/WYG4/1+Ivv9olM7/ZpLM/2SPyf9jjML/aJPL/2iT
+ y/9mkcj/YIm//1J4q/9DZpX1RWiZx1yEuYBqlc41aZTMBGeTywBnksoAZ5LKAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAZ5LKAGeSygBnksoAapbPAGuWzxpmkclUVXywkkZpmcdBY5LqRmmY+k91p/9Teq7/Vnyx/1V6
+ rP9Ve67/T3Sm/0hrm/pCZJPqRWmZx1V8sJNmkchVa5bPG2uX0ABnksoAZ5LKAGeSygAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGeSygBnksoAaJPLAGqWzwRrl9AgZ5LKTF2Gu3ZSeKuaSm6ftEZp
+ mcVFZ5fMRGeXzUZpmcVKbp+1UXeqml2Fu3dnkspMa5fQIWqWzwRok8sAZ5LKAGeSygAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGeSygBnksoAZ5LKAGeSygBumtQBbJnSD2yZ
+ 0iVrls88aJTMU2eSymNnkspjaJTMU2uWzzxsmdImbJnSD22a0wFnksoAZ5LKAGeSygBnksoAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/AAAP/gAAB/gAAAHwAAAA8AAAAOAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACAAAABwAAAA8AAAAPgAAAH+AAAH/wAAD8=
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.Ribbon/Properties/Settings.Designer.cs b/DotNet.Revit.Ribbon/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..ff2479a
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace DotNet.Revit.Ribbon.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/DotNet.Revit.Ribbon/Properties/Settings.settings b/DotNet.Revit.Ribbon/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/DotNet.Revit.Ribbon/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.ShortKey/CmdShortKey.cs b/DotNet.Revit.ShortKey/CmdShortKey.cs
new file mode 100644
index 0000000..81b6521
--- /dev/null
+++ b/DotNet.Revit.ShortKey/CmdShortKey.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.Attributes;
+using Autodesk.Windows;
+using System.Reflection;
+
+namespace DotNet.Revit.ShortKey
+{
+ ///
+ /// 动态设置命令控件的快捷键
+ ///
+ ///
+ [Transaction(TransactionMode.Manual)]
+ public class CmdShortKey : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
+ {
+ // 基于Revit的命令控件动态设置快捷键测试....
+
+ var panel = commandData.Application.CreateRibbonPanel("ShortKeyTest");
+ var data = new PushButtonData("ID_BIMAPI", "ShortKey", typeof(CmdTest).Assembly.Location, typeof(CmdTest).FullName);
+ var btn = panel.AddItem(data) as Autodesk.Revit.UI.RibbonButton;
+
+ btn.SetShortCut("BIMAPI");
+
+
+ // 修改 门 按钮的快捷键
+
+ var item = Autodesk.Windows.ComponentManager.Ribbon.FindItem("ID_OBJECTS_DOOR", false);
+ if (item == null)
+ return Result.Succeeded;
+
+ item.SetShortCut("DOOR");
+ return Result.Succeeded;
+ }
+ }
+
+ [Transaction(TransactionMode.Manual)]
+ public class CmdTest : IExternalCommand
+ {
+ public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ System.Windows.MessageBox.Show("Shortcut is valid!!");
+ return Result.Succeeded;
+ }
+ }
+}
diff --git a/DotNet.Revit.ShortKey/DotNet.Revit.ShortKey.csproj b/DotNet.Revit.ShortKey/DotNet.Revit.ShortKey.csproj
new file mode 100644
index 0000000..ff43bf1
--- /dev/null
+++ b/DotNet.Revit.ShortKey/DotNet.Revit.ShortKey.csproj
@@ -0,0 +1,79 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}
+ Library
+ Properties
+ DotNet.Revit.ShortKey
+ DotNet.Revit.ShortKey
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\AdWindows.dll
+ False
+
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPI.dll
+ False
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\UIFramework.dll
+ False
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\UIFrameworkServices.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.ShortKey/Properties/AssemblyInfo.cs b/DotNet.Revit.ShortKey/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..590ff4f
--- /dev/null
+++ b/DotNet.Revit.ShortKey/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNet.Revit.ShortKey")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.ShortKey")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d36eef7d-e6e8-454d-8bcd-b33459a6c9cd")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Revit.ShortKey/ShortKeyHelper.cs b/DotNet.Revit.ShortKey/ShortKeyHelper.cs
new file mode 100644
index 0000000..1ff7110
--- /dev/null
+++ b/DotNet.Revit.ShortKey/ShortKeyHelper.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using UIFramework;
+using UIFrameworkServices;
+
+namespace DotNet.Revit.ShortKey
+{
+ public static class ShortKeyHelper
+ {
+ ///
+ /// 基于Revit封装的RibbonButton设置其快捷键.
+ ///
+ /// RibbonButton.
+ /// 快捷键字符串.
+ ///
+ public static bool SetShortCut(this Autodesk.Revit.UI.RibbonButton btn, string key)
+ {
+ if (btn == null)
+ return false;
+
+ var item = btn.GetType().InvokeMember("getRibbonItem",
+ BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
+ Type.DefaultBinder, btn, null);
+
+ if (item == null)
+ return false;
+
+ return (item as Autodesk.Windows.RibbonItem).SetShortCut(key);
+ }
+
+ ///
+ /// 基于通用库封装的RibbonCommandItem设置其快捷键.
+ ///
+ /// RibbonCommandItem.
+ /// 快捷键字符串.
+ ///
+ public static bool SetShortCut(this Autodesk.Windows.RibbonItem commandItem, string key)
+ {
+ if (commandItem == null || string.IsNullOrEmpty(key))
+ return false;
+
+ var parentTab = default(Autodesk.Windows.RibbonTab);
+ var parentPanel = default(Autodesk.Windows.RibbonPanel);
+
+ Autodesk.Windows.ComponentManager.Ribbon.FindItem(commandItem.Id, false, out parentPanel, out parentTab, true);
+
+ if (parentTab == null || parentPanel == null)
+ return false;
+
+ var path = string.Format("{0}>{1}", parentTab.Id, parentPanel.Source.Id);
+ var cmdId = ControlHelper.GetCommandId(commandItem);
+
+ if (string.IsNullOrEmpty(cmdId))
+ {
+ cmdId = Guid.NewGuid().ToString();
+ ControlHelper.SetCommandId(commandItem, cmdId);
+ }
+
+ var shortcutItem = new ShortcutItem(commandItem.Text, cmdId, key, path);
+ shortcutItem.ShortcutType = StType.RevitAPI;
+ KeyboardShortcutService.applyShortcutChanges(new Dictionary()
+ {
+ {
+ cmdId,shortcutItem
+ }
+ });
+ return true;
+ }
+ }
+}
diff --git a/DotNet.Revit.ViewTransform/DotNet.Revit.ViewTransform.csproj b/DotNet.Revit.ViewTransform/DotNet.Revit.ViewTransform.csproj
new file mode 100644
index 0000000..d7d9635
--- /dev/null
+++ b/DotNet.Revit.ViewTransform/DotNet.Revit.ViewTransform.csproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}
+ Library
+ Properties
+ DotNet.Revit.ViewTransform
+ DotNet.Revit.ViewTransform
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPI.dll
+ False
+
+
+ ..\..\..\..\CYBIM\CYCommons\References\Revit\16\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.Revit.ViewTransform/Properties/AssemblyInfo.cs b/DotNet.Revit.ViewTransform/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..13719ac
--- /dev/null
+++ b/DotNet.Revit.ViewTransform/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNet.Revit.ViewTransform")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.Revit.ViewTransform")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("4f7735c6-e3bf-4dfb-8619-eab9ab4264e3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.Revit.ViewTransform/ViewTransformHelper.cs b/DotNet.Revit.ViewTransform/ViewTransformHelper.cs
new file mode 100644
index 0000000..ce91bf2
--- /dev/null
+++ b/DotNet.Revit.ViewTransform/ViewTransformHelper.cs
@@ -0,0 +1,54 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.Revit.ViewTransform
+{
+ public static class ViewTransformHelper
+ {
+ ///
+ /// 屏幕点转为空间三维点.
+ ///
+ /// 指定转换到的视图.
+ /// 指定屏幕上的点.
+ ///
+ public static XYZ ScreenToWorld(this View view, System.Drawing.Point point)
+ {
+ if (view == null)
+ throw new NullReferenceException();
+
+ var uiDoc = new UIDocument(view.Document);
+ var uiView = uiDoc.GetOpenUIViews().FirstOrDefault(m => m.ViewId == view.Id);
+
+ if (uiView == null)
+ throw new NullReferenceException();
+
+ var rect = uiView.GetWindowRectangle();
+ var corners = uiView.GetZoomCorners();
+
+ var mousePoint = new XYZ(point.X, point.Y, 0);
+
+ var screenLeftlower = new XYZ(rect.Left, rect.Bottom, 0);
+ var screenRightupper = new XYZ(rect.Right, rect.Top, 0);
+
+ // 换算比例
+ var scale = corners[0].DistanceTo(corners[1])
+ / screenLeftlower.DistanceTo(screenRightupper);
+
+ var xdis = (point.X - screenLeftlower.X) * scale;
+ var ydis = (screenLeftlower.Y - point.Y) * scale;
+
+ var vp = uiDoc.ActiveView.UpDirection;
+ var vr = uiDoc.ActiveView.RightDirection;
+
+ var distance = mousePoint.DistanceTo(screenLeftlower) * scale;
+ var result = corners[0] + vr * xdis + vp * ydis;
+
+ return result;
+ }
+ }
+}
diff --git a/DotNet.Revit.sln b/DotNet.Revit.sln
new file mode 100644
index 0000000..be4cbe1
--- /dev/null
+++ b/DotNet.Revit.sln
@@ -0,0 +1,101 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.InvokeCommand", "DotNet.Revit.InvokeCommand\DotNet.Revit.InvokeCommand.csproj", "{F40BCA44-2737-4530-866C-B8ECB07696BE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.ShortKey", "DotNet.Revit.ShortKey\DotNet.Revit.ShortKey.csproj", "{BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.GeometryObject", "DotNet.Revit.GeometryObject\DotNet.Revit.GeometryObject.csproj", "{61F38117-EB54-46B6-96BB-D62B3E0E599A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.Ribbon", "DotNet.Revit.Ribbon\DotNet.Revit.Ribbon.csproj", "{6519EF10-60A9-46DE-A14E-9B8787BCC5FC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.ViewTransform", "DotNet.Revit.ViewTransform\DotNet.Revit.ViewTransform.csproj", "{748628B2-77B6-4C20-AE98-7C78F71386AB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.ExternalEvent", "DotNet.Revit.ExternalEvent\DotNet.Revit.ExternalEvent.csproj", "{7164311A-01C1-4FAB-97DB-B9310C973800}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.NET", "DotNet.Revit.NET\DotNet.Revit.NET.csproj", "{A4D8216D-D414-4482-A1DC-98A972D09227}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Exchange.Revit", "DotNet.Exchange.Revit\DotNet.Exchange.Revit.csproj", "{22EDDE0F-0E6A-4C47-AEA5-17027830F236}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.Revit.Hook", "DotNet.Revit.Hook\DotNet.Revit.Hook.csproj", "{957A91DD-D04D-4811-82B7-7350A444CB12}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "frames", "frames", "{EED62B00-70DF-4A90-9EB3-DD11B848BDE1}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "DotNet.RevitUI", "DotNet.RevitUI\DotNet.RevitUI.shproj", "{824F3074-0794-4A6E-A2AD-36638408846C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNet.RevitUI (2016)", "DotNet.RevitUI (2016)\DotNet.RevitUI (2016).csproj", "{22F6CC59-E396-4477-9215-21777C68E044}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{1F01D2AB-DD0F-49E5-AE78-E157FDA5D42C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.DotNet.RevitUI (2016)", "Test.DotNet.RevitUI (2016)\Test.DotNet.RevitUI (2016).csproj", "{F4B2970D-431C-4801-A65D-F48FEE8C650A}"
+EndProject
+Global
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ DotNet.RevitUI\DotNet.RevitUI.projitems*{22f6cc59-e396-4477-9215-21777c68e044}*SharedItemsImports = 4
+ DotNet.RevitUI\DotNet.RevitUI.projitems*{824f3074-0794-4a6e-a2ad-36638408846c}*SharedItemsImports = 13
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F40BCA44-2737-4530-866C-B8ECB07696BE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BB36AF9B-E8EC-42BA-AEA8-21C7B6C94058}.Release|Any CPU.Build.0 = Release|Any CPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {61F38117-EB54-46B6-96BB-D62B3E0E599A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6519EF10-60A9-46DE-A14E-9B8787BCC5FC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {748628B2-77B6-4C20-AE98-7C78F71386AB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7164311A-01C1-4FAB-97DB-B9310C973800}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A4D8216D-D414-4482-A1DC-98A972D09227}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22EDDE0F-0E6A-4C47-AEA5-17027830F236}.Release|Any CPU.Build.0 = Release|Any CPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {957A91DD-D04D-4811-82B7-7350A444CB12}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22F6CC59-E396-4477-9215-21777C68E044}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22F6CC59-E396-4477-9215-21777C68E044}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22F6CC59-E396-4477-9215-21777C68E044}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22F6CC59-E396-4477-9215-21777C68E044}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {824F3074-0794-4A6E-A2AD-36638408846C} = {EED62B00-70DF-4A90-9EB3-DD11B848BDE1}
+ {22F6CC59-E396-4477-9215-21777C68E044} = {EED62B00-70DF-4A90-9EB3-DD11B848BDE1}
+ {1F01D2AB-DD0F-49E5-AE78-E157FDA5D42C} = {EED62B00-70DF-4A90-9EB3-DD11B848BDE1}
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A} = {1F01D2AB-DD0F-49E5-AE78-E157FDA5D42C}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4212863E-A4CB-4F93-877C-346926AF014E}
+ EndGlobalSection
+EndGlobal
diff --git a/DotNet.RevitUI (2016)/DotNet.RevitUI (2016).csproj b/DotNet.RevitUI (2016)/DotNet.RevitUI (2016).csproj
new file mode 100644
index 0000000..6989ea4
--- /dev/null
+++ b/DotNet.RevitUI (2016)/DotNet.RevitUI (2016).csproj
@@ -0,0 +1,72 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {22F6CC59-E396-4477-9215-21777C68E044}
+ Library
+ Properties
+ DotNet.RevitUI
+ DotNet.RevitUI
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\AdWindows.dll
+ False
+
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPI.dll
+ False
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\UIFramework.dll
+ False
+
+
+ D:\Program Files\Autodesk\Revit 2016\UIFrameworkServices.dll
+ False
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs b/DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c38428e
--- /dev/null
+++ b/DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("DotNet.RevitUI (2016)")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNet.RevitUI (2016)")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("22f6cc59-e396-4477-9215-21777c68e044")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DotNet.RevitUI/DotNet.RevitUI.projitems b/DotNet.RevitUI/DotNet.RevitUI.projitems
new file mode 100644
index 0000000..876422d
--- /dev/null
+++ b/DotNet.RevitUI/DotNet.RevitUI.projitems
@@ -0,0 +1,30 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ 824f3074-0794-4a6e-a2ad-36638408846c
+
+
+ DotNet.RevitUI
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DotNet.RevitUI/DotNet.RevitUI.shproj b/DotNet.RevitUI/DotNet.RevitUI.shproj
new file mode 100644
index 0000000..1e14f8f
--- /dev/null
+++ b/DotNet.RevitUI/DotNet.RevitUI.shproj
@@ -0,0 +1,13 @@
+
+
+
+ 824f3074-0794-4a6e-a2ad-36638408846c
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/DotNet.RevitUI/Extension/WindowExtension.cs b/DotNet.RevitUI/Extension/WindowExtension.cs
new file mode 100644
index 0000000..b69cb6c
--- /dev/null
+++ b/DotNet.RevitUI/Extension/WindowExtension.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows;
+
+namespace DotNet.RevitUI.MVVM.Extension
+{
+ public static class WindowExtension
+ {
+ ///
+ /// 非模态显示窗体,并指定此窗体的宿主窗体.
+ ///
+ /// The main.
+ /// The parent.
+ public static void Show(this Window main, IntPtr parent)
+ {
+ if (parent == IntPtr.Zero)
+ {
+ parent = Process.GetCurrentProcess().MainWindowHandle;
+ }
+
+ var mainHelper = new System.Windows.Interop.WindowInteropHelper(main)
+ {
+ Owner = parent
+ };
+
+ // self-adaption
+ if (Math.Abs(PrimaryScreen.ScaleX - 1.0) >= 1e-7)
+ {
+ main.Width = main.Width * PrimaryScreen.ScaleX;
+ main.Height = main.Height * PrimaryScreen.ScaleX;
+ }
+
+ main.Show();
+ }
+
+ ///
+ /// 模态显示窗体,并指定此窗体的宿主窗体.
+ ///
+ public static void ShowDialog(this Window main, IntPtr parent)
+ {
+ if (parent == IntPtr.Zero)
+ {
+ parent = Process.GetCurrentProcess().MainWindowHandle;
+ }
+
+ var mainHelper = new System.Windows.Interop.WindowInteropHelper(main)
+ {
+ Owner = parent
+ };
+
+ // self-adaption
+ if (Math.Abs(PrimaryScreen.ScaleX - 1.0) >= 1e-7)
+ {
+ main.Width = main.Width * PrimaryScreen.ScaleX;
+ main.Height = main.Height * PrimaryScreen.ScaleX;
+ }
+
+ main.ShowDialog();
+ }
+
+ ///
+ /// 获取WPF窗口句柄.
+ ///
+ /// The main.
+ ///
+ public static IntPtr GetHandle(this Window main)
+ {
+ var helper = new System.Windows.Interop.WindowInteropHelper(main);
+
+#if !NET35
+ if(helper.Handle==IntPtr.Zero)
+ {
+ return helper.EnsureHandle();
+ }
+#endif
+ return helper.Handle;
+ }
+ }
+
+ class PrimaryScreen
+ {
+ #region Win32 API
+ [DllImport("user32.dll")]
+ static extern IntPtr GetDC(IntPtr ptr);
+
+ [DllImport("gdi32.dll")]
+ static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
+
+ [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
+ static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
+
+ #endregion
+
+ #region DeviceCaps常量
+ const int HORZRES = 8;
+ const int VERTRES = 10;
+ const int LOGPIXELSX = 88;
+ const int LOGPIXELSY = 90;
+ const int DESKTOPVERTRES = 117;
+ const int DESKTOPHORZRES = 118;
+ #endregion
+
+ #region 属性
+ ///
+ /// 获取屏幕分辨率当前物理大小
+ ///
+ public static Size WorkingArea
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var size = new Size
+ {
+ Width = GetDeviceCaps(hdc, HORZRES),
+ Height = GetDeviceCaps(hdc, VERTRES)
+ };
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return size;
+ }
+ }
+
+ ///
+ /// 当前系统DPI_X 大小 一般为96
+ ///
+ public static int DpiX
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var DpiX = GetDeviceCaps(hdc, LOGPIXELSX);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return DpiX;
+ }
+ }
+
+ ///
+ /// 当前系统DPI_Y 大小 一般为96
+ ///
+ public static int DpiY
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var DpiX = GetDeviceCaps(hdc, LOGPIXELSY);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return DpiX;
+ }
+ }
+
+ ///
+ /// 获取真实设置的桌面分辨率大小
+ ///
+ public static Size DESKTOP
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var size = new Size();
+ size.Width = GetDeviceCaps(hdc, DESKTOPHORZRES);
+ size.Height = GetDeviceCaps(hdc, DESKTOPVERTRES);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return size;
+ }
+ }
+
+ ///
+ /// 获取宽度缩放百分比
+ ///
+ public static float ScaleX
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var t = GetDeviceCaps(hdc, DESKTOPHORZRES);
+ var d = GetDeviceCaps(hdc, HORZRES);
+ var ScaleX = (float)GetDeviceCaps(hdc, DESKTOPHORZRES) / (float)GetDeviceCaps(hdc, HORZRES);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return ScaleX;
+ }
+ }
+
+ ///
+ /// 获取高度缩放百分比
+ ///
+ public static float ScaleY
+ {
+ get
+ {
+ var hdc = GetDC(IntPtr.Zero);
+ var scaleY = (float)GetDeviceCaps(hdc, DESKTOPVERTRES) / (float)GetDeviceCaps(hdc, VERTRES);
+
+ ReleaseDC(IntPtr.Zero, hdc);
+ return scaleY;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/DotNet.RevitUI/Helper/MainHelper.cs b/DotNet.RevitUI/Helper/MainHelper.cs
new file mode 100644
index 0000000..5f62cb6
--- /dev/null
+++ b/DotNet.RevitUI/Helper/MainHelper.cs
@@ -0,0 +1,51 @@
+using Autodesk.Windows;
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows;
+using UIFrameworkServices;
+
+namespace DotNet.RevitUI.Helper
+{
+ ///
+ /// Revit UI helper.
+ ///
+
+ public static class MainHelper
+ {
+ const int MDI_ID = 0x0000E900;
+
+ const int StatusBar_ID = 0x0000E801;
+
+ const int OptionsBar_ID = 0x000EC801;
+
+ [DllImport("user32")]
+ static extern IntPtr GetDlgItem(IntPtr hWndParent, int cid);
+
+ ///
+ /// Revit 主窗口句柄.
+ ///
+ public static IntPtr RevitHandle = ComponentManager.ApplicationWindow;
+
+ ///
+ /// Revit MDI句柄.
+ ///
+ public static IntPtr RevitMDIHandle = GetDlgItem(ComponentManager.ApplicationWindow, MDI_ID);
+
+ ///
+ /// Revit StatusBar句柄.
+ ///
+ public static IntPtr RevitStatusBarHandle = GetDlgItem(ComponentManager.ApplicationWindow, StatusBar_ID);
+
+ ///
+ /// Revit OptionsBar句柄
+ ///
+ public static IntPtr RevitOptionsBarHandle = GetDlgItem(ComponentManager.ApplicationWindow, OptionsBar_ID);
+
+ ///
+ /// Revit MDI rect.
+ ///
+ public static Rect RevitMDIRect = FloatingService.getMDIClientRect();
+ }
+}
\ No newline at end of file
diff --git a/DotNet.RevitUI/Helper/RevitCommandHelper.cs b/DotNet.RevitUI/Helper/RevitCommandHelper.cs
new file mode 100644
index 0000000..555ba60
--- /dev/null
+++ b/DotNet.RevitUI/Helper/RevitCommandHelper.cs
@@ -0,0 +1,161 @@
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UIFrameworkServices;
+using System.Reflection;
+using Autodesk.Revit.DB;
+using System.Windows.Threading;
+
+namespace DotNet.RevitUI.Helper
+{
+ ///
+ /// Revit command helper
+ ///
+ public class RevitCommandHelper
+ {
+ private static RevitCommandHelper m_Instance;
+
+ private ConcurrentDictionary m_CommandIds;
+
+ public static RevitCommandHelper Instance
+ {
+ get
+ {
+ return m_Instance;
+ }
+
+ internal set
+ {
+ m_Instance = value;
+ }
+ }
+
+ internal RevitCommandHelper()
+ {
+ m_Instance = this;
+
+ m_CommandIds = new ConcurrentDictionary();
+ }
+
+ ///
+ /// 指定一个基于IExternalCommand全名称.执行此命令.
+ ///
+ public bool Execute(string className)
+ {
+ if (!m_CommandIds.ContainsKey(className))
+ {
+ return false;
+ }
+
+ var commnadId = m_CommandIds[className];
+
+ string text2 = string.Format("CustomCtrl_%{0}%{1}", "ZhongHao.He", commnadId);
+
+ ExternalCommandHelper.executeExternalCommand(text2);
+
+ return true;
+ }
+
+ ///
+ /// 指定一个Revit命令接口,执行此命令.
+ ///
+ /// 在执行此命令之前,应确保命令已被加入.
+ public bool Execute()
+ where T : IExternalCommand
+ {
+ return this.Execute(typeof(T).FullName);
+ }
+
+ ///
+ /// 指定Revit命令Id,调用内部命令.
+ ///
+ public bool Invoke(string cmdId)
+ {
+ if (ExternalCommandHelper.CanExecute(cmdId))
+ {
+ ExternalCommandHelper.executeExternalCommand(cmdId);
+ return true;
+ }
+ else if (CommandHandlerService.canExecute(cmdId))
+ {
+ CommandHandlerService.invokeCommandHandler(cmdId);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// 切回Revit上下文件环境调用命令.
+ ///
+ ///
+ public void Invoke(Action uiApp)
+ {
+ if (uiApp == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ if (Dispatcher.CurrentDispatcher != Autodesk.Windows.ComponentManager.Ribbon.Dispatcher)
+ {
+ Autodesk.Windows.ComponentManager.Ribbon.Dispatcher.Invoke(new Action(() =>
+ {
+ RevitCommandInvoke.InvokeHandlers.Enqueue(new InvokeHandler(uiApp));
+ this.Execute();
+
+ }));
+ }
+ else
+ {
+ RevitCommandInvoke.InvokeHandlers.Enqueue(new InvokeHandler(uiApp));
+ this.Execute();
+ }
+ }
+
+ ///
+ /// 注册一个命令.
+ ///
+ /// The assembly path.
+ /// Name of the class.
+ ///
+ public bool RegisterCommand(string assemblyPath, string className)
+ {
+ if (m_CommandIds.ContainsKey(className))
+ {
+ return false;
+ }
+
+ var guid = Guid.NewGuid().ToString();
+ var data = new PushButtonData(guid, guid, assemblyPath, className);
+ var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.InvokeMethod;
+
+ var btn = typeof(PushButtonData).InvokeMember("createPushButton",
+ flags,
+ Type.DefaultBinder,
+ null,
+ new object[] { data, false, "ZhongHao.He" });
+
+ btn.GetType().InvokeMember("getRibbonButton", flags, Type.DefaultBinder, btn, null);
+
+ return m_CommandIds.TryAdd(className, guid);
+ }
+
+ ///
+ /// 注册一个命令.
+ ///
+ ///
+ ///
+ public bool RegisterCommand()
+ where T : IExternalCommand
+ {
+ return RegisterCommand(typeof(T).Assembly.Location, typeof(T).FullName);
+ }
+ }
+}
diff --git a/DotNet.RevitUI/Helper/RibbonBindingHelper.cs b/DotNet.RevitUI/Helper/RibbonBindingHelper.cs
new file mode 100644
index 0000000..e1a90ff
--- /dev/null
+++ b/DotNet.RevitUI/Helper/RibbonBindingHelper.cs
@@ -0,0 +1,211 @@
+using Autodesk.Windows;
+using Autodesk.Windows.ToolBars;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Windows.Data;
+using System.Windows.Input;
+
+namespace DotNet.RevitUI.Helper
+{
+
+ class NonCommand : ICommand
+ {
+ public event EventHandler CanExecuteChanged;
+
+ public bool CanExecute(object parameter)
+ {
+ return true;
+ }
+
+ public void Execute(object parameter)
+ {
+ }
+ }
+
+
+ ///
+ ///
+ ///
+ ///
+
+ public static class RibbonBindingHelper
+ {
+ ///
+ /// 自动关联绑定Ribbon子控件数据.
+ ///
+ /// The ribbon.
+ /// The data context.
+
+ public static void Binding(RibbonControl ribbon, object dataContext)
+ {
+ if (ribbon == null)
+ {
+ throw new NullReferenceException("ribbon parameter is null rference !");
+ }
+
+ if (ribbon.Tabs.Count == 0)
+ {
+ return;
+ }
+
+ if (dataContext == null)
+ {
+ dataContext = ribbon.DataContext;
+ }
+
+ if (dataContext == null)
+ {
+ return;
+ }
+
+ var eum = ribbon.Tabs.GetEnumerator();
+
+ while (eum.MoveNext())
+ {
+ var current = eum.Current;
+
+ foreach (var panel in current.Panels)
+ {
+ ItemBinding(panel, dataContext);
+
+ if (panel.Source.DialogLauncher != null)
+ {
+ ItemBinding(panel.Source.DialogLauncher, dataContext);
+ }
+
+ foreach (var item in panel.Source.Items)
+ {
+ ItemRecursive(item, dataContext);
+ }
+ }
+ }
+ }
+
+ ///
+ /// 递归遍历Item.
+ ///
+ /// The item.
+ /// The data context.
+
+ private static void ItemRecursive(RibbonItem item, object dataContext)
+ {
+ if (item == null)
+ {
+ return;
+ }
+
+ switch (item)
+ {
+ case RibbonListButton listButton:
+
+ listButton.CommandHandler = new NonCommand();
+
+ for (int i = 0; i < listButton.Items.Count; i++)
+ {
+ RibbonBindingHelper.ItemRecursive(listButton.Items[i], dataContext);
+ }
+
+ break;
+
+ case ToolBarHistoryButton toolBar:
+
+ RibbonBindingHelper.ItemBinding(item, dataContext);
+
+ for (int i = 0; i < toolBar.Items.Count; i++)
+ {
+ var current = toolBar.Items[i] as RibbonItem;
+
+ if (current == null)
+ {
+ continue;
+ }
+
+ RibbonBindingHelper.ItemRecursive(current, dataContext);
+ }
+
+ break;
+ case RibbonMenuItem menuItem:
+
+ for (int i = 0; i < menuItem.Items.Count; i++)
+ {
+ RibbonBindingHelper.ItemRecursive(menuItem.Items[i], dataContext);
+ }
+
+ break;
+
+ case RibbonList list:
+
+
+ for (int i = 0; i < list.Items.Count; i++)
+ {
+ var current = list.Items[i] as RibbonItem;
+
+ if (current == null)
+ {
+ continue;
+
+ }
+ RibbonBindingHelper.ItemRecursive(current, dataContext);
+ }
+
+ break;
+ case RibbonRowPanel rowPanel:
+
+ for (int i = 0; i < rowPanel.Items.Count; i++)
+ {
+ RibbonBindingHelper.ItemRecursive(rowPanel.Items[i], dataContext);
+ }
+
+ break;
+ default:
+
+ RibbonBindingHelper.ItemBinding(item, dataContext);
+
+ break;
+ }
+ }
+
+ static void ItemBinding(object obj, object dataContext)
+ {
+ var properties = obj.GetType().GetProperties();
+
+ foreach (var property in properties)
+ {
+ var value = property.GetValue(obj, null);
+
+ if (value == null)
+ {
+ continue;
+ }
+
+ if (value is Binding binding)
+ {
+ if (string.IsNullOrEmpty(binding.Path.Path) || binding.Source != null)
+ {
+ continue;
+ }
+
+ try
+ {
+ binding.Source = dataContext;
+
+ if (obj is RibbonCommandItem commandItem
+ && property.Name == "CommandHandlerBinding")
+ {
+ commandItem.CommandParameter = obj;
+ }
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ Debug.WriteLine(ex.Message);
+#endif
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/DotNet.RevitUI/Helper/RibbonRegisterHelper.cs b/DotNet.RevitUI/Helper/RibbonRegisterHelper.cs
new file mode 100644
index 0000000..fedd3a2
--- /dev/null
+++ b/DotNet.RevitUI/Helper/RibbonRegisterHelper.cs
@@ -0,0 +1,117 @@
+
+using Autodesk.Windows;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Media;
+
+namespace DotNet.RevitUI.Helper
+{
+ ///
+ ///
+ ///
+ public static class RibbonRegisterHelper
+ {
+ ///
+ /// 基于指定泛型自动注册Ribbon下的Tab.
+ ///
+ ///
+ ///
+ public static T Register()
+ where T : FrameworkElement, new()
+ {
+ var frameworkElement = new T();
+
+ var flag = RibbonRegisterHelper.Register(frameworkElement);
+
+ if (flag)
+ {
+ return frameworkElement;
+ }
+
+ return default(T);
+ }
+
+ ///
+ /// 基于指定控件自动注册Ribbon下的Tab.
+ ///
+ /// The framework element.
+ ///
+ public static bool Register(FrameworkElement frameworkElement)
+ {
+ var mainRibbon = Autodesk.Windows.ComponentManager.Ribbon;
+
+ if (mainRibbon == null)
+ {
+ return false;
+ }
+
+ var ribbons = new List>();
+
+ if (frameworkElement is RibbonControl ribbon)
+ {
+ ribbons.Add(new KeyValuePair(ribbon, ribbon.DataContext));
+ }
+ else
+ {
+ var temps = new List();
+
+ frameworkElement.GetRibbonControl(ref temps);
+
+ foreach (var item in temps)
+ {
+ var dataContext = frameworkElement.DataContext;
+ if (dataContext == null)
+ {
+ dataContext = item.DataContext;
+ }
+
+ ribbons.Add(new KeyValuePair(item, dataContext));
+ }
+ }
+
+ if (ribbons.Count == 0)
+ {
+ return false;
+ }
+
+ var eum = ribbons.GetEnumerator();
+
+ while (eum.MoveNext())
+ {
+ var tabs = eum.Current.Key.Tabs;
+
+ RibbonBindingHelper.Binding(eum.Current.Key, eum.Current.Value);
+
+ foreach (var item in tabs)
+ {
+ mainRibbon.Tabs.Add(item);
+ }
+ }
+ return true;
+ }
+
+ static void GetRibbonControl(this DependencyObject obj, ref List ribbons)
+ {
+ var eum = LogicalTreeHelper.GetChildren(obj).GetEnumerator();
+
+ while (eum.MoveNext())
+ {
+ var current = eum.Current;
+
+ if (current is RibbonControl)
+ {
+ ribbons.Add((RibbonControl)current);
+ }
+
+ if (current is DependencyObject depend)
+ {
+ GetRibbonControl(depend, ref ribbons);
+ }
+ }
+ }
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/IExecuteWithObject.cs b/DotNet.RevitUI/MVVM/IExecuteWithObject.cs
new file mode 100644
index 0000000..a2d50a9
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/IExecuteWithObject.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ interface IExecuteWithObject
+ {
+ object Target
+ {
+ get;
+ }
+
+ void ExecuteWithObject(object parameter);
+
+ void MarkForDeletion();
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/IMessenger.cs b/DotNet.RevitUI/MVVM/IMessenger.cs
new file mode 100644
index 0000000..07fa5d7
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/IMessenger.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ public interface IMessenger
+ {
+ void Register(object recipient, Action action);
+
+ void Register(object recipient, object token, Action action);
+
+ void Register(object recipient, object token, bool receiveDerivedMessagesToo, Action action);
+
+ void Register(object recipient, bool receiveDerivedMessagesToo, Action action);
+
+ void Send(TMessage message);
+
+ void Send(TMessage message);
+
+ void Send(TMessage message, object token);
+
+ void Unregister(object recipient);
+
+ void Unregister(string token);
+
+ void Unregister(object recipient);
+
+ void Unregister(object recipient, object token);
+
+ void Unregister(object recipient, Action action);
+
+ void Unregister(object recipient, object token, Action action);
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/Messenger.cs b/DotNet.RevitUI/MVVM/Messenger.cs
new file mode 100644
index 0000000..417dbe7
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/Messenger.cs
@@ -0,0 +1,386 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Linq;
+
+namespace DotNet.RevitUI.MVVM
+{
+ public class Messenger : IMessenger
+ {
+ private static readonly object CreationLock = new object();
+ private static IMessenger m_DefaultInstance;
+ private readonly object m_RegisterLock = new object();
+ private Dictionary> m_RecipientsOfSubclassesAction;
+ private Dictionary> m_RecipientsStrictAction;
+
+ ///
+ /// 单例.
+ ///
+ public static IMessenger Default
+ {
+ get
+ {
+ if (m_DefaultInstance == null)
+ {
+ lock (CreationLock)
+ {
+ if (m_DefaultInstance == null)
+ {
+ m_DefaultInstance = new Messenger();
+ }
+ }
+ }
+ return m_DefaultInstance;
+ }
+ }
+
+
+
+ public virtual void Register(object recipient, Action action)
+ {
+ Register(recipient, null, false, action);
+ }
+
+ public virtual void Register(object recipient, bool receiveDerivedMessagesToo, Action action)
+ {
+ Register(recipient, null, receiveDerivedMessagesToo, action);
+ }
+
+ public virtual void Register(object recipient, object token, Action action)
+ {
+ Register(recipient, token, false, action);
+ }
+
+ public virtual void Register(object recipient, object token, bool receiveDerivedMessagesToo, Action action)
+ {
+ lock (m_RegisterLock)
+ {
+ var messageType = typeof(TMessage);
+
+ Dictionary> recipients;
+
+ if (receiveDerivedMessagesToo)
+ {
+ if (m_RecipientsOfSubclassesAction == null)
+ {
+ m_RecipientsOfSubclassesAction = new Dictionary>();
+ }
+
+ recipients = m_RecipientsOfSubclassesAction;
+ }
+ else
+ {
+ if (m_RecipientsStrictAction == null)
+ {
+ m_RecipientsStrictAction = new Dictionary>();
+ }
+
+ recipients = m_RecipientsStrictAction;
+ }
+
+ lock (recipients)
+ {
+ List list;
+
+ if (!recipients.ContainsKey(messageType))
+ {
+ list = new List();
+ recipients.Add(messageType, list);
+ }
+ else
+ {
+ list = recipients[messageType];
+ }
+
+ var weakAction = new WeakAction(recipient, action);
+
+ var item = new WeakActionAndToken
+ {
+ Action = weakAction,
+ Token = token
+ };
+
+ list.Add(item);
+ }
+ }
+
+ RequestCleanup();
+ }
+
+ private bool _isCleanupRegistered;
+
+ public virtual void Send(TMessage message)
+ {
+ SendToTargetOrType(message, null, null);
+ }
+
+ public virtual void Send(TMessage message)
+ {
+ SendToTargetOrType(message, typeof(TTarget), null);
+ }
+
+ public virtual void Send(TMessage message, object token)
+ {
+ SendToTargetOrType(message, null, token);
+ }
+
+ public virtual void Unregister(object recipient)
+ {
+ UnregisterFromListsByRecipient(recipient, m_RecipientsOfSubclassesAction);
+ UnregisterFromListsByRecipient(recipient, m_RecipientsStrictAction);
+ }
+
+ public void Unregister(string token)
+ {
+ UnregisterFromListsByToken(token, m_RecipientsOfSubclassesAction);
+ UnregisterFromListsByToken(token, m_RecipientsStrictAction);
+ }
+
+ public virtual void Unregister(object recipient)
+ {
+ Unregister(recipient, null, null);
+ }
+
+ public virtual void Unregister(object recipient, object token)
+ {
+ Unregister(recipient, token, null);
+ }
+
+ public virtual void Unregister(object recipient, Action action)
+ {
+ Unregister(recipient, null, action);
+ }
+
+ public virtual void Unregister(object recipient, object token, Action action)
+ {
+ UnregisterFromLists(recipient, token, action, m_RecipientsStrictAction);
+ UnregisterFromLists(recipient, token, action, m_RecipientsOfSubclassesAction);
+ RequestCleanup();
+ }
+
+
+ public static void OverrideDefault(IMessenger newMessenger)
+ {
+ m_DefaultInstance = newMessenger;
+ }
+
+ public static void Reset()
+ {
+ m_DefaultInstance = null;
+ }
+
+ public void ResetAll()
+ {
+ Reset();
+ }
+
+ public void RequestCleanup()
+ {
+ if (!_isCleanupRegistered)
+ {
+ Action cleanupAction = Cleanup;
+
+ System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(cleanupAction, System.Windows.Threading.DispatcherPriority.ApplicationIdle, null);
+ _isCleanupRegistered = true;
+ }
+ }
+
+ public void Cleanup()
+ {
+ CleanupList(m_RecipientsOfSubclassesAction);
+ CleanupList(m_RecipientsStrictAction);
+ _isCleanupRegistered = false;
+ }
+
+ private static void CleanupList(IDictionary> lists)
+ {
+ if (lists == null)
+ {
+ return;
+ }
+
+ lock (lists)
+ {
+ var listsToRemove = new List();
+ foreach (var list in lists)
+ {
+ var recipientsToRemove = list.Value
+ .Where(item => item.Action == null || !item.Action.IsAlive)
+ .ToList();
+
+ foreach (var recipient in recipientsToRemove)
+ {
+ list.Value.Remove(recipient);
+ }
+
+ if (list.Value.Count == 0)
+ {
+ listsToRemove.Add(list.Key);
+ }
+ }
+
+ foreach (var key in listsToRemove)
+ {
+ lists.Remove(key);
+ }
+ }
+ }
+
+ private static void SendToList(TMessage message, IEnumerable weakActionsAndTokens, Type messageTargetType, object token)
+ {
+ if (weakActionsAndTokens != null)
+ {
+ // Correction Messaging BL0004.007
+ var list = weakActionsAndTokens.ToList();
+ var listClone = list.Take(list.Count()).ToList();
+
+ foreach (var item in listClone)
+ {
+ var executeAction = item.Action as IExecuteWithObject;
+
+ if (executeAction != null
+ && item.Action.IsAlive
+ && item.Action.Target != null
+ && (messageTargetType == null
+ || item.Action.Target.GetType() == messageTargetType
+ || messageTargetType.IsAssignableFrom(item.Action.Target.GetType()))
+ && ((item.Token == null && token == null)
+ || item.Token != null && item.Token.Equals(token)))
+ {
+ executeAction.ExecuteWithObject(message);
+ }
+ }
+ }
+ }
+
+ private static void UnregisterFromListsByToken(object token, Dictionary> lists)
+ {
+ if (token == null || lists == null || lists.Count == 0)
+ {
+ return;
+ }
+
+ lock (lists)
+ {
+ foreach (var messageType in lists.Keys)
+ {
+ foreach (var item in lists[messageType])
+ {
+ if (item.Action != null && item.Token == token)
+ {
+ item.Action.MarkForDeletion();
+ }
+ }
+ }
+ }
+ }
+
+ private static void UnregisterFromListsByRecipient(object recipient, Dictionary> lists)
+ {
+ if (recipient == null || lists == null || lists.Count == 0)
+ {
+ return;
+ }
+
+ lock (lists)
+ {
+ foreach (var messageType in lists.Keys)
+ {
+ foreach (var item in lists[messageType])
+ {
+ var weakAction = (IExecuteWithObject)item.Action;
+
+ if (weakAction != null
+ && recipient == weakAction.Target)
+ {
+ weakAction.MarkForDeletion();
+ }
+ }
+ }
+ }
+ }
+
+ private static void UnregisterFromLists(object recipient, object token, Action action, Dictionary> lists)
+ {
+ var messageType = typeof(TMessage);
+
+ if (recipient == null || lists == null || lists.Count == 0 || !lists.ContainsKey(messageType))
+ {
+ return;
+ }
+
+ lock (lists)
+ {
+ foreach (var item in lists[messageType])
+ {
+ if (item.Action is WeakAction)
+ {
+ var weakActionCasted = item.Action as WeakAction;
+
+ if (recipient == weakActionCasted.Target
+ && (action == null || action.Method.Name == weakActionCasted.MethodName)
+ && (token == null || token.Equals(item.Token)))
+ {
+ item.Action.MarkForDeletion();
+ }
+ }
+ }
+ }
+ }
+
+
+ private void SendToTargetOrType(TMessage message, Type messageTargetType, object token)
+ {
+ var messageType = typeof(TMessage);
+
+ if (m_RecipientsOfSubclassesAction != null)
+ {
+ var listClone = m_RecipientsOfSubclassesAction.Keys.Take(m_RecipientsOfSubclassesAction.Count()).ToList();
+
+ foreach (var type in listClone)
+ {
+ List list = null;
+
+ if (messageType == type || messageType.IsSubclassOf(type) || type.IsAssignableFrom(messageType))
+ {
+ lock (m_RecipientsOfSubclassesAction)
+ {
+ list = m_RecipientsOfSubclassesAction[type].Take(m_RecipientsOfSubclassesAction[type].Count()).ToList();
+ }
+ }
+
+ SendToList(message, list, messageTargetType, token);
+ }
+ }
+
+ if (m_RecipientsStrictAction != null)
+ {
+ List list = null;
+
+ lock (m_RecipientsStrictAction)
+ {
+ if (m_RecipientsStrictAction.ContainsKey(messageType))
+ {
+ list = m_RecipientsStrictAction[messageType]
+ .Take(m_RecipientsStrictAction[messageType].Count())
+ .ToList();
+ }
+ }
+
+ if (list != null)
+ {
+ SendToList(message, list, messageTargetType, token);
+ }
+ }
+
+ RequestCleanup();
+ }
+
+ private struct WeakActionAndToken
+ {
+ public WeakAction Action;
+
+ public object Token;
+ }
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/ObservableObject.cs b/DotNet.RevitUI/MVVM/ObservableObject.cs
new file mode 100644
index 0000000..f28ec61
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/ObservableObject.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ ///
+ /// 属性通知基类.
+ ///
+
+ public class ObservableObject : System.ComponentModel.INotifyPropertyChanged
+ {
+ ///
+ /// 属性改变后触发事件.
+ ///
+ public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
+
+ ///
+ /// 属性改变前触发事件.
+ ///
+ public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging;
+
+ ///
+ /// 属性改变委托处理.
+ ///
+ protected System.ComponentModel.PropertyChangedEventHandler PropertyChangedHandler
+ {
+ get
+ {
+ return this.PropertyChanged;
+ }
+ }
+
+ ///
+ /// 属性改变委托处理.
+ ///
+ protected System.ComponentModel.PropertyChangingEventHandler PropertyChangingHandler
+ {
+ get
+ {
+ return this.PropertyChanging;
+ }
+ }
+
+ ///
+ /// 属性改变之前回调.
+ ///
+ /// Name of the property.
+ protected virtual void RaisePropertyChanging(string propertyName)
+ {
+ this.PropertyChanging?.Invoke(this, new System.ComponentModel.PropertyChangingEventArgs(propertyName));
+ }
+
+ ///
+ /// 属性改变之后回调.
+ ///
+ /// Name of the property.
+ protected virtual void RaisePropertyChanged(string propertyName)
+ {
+ this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/RelayCommand.cs b/DotNet.RevitUI/MVVM/RelayCommand.cs
new file mode 100644
index 0000000..effb55a
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/RelayCommand.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ ///
+ /// 不带参数通用命令类.
+ ///
+ ///
+
+ public class RelayCommand : System.Windows.Input.ICommand
+ {
+ private readonly Action m_Execute;
+
+ private readonly Func m_CanExecute;
+
+ public event EventHandler CanExecuteChanged
+ {
+ add
+ {
+ if (m_CanExecute != null)
+ System.Windows.Input.CommandManager.RequerySuggested += value;
+ }
+ remove
+ {
+ if (m_CanExecute != null)
+ System.Windows.Input.CommandManager.RequerySuggested -= value;
+ }
+ }
+
+ public RelayCommand(Action execute)
+ : this(execute, null)
+ {
+
+ }
+
+ public RelayCommand(Action execute, Func canExecute)
+ {
+ m_Execute = execute ?? throw new ArgumentNullException("execute");
+
+ m_CanExecute = canExecute;
+ }
+
+ [System.Diagnostics.DebuggerStepThrough]
+ public bool CanExecute(object parameter)
+ {
+ return m_CanExecute == null || m_CanExecute();
+ }
+
+ public void Execute(object parameter)
+ {
+ m_Execute();
+ }
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/RelayCommandGeneric.cs b/DotNet.RevitUI/MVVM/RelayCommandGeneric.cs
new file mode 100644
index 0000000..0405af2
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/RelayCommandGeneric.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ ///
+ /// 带参数通用命令类.
+ ///
+ ///
+ ///
+ class RelayCommand : System.Windows.Input.ICommand
+ {
+ private readonly Action m_Execute;
+ private readonly Predicate m_CanExecute;
+
+ public event EventHandler CanExecuteChanged
+ {
+ add
+ {
+ if (m_CanExecute != null)
+ System.Windows.Input.CommandManager.RequerySuggested += value;
+
+ }
+ remove
+ {
+ if (m_CanExecute != null)
+ System.Windows.Input.CommandManager.RequerySuggested -= value;
+ }
+ }
+
+ public RelayCommand(Action execute)
+ : this(execute, null)
+ {
+
+ }
+
+ public RelayCommand(Action execute, Predicate canExecute)
+ {
+ var flag = execute == null;
+ if (flag)
+ throw new ArgumentNullException("execute");
+
+ m_Execute = execute;
+ m_CanExecute = canExecute;
+ }
+
+ public bool CanExecute(object parameter)
+ {
+ return m_CanExecute == null || m_CanExecute((T)((object)parameter));
+ }
+
+ public void Execute(object parameter)
+ {
+ m_Execute((T)((object)parameter));
+ }
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/RevitRelayCommand.cs b/DotNet.RevitUI/MVVM/RevitRelayCommand.cs
new file mode 100644
index 0000000..e4e0f09
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/RevitRelayCommand.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Windows;
+
+namespace DotNet.RevitUI.MVVM
+{
+ ///
+ /// 委托式revit命令
+ ///
+ public class RevitRelayCommand : RevitCommand
+ {
+ private readonly Func m_Execute;
+
+ private readonly Func m_CanExecute;
+
+ public RevitRelayCommand(Func execute, Func canExecute)
+ {
+ m_Execute = execute ?? throw new ArgumentNullException("execute");
+
+ m_CanExecute = canExecute;
+ }
+
+ public RevitRelayCommand(Func execute)
+ : this(execute, null)
+ {
+
+ }
+
+ protected override bool CanExecute(Autodesk.Windows.RibbonItem parameter)
+ {
+ return m_CanExecute == null || m_CanExecute();
+ }
+
+ protected override Result Invoke(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ return m_Execute(commandData);
+ }
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/WeakAction.cs b/DotNet.RevitUI/MVVM/WeakAction.cs
new file mode 100644
index 0000000..97da739
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/WeakAction.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ class WeakAction
+ {
+ private Action m_StaticAction;
+
+ protected System.Reflection.MethodInfo Method { get; set; }
+
+ public virtual string MethodName
+ {
+ get
+ {
+ if (m_StaticAction != null)
+ {
+ return m_StaticAction.Method.Name;
+ }
+ return Method.Name;
+ }
+ }
+
+ protected WeakReference ActionReference { get; set; }
+
+ protected WeakReference Reference { get; set; }
+
+ public bool IsStatic
+ {
+ get
+ {
+ return m_StaticAction != null;
+ }
+ }
+
+ protected WeakAction()
+ {
+
+ }
+ public WeakAction(Action action)
+ : this(action?.Target, action)
+ {
+ }
+
+ public WeakAction(object target, Action action)
+ {
+ if (action.Method.IsStatic)
+ {
+ m_StaticAction = action;
+
+ if (target != null)
+ {
+ Reference = new WeakReference(target);
+ }
+
+ return;
+ }
+
+ Method = action.Method;
+ ActionReference = new WeakReference(action.Target);
+
+ Reference = new WeakReference(target);
+ }
+
+ public virtual bool IsAlive
+ {
+ get
+ {
+ if (m_StaticAction == null
+ && Reference == null)
+ {
+ return false;
+ }
+
+ if (m_StaticAction != null)
+ {
+ if (Reference != null)
+ {
+ return Reference.IsAlive;
+ }
+ return true;
+ }
+ return Reference.IsAlive;
+ }
+ }
+
+ public object Target
+ {
+ get
+ {
+ if (Reference == null)
+ {
+ return null;
+ }
+
+ return Reference.Target;
+ }
+ }
+
+ protected object ActionTarget
+ {
+ get
+ {
+ if (ActionReference == null)
+ {
+ return null;
+ }
+
+ return ActionReference.Target;
+ }
+ }
+
+ public void Execute()
+ {
+ if (m_StaticAction != null)
+ {
+ m_StaticAction();
+ return;
+ }
+
+ var actionTarget = ActionTarget;
+
+ if (IsAlive)
+ {
+ if (Method != null
+ && ActionReference != null
+ && actionTarget != null)
+ {
+ Method.Invoke(actionTarget, null);
+ return;
+ }
+ }
+ }
+ public void MarkForDeletion()
+ {
+ Reference = null;
+ ActionReference = null;
+ Method = null;
+ m_StaticAction = null;
+ }
+ }
+}
diff --git a/DotNet.RevitUI/MVVM/WeakActionGeneric.cs b/DotNet.RevitUI/MVVM/WeakActionGeneric.cs
new file mode 100644
index 0000000..75f20b5
--- /dev/null
+++ b/DotNet.RevitUI/MVVM/WeakActionGeneric.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DotNet.RevitUI.MVVM
+{
+ class WeakAction : WeakAction, IExecuteWithObject
+ {
+ private Action m_StaticAction;
+
+ public override string MethodName
+ {
+ get
+ {
+ if (m_StaticAction != null)
+ {
+ return m_StaticAction.Method.Name;
+ }
+ return Method.Name;
+ }
+ }
+
+ public override bool IsAlive
+ {
+ get
+ {
+ if (m_StaticAction == null && Reference == null)
+ {
+ return false;
+ }
+
+ if (m_StaticAction != null)
+ {
+ if (Reference != null)
+ {
+ return Reference.IsAlive;
+ }
+ return true;
+ }
+ return Reference.IsAlive;
+ }
+ }
+
+ public WeakAction(Action action)
+ : this(action?.Target, action)
+ {
+
+ }
+
+ public WeakAction(object target, Action action)
+ {
+ if (action.Method.IsStatic)
+ {
+ m_StaticAction = action;
+
+ if (target != null)
+ {
+ Reference = new WeakReference(target);
+ }
+
+ return;
+ }
+
+ Method = action.Method;
+ ActionReference = new WeakReference(action.Target);
+
+ Reference = new WeakReference(target);
+ }
+
+ public new void Execute()
+ {
+ Execute(default(T));
+ }
+
+ public void Execute(T parameter)
+ {
+ if (m_StaticAction != null)
+ {
+ m_StaticAction(parameter);
+ return;
+ }
+
+ var actionTarget = ActionTarget;
+
+ if (IsAlive)
+ {
+ if (Method != null && ActionReference != null && actionTarget != null)
+ {
+ Method.Invoke(actionTarget, new object[] { parameter });
+ }
+ }
+ }
+
+ public void ExecuteWithObject(object parameter)
+ {
+ var parameterCasted = (T)parameter;
+ Execute(parameterCasted);
+ }
+
+ public new void MarkForDeletion()
+ {
+ m_StaticAction = null;
+ base.MarkForDeletion();
+ }
+ }
+}
diff --git a/DotNet.RevitUI/RevitApp.cs b/DotNet.RevitUI/RevitApp.cs
new file mode 100644
index 0000000..6f9636a
--- /dev/null
+++ b/DotNet.RevitUI/RevitApp.cs
@@ -0,0 +1,99 @@
+using Autodesk.Revit.UI;
+using Autodesk.Windows;
+using DotNet.RevitUI.Helper;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNet.RevitUI
+{
+ ///
+ /// Revit入口App.
+ ///
+ public abstract class RevitApp : IExternalApplication
+ {
+ private static string WorkPath = Path.GetDirectoryName(typeof(RevitApp).Assembly.Location);
+
+ private static UIApplication m_Application;
+
+ public static UIApplication Application
+ {
+ get
+ {
+ return m_Application;
+ }
+ }
+
+ ///
+ /// Revit关闭后执行.
+ ///
+ ///
+ ///
+ protected abstract Result OnShutdown(UIControlledApplication application);
+
+ ///
+ /// Revit启动时执行.
+ ///
+ ///
+ ///
+ protected abstract Result OnStartup(UIControlledApplication application);
+
+ Result IExternalApplication.OnShutdown(UIControlledApplication application)
+ {
+ return this.OnShutdown(application);
+ }
+
+ Result IExternalApplication.OnStartup(UIControlledApplication application)
+ {
+ this.OnBefore(application);
+
+ var result = this.OnStartup(application);
+
+ this.OnAfter(application);
+
+ return result;
+ }
+
+ void OnBefore(UIControlledApplication application)
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
+
+ var flags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod;
+
+ if (m_Application == null)
+ {
+ m_Application = (UIApplication)application.GetType().InvokeMember("getUIApplication", flags, Type.DefaultBinder, application, null);
+ }
+
+ if (RevitCommandHelper.Instance == null)
+ {
+ RevitCommandHelper.Instance = new RevitCommandHelper();
+ }
+
+ RevitCommandHelper.Instance.RegisterCommand();
+ }
+
+ private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
+ {
+ var assemblyName = new AssemblyName(args.Name);
+
+ var file = System.IO.Path.Combine(WorkPath, string.Format("{0}.dll", assemblyName.Name));
+
+ if (System.IO.File.Exists(file))
+ {
+ return Assembly.LoadFrom(file);
+ }
+
+ return args.RequestingAssembly;
+ }
+
+ void OnAfter(UIControlledApplication application)
+ {
+
+ }
+ }
+}
diff --git a/DotNet.RevitUI/RevitCommand.cs b/DotNet.RevitUI/RevitCommand.cs
new file mode 100644
index 0000000..78ca99e
--- /dev/null
+++ b/DotNet.RevitUI/RevitCommand.cs
@@ -0,0 +1,138 @@
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using Autodesk.Revit.DB;
+using DotNet.RevitUI.Helper;
+
+namespace DotNet.RevitUI
+{
+ ///
+ /// Revit command interface.
+ ///
+ public abstract class RevitCommand : ICommand, IExternalCommand
+ {
+ private static UIApplication m_Application;
+
+ public static UIApplication Application
+ {
+ get
+ {
+ return m_Application;
+ }
+ }
+
+ ///
+ /// 当前激活文档.
+ ///
+ public Document ActiveDocument { get; private set; }
+
+ ///
+ /// 当前激活UI文档.
+ ///
+ public UIDocument ActiveUIDocument { get; private set; }
+
+ ///
+ /// Occurs when [can execute changed].
+ ///
+ event EventHandler ICommand.CanExecuteChanged
+ {
+ add
+ {
+ CommandManager.RequerySuggested += value;
+ }
+ remove
+ {
+ CommandManager.RequerySuggested -= value;
+ }
+ }
+
+ ///
+ /// Riibon控件是否可执行.
+ ///
+ ///
+ ///
+
+ bool ICommand.CanExecute(object parameter)
+ {
+ var p = parameter == null ? null : parameter as Autodesk.Windows.RibbonItem;
+
+ if (p == null)
+ return CanExecute(p);
+
+ p.Tag = RevitApp.Application;
+
+ var flag = this.CanExecute(p);
+
+ if (flag)
+ {
+ p.IsEnabled = true;
+ }
+ else
+ {
+ p.IsEnabled = false;
+ }
+
+ if (RevitApp.Application == null || p is Autodesk.Windows.RibbonItem item)
+ {
+ return flag;
+ }
+
+ return flag;
+ }
+
+ Result IExternalCommand.Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ Initialize(commandData);
+
+ m_Application = commandData.Application;
+
+ return this.Invoke(commandData, ref message, elements);
+ }
+
+ void ICommand.Execute(object parameter)
+ {
+ RevitCommandInvoke.ExecuteHandlers.Enqueue(((IExternalCommand)this).Execute);
+ RevitCommandHelper.Instance.Execute();
+ }
+
+ void Initialize(ExternalCommandData commandData)
+ {
+ if (RevitCommandHelper.Instance == null)
+ {
+ RevitCommandHelper.Instance = new RevitCommandHelper();
+ }
+
+ RevitCommandHelper.Instance.RegisterCommand();
+
+ if (commandData != null && commandData.Application != null)
+ {
+ this.ActiveUIDocument = commandData.Application.ActiveUIDocument;
+
+ if (this.ActiveUIDocument != null)
+ {
+ this.ActiveDocument = this.ActiveUIDocument.Document;
+ }
+ }
+ }
+
+ ///
+ /// 此命令是否能执行.
+ ///
+ ///
+ ///
+ protected abstract bool CanExecute(Autodesk.Windows.RibbonItem parameter);
+
+ ///
+ /// 在revit上下文件环境执行命令.
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected abstract Result Invoke(ExternalCommandData commandData, ref string message, ElementSet elements);
+ }
+}
diff --git a/DotNet.RevitUI/RevitCommandInvoke.cs b/DotNet.RevitUI/RevitCommandInvoke.cs
new file mode 100644
index 0000000..f435b4b
--- /dev/null
+++ b/DotNet.RevitUI/RevitCommandInvoke.cs
@@ -0,0 +1,53 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Autodesk.Revit.Attributes;
+using System.Threading.Tasks;
+
+namespace DotNet.RevitUI.Helper
+{
+ ///
+ /// Revit命令帮助.
+ ///
+
+ [Transaction(TransactionMode.Manual)]
+ class RevitCommandInvoke : IExternalCommand
+ {
+ public static Queue ExecuteHandlers { get; set; }
+
+ public static Queue InvokeHandlers { get; set; }
+
+ static RevitCommandInvoke()
+ {
+ ExecuteHandlers = new Queue();
+
+ InvokeHandlers = new Queue();
+ }
+
+ Result IExternalCommand.Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ while (ExecuteHandlers.Count > 0)
+ {
+ var first = ExecuteHandlers.Dequeue();
+
+ first(commandData, ref message, elements);
+ }
+
+ while (InvokeHandlers.Count > 0)
+ {
+ var first = InvokeHandlers.Dequeue();
+
+ first(commandData.Application);
+ }
+
+ return Result.Succeeded;
+ }
+ }
+
+ delegate Result ExecuteHandler(ExternalCommandData commandData, ref string message, ElementSet elements);
+
+ delegate void InvokeHandler(UIApplication uiApp);
+}
diff --git a/Test.DotNet.RevitUI (2016)/AppRun.cs b/Test.DotNet.RevitUI (2016)/AppRun.cs
new file mode 100644
index 0000000..ca748ce
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/AppRun.cs
@@ -0,0 +1,30 @@
+using Autodesk.Revit.UI;
+using DotNet.RevitUI;
+using DotNet.RevitUI.Helper;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Test.DotNet.RevitUI.View;
+
+namespace Test.DotNet.RevitUI
+{
+ ///
+ /// This is app run class .
+ ///
+ public class AppRun : RevitApp
+ {
+ protected override Result OnShutdown(UIControlledApplication application)
+ {
+ return Result.Succeeded;
+ }
+
+ protected override Result OnStartup(UIControlledApplication application)
+ {
+ RibbonRegisterHelper.Register();
+
+ return Result.Succeeded;
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/Command/DeleteElementCommand.cs b/Test.DotNet.RevitUI (2016)/Command/DeleteElementCommand.cs
new file mode 100644
index 0000000..7df1487
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Command/DeleteElementCommand.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Windows;
+using DotNet.RevitUI;
+using Autodesk.Revit.Attributes;
+
+namespace Test.DotNet.RevitUI.Command
+{
+ ///
+ /// 删除元素
+ ///
+ /// 测试基于ribbon自动化绑定命令下的事务开启测试
+ /// 如果基于addinmanager工具测试此命令,则需要声明特性,否则不需要声明此特性
+
+ [Transaction(TransactionMode.Manual)]
+ public class DeleteElementCommand : RevitCommand
+ {
+ protected override bool CanExecute(Autodesk.Windows.RibbonItem parameter)
+ {
+ if (parameter == null)
+ {
+ return true;
+ }
+
+ if (parameter.Tag is UIApplication uiApp)
+ {
+ return uiApp.ActiveUIDocument != null;
+ }
+
+ return true;
+ }
+
+ protected override Result Invoke(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ var uidoc = commandData.Application.ActiveUIDocument;
+
+ var doc = uidoc.Document;
+
+ while (true)
+ {
+ try
+ {
+ var reference = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, "请选择要删除的元素 :");
+
+ doc.Invoke(m =>
+ {
+ try
+ {
+ doc.Delete(reference.ElementId);
+ }
+ catch (Exception ex)
+ {
+ Autodesk.Revit.UI.TaskDialog.Show("错误", ex.Message);
+ }
+ });
+ }
+ catch (Exception ex)
+ {
+ return Result.Cancelled;
+ }
+ }
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/Command/DeleteMatchElementCommand.cs b/Test.DotNet.RevitUI (2016)/Command/DeleteMatchElementCommand.cs
new file mode 100644
index 0000000..96eb6b5
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Command/DeleteMatchElementCommand.cs
@@ -0,0 +1,54 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Windows;
+using DotNet.RevitUI;
+using DotNet.RevitUI.Helper;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Test.DotNet.RevitUI.View;
+using DotNet.RevitUI.MVVM.Extension;
+
+namespace Test.DotNet.RevitUI.Command
+{
+ ///
+ /// 分段墙体
+ ///
+ /// 1 . 测试基于WPF MVVM 的事务开启
+ /// 2 . 测试模态窗体立即调用命令
+
+ public class DeleteMatchElementCommand : RevitCommand
+ {
+ protected override bool CanExecute(Autodesk.Windows.RibbonItem parameter)
+ {
+ if (parameter == null)
+ {
+ return true;
+ }
+
+ if (parameter.Tag is UIApplication uiApp)
+ {
+ return uiApp.ActiveUIDocument != null;
+ }
+
+ return true;
+ }
+
+ protected override Result Invoke(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ var rect = MainHelper.RevitMDIRect;
+
+ var main = new MainDeleteMatchElement()
+ {
+ Top = rect.Top + 5,
+ Left = rect.Left
+ };
+
+ main.ShowDialog(MainHelper.RevitHandle);
+
+ return Result.Succeeded;
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/Command/FlowButton1Command.cs b/Test.DotNet.RevitUI (2016)/Command/FlowButton1Command.cs
new file mode 100644
index 0000000..d7946d7
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Command/FlowButton1Command.cs
@@ -0,0 +1,28 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Windows;
+using DotNet.RevitUI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Test.DotNet.RevitUI.Command
+{
+ public class FlowButton1Command : RevitCommand
+ {
+ protected override bool CanExecute(Autodesk.Windows.RibbonItem parameter)
+ {
+ return true;
+ }
+
+ protected override Result Invoke(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ Autodesk.Revit.UI.TaskDialog.Show("提示", "测试 Flow Button1 Command 有效点击 ");
+
+ return Result.Succeeded;
+ }
+ }
+
+}
diff --git a/Test.DotNet.RevitUI (2016)/Command/FlowButton2Command.cs b/Test.DotNet.RevitUI (2016)/Command/FlowButton2Command.cs
new file mode 100644
index 0000000..7c4652c
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Command/FlowButton2Command.cs
@@ -0,0 +1,26 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using DotNet.RevitUI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Test.DotNet.RevitUI.Command
+{
+ public class FlowButton2Command : RevitCommand
+ {
+ protected override bool CanExecute(Autodesk.Windows.RibbonItem parameter)
+ {
+ return true;
+ }
+
+ protected override Result Invoke(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ Autodesk.Revit.UI.TaskDialog.Show("提示", "测试 Flow Button2 Command 有效点击 ");
+
+ return Result.Succeeded;
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/Command/SplitButton1Command.cs b/Test.DotNet.RevitUI (2016)/Command/SplitButton1Command.cs
new file mode 100644
index 0000000..dcb62d0
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Command/SplitButton1Command.cs
@@ -0,0 +1,27 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Windows;
+using DotNet.RevitUI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Test.DotNet.RevitUI.Command
+{
+ public class SplitButton1Command : RevitCommand
+ {
+ protected override bool CanExecute(Autodesk.Windows.RibbonItem parameter)
+ {
+ return true;
+ }
+
+ protected override Result Invoke(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ Autodesk.Revit.UI.TaskDialog.Show("提示", "测试 Split Button1 Command 有效点击 ");
+
+ return Result.Succeeded;
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/Command/SplitButton2Command.cs b/Test.DotNet.RevitUI (2016)/Command/SplitButton2Command.cs
new file mode 100644
index 0000000..4615376
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Command/SplitButton2Command.cs
@@ -0,0 +1,27 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using DotNet.RevitUI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Test.DotNet.RevitUI.Command
+{
+
+ public class SplitButton2Command : RevitCommand
+ {
+ protected override bool CanExecute(Autodesk.Windows.RibbonItem parameter)
+ {
+ return true;
+ }
+
+ protected override Result Invoke(ExternalCommandData commandData, ref string message, ElementSet elements)
+ {
+ Autodesk.Revit.UI.TaskDialog.Show("提示", "测试 Split Button2 Command 有效点击 !");
+
+ return Result.Succeeded;
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/Extension/DocumentExtension.cs b/Test.DotNet.RevitUI (2016)/Extension/DocumentExtension.cs
new file mode 100644
index 0000000..4e0a234
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Extension/DocumentExtension.cs
@@ -0,0 +1,79 @@
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Test.DotNet.RevitUI
+{
+ public static class DocumentExtension
+ {
+ ///
+ /// 使用委托启动事务.事务内自动进行事务启动,提交、回滚等处理。
+ ///
+ /// The document.
+ /// The action.
+ /// The name.
+ public static void Invoke(this Document doc, Action action, string name = "default")
+ {
+ using (var tr = new Transaction(doc, name))
+ {
+ tr.Start();
+
+ action(tr);
+
+ var status = tr.GetStatus();
+
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ return;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return;
+ default:
+ return;
+ }
+ }
+ }
+
+ ///
+ /// 使用委托启动事务,并返回委托执行结果.事务内自动进行事务启动,提交、回滚等处理。
+ ///
+ /// The type of the result.
+ /// The document.
+ /// The action.
+ /// The name.
+ ///
+ public static TResult Invoke(this Document doc, Func func, string name = "default")
+ {
+ using (var tr = new Transaction(doc, name))
+ {
+ tr.Start();
+
+ var result = func(tr);
+
+ var status = tr.GetStatus();
+ switch (status)
+ {
+ case TransactionStatus.Started:
+ tr.Commit();
+ return result;
+ case TransactionStatus.Committed:
+ case TransactionStatus.RolledBack:
+ return result;
+ case TransactionStatus.Error:
+ tr.RollBack();
+ return result;
+ default:
+ return result;
+ }
+ }
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/Images/delete32.png b/Test.DotNet.RevitUI (2016)/Images/delete32.png
new file mode 100644
index 0000000..2d58688
Binary files /dev/null and b/Test.DotNet.RevitUI (2016)/Images/delete32.png differ
diff --git a/Test.DotNet.RevitUI (2016)/Images/split32.png b/Test.DotNet.RevitUI (2016)/Images/split32.png
new file mode 100644
index 0000000..39bda8f
Binary files /dev/null and b/Test.DotNet.RevitUI (2016)/Images/split32.png differ
diff --git a/Test.DotNet.RevitUI (2016)/Images/test16.png b/Test.DotNet.RevitUI (2016)/Images/test16.png
new file mode 100644
index 0000000..b41bfaa
Binary files /dev/null and b/Test.DotNet.RevitUI (2016)/Images/test16.png differ
diff --git a/Test.DotNet.RevitUI (2016)/Images/test32.png b/Test.DotNet.RevitUI (2016)/Images/test32.png
new file mode 100644
index 0000000..13ce8ca
Binary files /dev/null and b/Test.DotNet.RevitUI (2016)/Images/test32.png differ
diff --git a/Test.DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs b/Test.DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0fbf1cd
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("Test.DotNet.RevitUI (2016)")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Test.DotNet.RevitUI (2016)")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("f4b2970d-431c-4801-a65d-f48fee8c650a")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Test.DotNet.RevitUI (2016)/Test.DotNet.RevitUI (2016).csproj b/Test.DotNet.RevitUI (2016)/Test.DotNet.RevitUI (2016).csproj
new file mode 100644
index 0000000..3118e6d
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Test.DotNet.RevitUI (2016).csproj
@@ -0,0 +1,124 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {F4B2970D-431C-4801-A65D-F48FEE8C650A}
+ Library
+ Properties
+ Test.DotNet.RevitUI
+ Test.DotNet.RevitUI
+ v4.8
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ AnyCPU
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\AdWindows.dll
+ False
+
+
+ D:\Program Files\Autodesk\Revit 2016\Microsoft.Expression.Interactions.dll
+ False
+
+
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPI.dll
+ False
+
+
+ D:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MainDeleteMatchElement.xaml
+
+
+ RibbonView.xaml
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
+ {22f6cc59-e396-4477-9215-21777c68e044}
+ DotNet.RevitUI %282016%29
+
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+
+
+ PreserveNewest
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Test.DotNet.RevitUI (2016)/Test.DotNet.RevitUI.addin b/Test.DotNet.RevitUI (2016)/Test.DotNet.RevitUI.addin
new file mode 100644
index 0000000..9e63592
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/Test.DotNet.RevitUI.addin
@@ -0,0 +1,11 @@
+
+
+
+ Test.DotNet.RevitUI.dll
+ A53E2E82-43F5-420A-882D-8603D495DF47
+ Test.DotNet.RevitUI.AppRun
+ Test.DotNet.RevitUI
+ dotnet bim
+
+
+
diff --git a/Test.DotNet.RevitUI (2016)/View/MainDeleteMatchElement.xaml b/Test.DotNet.RevitUI (2016)/View/MainDeleteMatchElement.xaml
new file mode 100644
index 0000000..1233747
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/View/MainDeleteMatchElement.xaml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Test.DotNet.RevitUI (2016)/View/MainDeleteMatchElement.xaml.cs b/Test.DotNet.RevitUI (2016)/View/MainDeleteMatchElement.xaml.cs
new file mode 100644
index 0000000..ceccbab
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/View/MainDeleteMatchElement.xaml.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using DotNet.RevitUI.MVVM;
+using Test.DotNet.RevitUI.ViewModel;
+
+namespace Test.DotNet.RevitUI.View
+{
+ ///
+ /// MainSplitWall.xaml 的交互逻辑
+ ///
+ public partial class MainDeleteMatchElement : Window
+ {
+ internal const string ClosedToken = "ClosedToken";
+
+ public MainDeleteMatchElement()
+ {
+ InitializeComponent();
+
+ Messenger.Default.Register(this, ClosedToken, m => this.Close());
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/View/RibbonView.xaml b/Test.DotNet.RevitUI (2016)/View/RibbonView.xaml
new file mode 100644
index 0000000..42d9a7c
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/View/RibbonView.xaml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Test.DotNet.RevitUI (2016)/View/RibbonView.xaml.cs b/Test.DotNet.RevitUI (2016)/View/RibbonView.xaml.cs
new file mode 100644
index 0000000..b2185cd
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/View/RibbonView.xaml.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Test.DotNet.RevitUI.ViewModel;
+
+namespace Test.DotNet.RevitUI.View
+{
+ ///
+ /// RibbonView.xaml 的交互逻辑
+ ///
+ public partial class RibbonView : UserControl
+ {
+ public RibbonView()
+ {
+ InitializeComponent();
+
+ this.DataContext = new RibbonViewModel();
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/ViewModel/DeleteElementViewModel.cs b/Test.DotNet.RevitUI (2016)/ViewModel/DeleteElementViewModel.cs
new file mode 100644
index 0000000..5f43fb3
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/ViewModel/DeleteElementViewModel.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.UI;
+using DotNet.RevitUI;
+using DotNet.RevitUI.MVVM;
+using Test.DotNet.RevitUI.View;
+
+namespace Test.DotNet.RevitUI.ViewModel
+{
+ public class DeleteElementViewModel : ObservableObject
+ {
+ private int _elementId;
+
+ public int ElementId
+ {
+ get
+ {
+ return _elementId;
+ }
+
+ set
+ {
+ _elementId = value;
+
+ this.RaisePropertyChanged(nameof(ElementId));
+ }
+ }
+
+ ///
+ /// Revit动态委托命令
+ ///
+ /// 也可以直接绑定RevitCommand
+ public RevitRelayCommand OK { get; private set; }
+
+ public RelayCommand Cancel { get; private set; }
+
+ public DeleteElementViewModel()
+ {
+ this.ElementId = 0;
+
+ this.OK = new RevitRelayCommand(OnOK, () => ElementId > 0);
+
+ this.Cancel = new RelayCommand(OnCancel);
+ }
+
+ private void OnCancel()
+ {
+ Messenger.Default.Send(this, MainDeleteMatchElement.ClosedToken);
+ }
+
+ private Result OnOK(ExternalCommandData arg)
+ {
+ var uidoc = arg.Application.ActiveUIDocument;
+
+ var doc = uidoc.Document;
+
+ if (doc.GetElement(new Autodesk.Revit.DB.ElementId(ElementId)) is Autodesk.Revit.DB.Element elem)
+ {
+ doc.Invoke(m =>
+ {
+ try
+ {
+ doc.Delete(elem.Id);
+ }
+ catch (Exception ex)
+ {
+ Autodesk.Revit.UI.TaskDialog.Show("错误", ex.Message);
+ }
+ });
+
+ Autodesk.Revit.UI.TaskDialog.Show("提示", "删除元素完成");
+
+ return Result.Succeeded;
+ }
+
+ Autodesk.Revit.UI.TaskDialog.Show("警告", "输入元素ID不合法,或者未在当前文档找到此元素ID");
+
+ return Result.Succeeded;
+ }
+ }
+}
diff --git a/Test.DotNet.RevitUI (2016)/ViewModel/RibbonViewModel.cs b/Test.DotNet.RevitUI (2016)/ViewModel/RibbonViewModel.cs
new file mode 100644
index 0000000..1e25db7
--- /dev/null
+++ b/Test.DotNet.RevitUI (2016)/ViewModel/RibbonViewModel.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DotNet.RevitUI;
+using DotNet.RevitUI.MVVM;
+using Test.DotNet.RevitUI.Command;
+
+namespace Test.DotNet.RevitUI.ViewModel
+{
+ public class RibbonViewModel : ObservableObject
+ {
+ ///
+ /// 删除元素 测试
+ ///
+
+ public RevitCommand DeleteElement { get; set; }
+
+ ///
+ /// 删除匹配元素 测试
+ ///
+ public RevitCommand DeleteMatchElement { get; set; }
+
+ ///
+ /// This is command test
+ ///
+ public RevitCommand SplitButton1 { get; set; }
+
+ ///
+ /// This is command test
+ ///
+ public RevitCommand SplitButton2 { get; set; }
+
+ ///
+ /// This is command test
+ ///
+ public RevitCommand FlowButton1 { get; set; }
+
+ ///
+ /// This is command test
+ ///
+ public RevitCommand FlowButton2 { get; set; }
+
+
+ public RibbonViewModel()
+ {
+ this.DeleteElement = new DeleteElementCommand();
+
+ this.DeleteMatchElement = new DeleteMatchElementCommand();
+
+ this.SplitButton1 = new SplitButton1Command();
+
+ this.SplitButton2 = new SplitButton1Command();
+
+ this.FlowButton1 = new FlowButton1Command();
+
+ this.FlowButton2 = new FlowButton1Command();
+ }
+ }
+}