本帖最后由 highflybir 于 2012-8-24 22:00 编辑
尝试COM编程,和大家共同探讨一下,并交流一下自己的心得。
COM编程,实用范围广,它绝大部分可以运行于CAD的各个版本,运行效率高,因为是用VC++编写,故而程序的加密性也很好。
这里是我的示例流程:
1.首先用创建一个MFC的对话框工程,勾选Automation,其他按照默认来。
2.设计好对话框界面,增加一个ComboBox控件,用来选择CAD版本,并为之附加一个成员变量m_ctrVersion;
再增加两个按钮。详细过程不表。
3.在工程中增加一个类,选择MFC Class From TypeLib类。
从中选择文件或注册表的,都可以,我这里选择了文件,acad.tlb --这个是AutoCAD 2002的接口类。
你也可以选其他版本,譬如,acax16chs.tlb ,acax17enu.tlb之类。 这里只是为照顾低版本的,有可能会有极少数的几
个函数低版本不支持。
4.接口中选择你需要的类,譬如我只选择了跟这个工程有关的几个:
CAcadApplication,CAcadDocuments,CAcadDocument,CAcadModelSpace,CAcadUtility
也是最常用的几个了。增加的工程中,向导为你自动生成头文件。可能你要对CAcadUtility.h文件稍做修改,才能编译运行
。
5.在stdafx.h中添加:
- #include "CAcadDocument.h"
- #include "CAcadDocuments.h"
- #include "CAcadApplication.h"
- #include "CAcadModelSpace.h"
- #include "CAcadUtility.h"
6.在对话框的头文件COMSampleDlg.h中添加几个变量:
- CAcadApplication m_cadApp;
- CAcadDocument m_Doc;
7.至次,准备工作完成。
8.连接到CAD中的代码部分如下:
- void CCOMSampleDlg::OnBnClickedLinktoCAD()
- {
- if (m_cadApp != NULL ) m_cadApp.DetachDispatch();
- CLSID clsid;
- HRESULT hr = CLSIDFromProgID(m_version,&clsid);
- IUnknown *m_pUnkn = NULL;
- IDispatch *m_pDisp = NULL;
- if (GetActiveObject(clsid, NULL,&m_pUnkn) == S_OK) //if
- (GetActiveObject(__uuidof(AcadApplication), NULL,&m_pUnkn) != S_OK)
- if (m_pUnkn->QueryInterface(IID_IDispatch, (void**)&m_pDisp) == S_OK)
- m_cadApp.AttachDispatch(m_pDisp);
- if (m_cadApp == NULL)
- {
- m_cadApp.CreateDispatch(m_version);
- if (m_cadApp == NULL)
- {
- AfxMessageBox(LoadStringFromID(IDS_ATTACHFAILURE));
- return;
- }
- }
- }
思路是,如果你选择版本的CAD在运行,则连接,否则从创建一个CAD实例程序。由此建立程序与CAD的连接和通信。
9.画图部分代码我省略掉了。
大致流程如下,前面的连接到CAD已经得到程序的实例CAcadApplication m_cadApp;
由此得到当前文档m_Doc = m_cadApp.get_ActiveDocument();
再得到模型空间实例,CAcadModelSpace modelSpace = m_Doc.get_ModelSpace();
在此空间中创建一条轻多段线,放大这条线段。
最后是与用户交互创建一条直线。
其中有一个难点题目,就是如和传递可选参数,这个问题困惑了我好几天。后来终于在国外找到答案。
参见:http://support.microsoft.com/kb/238981
当调用具有从 Visual c + + 的可选参数的方法时,您不能省略了可选参数。您需要改为传递一个特殊的变量。
某些方法具有"可选"参数。在 Visual Basic,则可以省略它们调用该方法时。但是,当使用 Visual c + + 调用时,必须
传递特殊变量的.vt 字段具有值 VT_ERROR 和.scode 字段具有值 DISP_E_PARAMNOTFOUND。这就是:
-
- // VARIANT used in place of optional-parameters.
- VARIANT varOpt;
- varOpt.vt = VT_ERROR;
- varOpt.scode = DISP_E_PARAMNOTFOUND;
10.在CAD中测试运行。呵呵,因为仅仅是示例,所以有些地方的并没有catch 处理。商业化软件应该要处理的。
好,为你介绍到这里。本人水平有限,在此献丑了,大家有什么好的办法和建议拿出来哦。
工程源码附后。
附注:为了使得编译后的工程有广泛性,需编译的时候选择静态库。
|