CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

ObjectARX 开发指南

使用 COM 访问 AutoCAD ActiveX 自动化

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

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

设置新的 ObjectARX 项目

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

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

打开新的 DEF 文件,并将以下行添加到“导出”部分:

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

Add the following declarations to the () function: addMenuThroughCom

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

Now that your application imports the proper interfaces, you can use them to implement AutoCAD functionality. The more direct COM approach to Automation uses to access the of AutoCAD and its Automation components. The next procedure shows how to accomplish this. All code examples in this procedure should be added to your () function in the sequence presented. acedGetIDispatch()IDispatchaddMenuThroughCOM

To implement AutoCAD ActiveX Automation calls

In the AsdkPlainComSamp.cpp file, add the following code to the empty function to get AutoCAD's : addMenuThroughCOM()IDispatch

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

Use to get the AutoCAD application object. Also, make sure AutoCAD is visible. This is shown in the following code: IUnknown

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

From the AutoCAD application interface, get the menu bar and menu groups collections:

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

Determine how many menus are current on the menu bar:

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

Get the first menu from the menu groups collection. This normally is , but could be something else: ACAD

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

Get the shortcut menus collection from the first menu group:

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

Depending on whether the menu is already created, either construct a new shortcut menu or remove the previously created one. The following code completes the example:

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();

Here is the finished function:

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 )

GMT+8, 2024-5-19 16:18

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部