阅读本文章前应具有一定编程基础和 Window API 相关知识


第一步,先封装HookBase抽象类,因所有Hook的都具有注册、卸载逻辑,且注册、卸载大同小易。如下:

 public abstract class HookBase : IHook{private static Dictionary<int, IHook> m_Hooks;private IntPtr m_ProcessId;private int m_ThreadId;private HookType m_HookType;private HookProc m_HookProc;protected internal int m_HookId;static HookBase(){m_Hooks = new Dictionary<int, IHook>();}private HookBase(HookType hookType){m_HookType = hookType;m_HookProc = HookProc;}protected HookBase(IntPtr processId, HookType hookType): this(hookType){m_ProcessId = processId;if (m_ProcessId == IntPtr.Zero){m_ProcessId = HookHelper.GetCurrentProcessId();}}protected HookBase(int threadId, HookType hookType): this(hookType){m_ThreadId = threadId;if (m_ThreadId == 0){m_ThreadId = HookHelper.GetCurrentThreadId();}}public void Install(){if (m_ThreadId != 0){m_HookId = HookHelper.SetWindowsHookEx(m_HookType, m_HookProc, IntPtr.Zero, m_ThreadId);}else{if (m_ProcessId == IntPtr.Zero){return;}m_HookId = HookHelper.SetWindowsHookEx(m_HookType, m_HookProc, m_ProcessId, 0);}if (m_HookId == 0){return;}if (!m_Hooks.ContainsKey(m_HookId)){m_Hooks.Add(m_HookId, this);}}public void Uninstall(){if (m_HookId == 0){return;}var flag = HookHelper.UnhookWindowsHookEx(m_HookId);if (flag){if (m_Hooks.Remove(m_HookId)){m_HookId = 0;}}}protected abstract int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

第二步 ,因鼠标Hook分为线程鼠标Hook以及全局鼠标Hook两种,仅注册方式有点区别。为使用方便,将其封装为事件注册方式。如下

 public abstract class MouseHookBase : HookBase{protected MouseHookBase(IntPtr processId): base(processId, HookType.WH_MOUSE_LL){}protected MouseHookBase(int threadId): base(threadId, HookType.WH_MOUSE){}/// <summary>/// 鼠标双击/// </summary>public event HookHandler<MouseEventArgs> MouseDoubleClick;/// <summary>/// 鼠标移动/// </summary>public event HookHandler<MouseEventArgs> MouseMove;/// <summary>/// 鼠标按下/// </summary>public event HookHandler<MouseEventArgs> MouseDown;/// <summary>/// 鼠标弹起/// </summary>public event HookHandler<MouseEventArgs> MouseUp;protected override int HookProc(int nCode, IntPtr wParam, IntPtr lParam){if (nCode < 0){return HookHelper.CallNextHookEx(m_HookId, nCode, wParam, lParam);}var mouseMsg = (MouseMessage)wParam.ToInt32();var mouseHookStruct = lParam.ToStruct<MOUSEHOOKSTRUCT>();var button = this.GetMouseButtons(mouseMsg);switch (mouseMsg){case MouseMessage.WM_LBUTTONDOWN:case MouseMessage.WM_RBUTTONDOWN:case MouseMessage.WM_MBUTTONDOWN:return this.OnRaiseMouseDown(button, 1, mouseHookStruct.pt.X, mouseHookStruct.pt.Y, mouseHookStruct.mouseData);case MouseMessage.WM_LBUTTONUP:case MouseMessage.WM_MBUTTONUP:case MouseMessage.WM_RBUTTONUP:return this.OnRaiseMouseUp(button, 1, mouseHookStruct.pt.X, mouseHookStruct.pt.Y, mouseHookStruct.mouseData);case MouseMessage.WM_LBUTTONDBLCLK:case MouseMessage.WM_RBUTTONDBLCLK:case MouseMessage.WM_MBUTTONDBLCLK:return this.OnRaiseMouseDoubleClick(button, 2, mouseHookStruct.pt.X, mouseHookStruct.pt.Y, mouseHookStruct.mouseData);case MouseMessage.WM_MOUSEMOVE:return this.OnRaiseMouseMove(MouseButtons.None, 0, mouseHookStruct.pt.X, mouseHookStruct.pt.Y, mouseHookStruct.mouseData);default:return HookHelper.CallNextHookEx(m_HookId, nCode, wParam, lParam);}}private MouseButtons GetMouseButtons(MouseMessage mouseMsg){MouseButtons result = MouseButtons.None;switch (mouseMsg){case MouseMessage.WM_LBUTTONDBLCLK:case MouseMessage.WM_LBUTTONDOWN:case MouseMessage.WM_LBUTTONUP:result = MouseButtons.Left;break;case MouseMessage.WM_MBUTTONDBLCLK:case MouseMessage.WM_MBUTTONDOWN:case MouseMessage.WM_MBUTTONUP:result = MouseButtons.Middle;break;case MouseMessage.WM_RBUTTONDBLCLK:case MouseMessage.WM_RBUTTONDOWN:case MouseMessage.WM_RBUTTONUP:result = MouseButtons.Right;break;}return result;}private int OnRaiseMouseDoubleClick(MouseButtons button, int clicks, int x, int y, int delta){if (this.MouseDoubleClick != null){return this.MouseDoubleClick(this, new MouseEventArgs(button, clicks, x, y, delta));}return 0;}private int OnRaiseMouseDown(MouseButtons button, int clicks, int x, int y, int delta){if (this.MouseDown != null){return this.MouseDown(this, new MouseEventArgs(button, clicks, x, y, delta));}return 0;}private int OnRaiseMouseUp(MouseButtons button, int clicks, int x, int y, int delta){if (this.MouseUp != null){return this.MouseUp(this, new MouseEventArgs(button, clicks, x, y, delta));}return 0;}private int OnRaiseMouseMove(MouseButtons button, int clicks, int x, int y, int delta){if (this.MouseMove != null){return this.MouseMove(this, new MouseEventArgs(button, clicks, x, y, delta));}return 0;}}

第三步,依次实现线程鼠标Hook以及全局鼠标Hook.

    /// <summary>/// 线程鼠标Hook./// </summary>/// <seealso cref="DotNet.Hook.Achieve.MouseHookBase" />public class MouseHook : MouseHookBase{public MouseHook(int threadId = 0): base(threadId){}}/// <summary>/// 全局鼠标钩子/// </summary>/// <seealso cref="DotNet.Hook.Achieve.MouseHookBase" />public class GlobalMouseHook : MouseHookBase{public GlobalMouseHook(IntPtr processId): base(processId){}}

第四步,有了鼠标Hook,我们如果在Revit内使用并且拦截鼠标双击元素事件呢?我们继续封装一个元素监控类 ,如下:

    /// <summary>/// 元素监控./// </summary>public class ElementMonitor{private static ElementMonitor m_Instance;private MouseHook m_MouseHook;private bool m_IsMonitor;private UIApplication m_UIApplication;private ElementMonitor(UIApplication uiApp){m_Instance = this;m_UIApplication = uiApp;m_MouseHook = new MouseHook();m_MouseHook.Install();m_MouseHook.MouseDoubleClick += OnRaiseMouseDoubleClick;}/// <summary>/// 静态实例,可在入口类判断此实例是否为null,防止重复注册./// </summary>public static ElementMonitor Instance{get{return m_Instance;}}/// <summary>/// 当鼠标双击元素时触发此事件./// </summary>public event HookHandler<DoubleClickElementEventArgs> DoubleClickElement;/// <summary>/// 注册元素监控,并指定是否立即监控./// </summary>public static void Register(UIApplication uiApp, bool immediatelyMonitor = true){if (uiApp == null){throw new ArgumentNullException(nameof(uiApp));}new ElementMonitor(uiApp){m_IsMonitor = immediatelyMonitor};}/// <summary>/// 注册元素监控,并指定是否立即监控./// </summary>public static void Register(UIControlledApplication uiControllApp, bool immediatelyMonitor = true){if (uiControllApp == null){throw new ArgumentNullException(nameof(uiControllApp));}var flag = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod;var uiApp = (UIApplication)uiControllApp.GetType().InvokeMember("getUIApplication", flag, Type.DefaultBinder, uiControllApp, null);Register(uiApp, immediatelyMonitor);}/// <summary>/// 返回1,则拦截鼠标消息,返回0则传递给真正消息接收者./// </summary>private int OnRaiseMouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e){if (!m_IsMonitor || e.Button != MouseButtons.Left || e.Clicks != 2){return 0;}var uiDoc = m_UIApplication.ActiveUIDocument;if (uiDoc == null){return 0;}var elemIds = uiDoc.Selection.GetElementIds();if (elemIds.Count == 1){var elem = uiDoc.Document.GetElement(elemIds.First());if (elem == null){return 0;}if (this.DoubleClickElement == null){return 0;}return this.DoubleClickElement(this, new DoubleClickElementEventArgs(elem));}return 0;}}

第五步,调用测试,如下

    [Transaction(TransactionMode.Manual)]public class MouseHookTest : IExternalCommand{Result IExternalCommand.Execute(ExternalCommandData commandData, ref string message, ElementSet elements){if (ElementMonitor.Instance == null){ElementMonitor.Register(commandData.Application);}ElementMonitor.Instance.DoubleClickElement += OnRaiseDoubleClickElement;return Result.Succeeded;}private int OnRaiseDoubleClickElement(object sender, DoubleClickElementEventArgs e){if (e.Element == null){return 0;}System.Windows.Forms.MessageBox.Show(string.Format("双击击元素Id: {0}", e.Element.Id));return 1;}}

Github 源码 : https://github.com/HeZhongHao/DotNet.Revit/tree/master/DotNet.Revit/DotNet.Revit.Hook

Revit API Hook 之 拦截鼠标双击元素事件相关推荐

  1. html 左键右键双击事件,html中在鼠标双击元素时触发的事件属性ondblclick

    实例Copy Text 浏览器支持 IE Firefox Chrome Safari Opera 所有主流浏览器都支持 ondblclick 属性. 定义和用法 ondblclick 属性在鼠标双击元 ...

  2. C#联合Halcon 自定义控件鼠标双击响应事件

    自定义控件鼠标双击响应事件 1. halcon的自定义控件 2. HMouseDown事件 1. halcon的自定义控件 这两天做项目发现一个问题,halcon自带的控件hWindowControl ...

  3. MFC鼠标单击截获鼠标双击事件,且无法记录单击的数据的解决方案

    遇到的问题: 鼠标点击会截断鼠标双击的事件,无法保存椭圆的数据.也就是说双击执行的过程是OnLButtonDown,OnLButtonUp,OnLButtonDblClk,OnLButtonUp.并不 ...

  4. Unity 鼠标连续双击执行事件

    以下代码为鼠标双击执行事件的方法. using System; using UnityEngine;public class DoubleClickMouseButton : MonoBehaviou ...

  5. win32中如何区别“鼠标单击”和 “鼠标双击”

    今天在编写一个win32的程序时,遇到了一个问题,那就是在我响应鼠标双击这个事件时,先响应了鼠标单击这个事件.于是下决心解决这个问题.后来才明白,鼠标双击是由两次鼠标的单击组成的,只不过windows ...

  6. JavaScript鼠标点击事件

    鼠标事件指通过鼠标触发事件, 类似用户的行为: Onclick:当单击鼠标时运行脚本 Ondblclick:当双击鼠标时运行脚本 Onmousedown:当按下鼠标按钮时运行脚本 onmousemov ...

  7. Hook技术之API拦截(API Hook)

    一.关于API Hook API Hook可以通过Hook指定的消息和API来实现进程隐藏,文件隐藏,端口隐藏等. 通过拦截进程API来隐藏进程,通过拦截文件读写API来隐藏文件,通过拦截网络相关AP ...

  8. Revit API:楼梯元素 Run、Landing、Support

    前言 Revit 目前仅能创建组合楼梯,即所有楼梯都必须是梯段(Run).平台(Landing)以及支撑(Support)组成.另外,栏杆扶手可以附着在它上面. 梯段 - Run 通过 API,可以创 ...

  9. API HOOK 金山词霸取词功能原理1

    http://blog.csdn.net/alentam/article/details/2217566 1 屏幕抓词     屏幕抓词(或者叫动态翻译)是指随着鼠标的移动,软件能够随时获知屏幕上鼠标 ...

最新文章

  1. android常用命令
  2. select2 使用
  3. 请教context:component-scan/和mvc:annotation-driven/的区别20
  4. 前端学习(2):什么是html和css
  5. php实现数字英文验证码,PHP英文数字验证码生成类
  6. PKI与证书服务应用-要点总结
  7. linux目录与文件,Linux目录与文件基本操作
  8. Rootkit Hacking Technology Defence Strategy Research
  9. 古墓丽影10linux,《古墓丽影:崛起》推出Linux系统版:Ubuntu 17.10可玩
  10. MyBatisCodeHelper-Pro2.8.2
  11. 共享文件 服务器存储空间不足,Win7 文件共享报错 存储空间不足,无法处理此命令...
  12. 深入浅出Mybatis-改造Cache
  13. 5福最多多少钱_2018支付宝集5福攻略介绍 一天内集齐不是没可能
  14. Android项目实战--【谁是歌手-逻辑实现篇】
  15. 案例研究:设计令人震撼的名片!
  16. 大数据培训技术使用spark对phoenix的读写
  17. 浪潮nf5280m5使用U盘安装win2012
  18. hexo博客提交百度和谷歌收录
  19. Chrome通过ARChon插件加载运行Android应用
  20. Ubuntu12.04 Rhythmbox 乱码

热门文章

  1. 纳因特机器人综合技能编程模拟器_机器人组装模拟器官方下载_机器人组装模拟器apk安卓版下载v1.0.10_3DM手游...
  2. 异常(Exception)与错误(Error)
  3. mac输入拼音的方法
  4. 将绿色计算进行到底,蚂蚁集团四大硬核黑科技全公开
  5. 蓝奥声核心技术分享——基于物联网的无线智能标签刷新控制技术
  6. 直方图(亮度)正规化及直方图均衡化
  7. python找曲线拐点_4-曲线拐点模型分析
  8. 绘制一条透明背景的trace,并保存;
  9. stata面板数据gmm回归_STATA面板数据回归解读.ppt
  10. win11下Jenkins安装及配置