#import "acax19enu.tlb" raw_interfaces_only no_namespace
#define nRetry (100)
#define mSleep (500)
#define CallAcad(__x__) \
{ \
HRESULT hr; \
for (int i = 0; i < nRetry; i++) { \
if (!FAILED(hr = (__x__))) break; \
if (hr != RPC_E_CALL_REJECTED && \
hr != RPC_E_RETRY && \
hr != RPC_E_SERVERCALL_RETRYLATER) \
break; \
Sleep(mSleep); \
} \
_com_util::CheckError(hr); \
}
HRESULT PointToVariant(const double pt[3], VARIANT* pVal);
IAcadState* pState = NULL;
bool checkReady()
{
if (pState == NULL) return false;
VARIANT_BOOL bReady = VARIANT_FALSE;
for (int i = 0; i < nRetry; i++) {
if (pState->get_IsQuiescent(&bReady) == S_OK && bReady == VARIANT_TRUE) break;
Sleep(mSleep);
}
return (bReady == VARIANT_TRUE);
}
void CMFCAcadAppDlg::OnBnClickedStartacad()
{
// TODO: Add your control notification handler code here
::CoInitialize(NULL);
COleMessageFilter* pFilter = AfxOleGetMessageFilter();
if (pFilter != NULL) {
DWORD dTimedelay = 1000;
pFilter->SetMessagePendingDelay(dTimedelay); // Врем ожидания - 1 сек
pFilter->SetRetryReply(dTimedelay);
pFilter->EnableBusyDialog(FALSE); // Запрещаем диалог "сервер занят"
pFilter->EnableNotRespondingDialog(FALSE); // Запрещаем диалог "сервер не отвечает"
}
try
{
CLSID clsid ;
HRESULT hr = S_OK;
// Для AutoCAD 2014 - L"AutoCAD.Application.19.1"
// Если версия AutoCAD не важна, то можно L"AutoCAD.Application"
_com_util::CheckError(CLSIDFromProgID (L"AutoCAD.Application.19.1", &clsid));
IAcadApplicationPtr pApp;
CallAcad(pApp.CreateInstance(clsid)); // Запускаем AutoCAD
pState = NULL;
CallAcad(pApp->GetAcadState(&pState));
// Делаем AutoCAD видимым, если в этом есть необходимость
if (checkReady()) CallAcad(pApp->put_Visible(VARIANT_TRUE));
// Получаем список открытых документов AutoCAD
IAcadDocumentsPtr pDocs;
if (checkReady()) CallAcad(pApp->get_Documents(&pDocs));
IAcadDocumentPtr pDoc;
// Создаем новый документ-чертеж (для простоты с шаблоном acadiso.dwt)
if (checkReady()) CallAcad(pDocs->Add(_variant_t(_T("acadiso.dwt")), &pDoc));
// Будем работать с пространством модели
IAcadModelSpacePtr pSpace;
if (checkReady()) CallAcad(pDoc->get_ModelSpace(&pSpace));
// Добавим отрезок с началом в {0 0 0} и концом в {10 10 0}
IAcadLinePtr pLine;
_variant_t vStart, vEnd; // Начало и конец отрезка
const int iMax = 10;
double p1[3] = {0, 0, 0}, p2[3] = { iMax, iMax, 0};
CallAcad(PointToVariant(p1, &vStart));
CallAcad(PointToVariant(p2, &vEnd));
if (checkReady()) {
CallAcad(pSpace->AddLine(/*начало*/ vStart, /*конец*/ vEnd, &pLine));
}
if (checkReady()) {
CallAcad(pLine->put_color(acYellow)); // Меняем цвет на желтый
}
// Добавим окружности вдоль отрезка с радиусом 1
IAcadCirclePtr pCircle;
for (int i = 0; i <= iMax; i++) {
p1[0] = i; p1[1] = i;
PointToVariant(p1, &vStart);
if (checkReady()) {
CallAcad(pSpace->AddCircle( /*центр*/ vStart, /*радиус*/ 1.0, &pCircle));
}
if (checkReady()) {
CallAcad(pCircle->put_color(acGreen)); // Меняем цвет на зеленый
}
}
if (checkReady()) CallAcad(pApp->ZoomExtents()); // Показываем границы
if (checkReady()) CallAcad(pDoc->SaveAs(_bstr_t(_T("C:\\test.dwg"))));
if (checkReady()) CallAcad(pApp->Quit());
}
catch(const _com_error e)
{
if (e.ErrorMessage()!=NULL) {
CString msg; msg.Format(_T("Error: %s"),e.ErrorMessage());
AfxMessageBox(msg,MB_ICONERROR);
}
}
::CoUninitialize();
}
//////////////////////////////////////////////////////////////////////////
// Функция для преобразования точки double pt[3] в VARIANT
//////////////////////////////////////////////////////////////////////////
HRESULT PointToVariant(const double pt[3], VARIANT* pVal)
{
pVal->vt = VT_ARRAY | VT_R8;
SAFEARRAYBOUND rgsaBound;
rgsaBound.lLbound = 0L;
rgsaBound.cElements = 3;
pVal->parray = SafeArrayCreate(VT_R8, 1, &rgsaBound);
if (!pVal->parray) return E_OUTOFMEMORY;
HRESULT hr;
for (long i = 0; i < 3; i++) {
if ((hr = SafeArrayPutElement(pVal->parray,&i,(void*)&pt[i])) != S_OK) return hr;
}
return S_OK;
}