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