CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

AutoCAD 2022 开发者帮助

将自定义对象或实体添加到对象模型

2024-5-18 18:50| 发布者: admin| 查看: 117| 评论: 0|原作者: admin|来自: AutoCAD

将自定义对象或实体添加到对象模型

如果 COM 包装类封装自定义对象或实体,则需要修改 ATL 生成的代码以支持相应的接口。ObjectARX samples\com\AsdkSquareWrapper_dg\square 目录包含作为单独 DLL 编写的自定义实体的包装类示例。

您还必须确保 ObjectARX 组件满足 ActiveX 自动化要求,并且必须扩展包装应用程序以支持 ObjectARX 组件。以下各节提供了演示如何完成此操作的过程:

为自定义对象或实体创建自动化包装器项目

  1. 根据设置 ATL 项目文件中的步骤设置项目。
  2. stdafx.h 中,紧接在 之后,包括 acad24.hdbmain.h 和任何其他必要的 ObjectARX 头文件。#include <atlcom.h>
  3. 在stdafx.cpp中,在文件末尾添加以下代码:
#include "acadi_i.c"

您刚刚创建的项目包含大量生成的代码。必须扩展其中的某些代码才能使用 ObjectARX,如下一过程所示。

调整 ATL 生成的代码以实现 ObjectARX 兼容性

  1. 在 COM 对象头文件中,包括 axtempl.h(主 ActiveX 自动化模板头文件)和自定义对象或实体的头文件。
  2. 通过删除派生部分并将其替换为以下声明之一来更改 COM 对象或实体的派生:IDispatchImpl
// For a custom object.
//
public IAcadObjectDispatchImpl<CWrapperClass,
    &CLSID_WrapperClass,IWrapperClass,
    &IID_IWrapperClass,&LIBID_LIBRARYLib>
 
// For a custom entity.
//
public IAcadEntityDispatchImpl<CWrapperClass,
    &CLSID_WrapperClass,IWrapperClass,
    &IID_IWrapperClass,&LIBID_LIBRARYLib>

将以下条目添加到:COM_MAP

COM_INTERFACE_ENTRY(IAcadBaseObject)
COM_INTERFACE_ENTRY(IAcadObject)
COM_INTERFACE_ENTRY(IAcadEntity) // For an entity only.
COM_INTERFACE_ENTRY(IRetrieveApplication)
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) // Only 
                                 // necessary to support events.

必须在 COM 代码中实现一个特殊函数,以公开自定义对象和实体。以下过程演示了如何提供此支持。

添加 ObjectARX 自定义对象和自定义实体支持

将以下必需的替代添加到 COM 类的公共声明:

// IAcadBaseObjectImpl
//
virtual HRESULT 
CreateNewObject(
    AcDbObjectId& objId, 
    AcDbObjectID& ownerId, 
    TCHAR* keyName);

此抽象函数是类的公共成员。COM 包装类通过 或 继承。 必须重写才能将默认对象添加到数据库中。IAcadBaseObjectImplIAcadBaseObjectImplIAcadObjectDispatchImplIAcadEntityDispatchImplCreateNewObject

实现该函数和任何其他特定于对象或特定于实体的函数。CreateNewObject()

以下示例显示了 from 的实现:CreateNewObject()AsdkSquareWrapper

HRESULT CAsdkSquareWrapper::CreateNewObject(
    AcDbObjectId& objId, 
    AcDbObjectId& ownerId, 
    TCHAR* keyName)
{
    try 
    {
        AcAxDocLock docLock(ownerId, AcAxDocLock::kNormal);
        Acad::ErrorStatus es;
        AcDbObjectPointer<AsdkSquare> pSq;
        if((es = pSq.create()) != Acad::eOk)
            throw es;
        AcDbDatabase* pDb = ownerId.database();
        pSq->setDatabaseDefaults(pDb);
        AcDbBlockTableRecordPointer 
            pBlockTableRecord(ownerId, AcDb::kForWrite);
        if((es = pBlockTableRecord.openStatus()) != Acad::eOk)
            throw es;
        if((es = pBlockTableRecord->
            appendAcDbEntity(objId, pSq.object())) != Acad::eOk)
            throw es;
    }
    catch(const Acad::ErrorStatus)
    {
        //To become more sophisticated 
        //
        return Error(L"Failed to create square",
            IID_IAsdkSquareWrapper, E_FAIL);
    }
    return S_OK;
}

