【飞鸟集】AutoCAD的三大程序语言(ARX,LISP,VBA)的连接
定制自己的ActiveX ,实现ARX和LISP,VBA的三方通信ActiveX技术是微软组件化开发技术的基础,AutoCAD本身就是一个ActiveX自动化服务器,它提供了一系列的activeX对象.通过这些对象的属性和方法,VBA,VisualLisp就能控制autoCAD程序。
因此我们如果在开发的OjbectARX程序中实现ActiveX自动化,就可以实现Vlisp,VBA和ARX的三方的互相通信。在某些情况下,可以为我们带来很多便利。
譬如我们的核心数据处理(数值计算,等等)由arx开发,其他容易的代码则由vlisp或者VBA实现,这样我们可以达到高效和易用性的统一。
Vlisp和VBA可以调用arx定义的类和函数,并可以得到返回值,甚至可以调用其对话框资源,等等。
下面我抛砖引玉,通过这样的一个教程,演示如何实现这样的三方通信。
这个教程的大致流程如下: 由visual C++ 开发一个MFC DLL,并在其中建立一个类,定义了两个简单的函数,生成以供lisp和VBA调用。
首先创建一个MFC DLL工程,工程名为:MyActTest:
在用向导方式创建的这步,勾选自动化(Automation)
完成文件的创建之后,记得把arx工程所需要的库文件和包含文件加入进来。
并在stdafx.h文件的末尾添加如下头文件:
#include "arxHeaders.h"// 为objectARX应用添加
然后用向导方式创建一个MFC类。
这个类的名字叫CActTest,基类为CCmdTarget,在自动化(automation)中勾选可按类型ID创建(Createable by type ID)
然后按OK.
为这个类添加你自己定制的成员函数。我在这里定义了两个简单的函数,一个函数用对话框弹出你需要的文字(就像 Hello,world那样),另外的一个则是返回一个整数的平方。
这样函数申明和定义完成后,不要忘记在类实现文件(ActTest.cpp)中的这段中添加函数的引用。(//那一行处为添加部分)
如:showStr,MySquare。
BEGIN_DISPATCH_MAP(CActTest, CCmdTarget)
DISP_FUNCTION(CActTest, "ShowStr", ShowStr, VT_EMPTY, VTS_BSTR) //函数ShowStr的调用及其参数
DISP_FUNCTION(CActTest, "MySquare", MySquare, VT_I4, VTS_I4)//函数MySquare的调用及其参数
END_DISPATCH_MAP()
然后编译它,生成DLL文件,以供调用.
VLisp中的调用:
;;; 本程序演示了如何通过Activex来调用arx中的类(class)和函数。
;;; 程序先注册ActiveX,后创建一个object,用vlax-invoke-method
;;; 来调用其中的函数的功能,也可以通过它得到返回值。
;;; 程序未加出错判断,请自行加入。
;;; highflybird 2009-5-23 Haikou
(vl-load-com)
(defun c:test (/ obj)
(DllRegister "F:\\ZQY\\MyProject\\MyActTest\\Debug\\MyActTest.DLL") ; 也可以增加判断,如果注册了则无需再注册
(setq obj (vlax-create-object "MyActTest.ActTest")) ; 创建一个实例(对象)
(vlax-invoke-method obj 'ShowStr "highflybird") ; 调用其MyActTest中的函数
(print (vlax-invoke-method obj 'MySquare 12)) ; 得到返回值
(vlax-release-object obj) ; 别忘记释放实例
(UnDllRegister "F:\\ZQY\\MyProject\\MyActivex\\Debug\\MyActTest.DLL") ; 反注册
(princ)
)
;;; DLL 的注册
(defun DLLRegister (dll)
(startapp "regsvr32.exe" (strcat "/s \"" dll "\""))
)
;;; DLL 的反注册
(defun UnDLLRegister (dll)
(startapp "regsvr32.exe" (strcat "/u /s \"" dll "\""))
)
VBA中的调用:
打开VBA编辑器,选择菜单的工具--引用,弹出对话框,点击浏览,选择你生成的DLL文件的目录,找到它,打开它并按下引用对话框的确定,
这样我们就可以再VBA中引用自己定义的ActiveX了.
定义一个过程,在编辑器中输入代码:
Sub test()
Dim obj As ActTest
Set obj = New ActTest
obj.ShowStr "hello,highflybird!"
Set obj = Nothing
End Sub
运行,就看到你出现的效果了。
本程序由Visual Studio 2002 + ObjectARX2006 + AutoCAD 2006开发,在AutoCAD2006中运行通过。
如果有什么问题,请看我下面的程序包。
顺便说一句,感觉到此类话题属于objectARX编程类,如有必要,请总版主移至其相应版块。
(defun DLLRegister (dll)
(startapp "regsvr32.exe" (strcat "/s "" dll """))
)
这个函数怕是有错误吧,我觉得应该是
(defun DLLRegister (dll)
(startapp "regsvr32.exe" (strcat "/s \"" dll "\""))
) <p>只有C语言简单基础,完全看不懂</p><p>ARX编程尝试过,好容易半天输入几页代码,调试始终不能通过,只好放弃</p><p>对于MFC,成员函数,DLL,,类,基类,类实现文件等术语完全没有概念</p><p>烦请版主给个基本的简单些的介绍</p><p></p><p></p> <p>这方面.net与LISP连接的方法会更简单一些,可以使用:<br/><LispFunction("changeArgs")><br/>来生成供LISP直接调用的函数。</p> gisshow发表于2009-5-23 23:44:00static/image/common/back.gif只有C语言简单基础,完全看不懂ARX编程尝试过,好容易半天输入几页代码,调试始终不能通过,只好放弃对于MFC,成员函数,DLL,,类,基类,类实现文件等术语完全没有概念烦请版主给个基本的简单
<p>这个不太好介绍。</p><p><font color="#ff0000">C++语言是基于面向对象的语言,类是其基本的数据类型,封装了属性和实现方法(包括成员函数)</font></p><p>这就像一个零件(可能比喻不怎么恰当),举个例子来说吧:</p><p>C++这样用类来描述动物:</p><p>所有的动物是一个类: animal。</p><p>animal有自己的属性,如age,weight,color等。</p><p>animal也有自己的方法,例如getAge(),getWeight(),getColor(),speak(),move()等等;这些就是其<font color="#ff0000">成员函数</font>。</p><p>所以animal是一个<font color="#ff0000">基类</font>。</p><p>然后可以从animal派生出很多类别,如dog,cat,</p><p>dog除了有基类的一些属性,也可以有自己的一些属性,如,breed,</p><p>dog也有自己的方法,这些方法可以继承自animal,也可以覆盖animal的方法,还可以创建新的方法或者成员函数。</p><p>如,dog 会dog.speak(),dog.move(),dog.bark()等等。</p><p>C++继承了C语言的一些东西,把类型的申明放在 .h文件中(头文件)</p><p>把定义放在.cpp文件中(实现文件)</p><p>如我先申明了一个函数 </p><p>int myfunc();</p><p>然后在.cpp文件中实现 </p><p> int myfunc()</p><p>{ </p><p> //下面是实现代码</p><p> ........</p><p> return 0 ;</p><p>}</p><p><font color="#ff0000"><strong>MFC</strong>,</font><a href="http://baike.baidu.com/view/2353.htm" target="_blank"><font color="#ff0000">微软</font></a><font color="#ff0000">基础类(<b>Microsoft Foundation Classes</b>),说白了就是对话框及菜单等各种资源。</font></p><p><font color="#ff0000">什么是DLL</font>,DLL 是一个包含可由多个程序同时使用的代码和数据的库。DLL是Dynamic Link Library的缩写,意为动态链接库,当执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可有多个DLL文件,一个DLL文件也可能被几个应用程序所共用,这样的DLL文件被称为共享DLL文件.</p><p>通过使用 DLL,程序可以实现模块化,由相对独立的组件组成。例如,一个计帐程序可以按模块来销售。可以在运行时将各个模块加载到主程序中(如果安装了相应模块)。因为模块是彼此独立的,所以程序的加载速度更快,而且模块只在相应的功能被请求时才加载。<br/><br/>此外,可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。例如,您可能具有一个工资计算程序,而税率每年都会更改。当这些更改被隔离到 DLL 中以后,您无需重新生成或安装整个程序就可以应用更新。<br/><br/>下表说明了 Windows 操作系统中的一些作为 DLL 实现的文件: </p><ul><li><b>ActiveX 控件 (.ocx) 文件</b><br/>ActiveX 控件的一个示例是日历控件,它使您可以从日历中选择日期。 </li><li><b>控制面板 (.cpl) 文件</b><br/>.cpl 文件的一个示例是位于控制面板中的项。每个项都是一个专用 DLL。 </li><li><b>设备驱动程序 (.drv) 文件</b><br/>设备驱动程序的一个示例是控制打印到打印机的打印机驱动程序。</li></ul><p>这些都扯远了,跟lisp扯不上关系。如果你要了解,不妨买一本C++语言的书来看看。</p><p>我这篇主要是谈如何让lisp也能利用C++的类。</p> 好。值得借鉴。 好像都只能支持32位的,在64位机器上就用不了了,不知道如何解决~~~ 谢谢楼主分享 highflybir :您好
“(DllRegister "F:\\ZQY\\MyProject\\MyActTest\\Debug\\MyActTest.DLL") ; 也可以增加判断,如果注册了则无需再注册”
用lisp 如果判断.dll 文件是否被注册过了? 谢谢! flowerson 发表于 2012-12-6 20:58 static/image/common/back.gif
highflybir :您好
“(DllRegister "F:\\ZQY\\MyProject\\MyActTest\\Debug\\MyActTest.DLL") ; 也可 ...
(setq obj (vlax-create-object "MyActTest.ActTest"))
像上面的那样,如果能创建这个object ,object返回值不为nil,说明已经注册了,否则要注册。 谢谢了。看明白了。
页:
[1]
2