明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 13210|回复: 18

[重定义] 想过使用.net开发自定义实体没有(一)-源程序

  [复制链接]
发表于 2010-12-23 14:47 | 显示全部楼层 |阅读模式
本帖最后由 fivegg 于 2010-12-23 19:48 编辑

是否一直期盼着AutoCAD能支持.net开发自定义实体呢。我等了很久一直没有等到。后来我想既然.net可以包裹arx类,那可能编写一个arx代理实体,将所有自定义实体的函数调用转到.net类实现呢。下面我用2007开发了一个代理类,欢迎大家拍砖。

二。使用方法

TomCustomEntityDBX.DBX  arx对象
TomCustomEntityMgd.dll  arx对象的manage class
RealEntityLib.dll       .net对象的接口,里面包含了我实现的简单例子
mgPolyTestVB.dll        生成SimpleEntity的例子
TomCustomEntityMgd.dll  显示属性的面板

复制RealEntityLib.dll到autocad2007的目录下,运行_appload加载TomCustomEntityDBX.DBX 。
运行netload加载mgPolyTestVB.dll,TomCustomEntityMgd.dll。
使用命令ttt绘制对象,使用dtpalette显示属性面板,选择生成的对象,就可以修改显示属性了。


三。目前问题
修改属性后对象不会立即绘制,需要在cad中移动一下鼠标才会刷新

QQ104794806,fivegg@163.com

后续文章:
2.C++代码分析http://bbs.mjtd.com/thread-84747-1-1.html
3。.net代码分析 http://bbs.mjtd.com/thread-84748-1-1.html

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 1威望 +1 明经币 +2 金钱 +12 收起 理由
雪山飞狐_lzh + 1 + 2 + 12 精品文章

查看全部评分

 楼主| 发表于 2010-12-23 14:52 | 显示全部楼层

想过使用.net开发自定义实体没有(三) -.net代码分析

.net实现的项目:
3.RealDotNetLib:实际的.net实体