将所需的 ActiveX 方法和属性添加到包装类中,如通过 ActiveX 公开功能中所述。

为了正确定义对象的自动化接口,必须修改生成的接口定义语言 (IDL) 文件。

调整 IDL 文件以适应 ObjectARX 使用

在 IDL 文件中,将 COM 对象的接口派生从自定义对象的 to 更改为自定义实体的接口派生。下面是 AsdkSquareLib.idl 示例文件中的示例:IDispatchIAcadObjectIAcadEntity

interface IAsdkSquareWrapper : IAcadEntity

在 和 之后添加以下代码:importlib stdole32.tlbimportlib stdole2.tlb

importlib("acax24enu.tlb"); // revise the path to match your
                            // own AutoCAD installation

请确保替换与AutoCAD安装匹配的路径。

在与包装器 coclass 对应的 IDL 文件部分中,在行后添加以支持事件。[source] interface IAcadObjectEvents;[default]

acax24enu.tlb 部分移动到 IDL 文件的顶部,并移动自定义目标代码,使其位于该部分中。

IDL 文件现在类似于以下代码:

import "oaidl.idl";
import "ocidl.idl";
[
    uuid(800F70A1-6DE9-11D2-A7A6-0060B0872457),
    version(1.0),
    helpstring("AsdkSquareLib 1.0 Type Library")
]
library ASDKSQUARELIBLib
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");
    importlib("acax23enu.tlb");
    [
        object,
        uuid(800F70AD-6DE9-11D2-A7A6-0060B0872457),
        dual,
        helpstring("IAsdkSquareWrapper Interface"),
        pointer_default(unique)
    ]
    interface IAsdkSquareWrapper : IAcadEntity
    {
        [propget, id(1), helpstring("property Number")] 
            HRESULT Number([out, retval] short *pVal);
        [propput, id(1), helpstring("property Number")] 
            HRESULT Number([in] short newVal);
    };
    [
        uuid(800F70AE-6DE9-11D2-A7A6-0060B0872457),
        helpstring("AsdkSquareWrapper Class")
    ]
    coclass AsdkSquareWrapper
    {
        [default] interface IAsdkSquareWrapper;
        [source] interface IAcadObjectEvents;
    };
};
注意:IDL 文件修改将导致编译器发出警告,指出接口不符合。您可以忽略此消息。

接下来,请确保 ObjectARX 组件实现必要的替代以支持 ActiveX 自动化。如果要生成单独的 COM 和 ObjectARX DLL,请切换到 ObjectARX 项目以执行下一个过程。

AutoCAD 特性选项板使用该函数检索自定义图元的类型信息。有关实现属性选项板功能的信息,请参阅属性面板 API。如果不按下述进行覆盖,则“属性”选项板仅显示自定义实体的基类信息。但是,如果重写但未实现自定义实体的 OPM 接口,则“属性”选项板无法显示您自己的类信息或基类数据。有关 的更多信息,请参见获取自定义类的 CLSIDgetClassID()getClassID()getClassID()getClassID()

准备 ObjectARX 项目以实现 ActiveX 兼容性

在每个正在包装的基于 ObjectARX 的类中,重写该函数:getClassID()

Acad::ErrorStatus
AcDbMyClass::getClassID(CLSID* pClsid) const
{
    *pClsid = CLSID_WrapperClass; // replace CLSID_WrapperClass with                                   // your COM class CLSID
    return Acad::eOk;
}

在包含 的重写的每个文件中,包括必要的 COM 头文件以及编译器生成的 ID 文件:getClassId()

#include <objbase.h>
#include <initguid.h>
#include "library_i.c" // File containing definitions of the
                       // IIDs and CLSIDs for the COM project.
                       // “library” is replaced by your COM project
                       // name. This file resides in your COM
                       // project directory.

根据生成和注册 COM DLL 中的步骤生成并注册 COM 应用程序。如果要生成单独的 COM 和 ObjectARX 或 ObjectDBX DLL,在生成 COM 应用程序之前生成 ObjectARX 或 ObjectDBX 模块。

父主题:

  1. 编写 COM 包装器

路过

雷人

握手

鲜花

鸡蛋

最新评论

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

GMT+8, 2025-3-14 06:22

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部