本帖最后由 yxp 于 2018-5-12 14:30 编辑
利用 DynamicWrapperX 插件,可以在 LISP 里使用系统 DLL,Windows 系统自带了大量的 MFC 基础类库,每个库文件又包含了很多函数,据说连微软自己都不知道有多少 API 函数。
下面代码将演示用 lisp 控制 API 后台打开一个记事本,激活记事本窗口,模拟按键输出字符。
- ;;by: yxp 2018/04/12
- ;;Windows API 在 lisp 中应用示例 2
- ;;演示: 打开一个记事本,使记事本窗口在最前,并向记事本输出一段文字
- (defun c:outputtext( / *CAD* *dwg* hCAD DWX jsb)
- ;;变量初始化
- (setq *CAD* (vlax-get-acad-object) ;;当前打开的 CAD 对象
- *dwg* (vla-get-ActiveDocument *CAD*) ;;当前激活的 dwg 文档对象
- hCAD (vla-get-hwnd *CAD*) ;;顶层 CAD 对象句柄
- hdwg (vla-get-hwnd *dwg*) ;;当前 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")
- ;;后台启动一个记事本,但不显示,用参数 0
- ;;注意,记事本和 CAD 是兄弟关系,不是父子关系
- (vlax-invoke DWX 'ShellExecuteW hCAD "open" "notepad" "" "" 0)
- (setq jsb (get-fun-hand hCAD "*记事本")) ;;获取记事本进程的句柄
- (if (= jsb 0) (princ "\n记事本未启动。"))
- (vlax-invoke DWX 'SetWindowTextW jsb "虚拟按键演示中...")
- ;;SetWindowPos 激活记事本并获取焦点, 各参数如下
- ;; -1 将窗口置于所有非顶层窗口之上
- ;; 300 左边界距离, 200 顶边界距离
- ;; 500 指定窗口宽度像素, 400 高度像素
- ;; 64 立即显示窗口
- (vlax-invoke DWX 'SetWindowPos jsb -1 300 200 500 400 64)
- (if (zerop (vlax-invoke DWX 'GetKeyState 20))(progn
- (vlax-invoke DWX 'keybd_event 20 0 0 0) ;;CAPS LOCK 键按下
- (vlax-invoke DWX 'keybd_event 20 0 2 0) ;;CAPS LOCK 键弹起
- ))
- (foreach x (vl-string->list "HOW ARE YOU FINE THANKS")
- (vlax-invoke DWX 'keybd_event x 0 0 0) ;;模拟键按下
- (vlax-invoke DWX 'keybd_event x 0 2 0) ;;模拟键弹起
- (vlax-invoke DWX 'Sleep 300) ;;系统等待 0.3 秒
- (vlax-invoke DWX 'Beep 800 30) ;;发出按键声
- )
- (vlax-invoke DWX 'SetWindowTextW jsb "演示完毕!")
- (princ)
- )
- ;;返回某程序最近打开的一个兄弟程序句柄,参数为标题
- ;; GetWindow 5 第一个子窗口 0 第一个兄弟窗口 2 下一个窗口
- (defun get-fun-hand(h s / x)
- (vlax-invoke DWX 'Register "user32" "GetWindow" "i=mm" "r=m")
- (setq x (vlax-invoke DWX 'GetWindow h 0))
- (while (and (/= x 0)(null (wcmatch (get-fun-txt x) s)))
- (setq x (vlax-invoke DWX 'GetWindow x 2))
- ) x
- )
- ;;获取某程序或控件的标题内容,参数为句柄
- ;;(get-fun-txt 1378520)
- (defun get-fun-txt(h / ss pStr)
- (vlax-invoke DWX 'Register "user32" "GetWindowTextW" "i=hpm" "r=m")
- (setq ss (vlax-invoke DWX 'Space 256 " "))
- (setq pStr (vlax-invoke DWX 'StrPtr ss))
- (vlax-invoke DWX 'GetWindowTextW h pStr 256)
- (vlax-invoke DWX 'strget pStr)
- )
利用 DynamicWrapperX 多少可以弥补一下 lisp 的弱点,例如:对指针的控制、多线程操作、执行高效的汇编代码等。
DynamicWrapperX 下载链接详见 http://bbs.mjtd.com/thread-176996-1-1.html 5楼
有兴趣的同学可以用 DWX 来引用 RAR 公司提供的 dll,这样可以用 lisp 调用 rar 函数进行压缩或解包,即使在系统里有没有安装 WinRAR 都无所谓了。 |