添加项目文件。

This commit is contained in:
GG Z
2024-09-22 11:05:41 +08:00
parent fb5d55723a
commit 49ceaae6a8
764 changed files with 78850 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
using Autodesk.Revit.DB;
using System;
namespace Sai.Toolkit.Revit.Helpers
{
public static class BuiltEnumDictionary
{
#if REVIT2025
public static string ToLabel(this ForgeTypeId source)
{
if (ParameterUtils.IsBuiltInParameter(source)) return LabelUtils.GetLabelForBuiltInParameter(source);
if (ParameterUtils.IsBuiltInGroup(source)) return LabelUtils.GetLabelForGroup(source);
if (UnitUtils.IsUnit(source)) return LabelUtils.GetLabelForUnit(source);
if (UnitUtils.IsSymbol(source)) return LabelUtils.GetLabelForSymbol(source);
if (SpecUtils.IsSpec(source)) return LabelUtils.GetLabelForSpec(source);
return LabelUtils.GetLabelForDiscipline(source);
}
#endif
public static Dictionary<T, string> GetBuiltInDictionary<T>()
where T : Enum
{
var dict = new Dictionary<T, string>();
foreach (object enumItem in Enum.GetValues(typeof(T)))
{
string name = string.Empty;
switch (enumItem)
{
#if REVIT2020
case BuiltInCategory category:
name = LabelUtils.GetLabelFor(category);
break;
#endif
case BuiltInParameter param:
name = LabelUtils.GetLabelFor(param);
break;
#if REVIT2018 || REVIT2020
case ParameterType type:
name = LabelUtils.GetLabelFor(type);
break;
case BuiltInParameterGroup group:
name = LabelUtils.GetLabelFor(group);
break;
case UnitType unitType:
name = LabelUtils.GetLabelFor(unitType);
break;
case DisplayUnitType displayUnitType:
name = LabelUtils.GetLabelFor(displayUnitType);
break;
case UnitSymbolType symbolType:
name = LabelUtils.GetLabelFor(symbolType);
break;
#endif
case ElementType elementType:
name = elementType.Name;
break;
case Element element:
name = element.Name;
break;
}
#if REVIT2025
if (enumItem is ForgeTypeId forgeTypeId)
{
var label = LabelUtils.GetLabelForBuiltInParameter(forgeTypeId);
}
#endif
dict.Add((T)enumItem, name);
}
return dict;
}
}
}

View File

@@ -0,0 +1,148 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Sai.Toolkit.Revit.Assist;
namespace Sai.Toolkit.Revit.Helpers
{
/// <summary>
/// 动态模型更新
/// </summary>
/// <typeparam name="T"></typeparam>
public static class DMUAssist
{
public static void AddTrigger(this IUpdater updater, Document document, ElementFilter filter, ChangeType change)
{
UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), document, filter, change);
}
}
public class Updater : IUpdater
{
/// <summary>
/// 应用程序范围的动态模型更新
/// </summary>
/// <param name="UiApplication"></param>
/// <param name="guid"></param>
/// <param name="execute"></param>
/// <param name="isOptional">true:只在本次生效,下次需要重新注册(不会发出警告)</param>
/// <param name="updateInfo"></param>
public Updater(UIApplication UiApplication, Guid guid, Action<UpdaterData> execute, bool isOptional = true, string updateInfo = "DynamicModelUpdate")
{
updaterId = new UpdaterId(UiApplication.ActiveAddInId, guid);
this.action = execute;
this.updateInfo = updateInfo;
if (!UpdaterRegistry.IsUpdaterRegistered(updaterId))
{
UpdaterRegistry.RegisterUpdater(this, isOptional);
/*
* 对FamilyInstance元素的增加和删除监听
*
* 如果需要关注某些有自己程序创建出来的Element可以把每个Element附上扩展数据
* 然后使用ExtensibleStorageFilter过滤器注册DMU即可
*
* DUM对用户的Ctrl + Z 无效, 可以在DocumentChanged事件中完善该机制
*/
}
}
private readonly Action<UpdaterData> action;
private readonly string updateInfo;
private readonly UpdaterId updaterId;
/// <summary>
/// 当注册的元素发生ChangeType触发时回调的函数
/// </summary>
/// <param name="data"></param>
public void Execute(UpdaterData data)
{
//var rvtDoc = data.GetDocument();
//var idsModified = data.GetModifiedElementIds();
//var idsDeleted = data.GetDeletedElementIds();
//var idsAdded = data.GetAddedElementIds();
//可以根据类型、元素Id、过滤器等等分情况执行更新的操作
action(data);
}
public void Enable()
{
UpdaterRegistry.EnableUpdater(updaterId);
}
public void Disable()
{
if (UpdaterRegistry.IsUpdaterEnabled(updaterId))
{
UpdaterRegistry.DisableUpdater(updaterId);
}
}
#region
public string GetAdditionalInformation()
{
return updateInfo;
}
public ChangePriority GetChangePriority()
{
return ChangePriority.FreeStandingComponents;
}
public UpdaterId GetUpdaterId()
{
return updaterId;
}
public string GetUpdaterName()
{
return updateInfo;
}
#endregion
public void RemoveAllTriggers()
{
UpdaterRegistry.RemoveAllTriggers(updaterId);
}
/// <summary>
/// 添加动态更新的对象和修改的类型的触发器
/// </summary>
/// <typeparam name="T">元素类型</typeparam>
/// <param name="change">修改的类型</param>
public void AddClassTrigger<T>(ChangeType change)
{
var filter = new ElementClassFilter(typeof(T));
UpdaterRegistry.AddTrigger(updaterId, filter, change);
}
public void AddFilterTrigger<T>(ElementFilter filter, ChangeType change)
{
UpdaterRegistry.AddTrigger(updaterId, filter, change);
}
public void UnRegister()
{
UpdaterRegistry.UnregisterUpdater(updaterId);
}
}
//internal class test
//{
// private readonly ChangeType change = null;
// private readonly ICollection<ElementId> elements = null;
// private readonly uiApplication uiApplication = null;
// private Guid guid = new();
// public void MyMethod()
// {
// var guid = new Guid();
// Updater updater = new Updater
// {
// addinID = null,
// Guid = guid
// };
// DMUAssist<Updater> dynamicModel =
// new DMUAssist<Updater>(uiApplication, elements, change);
// dynamicModel.UseUpdater();
// }
//}
}

View File

@@ -0,0 +1,51 @@
using Autodesk.Revit.DB;
using System;
using System.ComponentModel;
namespace Sai.Toolkit.Revit.Helpers;
/// <summary>
/// 复制元素处理方法
/// </summary>
/// <example>
///<c>
///var options = new CopyPasteOptions();
///options.SetDuplicateTypeNamesHandler(new DuplicateTypeNamesHandler());
///options.SetDuplicateTypeNamesHandler(new DuplicateTypeNamesHandler(() => DuplicateTypeAction.Abort));
///options.SetDuplicateTypeNamesHandler(new DuplicateTypeNamesHandler(DuplicateTypeAction.UseDestinationTypes));
///ElementTransformUtils.CopyElements(source, elementIds, destination, null, options);</c>
/// </example>
public class DuplicateTypeNamesHandler : IDuplicateTypeNamesHandler
{
/// <summary>
/// 创建一个新的处理程序,默认其中包括 <see cref="DuplicateTypeAction.UseDestinationTypes"/>
/// </summary>
public DuplicateTypeNamesHandler() => duplicateTypeAction = DuplicateTypeAction.UseDestinationTypes;
/// <summary>
/// Creates a new handler
/// </summary>
/// <param name="action">一个结构,提供关于试图复制名称在目标文件中已经存在的类型的信息。</param>
public DuplicateTypeNamesHandler(DuplicateTypeAction action) => duplicateTypeAction = action;
/// <summary>
/// Creates a new handler
/// </summary>
/// <param name="actionHandler">
/// 封装了在一个结构,提供关于试图复制名称在目标文件中已经存在的类型的信息。
/// </param>
public DuplicateTypeNamesHandler(Func<DuplicateTypeAction> actionHandler) => duplicateTypeAction = actionHandler();
private readonly DuplicateTypeAction duplicateTypeAction;
/// <summary>
/// 当目标文件包含与被复制的类型相同名称的类型时被调用。
/// </summary>
/// <param name="args">名称重复的类型的信息</param>
/// <returns>
/// 要采取的行动:只复制具有唯一名称的类型或取消操作。
/// </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public DuplicateTypeAction OnDuplicateTypeNamesFound(DuplicateTypeNamesHandlerArgs args) => duplicateTypeAction;
}

