@版權(quán)聲明:本文為版權(quán)歸作者所有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出,
本文鏈接http://www.itdecent.cn/p/6d9bf7b96295
如有問題, 可郵件(yumxuanyi@qq.com)咨詢。
關(guān)鍵字:AutoCAD、浩辰CAD、netWrapper 、ComWrapper、objectARX
1. 編譯器常規(guī)配置
繪圖時繪制圓 請new AcDbCircle不要用mode->Geometry().circularArc浩辰中用mode繪制圓會顯示不出來,圓弧可以用mode
項目中刪除DocData.h和DocData.cpp如果不用的話,否則退出時報錯 acDocManager->會報錯
a 常規(guī)目標文件擴展名 改為.grx
b 平臺工具集 改為Visual Studio 2017(v141)
SDK版本10.0.17763.0
c c++附加包含目錄改為Grx2020\inc\arx;Grx2020\inc\Arx2010
d 預(yù)處理器最后添加 _TOOLKIT_IN_DLL_
e 鏈接器 附加庫目錄為 Grx2020\lib-x64
f 鏈接器 模塊定義文件 Grx2020\inc\Arx2010\RxExport.def
g 鏈接器 附加依耐項 為
grxport.lib(這個必須是第一個)
TD_Alloc.lib
Td_Root.lib
Td_DbRoot.lib
Td_Db.lib
Td_Ge.lib
Td_Gi.lib
Td_Gs.lib
gcax.lib
gcad.lib
gcap.lib
gcui.lib
gcut.lib
gcdb.lib
gced.lib
gcgs.lib
一. Dbx自定義實體部分處理
1 不能使用原AutoCAD的宏ACDB_REGISTER_OBJECT_ENTRY_AUTO(className)進行注冊
解決方法: 在On_InitAppMsg中手動注冊
CMyLine::rxInit();
acrxBulidClassHierarchy();
2. 不在RegisterServerComponents中進行注冊!
3.AcString 和CString比較時會調(diào)用compare方法 ,這個方法中參數(shù)不能為NULL否則報錯
4.對于曲線的intersectWith方法返回值,AutoCAD中沒有交點也會返回Acad::eok,而浩辰中則會返回Acad::eNotIntersections。所以轉(zhuǎn)換是需要判斷。
3. 繼承于AcDbCurve的類需要實現(xiàn)
getStartParam getEndParam getStartPoint getEndPoint getPointAtParam
getParamAtPoint getDistAtParam getParamAtDist getFirstDeriv等虛方法
因為浩辰中為純虛方法 并且沒有默認實現(xiàn)!
二. NetWrapper部分問題處理
- 公共語言運行時支持改為 (/clr)
- StdAfx.h中去掉acdbmgd.dll acmgd.dll AcCui.dll的引用
添加 #using <gmdb.dll>
#using <gmap.dll> - StdAfx.h中添加包含 #include "mgdinterop.h"
- Autodesk::AutoCAD 替換為GrxCAD
5 Runtime::Wrapper 替換為Runtime::WrapperAttribute - 按運行時新的語法設(shè)置類的屬性和方法,比如__gc 換成 ref class 等
7 public private 構(gòu)造函數(shù)換成public 因為在c#中需要調(diào)用這個構(gòu)造函數(shù)
8 acrxEntryPoint中添加包含文件 #include <rxservice.h>
當我們需要封裝C++對象供C#調(diào)用時,net托管代碼需要特殊處理。會出現(xiàn) 如下問題
- 在c#中不能new托管對象。
- 托管對象插入cad后,操作無反映,比如選擇無反應(yīng),如果設(shè)置了夾點,夾點無顯示等。
- 通過選擇集選擇獲取id后打開,無法識別到具體類型。
namespace Test
{
namespace EntityDb
{
//注意要寫WrapperAttribute不寫Wrapper
[GrxCAD::Runtime::WrapperAttribute("CMyLine")]
public ref class MgMyLine : public GrxCAD::DatabaseServices::Line
{
public:
//- Constructor
MgMyLine () ;
~MgMyLine () ;
//internal:
//internal改為public 因為在c#中要用這個函數(shù)創(chuàng)建一個臨時對象 net中類型識別是有問題的
//改為public 可以在c#中調(diào)用該函數(shù)來創(chuàng)建臨時對象 從而進行類型判斷
public:
MgMyLine (System::IntPtr unmanagedPointer, bool bAutoDelete) ;
//- Returns the unmanaged ARX Object
inline CMyLine *GetImpObj () {
return (static_cast<CMyLine *>(UnmanagedObject.ToPointer ())) ;
}
public:
//- To define properties which get/set values of your object
//- the format you must use is
//- __property void set_Center(Point2d point);
//- __property Point2d get_Center();
//設(shè)置定位點坐標
property GrxCAD::Geometry::Point3d MStartPoint
{
GrxCAD::Geometry::Point3d get()
{
return ToPoint3d(GetImpObj()->get_StartPoint());
}
void set(GrxCAD::Geometry::Point3d locationPoint)
{
GetImpObj()->set_StartPoint(GETPOINT3D(locationPoint));
}
}
property GrxCAD::Geometry::Point3d MEndPoint
{
GrxCAD::Geometry::Point3d get()
{
return ToPoint3d(GetImpObj()->get_EndPoint());
}
void set(GrxCAD::Geometry::Point3d locationPoint)
{
GetImpObj()->set_EndPoint(GETPOINT3D(locationPoint));
}
}
} ;
}
}
#include <gcroot.h>
namespace Test
{
namespace EntityDb
{
//-----------------------------------------------------------------------------
//1. GrxCAD::DatabaseServices::Line ( (System::IntPtr)(new CMyLine()),true) //單獨這種寫法 autodelete = true 為原默認寫法
// 寫法1造成. C#中通過new 將MgMyLine添加到塊表記錄后 選擇不了 操作不了 簡單的說無法識別
//2. GrxCAD::DatabaseServices::Line (((System::IntPtr) CMyLine::createObject().get()), true)
// 寫法2 解決了寫法1 無法選擇的問題。但是會照成
// a 通過獲取objectID打開后識別不到MgMyLine
// b 當含有有參數(shù)的構(gòu)造函數(shù)時 就不行了
//正確寫法如下 注意 autodelete = false 。因為在構(gòu)造函數(shù)中需要重新設(shè)置為true
MgMyLine::MgMyLine () : GrxCAD::DatabaseServices::Line ( (System::IntPtr)(new CMyLine()),false)
{
m_imp = UnmanagedObject ;
m_bAutoDelete = true;
}
//-----------------------------------------------------------------------------
MgMyLine::MgMyLine (System::IntPtr unmanagedPointer, bool bAutoDelete)
: GrxCAD::DatabaseServices::Line (unmanagedPointer, bAutoDelete)
{
}
MgMyLine::~MgMyLine ()
{
}
}
}
在c#中選擇托管對象并進行類型識別的方法如下
[CommandMethod("SelectLine")]
static public void SelectLine()
{
Document doc = GrxCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
PromptSelectionResult sr = ed.GetSelection();
ObjectId[] entityIds = new ObjectId[] { } ;
if (sr.Status == PromptStatus.OK)
{
entityIds = sr.Value.GetObjectIds();
}
using (DocumentLock dlock = doc.LockDocument())
{
using (Transaction trans = doc.TransactionManager.StartTransaction())
{
foreach (ObjectId entityId in entityIds)
{
//下面注釋部分為 傳統(tǒng)方法是識別不出來的
//Entity ent = trans.GetObject(entityId, OpenMode.ForRead) as Entity;
//if (ent is MgMyLine)
//{
// MgMyLine theLine = ent as MgMyLine;
// Point3d startPoint = theLine.MStartPoint;
//}
//改用如下方法
Entity ent = trans.GetObject(entityId, OpenMode.ForRead) as Entity;
string dxfName = ent.GetRXClass().DxfName;//用這個先進行判斷是哪一個類
System.IntPtr unManagedObjectPointer = ent.UnmanagedObject;//獲取非托管類的指針 用于創(chuàng)建臨時托管對象
if (dxfName == "MYLINE")
{
//判斷是這種類型后 根據(jù)非托管指針創(chuàng)建臨時托管對象
//注意第二個參數(shù)必須為false,因為這里是臨時當臨時托管對象析構(gòu)時不能將原指針給刪除了
MgMyLine managedLine = new MgMyLine(unManagedObjectPointer, false);
//下面就能正常獲取屬性了
//因為該臨時托管對象的底層數(shù)據(jù)時原非托管對象 所以本質(zhì)上操作的的是同一個對象的屬性和方法
Point3d startPoint = managedLine.MStartPoint;
Point3d endPoint = managedLine.MEndPoint;
//下面是修改屬性的方法
//因為上面是以只讀的方式打開的 所以這里升級模式
managedLine.UpgradeOpen();
managedLine.MStartPoint = new Point3d(100, 100, 0);
managedLine.MEndPoint = new Point3d(1000,300, 0);
managedLine.DowngradeOpen();
trans.Commit();//修改后提交 不修改不提交
}
}
}
}
}
三 App中處理
StdAfx.h中 0x0400改為0x0601
#include <rxsrvice.h>
四. COMWrapper部分問題處理
該部分內(nèi)容較多,如有疑問請聯(lián)系博主。
5. 數(shù)據(jù)庫讀取時,
對于采用Database dbSource = new Database() ;
a 不帶參數(shù)的統(tǒng)一換成帶參數(shù)的,如下
using(Database dbSource = new Database(false,true))
{
dbSource.ReadDwgFile(filePath,FileShare.Read,True,null);
dbSource.CloseInput(true)
}
b 使用玩ReadDwgfFile后必須關(guān)閉源
dbSource.CloseInput(true)
6 數(shù)據(jù)庫拷貝問題
使用WblockCloneObjects后 獲取拷貝后的對象的id 直接用map中的
ObjectidCollecion blockids = new ObjectIdCollection();
objectId blockDefinitionId =
using(IdMapping mapping = new idMapping())
{
blockids.Add(blockDefinitionId );
sourceDB.WblockCloneObjects(blockids,currentDB.BlockTableId,mapping,DuplicateRecordCloning.Replace,false);
newId = maping[blockDefinitionId].Value;
}
7 文件保存
GcadDocument acad = doc.AcadDocument as GcadDocument;
acad.save();
acad.Close(true);
//下面兩句在浩成cad中不能報錯文件 改用上面GcadDocument進行保存
//doc.CloseAndSave(doc.Name);
//doc.SendStringToExecute("-QSave\n",true,true,false);
8 SymbolUitlityServices.GetSymbolNameFromPathName報錯 用
Path類替代
9 使用CADApplication.SystemV ariableChanged事件會報錯 替代方案
GcadApplication.SysVarChanged事件
10 菜單加載方式
1. 用LISP會導(dǎo)致崩潰
2. 用COM方式,不同菜單會串項
解決方法:
使用.cuix文件加載
先判斷是否含有指定的組GcadMenuGroup,
如果沒有使用GrxCAD.ApplicationServices.Application.LoadPartialMenu(menuPath);來進行加載
Ribbion也是一樣
11 c
12 不支持的
1. attipedit
2. TextEditor