CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

AutoCAD 2023 开发者帮助

使用 COM 访问 AutoCAD ActiveX Automation

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

使用 COM 访问 AutoCAD ActiveX Automation

此方法通过纯 COM 技术访问 AutoCAD ActiveX Automation。此方法需要更多的编码,但不依赖于 MFC。示例程序使用 COM ActiveX 自动化接口向 AutoCAD 菜单栏添加新的快捷菜单。以下各节提供了演示必要步骤的过程:

设置新的 ObjectARX 项目

  1. 启动 Visual C++ 并创建一个名为 AsdkPlainComSamp 的新 Win32 DLL 项目。
  2. 将适当的值添加到项目设置中,以使项目构建为 ObjectARX 程序。该程序需要链接到以下库:
acad.lib
acdb24.lib
rxapi.lib

将名为 AsdkPlainComSamp.def 的新定义 (DEF) 文件添加到项目中。

打开新的 DEF 文件,并将以下行添加到 EXPORTS 部分:

acrxEntryPoint        PRIVATE
acrxGetApiVersion     PRIVATE

将名为 AsdkPlainComSamp.cpp 的新源 (CPP) 文件添加到项目中。

打开新的 CPP 文件,并添加以下代码以使程序 ObjectARX 兼容:

#include <rxregsvc.h>
#include <aced.h>
// Used to add/remove the menu with the same command.
//
static bool bIsMenuLoaded = false;
static void initApp()
{
    acedRegCmds->addCommand(
        "ASDK_PLAIN_COM", 
        "AsdkComMenu",
        "ComMenu", 
        ACRX_CMD_MODAL, 
        addMenuThroughCom);
}
static void unloadApp()
{
    acedRegCmds->removeGroup("ASDK_PLAIN_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;
}

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

void addMenuThroughCom()
{
}

下一步是确定访问AutoCAD菜单栏需要哪些界面。在本例中,、、、和为必填项。要获取这些接口的定义,请使用 AutoCAD 类型库 acax24<language>.tlb,如下一过程所示。IAcadApplicationIAcadMenuBarIAcadMenuGroupsIAcadMenuGroupIAcadPopupMenusIAcadPopupMenuIAcadPopupMenuItem

导入 AutoCAD ActiveX 界面的步骤

将以下行添加到AsdkPlainComSamp.cpp文件的顶部,确保使用系统上安装AutoCAD的路径:

import "c:\\acad\\acax24<language>.tlb" no_implementation \
    raw_interfaces_only named_guids

将以下声明添加到 () 函数:addMenuThroughCom

AutoCAD::IAcadApplication *pAcad;
AutoCAD::IAcadMenuBar *pMenuBar;
AutoCAD::IAcadMenuGroups *pMenuGroups;
AutoCAD::IAcadMenuGroup *pMenuGroup;
AutoCAD::IAcadPopupMenus *pPopUpMenus;
AutoCAD::IAcadPopupMenu *pPopUpMenu;
AutoCAD::IAcadPopupMenuItem *pPopUpMenuItem;

现在,您的应用程序导入了正确的界面,您可以使用它们来实现 AutoCAD 功能。自动化的更直接的 COM 方法用于访问 AutoCAD 及其自动化组件。下一个过程演示如何实现此目的。此过程中的所有代码示例都应按显示的顺序添加到 () 函数中。acedGetIDispatch()IDispatchaddMenuThroughCOM

实现 AutoCAD ActiveX Automation 调用的步骤

AsdkPlainComSamp.cpp文件中,将以下代码添加到空函数中以获取AutoCAD:addMenuThroughCOM()IDispatch

HRESULT hr = NOERROR;
LPUNKNOWN pUnk = NULL;
LPDISPATCH pAcadDisp = acedGetIDispatch(TRUE);

用于获取 AutoCAD 应用程序对象。此外,请确保 AutoCAD 可见。如下代码所示:IUnknown

hr = pAcadDisp->QueryInterface(AutoCAD::IID_IAcadApplication,
        (void**)&pAcad);
pAcadDisp->Release();
if (FAILED(hr))
    return;
pAcad->put_Visible(true);

在AutoCAD应用程序界面中,获取菜单栏和菜单组集合:

pAcad->get_MenuBar(&pMenuBar);
pAcad->get_MenuGroups(&pMenuGroups);
pAcad->Release();

确定菜单栏上当前有多少个菜单:

long numberOfMenus;
pMenuBar->get_Count(&numberOfMenus);
pMenuBar->Release();

从菜单组集合中获取第一个菜单。这通常是 ,但也可能是其他东西:ACAD

VARIANT index;
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = 0;
pMenuGroups->Item(index, &pMenuGroup);
pMenuGroups->Release();

从第一个菜单组中获取快捷菜单集合:

pMenuGroup->get_Menus(&pPopUpMenus);
pMenuGroup->Release();

根据菜单是否已创建,可以构建新的快捷菜单或删除以前创建的快捷菜单。以下代码完成了该示例:

WCHAR wstrMenuName[256];
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, 
   "AsdkComAccess", -1, wstrMenuName, 256); 