我实现的一个简单的实体,这个对象目前必须拷贝到autocad2007目录下,否则它提示找不到。
    //[DefaultPropertyAttribute("简单DotNet对象")]
    public class SimpleEntity : IRealEntity
    {
        private Entity _proxy;
        private ObjectId _myId;

        public Point3d _PtA, _PtAB, _PtB, _PtBA;
        [Description("PtBA"),
        CategoryAttribute("位置"),
        TypeConverterAttribute(typeof(Point3dConverter))]
        public Point3d PtBA
        {
            get { return _PtBA; }
            set {
                _PtBA = value;
            }
        }
        [Description("PtB"),
        CategoryAttribute("位置"),
        TypeConverterAttribute(typeof(Point3dConverter))]
        public Point3d PtB
        {
            get { return _PtB; }
            set {
                _PtB = value;
            }
        }
        [Description("PtAB"),
        CategoryAttribute("位置"),
        TypeConverterAttribute(typeof(Point3dConverter))]
        public Point3d PtAB
        {
            get { return _PtAB; }
            set {
                _PtAB = value;
            }
        }
        [Description("PtA"),
        CategoryAttribute("位置"),
        TypeConverterAttribute(typeof(Point3dConverter))]
        public Point3d PtA
        {
            get { return _PtA; }
            set {
                _PtA = value;
            }
        }
        public String Text;
        public SimpleEntity()
        {
            PtA = new Point3d();
            PtAB = new Point3d();
            PtB = new Point3d();
            PtBA = new Point3d();
            Text = "";
        }

        #region IRealEntity 成员
        [Browsable(false)]
        public Entity Proxy
        {
            get
            {
                return _proxy;
            }
            set
            {
                _proxy = value;
            }
        }

        public void DwgInFields(DwgFiler filer)
        {
            PtA = filer.ReadPoint3d();
            PtAB = filer.ReadPoint3d();
            PtB = filer.ReadPoint3d();
            PtBA = filer.ReadPoint3d();
        }

        public void DwgOutFields(DwgFiler filer)
        {
            filer.WritePoint3d(PtA);
            filer.WritePoint3d(PtAB);
            filer.WritePoint3d(PtB);
            filer.WritePoint3d(PtBA);
        }

        public string List()
        {
            return this.ToString();
        }

        public bool WorldDraw(WorldDraw wd)
        {
            Point3dCollection pts = new Point3dCollection();
            pts.Add(PtA);
            pts.Add(PtAB);
            pts.Add(PtB);
            pts.Add(PtBA);

            wd.SubEntityTraits.SetSelectionMarker(1);

            //Database db = HostApplicationServices.WorkingDatabase;
            //Transaction trans = db.TransactionManager.StartTransaction();

            //Entity Proxy=(Entity)trans.GetObject(myId, OpenMode.ForRead);
            wd.SubEntityTraits.Color = (short)Proxy.ColorIndex;

            //trans.Commit();
            wd.Geometry.Polygon(pts);

            /*
            AcGiTextStyle style;
    style.setFileName("txt.shx");
    style.setBigFontFileName("");
    style.setTextSize(25);
    style.loadStyleRec();
    AcGePoint3d txtPt((m_PtB.x+m_PtA.x)/2.0,(m_PtB.y+m_PtA.y)/2.0,     m_PtA.z);

    mode->geometry().text(txtPt, AcGeVector3d::kZAxis,
    (m_PtAB-m_PtA),m_Text,m_Text.GetLength(),Adesk::kFalse, style);
            */
            TextStyle style = new TextStyle();
            style.FileName = "txt.shx";
            style.BigFontFileName = "";
            style.TextSize = 25;
            //style.LoadStyleRec;
            Point3d txtPt = new Point3d((PtB.X + PtA.X) / 2, (PtB.Y + PtA.Y) / 2, PtA.Z);
            wd.Geometry.Text(txtPt, new Vector3d(0, 0, 1), PtAB - PtA, Text, false, style);
            return true;
        }

        public void Dispose()
        {

        }
        public void TransformBy(Matrix3d transform)
        {
            PtA = PtA.TransformBy(transform);
            PtAB = PtAB.TransformBy(transform);
            PtB = PtB.TransformBy(transform);
            PtBA = PtBA.TransformBy(transform);
        }
        #endregion

        private string name, email;
        [CategoryAttribute("用户信息"), DescriptionAttribute("设置消费者姓名")]
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        [CategoryAttribute("用户信息"), DescriptionAttribute("设置消费者Email地址")]
        public string Email
        {
            get
            {
                return email;
            }
            set
            {
                email = value;
            }
        }
    }
4.mgPolyTestVB:使用.net代码在cad中绘制实体

<Autodesk.AutoCAD.Runtime.CommandMethod("ttt")> _
Public Sub TestFunction()

    ' get the working databasre
    Dim db As Database = HostApplicationServices.WorkingDatabase
    ' get the transaction manager for the working database
    Dim tm As DBTransMan = db.TransactionManager
    ' create a new transaction
    Dim myT As Transaction = tm.StartTransaction()
    ' start our try/catch block
    Try
            'Assembly.LoadFrom("RealEntityLib.dll")
        ' create a poly samp object via the .net wrapper
        Dim poly As New Tomcad.CustomObject.DotNetEntity() //用manager class生成CustomEntityDBX
        ' set the properties for the poly
        Dim simpEntity As New SimpleEntity()
        simpEntity.PtA = New Point3d(0, 0, 0)
        simpEntity.PtAB = New Point3d(100, 0, 0)
        simpEntity.PtB = New Point3d(100, 200, 0)
        simpEntity.PtBA = New Point3d(0, 200, 0)

        poly.SetManagedObject(simpEntity)  //这步很关键,将CustomEntityDBX的.net句柄赋值,指向我们生成的SimpleEntity。


        ' get the blocktable as before, but lets open it for read within the transaction manager
        Dim bt As BlockTable = CType(tm.GetObject(db.BlockTableId, OpenMode.ForRead, False), BlockTable)
        ' do the same again but for the model space itself, we will need to open model space for write as
        ' we will be adding to it
        Dim btr As BlockTableRecord = CType(tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False), BlockTableRecord)
        ' add the new line to the model space as before
        btr.AppendEntity(poly)
        ' and then make sure that the transaction knows about this new object
        tm.AddNewlyCreatedDBObject(poly, True)
        ' finally commit the changes
        myT.Commit()

    Catch ex As Exception

        ' an error occurred
        ' ...


    Finally

        ' for the transactions we need to call the dispose to finish off
        myT.Dispose()

    End Try
