使用钩子(Hook)实现Revit API中 PickObjects 完成按钮的触发

简介: 使用钩子(Hook)实现Revit API中 PickObjects 完成按钮的触发

在实际的Revit 二次开发项目中,经常需要与Revit 模型元素进行交互,那么除了借助于过滤器来获取对应元素之外,直接拾取元素(PickObjects 函数)也是常见的一种方式。然而在多选操作中,如果不是熟手,很容易找不到多选完成的按钮(其位置见图1,确实显得不起眼)。20200310161356167.png

图1

在Windows中,提供一种Hook机制,中文里常常被译作“钩子”或者“挂钩”,可以把Hook理解为Windows操作系统消息处理机制的一个平台;应用程序可以通过设置Hook对某个进程或窗口进行监视,即:对特定事件“挂钩”;一旦预定义特定事件发生,Windows操作系统即会向钩子hook发送通知消息,这时,应用程序可进行响应。


接下来我们来使用钩子自动实现点击多选操作中“完成”的按钮!


Step 1

首先我们在NuGet 中安装如图的工具包(MouseKeyHook);

20200310142423267.png


 Step 2

安装各种钩子;

    public static class WindowsHelper
    {
        [DllImport("user32.dll", CharSet = CharSet.None, ExactSpelling = false)]
        public static extern bool EnumChildWindows(IntPtr hwndParent, CallBack lpEnumFunc, IntPtr lParam);
        public delegate bool CallBack(IntPtr hwnd, int lParam);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpText, int nCount);
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
        [DllImport("user32.dll", EntryPoint = "SendMessageA")]
        public static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam);
    }


Step 3

注册鼠标和键盘监视事件,作者添加了一个右键的鼠标事件和一个空格的键盘事件;

        public void Subscribe()
        {
            // Note: for the application hook, use the Hook.AppEvents() instead
            m_GlobalHook = Hook.GlobalEvents();
            m_GlobalHook.KeyUp += GlobalHookKeyUpExt;
            m_GlobalHook.MouseUpExt += GlobalHookMouseUpExt;
        }
        private void GlobalHookMouseUpExt(object sender, MouseEventExtArgs e)
        {
            if (e.Button == MouseButtons.Right) { CompleteMultiSelection(); }
        }
        private void GlobalHookKeyUpExt(object sender, KeyEventArgs e)
        {
            // 32 represent Space
            if (e.KeyValue == 32) { CompleteMultiSelection(); }
        }

Step 4

获取Revit 主窗体下的所有句柄,找到“完成”按钮并发送Click消息;

        private void CompleteMultiSelection()
        {
            var rvtWindow = Autodesk.Windows.ComponentManager.ApplicationWindow;
            var list = new List<IntPtr>();
            var flag = WindowsHelper.EnumChildWindows(rvtWindow,
                       (hwnd, l) =>
                       {
                           StringBuilder windowText = new StringBuilder(200);
                           WindowsHelper.GetWindowText(hwnd, windowText, windowText.Capacity);
                           StringBuilder className = new StringBuilder(200);
                           WindowsHelper.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();
            WindowsHelper.SendMessage(complete, 245, 0, 0);
        }

Step 5

注销监视事件。

        public void Unsubscribe()
        {
            m_GlobalHook.MouseUpExt -= GlobalHookMouseUpExt;
            m_GlobalHook.KeyUp -= GlobalHookKeyUpExt;
            //It is recommened to dispose it
            m_GlobalHook.Dispose();
        }

Step 6

功能测试!


image.png


问题

运行钩子程序之后,图2的区域的按钮失效,无法关闭当前窗口,也无法实现ViewCube功能!

经多次尝试,需右击Revit模型显示区域,点击“取消”,即可恢复操作!


2020031016484678.png


参考资料:

钩子让PickObjects功力大增—BIMCoder梁老师

Revit二次开发番外篇之改变PickObjects完成按钮的触发

各个键盘按键KeyValue值


相关文章
|
1月前
|
安全 API
触发式邮件邮箱API发送邮件的步骤
触发式邮件邮箱API是自动化邮件发送的高效工具,如AokSend、Mailgun和蜂邮EDM等提供此类服务。主要步骤包括:选择服务提供商、注册获取API密钥、配置触发事件(如用户注册或下单)、编写邮件模板及调用API发送邮件。使用时注意遵循服务提供商规则,保证安全可靠性。
|
24天前
|
API 开发者
触发式邮件邮箱API发送邮件的方法和步骤
触发式邮件API如Aoksend让开发者能基于特定事件自动发送邮件。选择邮箱提供商(如Aoksend、Mailgun、AWS SES),注册并获取API密钥,设置权限和验证。编写代码调用API(示例代码提供),并在用户注册、订单处理等事件触发时发送邮件,提升效率和准确性。
|
4月前
|
监控 JavaScript 前端开发
这个 hook api,是 useState 的双生兄弟
这个 hook api,是 useState 的双生兄弟
|
6月前
|
JSON API 数据格式
Spartacus 6.0 baseSites API 的准确触发位置
Spartacus 6.0 baseSites API 的准确触发位置
31 0
|
7月前
|
API 定位技术 数据库
低代码平台里如何通过按钮调用 API 请求
低代码平台里如何通过按钮调用 API 请求
116 0
|
11月前
|
JavaScript API
Vue3 —— 常用 Composition API(二)(hook 函数、toRef 和 toRefs)
Vue3 —— 常用 Composition API(二)(hook 函数、toRef 和 toRefs)
Revit API获取链接模型状态
Revit API获取链接模型状态
快速设置Revit模型材质(Dynamo和API)
快速设置Revit模型材质(Dynamo和API)
快速设置Revit模型材质(Dynamo和API)