if (!bIsMenuLoaded) {
    pPopUpMenus->Add(wstrMenuName, &pPopUpMenu);
    if (pPopUpMenu != NULL) {
        pPopUpMenu->put_Name(wstrMenuName);
        WCHAR wstrMenuItemName[256];
        MultiByteToWideChar(CP_ACP, 0,"&Add A ComCircle",
            -1, wstrMenuItemName, 256); 
        WCHAR wstrMenuItemMacro[256];
        MultiByteToWideChar(CP_ACP, 0, "AsdkComCircle ",
            -1, wstrMenuItemMacro, 256); 
        VariantInit(&index);
        V_VT(&index) = VT_I4;
        V_I4(&index) = 0;
        pPopUpMenu->AddMenuItem(index, wstrMenuItemName,
            wstrMenuItemMacro, &pPopUpMenuItem);
        VariantInit(&index);
        V_VT(&index) = VT_I4;
        V_I4(&index) = 1;
        pPopUpMenu->AddSeparator(index, 
            &pPopUpMenuItem);
        MultiByteToWideChar(CP_ACP, 0,
            "Auto&LISP Example", -1, 
            wstrMenuItemName, 256); 
        MultiByteToWideChar(CP_ACP, 0,
            "(prin1 \"Hello\") ", -1, 
            wstrMenuItemMacro, 256); 
        VariantInit(&index);
        V_VT(&index) = VT_I4;
        V_I4(&index) = 2;
        pPopUpMenu->AddMenuItem(index, wstrMenuItemName,
            wstrMenuItemMacro, &pPopUpMenuItem);
        VariantInit(&index);
        V_VT(&index) = VT_I4;
        V_I4(&index) = numberOfMenus - 2;
        pPopUpMenu->InsertInMenuBar(index);
        pPopUpMenu->Release();
        pPopUpMenuItem->Release();
        bIsMenuLoaded = true;
    }else {
        acutPrintf("\nMenu not created.");
    }
 }else {
    VariantInit(&index);
    V_VT(&index) = VT_BSTR;
    V_BSTR(&index) = wstrMenuName;
    pPopUpMenus->RemoveMenuFromMenuBar(index);
    VariantClear(&index);
    bIsMenuLoaded = false;
}
pPopUpMenus->Release();

这是完成的函数:

