明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 5649|回复: 26

[源码] LISP+DWX 之一:Windows API 调用示例

[复制链接]
发表于 2018-4-12 09:19:57 | 显示全部楼层 |阅读模式
本帖最后由 yxp 于 2018-5-12 14:30 编辑

利用 DynamicWrapperX 插件,可以在 LISP 里使用系统 DLL,Windows 系统自带了大量的 MFC 基础类库,每个库文件又包含了很多函数,据说连微软自己都不知道有多少 API 函数。

下面代码将演示用 lisp 控制 API 后台打开一个记事本,激活记事本窗口,模拟按键输出字符。

  1. ;;by:  yxp    2018/04/12
  2. ;;Windows API 在 lisp 中应用示例 2
  3. ;;演示: 打开一个记事本,使记事本窗口在最前,并向记事本输出一段文字
  4. (defun c:outputtext( / *CAD* *dwg* hCAD DWX jsb)
  5. ;;变量初始化
  6. (setq *CAD* (vlax-get-acad-object)       ;;当前打开的 CAD 对象
  7.   *dwg* (vla-get-ActiveDocument *CAD*) ;;当前激活的 dwg 文档对象
  8.   hCAD (vla-get-hwnd *CAD*)            ;;顶层 CAD 对象句柄
  9.   hdwg (vla-get-hwnd *dwg*)            ;;当前 dwg 对象句柄
  10.   DWX (vlax-get-or-create-object "DynamicWrapperX")) ;; 创建一个 DWX 对象
  11.   
  12. ;;Windows API 函数声明
  13. (vlax-invoke DWX 'Register "shell32.dll" "ShellExecuteW" "i=hwwwwl" "r=m")
  14. (vlax-invoke DWX 'Register "user32" "SetWindowTextW" "i=hw" "r=m")
  15. (vlax-invoke DWX 'Register "user32" "GetKeyState" "i=n" "r=l")
  16. (vlax-invoke DWX 'Register "user32" "keybd_event" "i=llll" "r=m")
  17. (vlax-invoke DWX 'Register "user32" "SetWindowPos" "i=hmmmmmm" "r=m")
  18. (vlax-invoke DWX 'Register "kernel32" "Beep" "i=mm" "r=m")
  19. (vlax-invoke DWX 'Register "kernel32" "Sleep" "i=m")


  20. ;;后台启动一个记事本,但不显示,用参数 0
  21. ;;注意,记事本和 CAD 是兄弟关系,不是父子关系
  22. (vlax-invoke DWX 'ShellExecuteW hCAD "open" "notepad" "" "" 0)

  23. (setq jsb (get-fun-hand hCAD "*记事本"))  ;;获取记事本进程的句柄
  24. (if (= jsb 0) (princ "\n记事本未启动。"))

  25. (vlax-invoke DWX 'SetWindowTextW jsb "虚拟按键演示中...")

  26. ;;SetWindowPos 激活记事本并获取焦点, 各参数如下
  27. ;; -1  将窗口置于所有非顶层窗口之上
  28. ;; 300 左边界距离,  200 顶边界距离
  29. ;; 500 指定窗口宽度像素,  400 高度像素
  30. ;; 64  立即显示窗口
  31. (vlax-invoke DWX 'SetWindowPos jsb -1 300 200 500 400 64)

  32. (if (zerop (vlax-invoke DWX 'GetKeyState 20))(progn
  33.   (vlax-invoke DWX 'keybd_event 20 0 0 0) ;;CAPS LOCK 键按下
  34.   (vlax-invoke DWX 'keybd_event 20 0 2 0) ;;CAPS LOCK 键弹起
  35. ))

  36. (foreach x (vl-string->list "HOW ARE YOU FINE THANKS")
  37.   (vlax-invoke DWX 'keybd_event x 0 0 0) ;;模拟键按下
  38.   (vlax-invoke DWX 'keybd_event x 0 2 0) ;;模拟键弹起
  39.   (vlax-invoke DWX 'Sleep 300)   ;;系统等待 0.3 秒
  40.   (vlax-invoke DWX 'Beep 800 30) ;;发出按键声
  41. )

  42. (vlax-invoke DWX 'SetWindowTextW jsb "演示完毕!")
  43. (princ)
  44. )



  45. ;;返回某程序最近打开的一个兄弟程序句柄,参数为标题
  46. ;; GetWindow  5 第一个子窗口  0 第一个兄弟窗口  2 下一个窗口
  47. (defun get-fun-hand(h s / x)
  48. (vlax-invoke DWX 'Register "user32" "GetWindow" "i=mm" "r=m")
  49. (setq x (vlax-invoke DWX 'GetWindow h 0))
  50. (while (and (/= x 0)(null (wcmatch (get-fun-txt x) s)))
  51.   (setq x (vlax-invoke DWX 'GetWindow x 2))
  52. ) x
  53. )


  54. ;;获取某程序或控件的标题内容,参数为句柄
  55. ;;(get-fun-txt 1378520)
  56. (defun get-fun-txt(h / ss pStr)
  57. (vlax-invoke DWX 'Register "user32" "GetWindowTextW" "i=hpm" "r=m")
  58. (setq ss (vlax-invoke DWX 'Space 256 " "))
  59. (setq pStr (vlax-invoke DWX 'StrPtr ss))
  60. (vlax-invoke DWX 'GetWindowTextW h pStr 256)
  61. (vlax-invoke DWX 'strget pStr)
  62. )




利用 DynamicWrapperX  多少可以弥补一下 lisp 的弱点,例如:对指针的控制、多线程操作、执行高效的汇编代码等。

DynamicWrapperX  下载链接详见 http://bbs.mjtd.com/thread-176996-1-1.html  5楼

有兴趣的同学可以用 DWX 来引用 RAR 公司提供的 dll,这样可以用 lisp 调用 rar 函数进行压缩或解包,即使在系统里有没有安装 WinRAR 都无所谓了。

本帖子中包含更多资源

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

x
"觉得好,就打赏"
还没有人打赏,支持一下
 楼主| 发表于 2018-4-13 10:54:20 | 显示全部楼层
本帖最后由 yxp 于 2018-4-13 11:04 编辑
669423907 发表于 2018-4-13 10:22
可以用来开启数字键 numlock (只开不关),numlock总有时候会莫名其妙的关闭,目前用vbs只开不关
'打开数 ...

用什么脚本,用 lisp 也可以啊:

  1. ;;检测 NUM LOCK 状态,如果关闭就打开。
  2. ;;将本函数加入反应器,可以使 NUM LOCK 在 CAD 运行期间一直打开。
  3. (defun c:OpenNumLock( / DWX)
  4. (setq DWX (vlax-create-object "DynamicWrapperX"))
  5. (vlax-invoke DWX 'Register "user32" "GetKeyState" "i=n" "r=l")
  6. (vlax-invoke DWX 'Register "user32" "keybd_event" "i=llll" "r=m")
  7. (if (= 0 (vlax-invoke DWX 'GetKeyState 144))(foreach x '(0 2)(vlax-invoke DWX 'keybd_event 144 0 x 0)))
  8. (princ)
  9. )


点评

好厉害的大神  发表于 2018-4-13 11:03

评分

参与人数 1明经币 +1 收起 理由
669423907 + 1 很给力!

查看全部评分

回复 支持 1 反对 0

使用道具 举报

发表于 2019-4-9 21:30:52 | 显示全部楼层
请教版主
批打印时每生成一个PDF以后
都会在PDF浏览器中打开
希望累计打印50张图纸以后
关闭PDF浏览器
避免内存占用过大

已用下面的语句获取了PDF浏览器的句柄
如何关闭就不知道怎么弄了

;;变量初始化
(setq *acad*   (vlax-get-acad-object)
         *doc*   (vla-get-ActiveDocument *acad*)
         hCAD    (vla-get-hwnd *acad*)                  ;;顶层 CAD 对象句柄
         hdwg    (vla-get-hwnd *doc*)                  ;;当前 dwg 对象句柄
         *dwx*   (vlax-get-or-create-object "DynamicWrapperX")  ;;创建一个 DWX 对象
)
;;Windows API 函数声明
(vlax-invoke *dwx* 'Register "shell32.dll" "ShellExecuteW" "i=hwwwwl" "r=m")
(vlax-invoke *dwx* 'Register "user32" "SetWindowTextW" "i=hw" "r=m")
(vlax-invoke *dwx* 'Register "user32" "GetKeyState" "i=n" "r=l")
(vlax-invoke *dwx* 'Register "user32" "keybd_event" "i=llll" "r=m")
(vlax-invoke *dwx* 'Register "user32" "SetWindowPos" "i=hmmmmmm" "r=m")
(vlax-invoke *dwx* 'Register "kernel32" "Beep" "i=mm" "r=m")
(vlax-invoke *dwx* 'Register "kernel32" "Sleep" "i=m")

(setq name "SD-51"   pdf_num 51)    ;;假定已打印50张
(setq jsb (get-fun-hand hCAD (strcat "*" name "*.pdf*")))   ;;获取PDF浏览器窗体的句柄

(if (> pdf_num 50)
(...)  ;;如何关闭PDF浏览器???
)

完全不懂VB
看帮助似乎要用到“CloseHandle”
但是下面的语句没能达到预期的目的
(vlax-invoke *dwx* 'Register "kernel32" "CloseHandle" "i=h")
(vlax-invoke *dwx* 'CloseHandle jsb)
 楼主| 发表于 2018-5-12 14:14:16 | 显示全部楼层
本帖最后由 yxp 于 2018-5-12 14:17 编辑
masterlong 发表于 2018-5-12 13:54
如何控制某个已打开窗体
已经摸到点边
首先通过窗体标题栏的文字内容

参考一下

SetWindowPos
;;参数 2:
;;                1        将窗口置于窗口列表底部
;;                0        将窗口置于Z序列的顶部;Z序列代表在分级结构中,窗口针对一个给定级别的窗口显示的顺序
;;                -1        将窗口置于列表顶部,并位于任何最顶部窗口的前面(类似 QQ 界面)
;;                -2        将窗口置于列表顶部,并位于任何最顶部窗口的后面(正常)
;;参数 34: 窗口坐标 x y
;;参数 56: 窗口大小 w h
;;参数 7:
;                1 保持当前大小
;                2 保持当前位置
;                4 保持窗口在列表的当前位置
;                8 窗口不自动重画
;                16 不激活窗口
;                32 围绕窗口画一个框
;                64 显示窗口

本帖子中包含更多资源

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

x
发表于 2018-4-12 13:19:19 | 显示全部楼层
好贴,我来沙发
发表于 2018-4-13 10:22:13 | 显示全部楼层
可以用来开启数字键 numlock (只开不关),numlock总有时候会莫名其妙的关闭,目前用vbs只开不关
'打开数字键盘 yu2n 2017-4-11 http://www.bathome.net/thread-43783-1-1.html
Set objWord = CreateObject("Word.Application")
If objWord.NumLock = False Then '<>
Set WshShell = CreateObject("WScript.shell")
WshShell.SendKeys "{NUMLOCK}" '大小写{CapsLock}
End If
objWord.Quit
Set objWord = Nothing
Set WshShell = Nothing
发表于 2018-4-13 11:49:57 | 显示全部楼层
有时会失灵,运行好多次都开不了

点评

yxp
lisp 失灵还是脚本失灵?  发表于 2018-4-13 18:58
发表于 2018-4-13 14:31:55 | 显示全部楼层
问一个问题
这种方式在win7、10里
可以控制已经打开的文件夹吗?

点评

yxp
可以  发表于 2018-4-13 19:59
发表于 2018-4-13 16:35:01 | 显示全部楼层
是挺不错的,就是太麻烦了,当然对于只用lisp的朋友 ,那是非常好的
发表于 2018-4-13 21:31:02 | 显示全部楼层
是lsp失灵,有时也会数字指示灯闪一下
发表于 2018-4-14 20:46:02 来自手机 | 显示全部楼层
文章很好,但是对于WindowsAPI不熟悉的同学去调用API还是很困难的,调用API确实弥补了lisp的不足!啥时候楼主给个多线程的例子吧!或者是非模态对话框的例子,不知道能搞的了不?
发表于 2018-4-18 07:37:52 来自手机 | 显示全部楼层
这个用不用提前设置引用什么库呢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-23 04:48 , Processed in 0.243872 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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