找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1192|回复: 6

[教学] 让LISP控制WINDOWS消息循环(给ACAD注入钩子)监控键盘鼠标消息

[复制链接]

已领礼包: 145个

财富等级: 日进斗金

发表于 2018-1-8 14:13:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
关于WINDOWS系统的消息循环可以网络搜索,参考文献。


WINDOWS系统的所有软件都是通过消息循环和系统交互,我们按下键盘或者移动鼠标,WINDOWS系统会把消息发送到AUTOCAD,AUTOCAD接受消息处理并返回信息给系统。


那AUTOCAD接受到的系统键盘消息,通过ARX的钩子相关函数,可以截获,这个消息应用程序处理后可以继续传给AUTOCAD后续操作,也可以截获,让AUTOCAD不知道有这个“消息”过来,AUTOCAD也就不能继续响应消息然后操作。
一般的钩子函数定义如下:
  1. BOOL HOOK(MSG *pMsg)
  2. {
  3.         switch(pMsg->message){
  4.         case WM_KEYDOWN:
  5.         case WM_SYSKEYDOWN:
  6.                 if (...)
  7.                 {
  8.                         return TRUE; // TRUE 截获消息,不让AUTOCAD继续处理。
  9.                 }
  10.                 break;
  11.         }
  12.         return FALSE;// 返回FALSE,AUTOCAD可以继续接受该消息
  13. }


那A/VLISP能不能也截获消息处理呢,不能,LISP没提供这样的功能。

下面通过XDRX API提供给LISP的自定义函数,来完成上面的操作。

API提供的“钩子”相关的函数有:
  1. xdrx-hook-register
  2. xdrx-hook-enable
  3. xdrx-hook-status
  4. xdrx-hook-remove
  5. xdrx-hook-tracemouse
  6. xdrx-hook-block-messageloop
  7. xdrx-system-keystate
  8. xdrx-system-ctrl-down
  9. xdrx-system-ctrl-shift-down
  10. xdrx-system-ctrl-alt-shift-down
  11. xd::hook:register
  12. xd::hook:enable
  13. xd::hook:remove


xdrx-hook-block-messageloop函数的作用相当于上面说的return TRUE,终止消息继续给AUTOCAD。

LISP的典型钩子回调函数结构如下:

  1. (defun hook (hwnd msg wparam lparam time pos)
  2. ;|
  3. hwnd -- 窗口句柄
  4. msg --- 消息
  5. wparam -- 主参数
  6. lparam ---- 第二参数
  7. time ------- 发生时间
  8. pos  ------- 鼠标屏幕坐标
  9. |;

  10.   (cond        ((= msg WM_KEYUP)                ;按键抬起
  11.         )
  12.         ((= msg WM_KEYDOWN)                ;键按下
  13.          (setq txt (chr wparam))
  14.         )
  15.         ((= msg WM_SYSKEYDOWN))                ;系统键按下
  16.         ((= msg WM_CHAR)
  17.         )
  18.         ((= msg WM_MOUSEWHEEL)                ;拨动滚轮
  19.         )
  20.         ((= msg WM_LBUTTONUP)                ;鼠标左键弹起
  21.         )
  22.         ((= msg WM_LBUTTONDOWN)                ;鼠标左键按下
  23.         )
  24.         ((= msg WM_LBUTTONDBLCLK)        ;鼠标左键双击
  25.         )
  26.         ((= msg WM_RBUTTONUP)                ;鼠标右键弹起
  27.         )
  28.         ((= msg WM_RBUTTONDOWN)                ;鼠标右键按下
  29.         )
  30.         ((= msg WM_RBUTTONDBLCLK)        ;鼠标右键双击
  31.         )
  32.         ((= msg WM_MBUTTONUP)                ;鼠标中键弹起
  33.         )
  34.         ((= msg WM_MBUTTONDOWN)                ;鼠标中键按下
  35.         )
  36.         ((= msg WM_MBUTTONDBLCLK)        ;鼠标中键双击
  37.         )
  38.         ((= msg WM_MOUSEMOVE)                ;鼠标移动
  39.         )
  40.         ((= msg WM_PAINT)                ;屏幕绘制
  41.         )
  42.         ((= msg WM_HOTKEY)                ;热键
  43.         )
  44.         ((= msg WM_INPUT)                ;输入
  45.         )
  46.         ((= msg WM_VSCROLL)                ;屏幕滚动
  47.         )
  48.   )
  49. )