View File

@@ -0,0 +1,15 @@
namespace Sai.Toolkit.Revit.Helpers
{
public enum ElementOrientation
{
Horizontal,
Vertical,
CloseToHorizontal,
CloseToVertical,
Undefined
}
}

View File

@@ -0,0 +1,71 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace Sai.Toolkit.Revit.Helpers;
/// <summary>
/// 已经打开文档
/// </summary>
public class HasActiveDocument : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) => applicationData.ActiveUIDocument != null;
}
/// <summary>
/// 命令在平面视图可用
/// </summary>
public class EnableInViewPlan : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
{
return applicationData.ActiveUIDocument?.Document.ActiveView is ViewPlan
&& applicationData.ActiveUIDocument?.Document.IsFamilyDocument == false;
}
}
/// <summary>
/// 项目文档可用
/// </summary>
public class OnProjectDocument : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
{
var doc = applicationData?.ActiveUIDocument?.Document;
if (doc != null) { return !doc.IsFamilyDocument; }
return false;
}
}
/// <summary>
/// 图纸视图可用
/// </summary>
internal class EnableInViewSheet : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) =>
applicationData.ActiveUIDocument?.Document.ActiveView is ViewSheet && applicationData.ActiveUIDocument?.Document.IsFamilyDocument == false;
}
/// <summary>
/// 三维视图可用
/// </summary>
internal class EnableInView3D : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) =>
applicationData.ActiveUIDocument?.Document.ActiveView is View3D && applicationData.ActiveUIDocument?.Document.IsFamilyDocument == false;
}
/// <summary>
/// 命令在剖面、立面可用
/// </summary>
internal class EnableInViewSection : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) =>
applicationData.ActiveUIDocument?.Document.IsFamilyDocument == false && applicationData.ActiveUIDocument.Document.ActiveView is ViewSection;
}
/// <summary>
/// 族文档可用
/// </summary>
internal class EnableInFamilyDocument : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) =>
applicationData.ActiveUIDocument?.Document.IsFamilyDocument == true;
}

View File