void addMenuThroughCom()
{
    AutoCAD::IAcadApplication *pAcad;
    AutoCAD::IAcadMenuBar *pMenuBar;
    AutoCAD::IAcadMenuGroups *pMenuGroups;
    AutoCAD::IAcadMenuGroup *pMenuGroup;
    AutoCAD::IAcadPopupMenus *pPopUpMenus;
    AutoCAD::IAcadPopupMenu *pPopUpMenu;
    AutoCAD::IAcadPopupMenuItem *pPopUpMenuItem;
    HRESULT hr = NOERROR;
    LPUNKNOWN pUnk = NULL;
    LPDISPATCH pAcadDisp = acedGetIDispatch(TRUE); 
 
    hr = pAcadDisp->QueryInterface(AutoCAD::IID_IAcadApplication, (void**)&pAcad);
    pAcadDisp->Release();
    if (FAILED(hr))
        return;
    pAcad->put_Visible(true);
    pAcad->get_MenuBar(&pMenuBar);
    pAcad->get_MenuGroups(&pMenuGroups);
    pAcad->Release();
    long numberOfMenus;
    pMenuBar->get_Count(&numberOfMenus);
    pMenuBar->Release();
    VARIANT index;
    VariantInit(&index);
    V_VT(&index) = VT_I4;
    V_I4(&index) = 0;
    pMenuGroups->Item(index, &pMenuGroup);
    pMenuGroups->Release();
    pMenuGroup->get_Menus(&pPopUpMenus);
    pMenuGroup->Release();
    WCHAR wstrMenuName[256];
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, 
        "AsdkComAccess", -1, wstrMenuName, 256); 
    if (!bIsMenuLoaded) {
        pPopUpMenus->Add(wstrMenuName, &pPopUpMenu);
        if (pPopUpMenu != NULL) {
            pPopUpMenu->put_Name(wstrMenuName);
            WCHAR wstrMenuItemName[256];
            MultiByteToWideChar(CP_ACP, 0,"&Add A ComCircle",
                -1, wstrMenuItemName, 256); 
            WCHAR wstrMenuItemMacro[256];
            MultiByteToWideChar(CP_ACP, 0, "AsdkComCircle ",
                -1, wstrMenuItemMacro, 256); 
            VariantInit(&index);
            V_VT(&index) = VT_I4;
            V_I4(&index) = 0;
            pPopUpMenu->AddMenuItem(index, wstrMenuItemName,
                wstrMenuItemMacro, &pPopUpMenuItem);
            VariantInit(&index);
            V_VT(&index) = VT_I4;
            V_I4(&index) = 1;
            pPopUpMenu->AddSeparator(index, 
                &pPopUpMenuItem);
            MultiByteToWideChar(CP_ACP, 0,
                "Auto&LISP Example", -1, 
                wstrMenuItemName, 256); 
            MultiByteToWideChar(CP_ACP, 0,
                "(prin1 \"Hello\") ", -1, 
                wstrMenuItemMacro, 256); 
            VariantInit(&index);
            V_VT(&index) = VT_I4;
            V_I4(&index) = 2;
            pPopUpMenu->AddMenuItem(index, wstrMenuItemName,
                wstrMenuItemMacro, &pPopUpMenuItem);
            VariantInit(&index);
            V_VT(&index) = VT_I4;
            V_I4(&index) = numberOfMenus - 2;;
            pPopUpMenu->InsertInMenuBar(index);
            pPopUpMenu->Release();
            pPopUpMenuItem->Release();
            bIsMenuLoaded = true;
        } else {
            acutPrintf("\nMenu not created.");
        }
    } else {
        VariantInit(&index);
        V_VT(&index) = VT_BSTR;
        V_BSTR(&index) = wstrMenuName;
        pPopUpMenus->RemoveMenuFromMenuBar(index);
        VariantClear(&index);
        bIsMenuLoaded = false;
    }
    pPopUpMenus->Release();
}

这两个示例都可以在 ObjectARX SDK 中找到。它们位于 samples\com 目录中。每个示例都包含使用 Win32 API 或 MFC 编程技术添加圆圈和菜单的代码。由于这些方法通过 COM 接口访问 AutoCAD,因此可以从其他 C++ 上下文中使用这些编程技术,而不仅仅是从 ObjectARX 使用。类似的技术也可以用于其他语言,如 Visual Basic。


路过

雷人

握手

鲜花

鸡蛋

最新评论

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

GMT+8, 2025-3-14 07:36

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部