使用 COM 访问 AutoCAD ActiveX Automation
此方法通过纯 COM 技术访问 AutoCAD ActiveX Automation。此方法需要更多的编码,但不依赖于 MFC。示例程序使用 COM ActiveX 自动化接口向 AutoCAD 菜单栏添加新的快捷菜单。以下各节提供了演示必要步骤的过程: 设置新的 ObjectARX 项目
acad.lib acdb22.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 类型库 acax21<lang>.tlb,如以下过程所示。IAcadApplicationIAcadMenuBarIAcadMenuGroupsIAcadMenuGroupIAcadPopupMenusIAcadPopupMenuIAcadPopupMenuItem 导入 AutoCAD ActiveX 界面的步骤将以下行添加到AsdkPlainComSamp.cpp文件的顶部,确保使用系统上安装AutoCAD的路径: import "c:\\acad\\acax22<lang>.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。 |
|Archiver|CAD开发者社区
( 苏ICP备2022047690号-1 苏公网安备32011402011833)
GMT+8, 2025-3-14 05:43
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.