@@ -0,0 +1,138 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Linq;
using System.Reflection;
namespace Sai.Toolkit.Revit.Helpers;
internal class EncryptParameters
{
public static bool InvokeModule(string mName, object[] parameters, bool apiModule = true)
{
try
{
MethodInfo m;
if (apiModule)
m = NativeModule.GetApiModuleMethod(mName);
else
m = NativeModule.GetUiModuleMethod(mName);
m.Invoke(null, parameters);
return true;
}
catch (Exception)
{
return false;
}
}
}
public class NativeModule
{
/// <summary>
/// 获取RevitAPI程序集Module内的方法名称.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static MethodInfo GetApiModuleMethod(string name)
{
var module = GetApiModule();
var rs = module.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(m => m.Name == name).ToList();
return !rs.Any() ? null : rs.First();
}
/// <summary>
/// 获取RevitAPIUI程序集Module内的方法名称.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static MethodInfo GetUiModuleMethod(string name)
{
var module = GetUiModule();
var rs = module.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(m => m.Name == name).ToList();
return !rs.Any() ? null : rs.First();
}
/// <summary>
/// 获取RevitAPI Modules.
/// </summary>
/// <returns></returns>
internal static Module GetApiModule()
{
return typeof(Document).Assembly.Modules.First();
}
/// <summary>
/// 获取RevitAPIUI Modules.
/// </summary>
/// <returns></returns>
internal static Module GetUiModule()
{
return typeof(UIDocument).Assembly.Modules.First();
}
}
public static class ParameterExtension
{
/// <summary>
/// 设置参数对象对用户是否可见.
/// </summary>
/// <param name="parameter"></param>
/// <param name="visible"></param>
/// <returns></returns>
public static bool SetVisibility(this Parameter parameter, bool visible)
{
var parameterIntPtr = parameter.ToParamDef();
if (parameterIntPtr == IntPtr.Zero)
{
return false;
}
var result = EncryptParameters.InvokeModule("ParamDef.setUserVisible", new object[] { parameterIntPtr, visible });
return result;
}
/// <summary>
/// 将参数对象转为非托管指针.
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public static IntPtr ToParamDef(this Parameter parameter)
{
try
{
var m = typeof(Parameter).GetMethod("getParamDef", BindingFlags.NonPublic | BindingFlags.Instance);
return (m?.Invoke(parameter, null) as Pointer).ToIntPtr();
}
catch
{
return IntPtr.Zero;
}
}
}
public static class PointerExtension
{
/// 将指针转为句柄.
/// <summary>
/// 将指针转为句柄.
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
public static IntPtr ToIntPtr(this Pointer p)
{
return (IntPtr)p.GetType().GetMethod("GetPointerValue", BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(p, null)!;
}
}

View File

@@ -0,0 +1,12 @@
namespace Sai.Toolkit.Revit.Helpers;
public enum ExtremeWallVariant
{
Left,
Right,
Top,
Bottom
}

View File

@@ -0,0 +1,53 @@
using Autodesk.Revit.DB;
namespace Sai.Toolkit.Revit.Helpers
{
/// <summary>
/// 错误预处理
/// </summary>
public class FailuresPreProcessor : IFailuresPreprocessor
{
////警告、错误处理,放在发生警告的前面
public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
{
//获取所有的失败信息
var listFma = failuresAccessor.GetFailureMessages();
if (listFma.Count == 0)
{
return FailureProcessingResult.Continue;
}
foreach (var fma in listFma)
{
if (fma?.GetFailureDefinitionId() == BuiltInFailures.JoinElementsFailures.CannotJoinElementsError)
{
failuresAccessor.ResolveFailure(fma);
}
if (fma.GetFailureDefinitionId() == BuiltInFailures.OverlapFailures.WallsOverlap)
{
failuresAccessor.DeleteWarning(fma);
}
//如果是错误,则尝试解决
if (fma.GetSeverity() == FailureSeverity.Error)
{
//模拟手动单击"删除连接"按钮
if (fma.HasResolutions())
{
failuresAccessor.ResolveFailure(fma);
}
return FailureProcessingResult.ProceedWithRollBack;
}
//如果是警告,则禁止弹框
if (fma.GetSeverity() == FailureSeverity.Warning)
{
failuresAccessor.DeleteWarning(fma);
}
}
return FailureProcessingResult.ProceedWithCommit;
}
}
}

View File

@@ -0,0 +1,19 @@
using Autodesk.Revit.DB;
namespace Sai.Toolkit.Revit.Helpers
{
public class FailuresPreprocessorHandler : IFailuresPreprocessor
{
public FailuresPreprocessorHandler(Func<FailuresAccessor, FailureProcessingResult> func)
{
this.func = func;
}
FailureProcessingResult IFailuresPreprocessor.PreprocessFailures(FailuresAccessor failuresAccessor)
{
return func(failuresAccessor);
}
private readonly Func<FailuresAccessor, FailureProcessingResult> func;
}
}

View File

@@ -0,0 +1,131 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
namespace Sai.Toolkit.Revit.Helpers;
/// <summary>
/// 任意选择过滤器
/// </summary>
public class FuncFilter(Func<Element, bool> allowElement, Func<Reference, XYZ, bool> allowReference = null)
: ISelectionFilter
{
private readonly Func<Element, bool> elementFunc = allowElement;
private readonly Func<Reference, XYZ, bool> referenceFunc = allowReference;
public bool AllowElement(Element elem)
{
return elementFunc(elem);
}
public bool AllowReference(Reference reference, XYZ position)
{
return referenceFunc == null || referenceFunc(reference, position);
}
}
/// <summary>
/// 类型过滤
/// </summary>
/// <typeparam name="T"></typeparam>
public class GenericFilter<T> : ISelectionFilter
{
public bool AllowElement(Element elem)
{
return elem is T;
}
public bool AllowReference(Reference reference, XYZ position)
{
return true;
}
}
/// <summary>
/// 获取当前模型或链接模型的实体元素
/// </summary>
public class ElementInLinkOrCurrentDocument : ISelectionFilter
{
public ElementInLinkOrCurrentDocument(Document doc)
{
this.doc = doc;
}
private readonly Document doc;
public bool LastCheckedWasFromLink => null != LinkedDocument;
public Document LinkedDocument { get; private set; }
public bool AllowElement(Element e)
{
return true;
}
public bool AllowReference(Reference r, XYZ p)
{
LinkedDocument = null;
var e = doc.GetElement(r);
if (e is RevitLinkInstance li)
{
LinkedDocument = li.GetLinkDocument();
e = LinkedDocument.GetElement(r.LinkedElementId);
}
return e != null
&& e.CanHaveTypeAssigned()
&& e.HasPhases()
&& e.get_BoundingBox(null) != null
&& e.Category is { Parent: null }
&& e is not Panel;
}
}
public class DwgBlockSelection : ISelectionFilter
{
private Element e;
public bool AllowElement(Element elem)
{
e = elem;
return e.Document.GetElement(e.GetTypeId()) is CADLinkType;
}
public bool AllowReference(Reference reference, XYZ position)
{
//块
var instance = e.GetGeometryObjectFromReference(reference) as GeometryInstance;
if (instance == null)
{
return false;
}
////dwg
//foreach (var dwgIns in e.get_Geometry(new Options()))
//{
// if (dwgIns is not GeometryInstance item) continue;
// //遍历dwg包含的所有内容
// foreach (var obj in item.SymbolGeometry)
// {
// return obj is GeometryInstance ins && !ins.SymbolGeometry.Any();
// }
//}
//if (selectBlock == null)
//{
// return false;
//}
//块是否包含子块
//foreach (var item in instance.SymbolGeometry)
//{
// if (item is GeometryInstance)
// {
// return false;
// }
//}
//var isNest = selectBlock.SymbolGeometry.OfType<GeometryInstance>().Any();
return /*!isNest &&*/ reference.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_INSTANCE
&& instance.GraphicsStyleId != ElementId.InvalidElementId;
}
}

View File

@@ -0,0 +1,96 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.UI;
namespace Sai.Toolkit.Revit.Helpers;
public class FunctionByGuidLine
{
public static Line GetGuideLine(Document doc, List<ElementId> eleIdsAdded)
{
var referLineId = eleIdsAdded.FirstOrDefault();
var guideLine = doc.GetElement(referLineId) as FamilyInstance;
var line = (guideLine?.Location as LocationCurve)?.Curve as Line;
doc.Delete(referLineId);
return line;
}
#region 线
private static readonly bool PlaceSingleInstanceAbort = true;
//只有一条线
private readonly List<ElementId> eleIdsRefer = new();
private IntPtr revitWindow;
public bool PlaceElementsByLine(UIApplication uiapp)
{
var uidoc = uiapp.ActiveUIDocument;
var app = uiapp.Application;
var doc = uidoc.Document;
#if REVIT2018
revitWindow = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
#else
revitWindow = uiapp.MainWindowHandle;
#endif
var f = new FilteredElementCollector(doc).OfClass(typeof(Family)).Cast<Family>().FirstOrDefault(x => x.Name == "LocationCurve");
var symbol = doc.GetElement(f.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
eleIdsRefer.Clear();
using var tg = new TransactionGroup(doc, "创建");
tg.Start();
try
{
//var x = UiDocument.GetPlacementTypes(symbol, doc.ActiveView);
//存在不能切换布置在平面上还是工作平面上的问题(如果族不需要切换,则没问题)
app.DocumentChanged += App_DocumentChanged;
uidoc.PromptForFamilyInstancePlacement(symbol);
app.DocumentChanged -= App_DocumentChanged;
//UiDocument.PostRequestForElementTypePlacement(symbol);
}
catch (OperationCanceledException)
{
var n = eleIdsRefer.Count;
//XYZ place = UiDocument.Selection.PickPoint("请点击布置的一侧");
if (n > 0)
{
using var ts = new Transaction(doc, "删除");
ts.Start();
var eid = eleIdsRefer.FirstOrDefault();
var l = uidoc.ActiveView.GenLevel;
if (doc.GetElement(eid) is FamilyInstance fi)
{
Wall.Create(doc, (fi.Location as LocationCurve)?.Curve, l.Id, false);
}
doc.Delete(eid);
//Debug.Print(ex.ViewMessage);
ts.Commit();
}
}
tg.Assimilate();
return true;
}
private void App_DocumentChanged(object sender, DocumentChangedEventArgs e)
{
var idsAdded = e.GetAddedElementIds();
var n = idsAdded.Count;
eleIdsRefer.AddRange(idsAdded);
if (PlaceSingleInstanceAbort && 0 < n)
{
//KeyIntPtrHelper.OneKey(_revit_window, (char)System.Windows.Forms.Keys.Escape);
KeyIntPtrHelper.OneKey(revitWindow, '\u001b');
//System.Windows.Forms.SendKeys.SendWait("^{F4}");
//KeyIntPtrHelper.SendKeys(Autodesk.Windows.ComponentManager.ApplicationWindow, System.Windows.Forms.Keys.Escape);
}
}
#endregion
}

View File

@@ -0,0 +1,141 @@
using Autodesk.Revit.DB;
namespace Sai.Toolkit.Revit.Helpers
{
internal class GeometryAssist
{
public static void CreateDirectShape(
Document doc,
List<XYZ> vertices,
List<Face> faces,
ElementId graphicsStyleId,
ElementId categoryId,
string appGuid,
string shapeName
)
{
var nFaces = 0;
var builder = new TessellatedShapeBuilder { LogString = shapeName };
var corners = new List<XYZ>();
builder.OpenConnectedFaceSet(false);
foreach (var f in faces)
{
builder.LogInteger = nFaces;
//if (corners.Capacity < f.Indices.Count)//设置corner的Capacity值减少内存开销
//{
// corners = new ErrorModels<XYZ>(f.Indices.Count);
//}
//corners.Clear();
//foreach (Index i in f.Indices)
//{
// if (i.vertex >= vertices.Count)
// {
// return;
// }
// corners.Add(vertices[i.vertex]);
//}
try
{
builder.AddFace(new TessellatedFace(corners, ElementId.InvalidElementId));
}
catch (Autodesk.Revit.Exceptions.ArgumentException) { }
}
builder.CloseConnectedFaceSet();
builder.Target = TessellatedShapeBuilderTarget.AnyGeometry;
builder.Fallback = TessellatedShapeBuilderFallback.Mesh;
builder.GraphicsStyleId = graphicsStyleId;
builder.Build();
var ds = DirectShape.CreateElement(doc, categoryId);
ds.ApplicationId = appGuid;
ds.ApplicationDataId = shapeName;
ds.SetShape(builder.GetBuildResult().GetGeometricalObjects());
ds.Name = shapeName;
}
//public BRepBuilder CreateGeo()
//{
//BRepBuilder bRepBuilder=new BRepBuilder(BRepType.Solid);
//BRepBuilderEdgeGeometry.Create();
//BRepBuilderSurfaceGeometry.Create();
//BRepBuilderSurfaceGeometry.CreateNURBSSurface();
//}
public static void CreateDirectShapeFromCylinder(Document doc)
{
// Naming convention for faces and edges: we assume that x is to the left and pointing down, y is horizontal and pointing to the right, z is up
var brepBuilder = new BRepBuilder(BRepType.Solid);
// The surfaces of the four faces.
var basis = new Frame(new XYZ(50, -100, 0), new XYZ(0, 1, 0), new XYZ(-1, 0, 0), new XYZ(0, 0, 1));
var cylSurf = CylindricalSurface.Create(basis, 50);
var top = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), new XYZ(0, 0, 100)); // normal points outside the cylinder
var bottom = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), new XYZ(0, 0, 0)); // normal points inside the cylinder
// Add the four faces
var frontCylFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(cylSurf, null), false);
var backCylFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(cylSurf, null), false);
var topFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(top, null), false);
var bottomFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(bottom, null), true);
// Geometry for the four semi-circular edges and two vertical linear edges
var frontEdgeBottom = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 0), new XYZ(100, -100, 0), new XYZ(50, -50, 0)));
var backEdgeBottom = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(100, -100, 0), new XYZ(0, -100, 0), new XYZ(50, -150, 0)));
var frontEdgeTop = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 100), new XYZ(100, -100, 100), new XYZ(50, -50, 100)));
var backEdgeTop = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 100), new XYZ(100, -100, 100), new XYZ(50, -150, 100)));
var linearEdgeFront = BRepBuilderEdgeGeometry.Create(new XYZ(100, -100, 0), new XYZ(100, -100, 100));
var linearEdgeBack = BRepBuilderEdgeGeometry.Create(new XYZ(0, -100, 0), new XYZ(0, -100, 100));
// Add the six edges
var frontEdgeBottomId = brepBuilder.AddEdge(frontEdgeBottom);
var frontEdgeTopId = brepBuilder.AddEdge(frontEdgeTop);
var linearEdgeFrontId = brepBuilder.AddEdge(linearEdgeFront);
var linearEdgeBackId = brepBuilder.AddEdge(linearEdgeBack);
var backEdgeBottomId = brepBuilder.AddEdge(backEdgeBottom);
var backEdgeTopId = brepBuilder.AddEdge(backEdgeTop);
// Loops of the four faces
var loopIdTop = brepBuilder.AddLoop(topFaceId);
var loopIdBottom = brepBuilder.AddLoop(bottomFaceId);
var loopIdFront = brepBuilder.AddLoop(frontCylFaceId);
var loopIdBack = brepBuilder.AddLoop(backCylFaceId);
// Add coedges for the loop of the front face
brepBuilder.AddCoEdge(loopIdFront, linearEdgeBackId, false);
brepBuilder.AddCoEdge(loopIdFront, frontEdgeTopId, false);
brepBuilder.AddCoEdge(loopIdFront, linearEdgeFrontId, true);
brepBuilder.AddCoEdge(loopIdFront, frontEdgeBottomId, true);
brepBuilder.FinishLoop(loopIdFront);
brepBuilder.FinishFace(frontCylFaceId);
// Add coedges for the loop of the back face
brepBuilder.AddCoEdge(loopIdBack, linearEdgeBackId, true);
brepBuilder.AddCoEdge(loopIdBack, backEdgeBottomId, true);
brepBuilder.AddCoEdge(loopIdBack, linearEdgeFrontId, false);
brepBuilder.AddCoEdge(loopIdBack, backEdgeTopId, true);
brepBuilder.FinishLoop(loopIdBack);
brepBuilder.FinishFace(backCylFaceId);
// Add coedges for the loop of the top face
brepBuilder.AddCoEdge(loopIdTop, backEdgeTopId, false);
brepBuilder.AddCoEdge(loopIdTop, frontEdgeTopId, true);
brepBuilder.FinishLoop(loopIdTop);
brepBuilder.FinishFace(topFaceId);
// Add coedges for the loop of the bottom face
brepBuilder.AddCoEdge(loopIdBottom, frontEdgeBottomId, false);
brepBuilder.AddCoEdge(loopIdBottom, backEdgeBottomId, false);
brepBuilder.FinishLoop(loopIdBottom);
brepBuilder.FinishFace(bottomFaceId);
brepBuilder.Finish();
using var tr = new Transaction(doc, "Create a DirectShape");
tr.Start();
var ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
ds.SetShape(brepBuilder);
tr.Commit();
}
}
}

