美文网首页
浩辰CAD移植过程中遇到的问题及解决方式

浩辰CAD移植过程中遇到的问题及解决方式

作者: yumxuanyi | 来源:发表于2020-05-21 10:20 被阅读0次

    @版权声明:本文为版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出,
    本文链接https://www.jianshu.com/p/6d9bf7b96295
    如有问题, 可邮件(yumxuanyi@qq.com)咨询。


    关键字:AutoCAD、浩辰CAD、netWrapper 、ComWrapper、objectARX

    1. Dbx自定义实体部分处理

    注意:不能使用原AutoCAD的宏ACDB_REGISTER_OBJECT_ENTRY_AUTO(className)进行注册
    解决方法: 在On_InitAppMsg中手动注册

        CMyLine::rxInit();
        acrxBulidClassHierarchy();
    

    2. NetWrapper部分问题处理

    当我们需要封装C++对象供C#调用时,net托管代码需要特殊处理。会出现 如下问题

    1. 在c#中不能new托管对象。
    2. 托管对象插入cad后,操作无反映,比如选择无反应,如果设置了夹点,夹点无显示等。
    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#中要用这个函数创建一个临时对象 net中类型识别是有问题的
           //改为public 可以在c#中调用该函数来创建临时对象 从而进行类型判断
            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();
    
                        //设置定位点坐标
            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));
                    }
                }
    
            } ;
    
        }
    }
    
    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 当含有有参数的构造函数时 就不行了
            //正确写法如下  注意 autodelete = false 。因为在构造函数中需要重新设置为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)
                        {
                            //下面注释部分为 传统方法是识别不出来的
                            //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;//获取非托管类的指针 用于创建临时托管对象
                            if (dxfName == "MYLINE")
                            {
                                //判断是这种类型后 根据非托管指针创建临时托管对象
                                //注意第二个参数必须为false,因为这里是临时当临时托管对象析构时不能将原指针给删除了
                                MgMyLine managedLine = new MgMyLine(unManagedObjectPointer, false);
    
                                //下面就能正常获取属性了
                                //因为该临时托管对象的底层数据时原非托管对象 所以本质上操作的的是同一个对象的属性和方法
                                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();//修改后提交 不修改不提交
                            }
                        }
                    }
                } 
            }
    

    3. COMWrapper部分问题处理

    该部分内容较多,如有疑问请联系博主。

    相关文章

      网友评论

          本文标题:浩辰CAD移植过程中遇到的问题及解决方式

          本文链接:https://www.haomeiwen.com/subject/xqtzohtx.html