void CExcelaDlg::OnAutocadtest()
{
// TODO: Add your control notification handler code here
IAcadApplication m_autocad;
IAcadDocuments m_acaddocs;
IAcadDocument m_acaddoc;
IAcadModelSpace m_acadmodel;
LPDISPATCH pDisp;
LPUNKNOWN pUnk;
CLSID clsid;
BeginWaitCursor();
::CLSIDFromProgID(L"
AutoCAD.Application",&clsid);
if(::GetActiveObject(clsid,NULL,&pUnk)==S_OK)
{
VERIFY(pUnk->QueryInterface(IID_IDispatch,(void**) &pDisp)==S_OK);
m_autocad.AttachDispatch(pDisp);
pUnk->Release();
}
else
{
if(!m_autocad.CreateDispatch("Auto
CAD.Application"))
{
AfxMessageBox("Autocad program not found/n");
exit(1);
}
}
m_autocad.SetVisible(true);
m_acaddocs.AttachDispatch(m_autocad.GetDocuments(),true);
m_acaddoc.AttachDispatch(m_acaddocs.Add(vtMissing),true);
m_acadmodel.AttachDispatch(m_acaddoc.GetModelSpace(),true);
m_acadmodel.AddCircle(pVal,100);
m_acadmodel.ReleaseDispatch();
m_acaddoc.ReleaseDispatch();
m_acaddocs.ReleaseDispatch();
m_autocad.ReleaseDispatch();
有几个办法:
1.致信
Autodesk,要求autocad自身只能运行一个
实例
2.自己写个 Windows 外壳(Shell), 监控,只允许运行一个实例
3.拦截WinExec()
COleExceptione;HRESULThr=NOERROR;LPDISPATCHpDisp=NULL;LPUNKNOWNpUnk=NULL;CLSIDclsid;IAcadApplicationIApp=NULL;hr=::CLSIDFromProgID(L"AutoCAD.Application",&clsid);//获取类IDif(!SUCCEEDED(hr)){returnNULL;}if(::GetActiveObject(clsid,NULL,&pUnk)==S_OK){//ACAD已启动if(pUnk->QueryInte**ce(IID_IDispatch,(void**)&pDisp)==S_OK){IApp.AttachDispatch(pDisp);//建立与AutoCAD的连接pUnk->Release();returnIApp;}}elseif(!IApp.CreateDispatch(clsid,&e))//启动AutoCAD{TCHARpszErr[256];e.GetErrorMessage(pszErr,256);AfxMessageBox(pszErr);returnNULL;}
-- 一个使用ActiveX自动化技术读写DWG文件的程序
斑竹,请救!在VC环境下我用OLE自动化技术来读写AutoCAD的DWG文件,我完全按照别人文章的程序建立程序,但是出现AutoCAD无法启动的错误.请问这是什么原因?
其读写DWG文件的函数如下:
void CAcadRWDwgDoc::OnRwDwg()
{
// TODO: Add your command handler code here
VARIANT startPoint,endPoint;
SAFEARRAY* start = NULL;
SAFEARRAY* end = NULL;
IAcadApplication acad;
COleVariant covTrue((short)TRUE),
covFalse((short)FALSE),
covOne((long)0),
covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
//启动Autocad应用软件
if(!acad.CreateDispatch("AutoCAD.Application.15"))
{
AfxMessageBox("Autocad 启动失败");
return;
}
acad.SetVisible(TRUE);
IAcadDocuments docs = acad.GetDocuments();
long total = docs.GetCount();
IAcadDocument doc = docs.Open("C:Documents and SettingsAdministratorMyDocumentsDrawing1",covFalse);
IAcadModelSpace mSpace = doc.GetModelSpace();
long entitiesNum = mSpace.GetCount();
if(entitiesNum >= 1)
{
IAcadEntity entity = mSpace.Item(covOne);
CString name = entity.GetObjectName();
if(name == "AcDbLine"){
IAcadLine line = mSpace.Item(covOne);
startPoint = line.GetStartPoint();
endPoint = line.GetEndPoint();
}
}
start = PointToSafeArrayB(1,1,0);
startPoint.vt = VT_R8|VT_ARRAY;
startPoint.parray = start;
end = PointToSafeArrayA(100,200,0);
endPoint.vt = VT_R8|VT_ARRAY;
endPoint.parray = end;
mSpace.AddLine(startPoint,endPoint);
mSpace.AddCircle(endPoint,60);
mSpace.AddText("I LOVE YOU AUTOCAD",endPoint,100);
SafeArrayDestroy(start);
SafeArrayDestroy(end);
COleVariant name("C:Documents and SettingsAdministratorMy DocumentsDrawing1");
doc.Close(covTrue,name);
acad.Quit();
}
其中当程序执行到
if(!acad.CreateDispatch("AutoCAD.Application.15"))
{
AfxMessageBox("Autocad 启动失败");
return;
}
这里时,编译指出不能找到指定的文件,另外,在注册表HKEY_CLASSES_ROOT中里找不到AutoCAD
组件的DLL文件名称。我想AutoCAD无法启动可能跟这个有关系?
----------------------------
WAHAHA:
作者: NinthOcean
时间: 2010-4-2 02:49 PM
标题: 请教一个奇怪的COM问题!
机器装了AutoCAD 2004以及AutoCAD 2006
对应的ProgID分别为:AutoCAD.Application.16,AutoCAD.Application.16.2
我CreateDispatch指定启动2004,为什么每次都打开2006,
有高手遇到类似的问题吗????
CString szAcadVersion = _T("AutoCAD.Application.16");
CLSID clsid;
::CLSIDFromProgID(szAcadVersion.AllocSysString(), &clsid);
IApp.CreateDispatch(clsid);///
作者: Danielm103
时间: 2010-4-2 06:27 PM
can you use acedGetIDispatch ();
作者: zngsai
时间: 2010-4-3 03:46 PM
首先更正你的错误,ACAD2004的应用程序标识符,不是AutoCAD.Application.16,而是AutoCAD.Application.16.0。
不过,尽管你改成了正确的应用程序标识符,仍然无法达到预想效果,除非当你再打开一次ACAD2004后,再运行你的程序,则就会开启ACAD2004~
此后就会开启ACAD2004,要想开启ACAD2006,须再打开一次ACAD2006才行。
然,AutoCAD.Application.15.0不会出现这种情况,他会开启ACAD2002(假设你装了02、04、06)。
作者: niyao
时间: 2010-4-3 07:16 PM
//给一个完整的自动化菜单代码,经检测未发现不适用的AutoCAD版本,复制稍改就可以用了。其实ARX包内有示例,我不过小改了下。
void nycadacadamenu()
{
AutoCAD::IAcadApplication *pAcad;
AutoCAD::IAcadMenuBar *pMenuBar;
AutoCAD::IAcadMenuGroups *pMenuGroups;
AutoCAD::IAcadMenuGroup *pMenuGroup;
AutoCAD::IAcadPopupMenus *pPopUpMenus;
AutoCAD::IAcadPopupMenu *pPopUpMenu;
AutoCAD::IAcadPopupMenuItem *pPopUpMenuItem;
try{
HRESULT hr = NOERROR;
CLSID clsid;
LPUNKNOWN pUnk = NULL;
LPDISPATCH pAcadDisp = NULL;
hr = ::CLSIDFromProgID(L"AutoCAD.Application", &clsid);//不加AutoCAD版本号才是关键!!
if (SUCCEEDED(hr))
{
if(::GetActiveObject(clsid, NULL, &pUnk) == S_OK)//检测AutoCAD是否启动
{
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, "地籍(&C)", -1, wstrMenuName, 256);
// Enables the menu to be loaded/unloaded with the same command.
::VariantInit(&index);
V_VT(&index) = VT_BSTR;
V_BSTR(&index) = SysAllocString(wstrMenuName);
hr = pPopUpMenus->Item(index,&pPopUpMenu);
::SysFreeString(index.bstrVal);
if(hr == S_OK){
pPopUpMenus->Release();
VARIANT_BOOL bFlag;
pPopUpMenu->get_OnMenuBar(&bFlag);
if(bFlag == VARIANT_FALSE)
{
::VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = numberOfMenus - 2;//确保自己的下拉菜单位于AutoCAD主菜单右边数第三个
pPopUpMenu->InsertInMenuBar(index);
}
pPopUpMenu->Release();
return;
}
pPopUpMenus->Add(wstrMenuName, &pPopUpMenu);
pPopUpMenus->Release();
if (pPopUpMenu != NULL) {
pPopUpMenu->put_Name(wstrMenuName);
WCHAR wstrMenuItemName[256];
WCHAR wstrMenuItemMacro[256];
MultiByteToWideChar(CP_ACP, 0, "绘界址线", -1, wstrMenuItemName, 256);
MultiByteToWideChar(CP_ACP, 0, "INPUTLINE ", -1, wstrMenuItemMacro, 256);
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = 0;
pPopUpMenu->AddMenuItem(index, wstrMenuItemName, wstrMenuItemMacro, &pPopUpMenuItem);
pPopUpMenuItem->put_HelpString(L"地籍测量:绘制界址线段。");
MultiByteToWideChar(CP_ACP, 0, "界址边长", -1, wstrMenuItemName, 256);
MultiByteToWideChar(CP_ACP, 0, "INPUTDIST ", -1, wstrMenuItemMacro, 256);
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = 1;
pPopUpMenu->AddMenuItem(index, wstrMenuItemName, wstrMenuItemMacro, &pPopUpMenuItem);
pPopUpMenuItem->put_HelpString(L"地籍测量:拾取界址线输入边长。");
//省略其它菜单
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = 19;
pPopUpMenu->AddSeparator(index,&pPopUpMenuItem);//菜单分割条的代码提供一下
//省略其它菜单
MultiByteToWideChar(CP_ACP,0,"关于...",-1,wstrMenuItemName,256);
MultiByteToWideChar(CP_ACP, 0, "ABOUTTHIS ", -1, wstrMenuItemMacro, 256);
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = 32;
pPopUpMenu->AddMenuItem(index, wstrMenuItemName, wstrMenuItemMacro, &pPopUpMenuItem);
pPopUpMenuItem->put_HelpString(L"关于...:软件版本、版权说明。");
VariantInit(&index);
V_VT(&index) = VT_I4;
V_I4(&index) = numberOfMenus - 2;
pPopUpMenu->InsertInMenuBar(index);
pPopUpMenuItem->Release();
pPopUpMenu->Release();
}//if
else{
}
}//try
catch(...)
{
AfxMessageBox("Unexpect error.");
if(!pAcad) pAcad->Release();
if(!pMenuBar) pMenuBar->Release();
if(!pMenuGroups) pMenuGroups->Release();
if(!pMenuGroup) pMenuGroup->Release();
if(!pPopUpMenus) pPopUpMenus->Release();
if(!pPopUpMenu) pPopUpMenu->Release();
}
}//结束