下面通过一个ODCL的捕获鼠标热键的程序说明:
下面程序会把键盘的按键,包括CTRL,SHIFT,ALT和字母键的组合,实时写到文本框里面。

HOOK.gif

  1. (defun c:tt ()
  2.   (setq        odcl-data
  3.          '("YWt6A2YXAAAh3q+ZBuKTJsUwKi9qI/1OYh86Xl9frzx8ON3ysnVmUlK6Jtb29vdoaHSydoxmezrS"
  4. "zu26uLTmFh8Xn02Pa1XdcwgC/mE+nNVNeOsP4U0OYRVmUFYev6KaoEeVQohAGZHLqZss4OA1hb32"
  5. "XvRmZK96v4RQkzt03ZY5fKlu6ghxxE9+Yf6XHN46AIvKxNonZOif+jIW6Ndfursu3cocrGlo7T+X"
  6. "97byUBdLdXA3AXEk3qO42tk1KGTJFxNPUIOZ20EUKInmSx8nrRtSWBtSX9NoZxFIgOwcQxgusqYS"
  7. "5KHzYX/DJU/keNTfAla+glsQ9HC15/hPVu2ralRpOJjZ1u1W+p0sbZiamORv/ZTg5rEiQE8orfOD"
  8. "JkIec85jq9xjPRbrbXK3Jjw4JZswHzqklMm1nIjBy9a4IgjI07Lwy+U0hcJBiodBxNI8I1uCtOAR"
  9. "nIv8jjW8sXeBWgWd+oNASYAbmTllLEkuElspmdlIGcyh37bPbjTvm3HQ6y7Fk+PA6EXON2Alc9IZ"
  10. "MOvg7K7zNdZxnPRCObuXLnAAaz4nGRHJQyoVkglnU77Tp3ArOsVyxpwty+6b6hpH9rWcwDGipSeT"
  11. "7fKJ5dQtMfensXZB37ZBWIL2jj28W+rnX6kXfBOWunDHBXMledoDNuBp3lAklUwHN29gytyahdBN"
  12. "ojGdffpHsetqm6XKsVQFQtqPd2UxFALtsKc/jZkSgbigKaSxaVVw54vh9hmhko3nh+FTOBkOY9Oh"
  13. "F4XhrJ25F0E517zwbxBdAvpOApCGxpUcDUilqlD01t0MsLZjro9VTY5+KfDMVVlbwU8ab+AXucpS"
  14. "XbKXGQROA+YgMkHYGWmH5VoC5A78Tq2XUJ/NUCLfdQIyGgCmbJUw96bW744QN742SL/Cdpc7Tlga"
  15. "7AiW3xRzuvhuH7llCyh5wq40Jhii3/StZFHfJRhAlTD7E7GyIdBww8+DAK+F9O0hUWOnNZnW3Idw"
  16. "I8fRD0OrI+6OYMyB4IitP4gVNimIR6CabbaoY/nw6r3TXU0me2MX34PEC9oO/6o11/moId1gJXKK"
  17. "LPEWIEMM1DkSndf5AImaqx2Tq72C65ou8TUmUYv2UzFDfHgE1zla0WBHq13Ej6qdRIyUH6clPYtG"
  18. "eckEor8E1zkKB5QvFN7pBAYBk9FcSWEWshybuytoVdGRhauciBQBoQWrtDTBgccIJionCicagcuo"
  19. "JuonysMU7zviFU3Z1jkM98QpS4G5gQa6nyj1ySaaW89QlG+PKnEDg39nvMRW")
  20.   )
  21.   (defun c:hook-quit#OnClicked (/)
  22.     (xd::hook:remove "_hook-1")
  23.     (dcl-form-close hotkey-odcl/Form1)
  24.     (princ)
  25.   )
  26.   (defun c:hotkey-odcl/Form1#OnClose (UpperLeftX UpperLeftY /)
  27.     (xd::hook:remove "_hook-1")
  28.     (dcl-form-close hotkey-odcl/Form1)
  29.     (princ)
  30.   )
  31.   (defun c:hotkey-odcl/Form1#OnCancelClose (Reason /)
  32.     (xd::hook:remove "_hook-1")
  33.     (dcl-form-close hotkey-odcl/Form1)
  34.     (princ)
  35.   )
  36.   (defun c:hotkey-odcl/Form1#OnCancel (/)
  37.     (xd::hook:remove "_hook-1")
  38.     (dcl-form-close hotkey-odcl/Form1)
  39.     (princ)
  40.   )

  41.   (defun c:var1#OnSetFocus (/)
  42.     (setq #var-name (dcl-Control-GetProperty var1 "VarName"))
  43.   )
  44.   (defun c:var2#OnSetFocus (/)
  45.     (setq #var-name (dcl-Control-GetProperty var2 "VarName"))
  46.   )
  47.   (defun c:var3#OnSetFocus (/)
  48.     (setq #var-name (dcl-Control-GetProperty var3 "VarName"))
  49.   )
  50.   (defun c:var4#OnSetFocus (/)
  51.     (setq #var-name (dcl-Control-GetProperty var4 "VarName"))
  52.   )
  53.   (defun _hook-1 (hwnd msg wparam lparam time pos)
  54.     (and (dcl-Form-IsActive hotkey-odcl/Form1)
  55.          (cond ((= msg WM_KEYDOWN)
  56.                 (if (and (> wparam 46)
  57.                          (< wparam 91)
  58.                          (/= "" #var-name)
  59.                     )
  60.                   (progn
  61.                     (setq txt (chr wparam))
  62.                     (cond
  63.                       ((xdrx-system-ctrl-down)
  64.                        (dcl-Control-SetText
  65.                          (eval (read #var-name))
  66.                          (strcat "CTRL+" txt)
  67.                        )
  68.                       )
  69.                       ((xdrx-system-shift-down)
  70.                        (dcl-Control-SetText
  71.                          (eval (read #var-name))
  72.                          (strcat "SHIFT+" txt)
  73.                        )
  74.                       )
  75.                       ((xdrx-system-ctrl-shift-down)
  76.                        (dcl-Control-SetText
  77.                          (eval (read #var-name))
  78.                          (strcat "CTRL+SHIFT+" txt)
  79.                        )
  80.                       )
  81.                       ((xdrx-system-ctrl-alt-shift-down)
  82.                        (dcl-Control-SetText
  83.                          (eval (read #var-name))
  84.                          (strcat "CTRL+ALT+SHIFT+" txt)
  85.                        )
  86.                       )
  87.                     )
  88.                     (xdrx-hook-block-messageloop t) ;;阻断该消息让AUTOCAD继续处理。
  89.                   )
  90.                 )
  91.                )
  92.                (T)
  93.          )
  94.     )
  95.   )
  96.   (setq #var-name "")
  97.   (xd::hook:register "_hook-1" t "dd")
  98.   (dcl-project-import odcl-data "123456")
  99.   (dcl-Form-Show hotkey-odcl/Form1)
  100.   (princ)
  101. )


论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 8611个

财富等级: 富甲天下

发表于 2018-1-8 16:09:52 | 显示全部楼层
早就希望有这个功能了,这样可以对按下的键进行捕获
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 812个

财富等级: 财运亨通

发表于 2018-1-9 08:08:09 | 显示全部楼层
感谢楼主分享
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 8个

财富等级: 恭喜发财

发表于 2018-6-20 12:15:28 | 显示全部楼层
非常好,辛苦了                                                                              
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2021-1-11 11:36:07 | 显示全部楼层
多谢分享
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复

使用道具 举报

发表于 2022-5-27 19:24:06 | 显示全部楼层
(defun hook (hwnd msg wparam lparam time pos)
hwnd -- 窗口句柄
msg --- 消息,
大佬msg这个传入参数,怎么获取到
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 47个

财富等级: 招财进宝

发表于 2022-12-17 15:54:18 | 显示全部楼层
本帖最后由 pxt2015 于 2022-12-17 15:57 编辑

钩子应用例子,光ctrl,alt.shift组合有啥意思,以下截图为网友arx开发的“单键快捷”工具,
可以设置键盘的箭头按键,F1-F12功能键,PageDown按键,也就是将键盘按键一网打尽
版主能否给一个示例
单键快捷.png
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-3-29 18:26 , Processed in 0.396350 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表