使用 COM 访问 AutoCAD ActiveX Automation
此方法通过纯 COM 技术访问 AutoCAD ActiveX Automation。此方法需要更多的编码,但不依赖于 MFC。示例程序使用 COM ActiveX 自动化接口向 AutoCAD 菜单栏添加新的快捷菜单。以下各节提供了演示必要步骤的过程: 设置新的 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。 |
|Archiver|CAD开发者社区
( 苏ICP备2022047690号-1 苏公网安备32011402011833)
GMT+8, 2025-11-1 14:02
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.