添加项目文件。
This commit is contained in:
73
Sai.Toolkit.Revit/Helpers/BuiltEnumDictionary.cs
Normal file
73
Sai.Toolkit.Revit/Helpers/BuiltEnumDictionary.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
148
Sai.Toolkit.Revit/Helpers/DMUAssist.cs
Normal file
148
Sai.Toolkit.Revit/Helpers/DMUAssist.cs
Normal 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();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
51
Sai.Toolkit.Revit/Helpers/DuplicateTypeNamesHandler.cs
Normal file
51
Sai.Toolkit.Revit/Helpers/DuplicateTypeNamesHandler.cs
Normal 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;
|
||||
}
|
||||
15
Sai.Toolkit.Revit/Helpers/ElementOrientation.cs
Normal file
15
Sai.Toolkit.Revit/Helpers/ElementOrientation.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Sai.Toolkit.Revit.Helpers
|
||||
{
|
||||
public enum ElementOrientation
|
||||
{
|
||||
Horizontal,
|
||||
|
||||
Vertical,
|
||||
|
||||
CloseToHorizontal,
|
||||
|
||||
CloseToVertical,
|
||||
|
||||
Undefined
|
||||
}
|
||||
}
|
||||
71
Sai.Toolkit.Revit/Helpers/EnableAssist.cs
Normal file
71
Sai.Toolkit.Revit/Helpers/EnableAssist.cs
Normal 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;
|
||||
}
|
||||
138
Sai.Toolkit.Revit/Helpers/EncryptParameters.cs
Normal file
138
Sai.Toolkit.Revit/Helpers/EncryptParameters.cs
Normal 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)!;
|
||||
}
|
||||
}
|
||||
12
Sai.Toolkit.Revit/Helpers/ExtremeWallVariant.cs
Normal file
12
Sai.Toolkit.Revit/Helpers/ExtremeWallVariant.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Sai.Toolkit.Revit.Helpers;
|
||||
|
||||
public enum ExtremeWallVariant
|
||||
{
|
||||
Left,
|
||||
|
||||
Right,
|
||||
|
||||
Top,
|
||||
|
||||
Bottom
|
||||
}
|
||||
53
Sai.Toolkit.Revit/Helpers/FailuresPreProcessor.cs
Normal file
53
Sai.Toolkit.Revit/Helpers/FailuresPreProcessor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Sai.Toolkit.Revit/Helpers/FailuresPreprocessorHandler.cs
Normal file
19
Sai.Toolkit.Revit/Helpers/FailuresPreprocessorHandler.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
131
Sai.Toolkit.Revit/Helpers/Filters.cs
Normal file
131
Sai.Toolkit.Revit/Helpers/Filters.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
96
Sai.Toolkit.Revit/Helpers/FunctionByGuidLine.cs
Normal file
96
Sai.Toolkit.Revit/Helpers/FunctionByGuidLine.cs
Normal 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
|
||||
}
|
||||
141
Sai.Toolkit.Revit/Helpers/GeometryAssist.cs
Normal file
141
Sai.Toolkit.Revit/Helpers/GeometryAssist.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
679
Sai.Toolkit.Revit/Helpers/KeyIntPtrHelper.cs
Normal file
679
Sai.Toolkit.Revit/Helpers/KeyIntPtrHelper.cs
Normal 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,如果为松开 则设置成2,KEYEVENT_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
|
||||
}
|
||||
206
Sai.Toolkit.Revit/Helpers/KeyboardShortcutService.cs
Normal file
206
Sai.Toolkit.Revit/Helpers/KeyboardShortcutService.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Sai.Toolkit.Revit/Helpers/LoadFamilyOptions.cs
Normal file
28
Sai.Toolkit.Revit/Helpers/LoadFamilyOptions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
129
Sai.Toolkit.Revit/Helpers/OptionsBarAssist.cs
Normal file
129
Sai.Toolkit.Revit/Helpers/OptionsBarAssist.cs
Normal 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
|
||||
180
Sai.Toolkit.Revit/Helpers/RevitIniAssist.cs
Normal file
180
Sai.Toolkit.Revit/Helpers/RevitIniAssist.cs
Normal 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 = 0(0 = 以最后一次任务期间使用的窗口大小启动 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1011
Sai.Toolkit.Revit/Helpers/SharedParamsAssist.cs
Normal file
1011
Sai.Toolkit.Revit/Helpers/SharedParamsAssist.cs
Normal file
File diff suppressed because it is too large
Load Diff
22
Sai.Toolkit.Revit/Helpers/ShortcutRepAttribute.cs
Normal file
22
Sai.Toolkit.Revit/Helpers/ShortcutRepAttribute.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
42
Sai.Toolkit.Revit/Helpers/StatusBarAssist.cs
Normal file
42
Sai.Toolkit.Revit/Helpers/StatusBarAssist.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
71
Sai.Toolkit.Revit/Helpers/ViewFilterAssist.cs
Normal file
71
Sai.Toolkit.Revit/Helpers/ViewFilterAssist.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
51
Sai.Toolkit.Revit/Helpers/VisualAssist.cs
Normal file
51
Sai.Toolkit.Revit/Helpers/VisualAssist.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user