View File

@@ -0,0 +1,679 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using Autodesk.Windows;
namespace Sai.Toolkit.Revit.Helpers;
public class KeyIntPtrHelper
{
public delegate bool CallBack(IntPtr hwnd, int lParam);
public delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);
private static void CompleteMultiSelection()
{
var rvtwindow = ComponentManager.ApplicationWindow;
var list = new List<IntPtr>();
var flag = EnumChildWindows(
rvtwindow,
(hwnd, l) =>
{
var windowText = new StringBuilder(200);
_ = GetWindowText(hwnd, windowText, windowText.Capacity);
var className = new StringBuilder(200);
_ = GetClassName(hwnd, className, className.Capacity);
if (
(
windowText.ToString().Equals("完成", StringComparison.Ordinal)
|| windowText.ToString().Equals("Finish", StringComparison.Ordinal)
) && className.ToString().Contains("Button")
)
{
list.Add(hwnd);
return false;
}
return true;
},
new IntPtr(0)
);
var complete = list.FirstOrDefault();
_ = PostMessage(complete, 245, 0, 0);
}
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool DeleteObject(IntPtr hObject);
/// <summary>
/// 确定主窗口
/// </summary>
/// <param name="handles"></param>
/// <returns></returns>
private static IntPtr DetermineMainWindow(IReadOnlyList<IntPtr> handles)
{
IntPtr result;
if (handles == null || handles.Count <= 0)
{
result = IntPtr.Zero;
}
else
{
var intPtr = IntPtr.Zero;
if (handles.Count == 1)
{
intPtr = handles[0];
}
else
{
foreach (var intPtr2 in handles)
{
var windowTextLength = GetWindowTextLength(intPtr2);
if (windowTextLength != 0)
{
var stringBuilder = new StringBuilder(windowTextLength);
_ = GetWindowText(intPtr2, stringBuilder, windowTextLength + 1);
if (stringBuilder.ToString().ToLower().Contains("autodesk revit"))
{
intPtr = intPtr2;
break;
}
}
}
}
result = intPtr;
}
return result;
}
[DllImport("user32.dll", CharSet = CharSet.None, ExactSpelling = false)]
private static extern bool EnumChildWindows(IntPtr hwndParent, CallBack lpEnumFunc, IntPtr lParam);
[DllImport("user32.DLL")]
private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Unicode)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetKeyboardState(byte[] lpKeyState);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetKeyNameText(int lParam, [Out] StringBuilder lpString, int nSize);
[DllImport("user32.dll")]
private static extern short GetKeyState(short nVirtKey);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.DLL")]
private static extern IntPtr GetShellWindow();
[DllImport("user32.dll")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, int revert);
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
private static extern IntPtr GetWindowLongPtr_1(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpText, int nCount);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
[DllImport("user32.dll")]
private static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);
[DllImport("user32.DLL")]
private static extern bool IsWindowVisible(IntPtr hWnd);
/// <summary>
/// 键盘事件
/// </summary>
/// <param name="bVk">虚拟键值查询虚拟键值表</param>
/// <param name="bScan">扫描不设置为0</param>
/// <param name="dwFlags">按键状态选项按下为0如果为松开 则设置成2KEYEVENT_KEYUP</param>
/// <param name="dwExtraInfo">,一般为0</param>
[DllImport("user32.dll")]
private static extern void keybdEvent(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
/// <summary>
/// 虚拟按钮
/// </summary>
/// <param name="uCode"></param>
/// <param name="uMapType"></param>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
/// <summary>
///发送消息
/// </summary>
/// <param name="hWnd"></param>
/// <param name="msg"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <example>
/// <para>Press.PostMessage(_revit_window, (uint)Press.KEYBOARD_MSG.WM_KEYDOWN, (uint)System.Windows.Forms.Keys.Escape, 0);</para>
/// <para>Press.PostMessage(_revit_window, (uint)Press.KEYBOARD_MSG.WM_KEYDOWN, (uint)System.Windows.Forms.Keys.Escape, 0);</para></example>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern bool PostMessage(IntPtr hWnd, uint msg, uint wParam, uint lParam);
[DllImport("user32.dll")]
private static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool SetWindowText(IntPtr hWnd, string lpString);
/// <summary>
/// 显示窗口
/// </summary>
/// <param name="hWnd"></param>
/// <param name="nCmdShow">0隐藏窗口1恢复窗口大小2最小化窗口3最大化窗口</param>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern int ToUnicode(
int wVirtKey,
int wScanCode,
byte[] lpKeyState,
[MarshalAs(UnmanagedType.LPWStr)][Out] StringBuilder pwszBuff,
int cchBuff,
int wFlags
);
/// <summary>
/// 执行Esc两次退出Revit选择
/// </summary>
public static void ActionEsc()
{
SetForegroundWindow(ComponentManager.ApplicationWindow);
keybdEvent(27, 0, 0, 0);
keybdEvent(27, 0, 2, 0);
}
/// <summary>
/// 查找内容
/// </summary>
/// <param name="hwndParent"></param>
/// <param name="hwndChildAfter"></param>
/// <param name="lpszClass"></param>
/// <param name="lpszWindow"></param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "FindWindowEx", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindowEx(
IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindow
);
public static IntPtr GetMainWindow(int pid)
{
var shellWindow = GetShellWindow();
var windowsForPid = new List<IntPtr>();
_ = EnumWindows(
(hWnd, _) =>
{
if (hWnd == shellWindow) { }
else
{
if (!IsWindowVisible(hWnd))
{
return true;
}
GetWindowThreadProcessId(hWnd, out uint num);
if (num != (ulong)pid)
{
return true;
}
var parent = GetParent(hWnd);
if (parent == IntPtr.Zero)
{
windowsForPid.Add(hWnd);
}
}
return true;
},
0
);
return DetermineMainWindow(windowsForPid);
}
public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
{
return IntPtr.Size == 8 ? GetWindowLongPtr_1(hWnd, nIndex) : new IntPtr(GetWindowLong(hWnd, nIndex));
}
public static void HideWindow(string winName)
{
var parenthWndldsl = FindWindow(null, winName);
if (!parenthWndldsl.Equals(IntPtr.Zero))
{
_ = ShowWindow(parenthWndldsl, 0);
}
}
public static bool IsVisible(string winName)
{
var parenthWndldsl = FindWindow(null, winName);
return !parenthWndldsl.Equals(IntPtr.Zero);
}
/// <summary>
/// 提交一系列按钮
/// </summary>
/// <param name="revitHandle"></param>
/// <param name="command">快捷键命令</param>
public static void Keys(IntPtr revitHandle, string command)
{
//IntPtr revitHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
foreach (var letter in command)
{
OneKey(revitHandle, letter);
}
}
/// <summary>
/// 提交单个按键
/// </summary>
/// <param name="handle">窗口句柄</param>
/// <param name="letter"></param>
public static void OneKey(IntPtr handle, char letter)
{
var scanCode = MapVirtualKey(letter, (uint)MvkMapType.VkeyToScancode);
var keyDownCode = (uint)WhKeyboardLparam.Keydown | (scanCode << 16);
var keyUpCode = (uint)WhKeyboardLparam.Keyup | (scanCode << 16);
PostMessage(handle, (uint)KeyboardMsg.WmKeydown, letter, keyDownCode);
PostMessage(handle, (uint)KeyboardMsg.WmKeyup, letter, keyUpCode);
}
public static bool RestoreWindow(IntPtr hWnd)
{
return ShowWindow(hWnd, 1);
}
public static void SendKeys(IntPtr proc, byte bVk)
{
SetActiveWindow(proc);
SetForegroundWindow(proc);
//keybd_event(27, 0, 0, 0);
//keybd_event(27, 0, 2, 0);
keybdEvent(bVk, 0, 0, 0);
keybdEvent(bVk, 0, 2, 0);
keybdEvent(bVk, 0, 0, 0);
keybdEvent(bVk, 0, 2, 0);
}
public static void SetAsOwner(IntPtr mainHandler, Window childWindow)
{
new WindowInteropHelper(childWindow).Owner = mainHandler;
}
public static void ShowAndActive(string winname)
{
var parenthWndldsl = FindWindow(null, winname);
if (!parenthWndldsl.Equals(IntPtr.Zero))
{
ShowWindow(parenthWndldsl, 1);
SetActiveWindow(parenthWndldsl);
}
}
/// <summary>
/// 键盘消息
/// </summary>
public enum KeyboardMsg : uint
{
WmKeydown = 0x100,
WmKeyup = 0x101
}
private enum MvkMapType : uint
{
VkeyToScancode = 0,
ScancodeToVkey = 1,
VkeyToChar = 2,
ScancodeToLrVkey = 3
}
private enum WhKeyboardLparam : uint
{
Keydown = 0x00000001,
Keyup = 0xC0000001
}
#region Win32 API Hook
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private const int VbWH_MOUSE_LL = 14;
private const int VbWM_LBUTTONDOWN = 0x0201;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(HookProc proc)
{
using var curProcess = Process.GetCurrentProcess();
using var curModule = curProcess.MainModule;
return SetWindowsHookEx(VbWH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)VbWM_LBUTTONDOWN)
{
MessageBox.Show("Left button down");
CompleteMultiSelection();
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
public static void MouseLeftButtonAction(Action action)
{
_hookID = SetHook(MouseHookCallback);
action();
UnhookWindowsHookEx(_hookID);
}
#endregion
#region Keys
public const byte VbKey0 = 48;
public const byte VbKey1 = 49;
public const byte VbKey2 = 50;
public const byte VbKey3 = 51;
public const byte VbKey4 = 52;
public const byte VbKey5 = 53;
public const byte VbKey6 = 54;
public const byte VbKey7 = 55;
public const byte VbKey8 = 56;
public const byte VbKey9 = 57;
public const byte VbKeyA = 65;
public const byte VbKeyAdd = 107;
public const byte VbKeyAlt = 18;
public const byte VbKeyB = 66;
public const byte VbKeyBack = 8;
public const byte VbKeyC = 67;
public const byte VbKeyCancel = 3;
public const byte VbKeyCapital = 20;
public const byte VbKeyClear = 12;
public const byte VbKeyControl = 17;
public const byte VbKeyD = 68;
public const byte VbKeyDecimal = 110;
public const byte VbKeyDelete = 46;
public const byte VbKeyDivide = 111;
public const byte VbKeyDown = 40;
public const byte VbKeyE = 69;
public const byte VbKeyEnd = 35;
public const byte VbKeyEscape = 27;
public const byte VbKeyExecute = 43;
public const byte VbKeyF = 70;
public const byte VbKeyF1 = 112;
public const byte VbKeyF10 = 121;
public const byte VbKeyF11 = 122;
public const byte VbKeyF12 = 123;
public const byte VbKeyF2 = 113;
public const byte VbKeyF3 = 114;
public const byte VbKeyF4 = 115;
public const byte VbKeyF5 = 116;
public const byte VbKeyF6 = 117;
public const byte VbKeyF7 = 118;
public const byte VbKeyF8 = 119;
public const byte VbKeyF9 = 120;
public const byte VbKeyG = 71;
public const byte VbKeyH = 72;
public const byte VbKeyHelp = 47;
public const byte VbKeyHome = 36;
public const byte VbKeyI = 73;
public const byte VbKeyJ = 74;
public const byte VbKeyK = 75;
public const byte VbKeyL = 76;
public const byte VbKeyLButton = 1;
public const byte VbKeyLeft = 37;
public const byte VbKeyM = 77;
public const byte VbKeyMButton = 4;
public const byte VbKeyMenu = 18;
public const byte VbKeyMultiply = 106;
public const byte VbKeyN = 78;
public const byte VbKeyNumlock = 144;
public const byte VbKeyNumpad0 = 96;
public const byte VbKeyNumpad1 = 97;
public const byte VbKeyNumpad2 = 98;
public const byte VbKeyNumpad3 = 99;
public const byte VbKeyNumpad4 = 100;
public const byte VbKeyNumpad5 = 101;
public const byte VbKeyNumpad6 = 102;
public const byte VbKeyNumpad7 = 103;
public const byte VbKeyNumpad8 = 104;
public const byte VbKeyNumpad9 = 105;
public const byte VbKeyO = 79;
public const byte VbKeyP = 80;
public const byte VbKeyPageUp = 33;
public const byte VbKeyPause = 19;
public const byte VbKeyPrint = 42;
public const byte VbKeyQ = 81;
public const byte VbKeyR = 82;
public const byte VbKeyRButton = 2;
public const byte VbKeyReturn = 13;
public const byte VbKeyRight = 39;
public const byte VbKeyS = 83;
public const byte VbKeySelect = 41;
public const byte VbKeySeparator = 108;
public const byte VbKeyShift = 16;
public const byte VbKeySnapshot = 44;
public const byte VbKeySpace = 32;
public const byte VbKeySubtract = 109;
public const byte VbKeyT = 84;
public const byte VbKeyTab = 9;
public const byte VbKeyU = 85;
public const byte VbKeyUp = 38;
public const byte VbKeyV = 86;
public const byte VbKeyW = 87;
public const byte VbKeyX = 88;
public const byte VbKeyY = 89;
public const byte VbKeyZ = 90;
public const int WmChar = 258;
public const int WmClick = 245;
public const int WmClose = 16;
public const int WmDeadchar = 259;
public const int WmKeydown = 256;
public const int WmKeyup = 257;
public const int WmLbuttondblclk = 515;
public const int WmLbuttondown = 513;
public const int WmLbuttonup = 514;
public const int WmMbuttondblclk = 521;
public const int WmMbuttondown = 519;
public const int WmMbuttonup = 520;
public const int WmMousehwheel = 526;
public const int WmMousemove = 512;
public const int WmMousewheel = 522;
public const int WmRbuttondblclk = 518;
public const int WmRbuttonup = 517;
public const int WmSyschar = 262;
public const int WmSysdeadchar = 263;
public const int WmSyskeydown = 260;
public const int WmSyskeyup = 261;
public const int WmXbuttondblclk = 525;
public const int WmXbuttondown = 523;
public const int WmXbuttonup = 524;
#endregion
}

