创建可停靠窗口 Github地址 Address
引用 The Building Coder CSDN Revit二次开发之可停靠窗口 Revit二次开发——非模态窗口与Revit窗口焦点切换 雨花拾-Revit二次开发之ExternalEvent实现非模态窗体 Revit二次开发入门:第九章事件
创建WPF窗口
添加完WPF窗口后将usercontrol 修改为Page ,F7切入后台同样修改为Page,同时需要引用Autodesk.Revit.UI.IDockablePaneProvider页面位置使用Dockpositon枚举值进行控制,进行选择位置即可,页面此时就创建完成,按照自己需要添加UI布局即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public partial class UserControl1 : Page,Autodesk.Revit.UI.IDockablePaneProvider { public UserControl1() { InitializeComponent(); } public void SetupDockablePane(DockablePaneProviderData data) { data.FrameworkElement = this as FrameworkElement; data.InitialState = new DockablePaneState { DockPosition = DockPosition.Bottom }; } }
创建面板(CreatPanel) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public Result OnShutdown(UIControlledApplication application) { return Result.Succeeded; } public Result OnStartup(UIControlledApplication application) { thisApp = this; apiUntil = new APIUntil(); string tabName = "DockPane"; string PanelName = "DockPane"; string RegisterName = "Register"; application.CreateRibbonTab(tabName); RibbonPanel architecturePanel = application.CreateRibbonPanel(tabName, PanelName); PushButtonData buttonData = new PushButtonData("DockPane", "DockPane", Assembly.GetExecutingAssembly().Location, typeof(ShowPage).FullName); PushButton ShowPage = architecturePanel.AddItem(buttonData) as PushButton; ShowPage.AvailabilityClassName = typeof(ShowPage).FullName; RibbonPanel RegisterPanel = application.CreateRibbonPanel(tabName, RegisterName); PushButtonData buttonDataRegisterPage = new PushButtonData("RegisterDockPane", "RegisterDockPane", Assembly.GetExecutingAssembly().Location, typeof(RegisterPage).FullName); PushButton RegisterPage = RegisterPanel.AddItem(buttonDataRegisterPage) as PushButton; RegisterPage.AvailabilityClassName = typeof(RegisterPage).FullName; return Result.Succeeded; }
注册页面(RegisterPage) 最好是在项目启动时进行注册页面,我按照SDKSmple方式分为注册窗口与显示窗口
1 2 3 4 5 6 7 ThisApplication.thisApp.RegisterPage(app); public void RegisterPage(Autodesk.Revit.UI.UIApplication uiapp) { DockablePaneId dockablePaneId = new DockablePaneId(APIUntil.m_GUID); uiapp.RegisterDockablePane(dockablePaneId, "Pane", ThisApplication.thisApp.GetMainWindow() as IDockablePaneProvider); }
在这一步我们需要一个GUID 进行注册,最后单独创建一个类存储放置后面由于代码过多引用混乱
显示窗口 窗口显示由Show()进行控制,隐藏为Hide()
1 2 3 4 5 6 public void SetWindowAvibilable(Autodesk.Revit.UI.UIApplication uiApp) { DockablePane pane = uiApp.GetDockablePane(new DockablePaneId(APIUntil.m_GUID)); pane.Show(); }
到这一步为止我们已经将所有可停靠面板创建完成只需要将Addin文件注册一下打开revit就可以看到我们的面板
创建完成后我们需要完成在页面点击按钮可以在主界面进行选择构件并弹出相应的ID和Name 所以我们需要创建一个空闲事件进行选择 (Select) 操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public static void IdlingHandler(object sender, Autodesk.Revit.UI.Events.IdlingEventArgs args) { UIApplication uiapp = sender as UIApplication; if (uiapp != null) { Autodesk.Revit.UI.UIDocument uidoc = uiapp.ActiveUIDocument; Autodesk.Revit.DB.Document doc = uidoc.Document; if (uidoc != null && doc != null) { Reference re = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, ""); Element e = doc.GetElement(re); System.Windows.Forms.MessageBox.Show(e.Id.ToString() + e.Name); uiapp.Idling -= IdlingHandler; } } else { System.Windows.Forms.MessageBox.Show("Must Get should Idling!"); } }
此处有一个问题:此时WPF窗体作为一个独立进程无法与Revit进行直接交互,如果直接 应用空闲事件 会发现系统报错API不可调用,此处困扰了我很久,而且还去stackflow提问,问题链接 这次竟然是jimmy回复了我,可以通过外部事件与空闲事件进行调用命令并进行数据传递。
外部事件(ExternalEvent) 博客上外部事件的文章很多,这里我就直接写代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class ExternalHander : IExternalEventHandler { public void Execute(UIApplication app) { ThisApplication.thisApp.AddIdlingEvent(app); } public string GetName() { return "ExternalHander.Excute()"; } }
关于这个接口可以参照thebuildingcoder 里面由对于这个接口和Idling事件的解释 之后我们只需要将空闲事件嵌套进外部事件便可以执行命令