Files
ShrlAlgoToolkit/ShrlAlgo.Toolkit.Revit/Assist/UIAssist.cs

708 lines
23 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using adWin = Autodesk.Windows;
namespace ShrlAlgo.Toolkit.Revit.Assist;
public static class UIAssist
{
private static readonly string AddInPath = typeof(UIAssist).Assembly.Location;
/// <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)]
private static extern IntPtr FindWindowEx(
IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindow
);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SetWindowText(IntPtr hWnd, string lpString);
/// <summary>
/// 面板上添加项
/// </summary>
/// <param name="panel"></param>
/// <param name="item"></param>
public static void AddAwItem(this adWin.RibbonPanel panel, adWin.RibbonItem item)
{
panel.Source.Items.Add(item);
}
/// <summary>
/// 添加堆叠按钮组
/// </summary>
/// <param name="rowPanel"></param>
/// <param name="ribbonButtons"></param>
public static void AddAwStackItems(this adWin.RibbonRowPanel rowPanel, params adWin.RibbonButton[] ribbonButtons)
{
for (var i = 0; i < ribbonButtons.Length; i++)
{
rowPanel.Items.Add(ribbonButtons[i]);
//添加一个,打断一次
if (i < ribbonButtons.Length - 1)
{
//行打断=新建行
rowPanel.Items.Add(new adWin.RibbonRowBreak());
}
}
}
/// <summary>
/// Combobox是可以分组的
/// 组合框是与事件结合使用的
/// </summary>
public static ComboBox AddComboBox(
this RibbonPanel panel,
ComboBoxData comboBoxData,
params ComboBoxMemberData[] memberData
)
{
var comboBx = panel.AddItem(comboBoxData) as ComboBox ?? throw new ArgumentNullException(nameof(comboBoxData));
foreach (var item in memberData)
{
comboBx.AddItem(item);
}
comboBx.CurrentChanged += (sender, _) =>
{
if (sender is ComboBox comboBox)
{
var member = comboBox.Current;
TaskDialog.Show("组合框选择", "你的选择是: " + member.ItemText);
}
};
return comboBx;
}
/// <summary>
/// 创建一个下拉式按钮。
/// </summary>
/// <param name="pnl">面板</param>
/// <param name="name">下拉按钮名称</param>
/// <param name="pbds"></param>
/// <returns></returns>
public static PulldownButton AddPullDownButton(this RibbonPanel pnl, string name, params PushButtonData[] pbds)
{
if (pnl is null)
{
throw new ArgumentNullException(nameof(pnl));
}
if (pbds is null)
{
throw new ArgumentNullException(nameof(pbds));
}
var pbd = new PulldownButtonData(name, name);
if (pnl.AddItem(pbd) is not PulldownButton result)
{
throw new InvalidCastException();
}
result.ToolTip = pbd.ToolTip;
result.LongDescription = pbd.LongDescription;
result.LargeImage = pbd.LargeImage;
foreach (var pbdl in pbds)
{
var btn = result.AddPushButton(pbdl);
if (btn is null)
{
continue;
}
btn.ToolTip = pbdl.ToolTip;
btn.LongDescription = pbdl.LongDescription;
btn.LargeImage = pbdl.LargeImage;
}
return result;
}
/// <summary>
/// 添加按钮
/// </summary>
/// <typeparam name="T">命令类</typeparam>
/// <param name="panel">面板</param>
/// <param name="text">按钮名</param>
/// <param name="bitmap">按钮图片</param>
/// <param name="tooltip"></param>
/// <param name="availabilityClassName">控制可用性</param>
public static PushButtonData AddPushButton<T>(this RibbonPanel panel)
where T : class, IExternalCommand
{
var data = new PushButtonData(typeof(T).FullName, "外部命令", typeof(T).Assembly.Location, typeof(T).FullName);
panel.AddItem(data);
return data;
}
/// <summary>
/// 创建一个分割记忆按钮。
/// </summary>
/// <param name="pnl">面板</param>
/// <param name="pnl">名称</param>
/// <param name="array"></param>
/// <returns></returns>
public static SplitButton AddSplitButton(this RibbonPanel pnl, string name, params PushButtonData[] array)
{
if (pnl is null)
{
throw new ArgumentNullException(nameof(pnl));
}
if (array is null)
{
throw new ArgumentNullException(nameof(array));
}
if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(array));
}
var splitButton = new SplitButtonData(name, name);
if (pnl.AddItem(splitButton) is not SplitButton result)
{
throw new InvalidCastException();
}
result.ToolTip = splitButton.ToolTip;
result.LongDescription = splitButton.LongDescription;
result.LargeImage = splitButton.LargeImage;
foreach (var buttonData in array)
{
result.AddPushButton(buttonData);
}
return result;
}
public static void AddTextBox(this RibbonPanel panel, TextBoxData txtBoxData)
{
var txtBox = panel.AddItem(txtBoxData) as TextBox;
txtBox!.PromptText = "输入提示";
txtBox.ShowImageAsButton = true;
txtBox.EnterPressed += (sender, _) =>
{
if (sender is TextBox textBox)
{
TaskDialog.Show("文本输入", "输入内容: " + textBox.Value);
}
};
txtBox.Width = 180;
}
/// <summary>
/// 在Revit现有的标签下如不存在则创建创建创建面板
/// </summary>
/// <param name="application"></param>
/// <param name="panelName">创建的面板名称</param>
/// <param name="tabName">若Tab不存在则创建对应名称的Tab</param>
/// <returns></returns>
public static RibbonPanel AddUIPanel(this UIControlledApplication application, string tabName, string panelName)
{
var ribbonTab = adWin.ComponentManager.Ribbon.Tabs.FirstOrDefault(tab => tab.Id.Equals(tabName));
if (ribbonTab == null)
{
application.CreateRibbonTab(tabName);
return application.CreateRibbonPanel(tabName, panelName);
}
var ribbonPanel = application.GetRibbonPanels(tabName).Find(panel => panel.Name.Equals(panelName));
return ribbonPanel ?? application.CreateRibbonPanel(tabName, panelName);
}
public static adWin.RibbonItem ConvertToAwRibbonItem(this RibbonButton btn)
{
return (adWin.RibbonItem)btn.GetType()
.InvokeMember(
"getRibbonItem",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
Type.DefaultBinder,
btn,
null
);
}
/// <summary>
/// 帮助文档
/// </summary>
/// <param name="helpFileSafeName">"xxx.chm"</param>
/// <returns></returns>
public static ContextualHelp CreateContextualHelp(string helpFileSafeName)
{
//addin目录
FileInfo fileInfo = new(Assembly.GetExecutingAssembly().Location);
var text = Path.Combine(fileInfo.Directory!.FullName, helpFileSafeName);
if (new FileInfo(text).Exists)
{
return new ContextualHelp(ContextualHelpType.Url, text);
}
ImageAssist.ExtractResource(helpFileSafeName, text);
return new ContextualHelp(ContextualHelpType.ChmFile, text);
}
/// <summary>
/// 添加按钮
/// </summary>
/// <typeparam name="T">命令类</typeparam>
/// <param name="panel">面板</param>
/// <param name="text">按钮名</param>
/// <param name="bitmap">按钮图片</param>
/// <param name="tooltip"></param>
/// <param name="availabilityClassName">控制可用性</param>
public static PushButtonData CreatePushButton<T>(string name)
where T : class, IExternalCommand
{
return new PushButtonData(typeof(T).FullName, name, typeof(T).Assembly.Location, typeof(T).FullName);
}
/// <summary>
/// 查找面板
/// </summary>
/// <param name="rt"></param>
/// <param name="panelName"></param>
/// <returns></returns>
public static adWin.RibbonPanel FindAwPanel(this adWin.RibbonTab rt, string panelName)
{
return rt.Panels.FirstOrDefault(p => p.Source.Name == panelName);
}
/// <summary>
/// 查找Tab
/// </summary>
/// <param name="tabName">标签名</param>
/// <returns></returns>
public static adWin.RibbonTab FindAwTab(string tabName)
{
return adWin.ComponentManager.Ribbon.Tabs.FirstOrDefault(tab => tab.Id.Equals(tabName));
}
public static ToggleButton GetToggleButton(this RadioButtonGroup radioButtonGroup)
{
return radioButtonGroup.Current;
}
/// <summary>
/// 创建按钮
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="showText"></param>
/// <param name="largeImage"></param>
/// <param name="image"></param>
/// <param name="command">RelayCommand</param>
/// <param name="parameter">命令的参数</param>
/// <param name="toolTip"></param>
/// <returns></returns>
public static adWin.RibbonButton NewAwButton(string showText, Bitmap largeImage, Bitmap image, ICommand command, object parameter, string toolTip = default)
{
return new()
{
Image = image.ToBitmapSource(),
LargeImage = largeImage.ToBitmapSource(),
Size = adWin.RibbonItemSize.Standard,
ShowText = true,
Id = $"ID_{showText}",
Name = $"Btn_{showText}",
ToolTip = toolTip ?? showText,
Text = showText,
IsCheckable = true,
CommandHandler = command,
CommandParameter = parameter,
//Orientation = System.Windows.Controls.Orientation.Vertical
};
}
/// <summary>
/// 创建ToggleButton
/// </summary>
/// <param name="showText"></param>
/// <param name="largeImage"></param>
/// <param name="toolTip"></param>
/// <returns></returns>
public static adWin.RibbonToggleButton NewAwToggleButton(string showText, Bitmap largeImage, string toolTip = null)
{
return new adWin.RibbonToggleButton()
{
LargeImage = largeImage?.ToBitmapSource(),
Size = adWin.RibbonItemSize.Large,
ToolTip = toolTip ?? showText,
ShowText = true,
Id = $"ID_{showText}",
Name = $"Tog_{showText}",
Text = showText,
IsCheckable = true,
Orientation = System.Windows.Controls.Orientation.Vertical,
};
}
/// <summary>
/// Revit默认打开文件对话框
/// </summary>
/// <param name="filter">多个过滤器之间用”|“分隔,例如:"Revit文件(*.rfa;*.rvt;*.rft;*.rte;)|*.rfa;*.rvt;*.rft;*.rte"</param>
/// <returns></returns>
public static string OpenFile(string filter)
{
string filename = null;
FileOpenDialog openFileDialog =
new(filter)
{
DefaultFilterEntry = filter,
ShowPreview = true,
Title = "打开文件"
};
if (openFileDialog.Show() == ItemSelectionDialogResult.Confirmed)
{
var mp = openFileDialog.GetSelectedModelPath();
filename = ModelPathUtils.ConvertModelPathToUserVisiblePath(mp);
}
return filename;
}
/// <summary>
/// 设置按钮可用性
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="pushButtonData"></param>
/// <returns></returns>
public static PushButtonData SetAvailability<T>(this PushButtonData pushButtonData)
where T : IExternalCommandAvailability
{
pushButtonData.AvailabilityClassName = typeof(T).FullName;
return pushButtonData;
}
/// <summary>
/// 设置面板右下角箭头对话框
/// </summary>
public static void SetAwDialogLauncher(this adWin.RibbonPanel panel, adWin.RibbonCommandItem item)
{
if (panel != null)
{
panel.Source.DialogLauncher = item;
}
}
public static adWin.RibbonItem SetAwImage(this adWin.RibbonItem ribbonItem, Bitmap image)
{
ribbonItem.Image = image.ToBitmapSource();
return ribbonItem;
}
public static void SetAwImage(this adWin.RibbonItem ribbonItem, string uri)
{
ribbonItem.Image = new BitmapImage(new Uri(uri, UriKind.RelativeOrAbsolute));
}
public static adWin.RibbonItem SetAwLargeImage(this adWin.RibbonItem ribbonItem, Bitmap largeImage)
{
ribbonItem.LargeImage = largeImage.ToBitmapSource();
return ribbonItem;
}
/// <summary>
/// 从 URI 源添加 32x32px-96dpi 图像
/// </summary>
/// <param name="button">添加图标的按钮</param>
/// <param name="uri">图标的相对或绝对路径</param>
/// <example>button.SetAwLargeImage("/RevitAddIn;component/Resources/Icons/RibbonIcon32.png")</example>
public static void SetAwLargeImage(this adWin.RibbonItem ribbonItem, string uri)
{
ribbonItem.LargeImage = new BitmapImage(new Uri(uri, UriKind.RelativeOrAbsolute));
}
public static adWin.RibbonItem SetAwShowText(this adWin.RibbonItem ribbonItem, string text)
{
ribbonItem.Text = text;
return ribbonItem;
}
public static adWin.RibbonItem SetAwToolTip(this adWin.RibbonItem ribbonItem, string tooltip)
{
ribbonItem.ToolTip = tooltip;
return ribbonItem;
}
public static PushButtonData SetDescription(this PushButtonData pushButtonData, string longDescription)
{
pushButtonData.LongDescription = longDescription;
return pushButtonData;
}
/// <summary>
/// 设置面板右下角箭头对话框
/// </summary>
public static void SetDialogLauncher(string tabName, string panelName)
{
var group = adWin.ComponentManager.Ribbon.Tabs
.FirstOrDefault(tab => tab.Name == tabName)
.Panels.FirstOrDefault(p => p.AutomationName == panelName) ?? throw new ArgumentException("未找到标签或面板");
group.Source.DialogLauncher = group.Source.Items.First() as adWin.RibbonCommandItem;
}
/// <summary>
/// 设置面板右下角箭头对话框
/// </summary>
public static void SetDialogLauncher(adWin.RibbonTab tab, string panelName)
{
var group = tab.Panels.FirstOrDefault(p => p.AutomationName == panelName) ?? throw new ArgumentException("未找到标签或面板");
group.Source.DialogLauncher = group.Source.Items.First() as adWin.RibbonCommandItem;
}
/// <summary>
/// 双击选项
/// </summary>
public static void SetDoubleClickAction(DoubleClickTarget target, DoubleClickAction clickAction)
{
var doubleOpt = DoubleClickOptions.GetDoubleClickOptions();
//DoubleClickAction dca = doubleOpt.GetAction(DoubleClickTarget.Family);
doubleOpt.SetAction(target, clickAction);
}
/// <summary>
/// 提示包含短视频
/// </summary>
/// <param name="pushButtonData"></param>
/// <param name="title"></param>
/// <param name="videoPath">视频路径</param>
public static void SetExpandedVideo(this PushButtonData pushButtonData, string title, string videoPath)
{
//拿到Autodesk.Windows的RibbonItem转换
var internalGetRibbonItemMethod = typeof(RibbonItem).GetMethod(
"getRibbonItem",
BindingFlags.NonPublic | BindingFlags.Instance
);
if (internalGetRibbonItemMethod?.Invoke(pushButtonData, null) is Autodesk.Windows.RibbonButton button)
{
button.ToolTip = new adWin.RibbonToolTip { Title = title, ExpandedVideo = new Uri(videoPath) };
}
}
/// <summary>
/// 设置16x16的小图片
/// </summary>
/// <param name="pushButtonData"></param>
/// <param name="image"></param>
/// <returns></returns>
public static PushButtonData SetImage(this PushButtonData pushButtonData, Bitmap image)
{
pushButtonData.Image = image.ToBitmapSource();
return pushButtonData;
}
/// <summary>
/// 使用Uri设置16x16的小图片
/// </summary>
/// <param name="pushButtonData"></param>
/// <param name="uri"></param>
public static PushButtonData SetImage(this PushButtonData pushButtonData, string uri)
{
pushButtonData.Image = new BitmapImage(new Uri(uri, UriKind.RelativeOrAbsolute));
return pushButtonData;
}
/// <summary>
/// 消息中心
/// </summary>
/// <param name="head"></param>
/// <param name="content"></param>
public static void SetInfoCenterPaletteMsg(string head, string content)
{
var paletteMgr = Autodesk.Windows.ComponentManager.InfoCenterPaletteManager;
var resultItem = new Autodesk.Internal.InfoCenter.ResultItem
{
Category = head, // 气泡标题
Title = content // 气泡内容
};
resultItem.ResultClicked += (_, _) =>
{
TaskDialog.Show("气泡内容", "点击了气泡内容!");
}; // 当鼠标点击气泡内容时触发此事件
paletteMgr.ShowBalloon(resultItem);
}
/// <summary>
/// 设置32x32-96dpi的大图片
/// </summary>
/// <param name="pushButtonData"></param>
/// <param name="largeImage"></param>
/// <returns></returns>
public static PushButtonData SetLargeImage(this PushButtonData pushButtonData, Bitmap largeImage)
{
pushButtonData.LargeImage = largeImage.ToBitmapSource();
return pushButtonData;
}
/// <summary>
/// 从 URI 源添加 32x32px-96dpi 图像
/// </summary>
/// <param name="pushButtonData">添加图标的按钮</param>
/// <param name="uri">图标的相对或绝对路径</param>
/// <example>button.SetAwLargeImage("/RevitAddIn;component/Resources/Icons/RibbonIcon32.png")</example>
public static void SetLargeImage(this PushButtonData pushButtonData, string uri)
{
pushButtonData.LargeImage = new BitmapImage(new Uri(uri, UriKind.RelativeOrAbsolute));
}
/// <summary>
/// 状态栏
/// </summary>
/// <param name="msg"></param>
public static void SetRevitStatusBarMsg(string msg)
{
var mainWindowHandle = Process.GetCurrentProcess().MainWindowHandle;
if (mainWindowHandle == IntPtr.Zero)
{
return;
}
var statusBar = FindWindowEx(mainWindowHandle, IntPtr.Zero, "msctls_statusbar32", string.Empty);
if (statusBar != IntPtr.Zero)
{
SetWindowText(statusBar, msg);
}
}
/// <summary>
/// 设置显示文字
/// </summary>
/// <param name="pushButtonData"></param>
/// <param name="text"></param>
/// <returns></returns>
public static PushButtonData SetShowText(this PushButtonData pushButtonData, string text)
{
pushButtonData.Text = text;
return pushButtonData;
}
/// <summary>
/// 设置工具提示
/// </summary>
/// <param name="pushButtonData"></param>
/// <param name="tooltip"></param>
/// <returns></returns>
public static PushButtonData SetToolTip(this PushButtonData pushButtonData, string tooltip)
{
pushButtonData.ToolTip = tooltip;
return pushButtonData;
}
/// <summary>
/// 设置工具提示图片
/// </summary>
/// <param name="pushButtonData"></param>
/// <param name="toolTipImage"></param>
/// <returns></returns>
public static PushButtonData SetToolTipImage(this PushButtonData pushButtonData, Bitmap toolTipImage)
{
pushButtonData.ToolTipImage = toolTipImage.ToBitmapSource();
return pushButtonData;
}
/// <summary>
/// 通过判断keyTip来区分原始Tab与插件Tab然后切换插件Tab的可见性
/// </summary>
/// <param name="tabName"></param>
/// <param name="visible"></param>
public static void SetVisible(string tabName, bool visible)
{
var ribbonControl = adWin.ComponentManager.Ribbon;
var tab = ribbonControl.Tabs
.FirstOrDefault(
tab => !tab.IsContextualTab &&
!tab.IsMergedContextualTab &&
tab.KeyTip == null &&
tabName == tab.Name);
if (tab != null)
{
tab.IsVisible = visible;
}
}
#region
/// <summary>
/// 新建命令按钮
/// </summary>
/// <typeparam name="Command"></typeparam>
/// <param name="text"></param>
/// <param name="image"></param>
/// <param name="largeImage"></param>
/// <param name="toolTip"></param>
/// <param name="longDescription"></param>
/// <returns></returns>
public static PushButtonData NewPushButtonData<Command>(
string text,
Bitmap largeImage = null,
Bitmap image = null,
string toolTip = null,
string longDescription = null
)
where Command : class, IExternalCommand
{
return new(typeof(Command).FullName, text, AddInPath, typeof(Command).FullName)
{
LargeImage = largeImage?.ToBitmapSource(),
Image = image?.ToBitmapSource(),
ToolTip = toolTip ?? text,
LongDescription = longDescription
};
}
/// <summary>
/// 新建可控的命令按钮
/// </summary>
/// <typeparam name="Command"></typeparam>
/// <typeparam name="Availablility"></typeparam>
/// <param name="text"></param>
/// <param name="bitmap"></param>
/// <param name="largeBitmap"></param>
/// <param name="toolTip"></param>
/// <param name="longDescription"></param>
/// <returns></returns>
public static PushButtonData NewButtonData<Command, Availablility>(
string text,
Bitmap largeBitmap = null,
Bitmap bitmap = null,
string toolTip = null,
string longDescription = null
)
where Command : class, IExternalCommand
where Availablility : class, IExternalCommandAvailability
{
return new(typeof(Command).FullName, text, AddInPath, typeof(Command).FullName)
{
LargeImage = largeBitmap?.ToBitmapSource(),
Image = bitmap?.ToBitmapSource(),
ToolTip = toolTip ?? text,
LongDescription = longDescription,
AvailabilityClassName = typeof(Availablility).FullName
};
}
#endregion
}