CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

ObjectARX 开发指南

使用 MFC 和“从类型库添加类”向导访问 AutoCAD ActiveX 自动化

2022-12-31 12:57| 发布者: admin| 查看: 2007| 评论: 0|来自: AutoCAD

此方法使用 MFC 和 Visual C++ 从 Typelib 添加类向导来读取 AutoCAD 类型库 (acax24enu.tlb)。示例程序使用 AutoCAD 的 COM ActiveX 自动化界面在模型空间中创建圆。以下各节提供了指导您完成程序设置和实现的过程:

设置新的 MFC 项目文件

  1. 启动 Visual C++ 并创建一个名为AsdkMfcComSamp 的新 MFC DLL 项目。
  2. 在“应用程序设置”中,选择“MFC 扩展 DLL”。
  3. 选择“完成”以创建项目。

若要开始添加特定的 ObjectARX 功能,必须调整项目设置并添加样板代码。

添加对象 ARX 兼容性

将适当的值添加到项目属性中,以使项目生成为 ObjectARX 程序。确保 ObjectARX\inc\lib目录位于项目的搜索路径中。此程序需要与以下库链接:

acad.lib
acdb24.lib
rxapi.lib

在项目的定义 (DEF) 文件中,将以下行添加到“导出”部分:

acrxEntryPoint        PRIVATE
acrxGetApiVersion     PRIVATE

打开AsdkMfcComSamp.cpp源文件并添加以下代码以使程序 ObjectARX 兼容:

#include <rxregsvc.h>
#include <aced.h>
#include <rxmfcapi.h>
static void initApp()
{
    acedRegCmds->addCommand(
        "ASDK_MFC_COM", 
        "AsdkMfcComCircle",
        "MfcComCircle", 
        ACRX_CMD_MODAL, 
        addCircleThroughMfcCom);
}
static void unloadApp()
{
    acedRegCmds->removeGroup("ASDK_MFC_COM");
}
extern "C" AcRx::AppRetCode acrxEntryPoint
    (AcRx::AppMsgCode msg, void* appId)
{
    switch(msg)
    {
    case AcRx::kInitAppMsg: 
        acrxDynamicLinker->unlockApplication(appId);
        acrxDynamicLinker->registerAppMDIAware(appId);
        initApp(); 
        break;
    case AcRx::kUnloadAppMsg: 
        unloadApp(); 
        break;
    default:
        break;
    }
    return AcRx::kRetOK;
}

通过将以下代码添加到AsdkMfcComSamp.cpp源文件,在新的 AutoCAD 命令处理程序函数中存根:

void addCircleThroughMfcCom()
{
}

若要在没有链接器警告的情况下生成项目,必须使 MFC 知道调试项目链接到使用发布 MFC 库生成的库。这是通过在编译器处理 MFC 头文件时仅挂起调试符号的定义来实现的。

To exclude debug MFC code from the debug build of your project