5.TomPropertyMgr:根据kean代码实现的对象属性面板,可选。因为使用autocad的com对象接口实现自定义实体的动态属性太复杂了,我搞不定,就借用kean的代码,另外显示一个属性面板。
回复 支持 0 反对 1

使用道具 举报

发表于 2018-9-28 17:34 | 显示全部楼层
共享就是伟大,感谢,学习中
 楼主| 发表于 2010-12-23 14:51 | 显示全部楼层

想过使用.net开发自定义实体没有(二) -代码分析

一。代码组成
项目组成:
C++实现的两个项目:
1.CustomEntityDBX:arx实现自定义实体,实际调用转到.net实体。只要自己编程实现IRealEntity接口,就可以被该对象调用
class DLLIMPEXP TomDotNetEntityProxy : public AcDbEntity {
...
private:
    gcroot<IRealEntity*> iRealEntity;  //.net实体句柄
public:
    TomDotNetEntityProxy () ;
    virtual ~TomDotNetEntityProxy () ;
    void set_ManagedObject(gcroot<IRealEntity*> iObject);
    gcroot<IRealEntity*>  get_ManagedObject();  
   
...
}
关键的几个函数

输出dwg时,首先输出.net对象的名字。然后调用.net对象的DwgOutFields输出自定义属性
Acad::ErrorStatus TomDotNetEntityProxy::dwgOutFields (AcDbDwgFiler *pFiler) const {
    assertReadEnabled () ;
    //----- Save parent class information first.
    Acad::ErrorStatus es =AcDbEntity::dwgOutFields (pFiler) ;
    if ( es != Acad::eOk )
        return (es) ;
    //----- Object version number needs to be saved first
    if ( (es =pFiler->writeUInt32 (TomDotNetEntityProxy::kCurrentVersionNumber)) != Acad::eOk )
        return (es) ;
    //----- Output params
    //.....
    if (iRealEntity==NULL)
        return Acad::eNullObjectPointer;
   
    //write assembly and type info
    DwgFiler* f=dynamic_cast<DwgFiler*>(RXObject::Create(pFiler,false));
    Type* t=iRealEntity->GetType();
    //f->WriteString(t->AssemblyQualifiedName);
    StringToWchar stw(t->AssemblyQualifiedName);
    pFiler->writeString( (const wchar_t*)stw);   //首先输出.net对象的名字
    //pFiler->writeString(L"test.asfasdfa.asdfasf");

    iRealEntity->DwgOutFields(f);  //调用.net对象的DwgOutFields输出自定义属性

    return (pFiler->filerStatus ()) ;
}