View File

@@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autodesk.Revit.UI;
using UIFramework;
using UIFrameworkServices;
namespace Sai.Toolkit.Revit.Helpers
{
/// <summary>
/// 通过命令id设置快捷键
/// </summary>
public class KeyboardShortcutService
{
/// <summary>
/// 设置菜单快捷键
/// </summary>
/// <param name="id"></param>
/// <param name="shortcutsRep"></param>
/// <returns></returns>
public bool SetRibbonItemShortcut(string id, string shortcutsRep)
{
Dictionary<string, UIFrameworkServices.ShortcutItem> dictionary = this.LoadShortcuts();
if (this.Commands.TryGetValue(id, out UIFrameworkServices.ShortcutItem shortcutItem))
{
shortcutItem.ShortcutsRep = shortcutsRep;
shortcutItem.Shortcuts.Clear();
//多个快捷键中间以#分割
foreach (string text in shortcutsRep.Split('#'))
{
shortcutItem.Shortcuts.Add(text);
}
dictionary.Add(id, shortcutItem);
List<UIFrameworkServices.ShortcutItem> list = dictionary.Select((KeyValuePair<string, UIFrameworkServices.ShortcutItem> e) => e.Value).ToList<UIFrameworkServices.ShortcutItem>();
this.SaveShortcuts(list);
this.ArmCommands();
return true;
}
return false;
}
/// <summary>
/// 通过外部命令类设置快捷键
/// </summary>
/// <param name="id"></param>
/// <param name="shortcutsRep"></param>
/// <returns></returns>
public bool SetRibbonItemShortcut<T>() where T :IExternalCommand
{
var attribute=typeof(T).GetCustomAttribute<ShortcutRepAttribute>();
if (attribute==null)
{
return false;
}
Dictionary<string, UIFrameworkServices.ShortcutItem> dictionary = this.LoadShortcuts();
foreach (var item in Commands)
{
if (item.Key.EndsWith(nameof(T)))
{
ShortcutItem shortcutItem = item.Value;
shortcutItem.ShortcutsRep = attribute.Shortcuts;
shortcutItem.Shortcuts.Clear();
//多个快捷键中间以#分割
foreach (string text in attribute.Shortcuts.Split('#'))
{
shortcutItem.Shortcuts.Add(text);
}
dictionary.Add(item.Key, shortcutItem);
List<UIFrameworkServices.ShortcutItem> list = dictionary.Select((KeyValuePair<string, UIFrameworkServices.ShortcutItem> e) => e.Value).ToList<UIFrameworkServices.ShortcutItem>();
this.SaveShortcuts(list);
this.ArmCommands();
return true;
}
}
return false;
}
/// <summary>
/// 移除菜单快捷键
/// </summary>
/// <param name="id">命令id</param>
/// <returns></returns>
public bool RemoveRibbonItemShortcut(string id)
{
Dictionary<string, UIFrameworkServices.ShortcutItem> dictionary = this.LoadShortcuts();
UIFrameworkServices.ShortcutItem shortcutItem;
if (dictionary.TryGetValue(id, out shortcutItem))
{
dictionary.Remove(id);
List<UIFrameworkServices.ShortcutItem> list = dictionary.Select((KeyValuePair<string, UIFrameworkServices.ShortcutItem> e) => e.Value).ToList<UIFrameworkServices.ShortcutItem>();
this.SaveShortcuts(list);
this.ArmCommands();
return true;
}
return false;
}
/// <summary>
/// 是否具有菜单快捷键
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool HasRibbonItemShortcut(string id)
{
return this.LoadShortcuts().TryGetValue(id, out var _);
}
/// <summary>
/// 获取快捷键的映射(最多五个按键)
/// </summary>
/// <param name="id">CommandId</param>
/// <returns>快捷键</returns>
public string GetRibbonItemShortcutsRep(string id)
{
if (this.LoadShortcuts().TryGetValue(id, out var shortcutItem))
{
return shortcutItem.ShortcutsRep;
}
return "";
}
/// <summary>
/// 获取全部命令快捷键CommandId-ObservableCollect<string>()
/// </summary>
/// <returns></returns>
public Dictionary<string, IEnumerable<string>> GetCommandShortcuts()
{
return (from e in this.Commands
select e.Value into e
group e by e.CommandId).ToDictionary((IGrouping<string, UIFrameworkServices.ShortcutItem> i) => i.Key, (IGrouping<string, UIFrameworkServices.ShortcutItem> j) => j.SelectMany((UIFrameworkServices.ShortcutItem i) => i.Shortcuts));
}
/// <summary>
/// 获取自定义快捷键被关联到的命令CommandId
/// </summary>
/// <param name="shortcut">自定义的快捷键</param>
/// <returns>CommandId</returns>
public string GetCommandShortcut(string shortcut)
{
return this.Commands.FirstOrDefault((KeyValuePair<string, UIFrameworkServices.ShortcutItem> e) => e.Value.Shortcuts.Contains(shortcut)).Key;
}
/// <summary>
/// 自定义的快捷键是否已经被关联到某个命令上
/// </summary>
/// <param name="shortcut">自定义的快捷键</param>
/// <returns></returns>
public bool HasCommandShortcut(string shortcut)
{
return this.GetCommandShortcuts().Any((KeyValuePair<string, IEnumerable<string>> e) => e.Value.Contains(shortcut));
}
/// <summary>
/// 加载命令
/// </summary>
public void LoadCommands()
{
ShortcutsHelper.LoadCommands();
}
/// <summary>
/// 应用快捷键更改
/// </summary>
public void ApplyShortcutChanges()
{
UIFrameworkServices.KeyboardShortcutService.applyShortcutChanges(this.LoadShortcuts());
}
/// <summary>
/// 应用更改
/// </summary>
private void ArmCommands()
{
ShortcutsHelper.ArmCommands();
}
/// <summary>
/// 获取已经加载的ShortcutItems
/// </summary>
/// <returns></returns>
private Dictionary<string, UIFrameworkServices.ShortcutItem> LoadShortcuts()
{
return ShortcutsHelper.LoadShortcuts();
}
/// <summary>
/// 保存ShortcutItems
/// </summary>
/// <param name="shortcutList"></param>
private void SaveShortcuts(ICollection<UIFrameworkServices.ShortcutItem> shortcutList)
{
ShortcutsHelper.SaveShortcuts(shortcutList);
}
/// <summary>
/// 所有快捷命令条目字典
/// </summary>
private Dictionary<string, UIFrameworkServices.ShortcutItem> Commands
{
get
{
return ShortcutsHelper.Commands;
}
}
/// <summary>
/// 获取所有ShortcutItems
/// </summary>
/// <returns>ShortcutItems</returns>
public IEnumerable<UIFrameworkServices.ShortcutItem> GetShortcutItems()
{
return from e in this.LoadShortcuts()
select new UIFrameworkServices.ShortcutItem(e.Value);
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using Autodesk.Revit.DB;
namespace Sai.Toolkit.Revit.Helpers
{
/// <summary>
/// 载入族,覆盖,只会覆盖类型参数值
/// </summary>
public class LoadFamilyOptions: IFamilyLoadOptions
{
//族已载入
public bool OnFamilyFound(bool familyInUse, out bool overwriteParameterValues)
{
overwriteParameterValues = true;
return true;
}
//存在共享族
public bool OnSharedFamilyFound(Family sharedFamily, bool familyInUse, out FamilySource source, out bool overwriteParameterValues)
{
source = FamilySource.Family;
overwriteParameterValues = true;
return true;
}
}
}

View File

@@ -0,0 +1,129 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using UIFramework;
namespace Sai.Toolkit.Revit.Helpers;
#if REVIT2020||REVIT2025
public static class OptionsBarAssist
{
private static readonly Grid RootGrid;
private static ContentPresenter _panelPresenter;
private static readonly FrameworkElement InternalToolPanel;
static OptionsBarAssist()
{
//找到整个Revit界面的Grid
RootGrid = VisualAssist.FindVisualParent<Grid>(Autodesk.Windows.ComponentManager.Ribbon, "rootGrid");
if (RootGrid is null)
{
throw new InvalidOperationException("无法在 Revit UI 中找到root Grid");
}
//选项栏所在的Panel在第二行Index为1类型是DialogBarControl
InternalToolPanel = VisualAssist.FindVisualChild<DialogBarControl>(RootGrid, string.Empty);
if (InternalToolPanel is null)
{
throw new InvalidOperationException("无法在 Revit UI 中找到内部工具面板");
}
}
public static void ShowOptionsBar(FrameworkElement content)
{
if (_panelPresenter is not null)
{
//var actuallWidth = 0.0;
//var controlHost = VisualAssist.FindVisualChild<ControlHost>(InternalToolPanel, string.Empty);
//var size = VisualTreeHelper.GetChildrenCount(controlHost);
//for (int i = 0; i < size; i++)
//{
// var child = VisualTreeHelper.GetChild(controlHost, 0) as FrameworkElement;
// actuallWidth += child.ActualWidth;
//}
_panelPresenter.Content = content;
_panelPresenter.Visibility = System.Windows.Visibility.Visible;
//设为0隐藏内部的Panel
//InternalToolPanel.Height = 0;
return;
}
//第一次执行时,会创建
_panelPresenter = CreateOptionsBar();
_panelPresenter.Content = content;
//InternalToolPanel.Height = 0;
}
public static void HideOptionsBar()
{
if (_panelPresenter is null)
{
return;
}
_panelPresenter.Content = null;
_panelPresenter.Visibility = System.Windows.Visibility.Collapsed;
InternalToolPanel.Height = 26;
}
public static async void HideOptionsBar(TimeSpan delay)
{
await Task.Delay(delay);
HideOptionsBar();
}
private static ContentPresenter CreateOptionsBar()
{
const int panelRow = 1;
//在内部OptionsBar下方插入一行
RootGrid.RowDefinitions.Insert(panelRow, new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
//RootGrid.ColumnDefinitions.Insert(1,new ColumnDefinition { Width=new GridLength(1, GridUnitType.Auto) });
//把下方的所有元素都往下移动一行
foreach (UIElement child in RootGrid.Children)
{
var row = Grid.GetRow(child);
if (row > 0)
{
Grid.SetRow(child, row + 1);
}
//Grid.SetColumnSpan(child, 2);
}
var panelPresenter = new ContentPresenter();
Grid.SetRow(panelPresenter, panelRow);
//Grid.SetColumn(panelPresenter, panelRow);
RootGrid.Children.Add(panelPresenter);
return panelPresenter;
//var panelPresenter = new ContentPresenter();
//Grid.SetRow(panelPresenter, 1);
//RootGrid.Children.Add(panelPresenter);
//return panelPresenter;
}
/// <summary>
/// 简单注册并调用
/// </summary>
/// <typeparam name="TV"></typeparam>
/// <typeparam name="TM"></typeparam>
/// <param name="action"></param>
public static void RegisterOptionsBar<TV, TM>(Action<TV, TM> action)
where TV : Panel, new()
where TM : ObservableObject, new()
{
try
{
TM viewModel = new();
var view = new TV() { DataContext = viewModel };
action(view, viewModel);
ShowOptionsBar(view);
}
catch (Exception)
{
throw;
}
}
}
#endif

View File

@@ -0,0 +1,180 @@
// [Directories](文件位置)
//
// ·ProjectPath——打开项目时的默认路径
//
// ·ExternalParameters——共享参数文件保存路径
//
//
//
// [Graphics](图形设置)
//
// ·TempDimFontSizeInPoints——临时尺寸标注文字外观
//
// ·AllowNavigationDuringRedraw——重绘期间允许导航
//
// ·UseGpuOcclusionCulling——仅绘制可见图元
//
// ·Antialiasing——使用反失真平滑线条
//
// ·AntialiasingOptions——使用反失真平滑线条选项
//
// ·SemiTransparent——半透明
//
// ·ThinLinesEnabled——是否启用细线
//
// ·UseGraphicsHardware——是否使用硬件加速
//
//
//
// [Selection](选择设置)
//
// ·AllowFaceSelection——是否按面选择图元
//
// ·AllowLinkSelection——是否选择链接
//
// ·AllowPinnedSelection——是否选择锁定图元
//
// ·AllowPressAndDrag——是否选择时拖拽图元
//
// ·AllowUnderlaySelection——是否选择基线图元
//
//
//
// [Windows](窗口)
//
// ·Maximized = 00 = 以最后一次任务期间使用的窗口大小启动 Revit默认1 = 以最大化窗口启动 Revit。
using System;
using System.IO;
using System.Text;
namespace Sai.Toolkit.Revit.Helpers
{
public static class RevitIniAssist
{
public static string RevitVersion;
public static string IniPath { get; } =
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + $"\\Autodesk\\Revit\\Autodesk Revit {RevitVersion}\\Revit.ini";
/// <summary>
/// 添加项目样板
/// </summary>
/// <param name="revitVersion"></param>
/// <param name="revitTemplateIniFilePath">.ini文件的完整路径</param>
/// <param name="templateFilePath"></param>
public static void AddProjectTemplate(string revitVersion, string revitTemplateIniFilePath, string templateFilePath)
{
//Autodesk.Revit.ApplicationServices.Application.CurrentUsersDataFolderPath
string oriDateFilePath = Environment.GetEnvironmentVariable("appdata") + $"\\Autodesk\\Revit\\Autodesk Revit {revitVersion}\\Revit.ini";
if (File.Exists(oriDateFilePath))
{
using (StreamReader sr = new StreamReader(oriDateFilePath, Encoding.Unicode))
{
StreamWriter sw = new StreamWriter(revitTemplateIniFilePath, false, Encoding.Unicode);
string inputLine;
while ((inputLine = sr.ReadLine()) != null)
{
if (inputLine.StartsWith("DefaultTemplate="))
{
_ = inputLine.Insert(16, templateFilePath);
//if (inputLine.Contains("Example_SCHEMA.rte"))
//{
//}
//else
//{
// inputLine = inputLine + @", Example_SCHEMA=C:\temp\Example_SCHEMA.rte";
//}
}
sw.WriteLine(inputLine);
}
sw.Close();
}
File.Replace(revitTemplateIniFilePath, oriDateFilePath, null);
}
}
public static string ReadRevitIniData(string fileName, string targetTemplateFilePath)
{
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(fileName, Encoding.Unicode))
{
string lineBuf;
bool isTargetSection = false;
while ((lineBuf = sr.ReadLine()) != null)
{
if (lineBuf == "[DirectoriesCHS]")
{
isTargetSection = true;
}
if (isTargetSection)
{
if (lineBuf.Contains("DefaultTemplate"))
{
if (!lineBuf.Contains(targetTemplateFilePath))
{
int starIndex = "DefaultTemplate=".Length;
string endStr = lineBuf.Substring(starIndex);
lineBuf = "DefaultTemplate=" + targetTemplateFilePath;
lineBuf += ",";
lineBuf += endStr;
}
isTargetSection = false;
}
sb.AppendLine(lineBuf);
}
}
}
return sb.ToString();
}
public static void WriteFileData(string fileName, string value)
{
using (StreamWriter sw = new StreamWriter(fileName, false, Encoding.Unicode))
{
sw.Write(value);
sw.Flush();
sw.Close();
}
}
public static void WriteRevitIniData(string existFilePath, string templateFilePath)
{
string directory = Path.GetDirectoryName(existFilePath);
if (directory == null)
{
return;
}
DirectoryInfo dirInfo = new DirectoryInfo(directory);
try
{
if (dirInfo.Exists)
{
if (File.Exists(existFilePath))
{
string outPut = ReadRevitIniData(existFilePath, templateFilePath);
if (!string.IsNullOrEmpty(outPut))
{
WriteFileData(existFilePath, outPut);
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sai.Toolkit.Revit.Helpers
{
/// <summary>
/// 多个快捷键使用#分割
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
class ShortcutRepAttribute : Attribute
{
public ShortcutRepAttribute(string shortcuts)
{
Shortcuts = shortcuts;
}
public string Shortcuts { get; }
}
}

View File

@@ -0,0 +1,42 @@
using System.Runtime.InteropServices;
using Sai.Toolkit.Revit.Helpers;
namespace Sai.Toolkit.Revit.UserControls;
public class StatusBarAssist
{
private IntPtr statusBar = IntPtr.Zero;
protected StatusBarAssist()
{
// 找到状态栏,这样我们就可以添加信息了。
var revitHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
if (revitHandle != IntPtr.Zero)
{
statusBar = KeyIntPtrHelper.FindWindowEx(revitHandle, IntPtr.Zero, "msctls_statusbar32", string.Empty);
}
}
/// <summary>
/// 如果状态栏有有效句柄,则设置状态栏的值。
/// </summary>
/// <param name="msg">The message.</param>
public void Set(string msg)
{
if (statusBar != IntPtr.Zero)
{
KeyIntPtrHelper.SetWindowText(statusBar, msg);
}
}
/// <summary>
/// 创建一个新的 StatusBarAssist。
/// </summary>
/// <returns>The StatusBarAssist.</returns>
public static StatusBarAssist Create()
{
return new StatusBarAssist();
}
}

View File

@@ -0,0 +1,71 @@
using System.Windows;
using Autodesk.Revit.DB;
namespace Sai.Toolkit.Revit.Helpers;
/// <summary>
/// 创建参数的参数过滤器
/// </summary>
public class ViewFilterAssist
{
/// <summary>
/// 类别视图过滤器
/// </summary>
/// <param name="builtInCategory"></param>
/// <returns></returns>
public static ElementParameterFilter CreateCategoryFilter(BuiltInCategory builtInCategory)
{
ElementParameterFilter commonElementParameterFilter = null;
List<FilterRule> commonFilterRules = new();
List<ElementId> commonCategoryForRules = new() { new(builtInCategory) };
if (FilterCategoryRule.AllCategoriesFilterable(commonCategoryForRules))
{
FilterCategoryRule commonCategoryRule = new(commonCategoryForRules);
commonFilterRules.Add(commonCategoryRule);
commonElementParameterFilter = new ElementParameterFilter(commonFilterRules);
}
return commonElementParameterFilter;
}
/// <summary>
/// 参数的参数过滤器
/// </summary>
/// <param name="builtInCategory"></param>
/// <param name="rules"></param>
/// <returns></returns>
public static ElementParameterFilter CreateParameterFilter(BuiltInCategory builtInCategory, params FilterRule[] rules)
{
ElementParameterFilter commonFilter = null;
List<FilterRule> commonFilterRules = new();
List<ElementId> commonCategoryForRules = new() { new(builtInCategory) };
//判断类别是否可用于过滤器
if (FilterCategoryRule.AllCategoriesFilterable(commonCategoryForRules))
{
//类别规则
FilterCategoryRule commonCategoryRule = new(commonCategoryForRules);
commonFilterRules.Add(commonCategoryRule);
foreach (var rule in rules)
{
commonFilterRules.Add(rule);
}
commonFilter = new ElementParameterFilter(commonFilterRules);
}
return commonFilter;
}
/// <summary>
/// 视图过滤器过滤规则
/// </summary>
/// <param name="parameter"></param>
/// <param name="value">元素Id或整型值</param>
/// <returns></returns>
public static FilterRule CreateParameterFilterRule(BuiltInParameter parameter, int value)
{
var paramId = new ElementId(parameter);
var filterRule = ParameterFilterRuleFactory.CreateEqualsRule(paramId, value);
return filterRule;
}
}

View File

@@ -0,0 +1,51 @@
using System.Windows;
using System.Windows.Media;
namespace Sai.Toolkit.Revit.Helpers;
public static class VisualAssist
{
public static T FindVisualParent<T>(FrameworkElement element, string name)
where T : FrameworkElement
{
var parentElement = (FrameworkElement)VisualTreeHelper.GetParent(element);
while (parentElement != null)
{
if (parentElement is T parent)
{
if (parentElement.Name == name)
{
return parent;
}
}
parentElement = (FrameworkElement)VisualTreeHelper.GetParent(parentElement);
}
return null;
}
public static T FindVisualChild<T>(FrameworkElement element, string name)
where T : Visual
{
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var childElement = (FrameworkElement)VisualTreeHelper.GetChild(element, i);
if (childElement is T child)
{
if (childElement.Name == name)
{
return child;
}
}
var descendent = FindVisualChild<T>(childElement, name);
if (descendent != null)
{
return descendent;
}
}
return null;
}
}