In the generated stdafx.h file, before the first MFC include statement (usually ,add the following code: #include <afxwin.h>)

#ifdef _DEBUG
#undef _DEBUG
#endif

From the Build menu, select Build AsdkMfcComSamp to verify that your project setup is correct.

Your project should build successfully, but at this point it doesn't do anything. The next step is to implement the command handler with ActiveX Automation calls.

First, you must decide which interfaces are necessary. To add a new circle to model space, the , , and interfaces are required. You use the AutoCAD type library, acax24enu.tlb, to get the definitions of these interfaces, as shown in the next procedure. IAcadApplicationIAcadDocumentIAcadModelSpace

To import AutoCAD ActiveX interfaces

  1. Choose Add Class from the Microsoft Visual C++ Project menu.
  2. Choose MFC Class From TypeLib to bring up the Add Class From TypeLib Wizard.
  3. Choose the AutoCAD 2021 Type Library from the drop-down list. (Or, choose the File radio button and browse to the acax24enu.tlb file.)
  4. Select the desired interfaces (in this case, , , and ) and use the arrow button to add them to the list of generated classes. IAcadApplicationIAcadDocumentIAcadModelSpace
  5. Choose Finish. The wizard creates new header files for the interface wrapper classes and adds them to your project.
    Note: The AutoCAD ActiveX Automation interfaces are documented in the ActiveX and VBA Reference.

Now that you have imported the necessary interfaces, you are ready to implement the command-handling function.

To implement AutoCAD ActiveX Automation calls

  1. In the AsdkMfcComSamp.cpp file, include the header files for the interface wrapper classes.
  2. In the empty function, add declarations for the three interface wrapper classes: addCircleThroughMfcCom()
CAcadApplication IApp;
CAcadDocument IDoc;
CAcadModelSpace IMSpace;

Use the () function to obtain the MFC object for AutoCAD, and call the method: acedGetAcadWinAppCWinAppGetIDispatch

IDispatch *pDisp = acedGetAcadWinApp()->
GetIDispatch(TRUE);

Once you have the object, attach it to the locally defined object and make sure that AutoCAD is visible: IDispatchCAcadApplication

IApp.AttachDispatch(pDisp);
IApp.put_Visible(true);

Obtain the active document dispatch and attach it to the locally defined object: CAcadDocument

pDisp = IApp.get_ActiveDocument();
IDoc.AttachDispatch(pDisp);

Query the active document for model space:

pDisp = IDoc.get_ModelSpace();
IMSpace.AttachDispatch(pDisp);

A circle requires a center point and radius. To make this efficient and transparent to different programming languages, the COM interface uses the type. A point is stored in a as a . Add the following code to set up a and store it in a : VARIANTVARIANTSAFEARRAYSAFEARRAYVARIANT

SAFEARRAYBOUND rgsaBound;
rgsaBound.lLbound = 0L;
rgsaBound.cElements = 3;
SAFEARRAY* pStartPoint = NULL;
pStartPoint = SafeArrayCreate(VT_R8, 1, &rgsaBound);
// X value
//
long i = 0;
double value = 4.0;
SafeArrayPutElement(pStartPoint, &i, &value);
// Y value
//
i++;
value = 2.0;
SafeArrayPutElement(pStartPoint, &i, &value);
// Z value
//
i++;
value = 0.0;
SafeArrayPutElement(pStartPoint, &i, &value);
VARIANT pt1;
VariantInit(&pt1);
V_VT(&pt1) = VT_ARRAY | VT_R8;
V_ARRAY(&pt1) = pStartPoint;

Call the method from the object: AddCircleCAcadModelSpace

IMSpace.AddCircle(pt1, 2.0);

Here is the finished function, with clean-up code and exception handling added:

void addCircleThroughMfcCom()
{
    TRY
    {
        CAcadApplication IApp;
        CAcadDocument IDoc;
        CAcadModelSpace IMSpace;
        IDispatch *pDisp = acedGetAcadWinApp()->
            GetIDispatch(TRUE); // AddRef is called on the
                                // pointer
        IApp.AttachDispatch(pDisp); // does not call AddRef()
        IApp.put_Visible(true);
        pDisp = IApp.get_ActiveDocument(); // AddRef is called
        IDoc.AttachDispatch(pDisp);
        pDisp = IDoc.get_ModelSpace(); // AddRef is called
        IMSpace.AttachDispatch(pDisp);
        SAFEARRAYBOUND rgsaBound;
        rgsaBound.lLbound = 0L;
        rgsaBound.cElements = 3;
        SAFEARRAY* pStartPoint = NULL;
        pStartPoint = SafeArrayCreate(VT_R8, 1, &rgsaBound);
        // X value
        long i = 0;
        double value = 4.0;
        SafeArrayPutElement(pStartPoint, &i, &value);
        // Y value
        i++;
        value = 2.0;
        SafeArrayPutElement(pStartPoint, &i, &value);
        // Z value
        i++;
        value = 0.0;
        SafeArrayPutElement(pStartPoint, &i, &value);
        VARIANT pt1;
        VariantInit(&pt1);
        V_VT(&pt1) = VT_ARRAY | VT_R8;
        V_ARRAY(&pt1) = pStartPoint;
        IMSpace.AddCircle(pt1, 2.0);
        VariantClear(&pt1);
        // Release() is called implicitly on the local objects
    }
    CATCH(COleDispatchException,e) 
    {
        e->ReportError();
        e->Delete();
    }
    END_CATCH;
}

重新生成项目。

在AutoCAD中加载ARX文件,然后在命令行中输入MFCCOMCIRCLE以测试代码。

COM 程序员通常需要调用以前已调用的任何接口指针。在上面的示例中,MFC 通过内部调用其本地接口包装器对象来减轻您的此责任。但是,在使用完 COM 接口指针后,应注意需要释放它们。以下过程中演示了显式释放接口指针的技术。Release()AddRef()Release()


路过

雷人

握手

鲜花

鸡蛋

最新评论

QQ|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 )

GMT+8, 2024-5-19 14:00

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部