Использование COM, чтобы обратиться к AutoCAD ActiveX Автоматизация
Этот метод требует большего количества кодирования, но не полагается НА MFC.
Вызывать ActiveX Автоматизацию связывает с помощью интерфейса без MFC
1 типовая программа будет использовать COM ActiveX интерфейсы Автоматизации, чтобы добавить новое всплывающее меню к строке меню AutoCAD. Visual C++ Начала и создает новый Win32 проект Динамически компонуемой библиотеки по имени AsdkComDocSamp.
2 Добавляют соответствующие значения к проектным{*строительным*} назначениям, чтобы делать проектную{*строительную*} компоновку как программа ObjectARX. Эта программа должна связаться со следующими библиотеками:
Acad.lib
Rxapi.lib
Acrx15.lib
Acutil15.lib
Acedapi.lib
3 Добавляют новый файл определения к проекту по имени AsdkComDocSamp.def и добавляют следующие линии:
DESCRIPTION ’Autodesk AsdkCom ARX test application’
LIBRARY AsdkComDocSamp
EXPORTS acrxEntryPoint
_SetacrxPtp
acrxGetApiVersion
4 Добавляют новый исходный файл к проекту по имени AsdkComDocSamp.cpp и добавляют следующий код, чтобы делать программу ObjectARX совместимой:
#include <rxregsvc.h>
#include <aced.h>
#include <adslib.h>
// Used to add/remove the menu with the same command.
//
static bool bIsMenuLoaded = false;
void
addMenuThroughCom()
{
}
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;
}
5 Импортируют AutoCAD, напечатают библиотеку, чтобы приобрести определения для объектов COM. Добавьте следующую линию к вершине AsdkComDocSamp.cpp файла.
Удостоверитесь, чтобы использовать путь для AutoCAD, установленного на вашей системе:
#import "c:\\acad\\acad.tlb" no_implementation \
Raw_interfaces_only named_guids
6 Решают, который связывает с помощью интерфейса Вас, будет должен обратиться. Так как этот пример использует строку меню AutoCAD, это требует большинства объектов меню. Они объявлены в функции addMenuThroughCom следующим образом:
AutoCAD::IAcadApplication *pAcad;
AutoCAD::IAcadMenuBar *pMenuBar;
AutoCAD::IAcadMenuGroups *pMenuGroups;
AutoCAD::IAcadMenuGroup *pMenuGroup;
AutoCAD::IAcadPopupMenus *pPopUpMenus;
AutoCAD::IAcadPopupMenu *pPopUpMenu;
AutoCAD::IAcadPopupMenuItem *pPopUpMenuItem;
7 более прямой подход COM обращаться к интерфейсам Автоматизации использует QueryInterface. Следующий код возвращает IUNKNOWN для AutoCAD:
HRESULT hr = NOERROR;
CLSID clsid;
LPUNKNOWN pUnk = NULL;
LPDISPATCH pAcadDisp = NULL;
hr = ::CLSIDFromProgID(L"AutoCAD.Application", &clsid);
if (SUCCEEDED(hr))
{
if(::GetActiveObject(clsid, NULL, &pUnk) == S_OK)
{
if (pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &pAcadDisp) != S_OK)
return;
pUnk->Release();
}
}
8 Использования IUnknown, чтобы получить объект приложения AutoCAD. Также, удостоверитесь, что AutoCAD видим и получать объекты IACADMENUBAR И IACADMENUGROUPS.
Этому показывают в следующем коде:
if (SUCCEEDED(pAcadDisp->QueryInterface (AutoCAD::IID_IAcadApplication,(void**)&pAcad)))
{
pAcad->put_Visible(true);
}
else {
acutPrintf("\nQueryInterface trouble.");
return;
}
9 С приложением AutoCAD, получите строку меню и коллекции групп меню.
Определите, сколько меню текущие на строке меню:
pAcad->get_MenuBar(&pMenuBar);
pAcad->get_MenuGroups(&pMenuGroups);
pAcad->Release();
long numberOfMenus;
pMenuBar->get_Count(&numberOfMenus);
pMenuBar->Release();
10 Получают первое меню от коллекции групп меню. Это будет обычно 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();
11 В зависимости от того, создано ли меню уже, или создает новое всплывающее меню или удаляют предварительно созданный. Следующий код заканчивает пример:
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);
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;
CLSID clsid;
LPUNKNOWN pUnk = NULL;
LPDISPATCH pAcadDisp = NULL;
hr = ::CLSIDFromProgID(L"AutoCAD.Application", &clsid);
if (SUCCEEDED(hr))
{
if(::GetActiveObject(clsid, NULL, &pUnk) == S_OK)
{
if (pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &pAcadDisp) != S_OK)
return;
pUnk->Release();
}
}
if (SUCCEEDED(pAcadDisp->QueryInterface (AutoCAD::IID_IAcadApplication,(void**)&pAcad))) {
pAcad->put_Visible(true);
}
else {
acutPrintf("\nQueryInterface trouble.");
return;
}
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);
bIsMenuLoaded = false;
}
pPopUpMenus->Release();
}
Оба из этих примеров могут быть найдены в ObjectARX SDK. Они расположены в docsamps\COM каталоге. Каждая выборка содержит код для добавления круга и меню, используя или Win32 API или MFC программирование методов.
Так как эти методы обращаются К AutoCAD через COM, связывает с помощью интерфейса, эти методы программирования могут использоваться от других программ C++ (не только ObjectARX). Также, другие языки типа Java и Visual Basic могут использоваться.