浩辰CAD移植過程中遇到的問題及解決方式


@版權(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部分問題處理

  1. 公共語言運行時支持改為 (/clr)
  2. StdAfx.h中去掉acdbmgd.dll acmgd.dll AcCui.dll的引用
    添加 #using <gmdb.dll>
    #using <gmap.dll>
  3. StdAfx.h中添加包含 #include "mgdinterop.h"
  4. Autodesk::AutoCAD 替換為GrxCAD
    5 Runtime::Wrapper 替換為Runtime::WrapperAttribute
  5. 按運行時新的語法設(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) 如下問題

  1. 在c#中不能new托管對象。
  2. 托管對象插入cad后,操作無反映,比如選擇無反應(yīng),如果設(shè)置了夾點,夾點無顯示等。
  3. 通過選擇集選擇獲取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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容