读入dwg时,首先读出.net对象的名字。然后调用相应.net对象的DwgInFields输出自定义属性
Acad::ErrorStatus TomDotNetEntityProxy::dwgInFields (AcDbDwgFiler *pFiler) {
    assertWriteEnabled () ;
    //----- Read parent class information first.
    Acad::ErrorStatus es =AcDbEntity::dwgInFields (pFiler) ;
    if ( es != Acad::eOk )
        return (es) ;
    //----- Object version number needs to be read first
    Adesk::UInt32 version =0 ;
    if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk )
        return (es) ;
    if ( version > TomDotNetEntityProxy::kCurrentVersionNumber )
        return (Acad::eMakeMeProxy) ;
    //- Uncomment the 2 following lines if your current object implementation cannot
    //- support previous version of that object.
    //if ( version < TomDotNetEntityProxy::kCurrentVersionNumber )
    //    return (Acad::eMakeMeProxy) ;
    //----- Read params
    //.....
   
    //if (iRealEntity==NULL)
    //    return Acad::eNullObjectPointer;


    //first read assembly and type info and load,create it 读出.net对象的名字
    DwgFiler* f=dynamic_cast<DwgFiler*>(RXObject::Create(pFiler,false));
    //String* typeName=f->ReadString();
    TCHAR* pStr;
    pFiler->readString(&pStr);
    String* typeName=WcharToString(pStr);
    delString(pStr);

    Type* t=Type::GetType(typeName,false);
    if (t==NULL)
        return Acad::eNullObjectPointer;
    iRealEntity=dynamic_cast<IRealEntity*>(Activator::CreateInstance(t));  //创建.net对象
    Entity* ent=dynamic_cast<Entity*>(RXObject::Create(this,false));
    //AcDbObjectId id=this->id();
    //iRealEntity->myId=ToObjectId(id) ;
    iRealEntity->Proxy=ent;
    iRealEntity->DwgInFields(f);   //调用其DwgInFields输入函数

    return (pFiler->filerStatus ()) ;
}

//-----------------------------------------------------------------------------
//----- AcDbEntity protocols
Adesk::Boolean TomDotNetEntityProxy::worldDraw (AcGiWorldDraw *mode) {
    assertReadEnabled () ;
    //return (AcDbEntity::worldDraw (mode)) ;
    //AcGePoint3d pts[4];
    //pts[0] = *(new AcGePoint3d(0,0,0));
    //pts[1] = *(new AcGePoint3d(100,0,0));
    //pts[2] = *(new AcGePoint3d(100,200,0));
    //pts[3] = *(new AcGePoint3d(0,200,0));

    //mode->subEntityTraits().setSelectionMarker(1); // Mark 1
    //mode->subEntityTraits().setColor(1); // Red
    //mode->geometry().polygon(4,pts);
    if (iRealEntity==NULL)
        return Acad::eNullObjectPointer;

    WorldDraw* wd=dynamic_cast<WorldDraw*>(RXObject::Create(mode,false));  //dynamic_cast<WorldDraw*>(RXObject.Create(mode,true));
    iRealEntity->WorldDraw(wd);   //调用.net对象的绘制函数
   
    //(*pRealEntity)->WorldDraw(wd);
    return Adesk::kTrue;
}

// -----------------------------------------------------------------------------
void TomDotNetEntityProxy::list(void) const
{
    AcDbEntity::list () ;

    if (iRealEntity==NULL)
        return ;

    String* str=iRealEntity->List(); //调用.net对象的list函数
    StringToWchar w(str);
    acutPrintf((const wchar_t *)w);
}
//变化函数
Acad::ErrorStatus TomDotNetEntityProxy::transformBy(const AcGeMatrix3d &xform)
{
    assertWriteEnabled();
    if (iRealEntity==NULL)
        return Acad::eNullObjectPointer;

    Matrix3d m=ToMatrix3d(xform);
    iRealEntity->TransformBy(m);
    return Acad::eOk;
}
其他的getOsnapPoints等函数可以自己看情况实现
2.CustDotNetLib:CustomEntityDBX的.net类,类似cad中arx实体的.net类,例如Polyline2d ,Solid3d 都是对应的arx对象的managed class
其他函数都可以不用实现,因为这个对象只是一个arx代理对象的.net代理,我们实际操作的是另外的.net对象
namespace CustomObject
    {
        [Autodesk::AutoCAD::Runtime::Wrapper("TomDotNetEntityProxy")]
        public __gc class DotNetEntity: public Autodesk::AutoCAD::DatabaseServices::Entity
        {

        public:
            DotNetEntity();

        public private:
            DotNetEntity(System::IntPtr unmanagedPointer, bool autoDelete);
            inline TomDotNetEntityProxy*  GetImpObj()
            {
                return static_cast<TomDotNetEntityProxy*>(UnmanagedObject.ToPointer());
            }

        public:

        //static __property bool get_UseDragData();
        //static __property void set_UseDragData(bool value);

        //__property virtual bool get_Closed();
        //__property virtual bool get_IsPeriodic();
        //__property virtual bool get_IsPlanar(); this is missing from Curve!

        //__property virtual double get_StartParam();
        //__property virtual double get_EndParam();

        //AcGeVector3d GetSideVector(int whichSide);
            void SetManagedObject(IRealEntity* iObject);
            IRealEntity* GetManagedObject();
        };
    }
