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

Revit 专栏收录该内容
55 篇文章 3 订阅
关注公众号及时获取文章更新

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

图1

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

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


目录

Step 1  Step 2 Step 3Step 4Step 5Step 6 

问题

参考资料: 


 Step 1 

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

  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 

功能测试! 

本测试程序的功能为:获取所选元素的IDs

问题

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

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

图2

参考资料: 

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

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

各个键盘按键KeyValue值

  • 1
    点赞
  • 1
    评论
  • 8
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 鲸 设计师:meimeiellie 返回首页

打赏

硬核小青年

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值