发表于 2010-12-23 19:07 | 显示全部楼层
第三个问题能解决最好
这应该是Arx和NetApi结合的标准方式
但还有很多问题需要解决:)
1、需要C++功底,业余的开发者很难解决
2、自定义开发现在还只是ObjectArx的禁区
3、是否有更好的解决方案?
 楼主| 发表于 2010-12-23 19:45 | 显示全部楼层
本帖最后由 fivegg 于 2010-12-23 19:50 编辑
lzh741206 发表于 2010-12-23 19:07
第三个问题能解决最好
这应该是Arx和NetApi结合的标准方式
但还有很多问题需要解决:)


我的目的就是以后都使用这个代理对象,用户实现不同的.net类。使用了我的C++模块TomCustomEntityDBX.DBX  ,用户只需要自己用.net实现IRealEntity接口就可以了。我给出C++代码只是用于高级用户的研究。过两天给出一个例子。
 楼主| 发表于 2010-12-24 11:25 | 显示全部楼层

想过使用.net开发自定义实体没有(四)--纯.net例子

四。使用例子
目录:SampleCase
1.自定义实体:新建.net类库,引用acdbmgd,acmgd,RealEntityLib
实现Tomcad.IRealEntity接口
2.在cad中使用实体的命令:新建.net类库,引用acdbmgd,acmgd,RealEntityLib,TomCustomEntityMgd
用类似代码创建:
            Dim poly As New Tomcad.CustomObject.DotNetEntity()
            ' set the properties for the poly
            Dim ent As New MyCircleEntity.MyCircleEntity()
            ent.PtCenter = New Point3d(0, 0, 0)
            ent.R = 50
            ent.Text = "Hello Circle"

            poly.SetManagedObject(ent)
3.使用步骤:
    复制MyCircleEntity.dll,RealEntityLib.dll到C:\program files\autocad2007
    将TomCustomEntityDBX.DBX,TomCustomEntityMgd.dll复制在同一个目录下
    启动autocad2007,appload加载TomCustomEntityDBX.DBX,netload加载TomCustomEntityMgd.dll,MyCircleEntity.dll。
    如果要显示属性框,netload加载Tom.PropertyMgr.dll
    运行mycicle(我拼写错误,不是mycircle)即可,可以移动复制实体。如果要改属性,使用命令dtpalette显示属性框,选择一个实体。

其他版本的auotcad请使用我的源程序编译

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2010-12-24 11:45 | 显示全部楼层
下来学习一下!谢谢。
发表于 2010-12-24 11:59 | 显示全部楼层
要点时间慢慢研究了
为了查找方便,我直接把这几个相关的帖子合并了
望见谅
 楼主| 发表于 2010-12-24 16:07 | 显示全部楼层
本帖最后由 fivegg 于 2010-12-24 16:08 编辑
lzh741206 发表于 2010-12-24 11:59
要点时间慢慢研究了
为了查找方便,我直接把这几个相关的帖子合并了
望见谅

谢谢版主,我赶出一个2011的源程序。其中C++代码中的list,worlddraw等几个函数变成了subList,subWorldDraw。.net代码不影响
由于使用civil 3d2011开发,路径请大家自己修改。


SimpleCase目录是(四)部分例子的2011代码,由于使用.net开发,没有任何改动,只是引用改了一下

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2010-12-27 22:26 | 显示全部楼层
要是能有原理的解释就更好了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-5-8 11:29 , Processed in 0.473273 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表