想过使用.net开发自定义实体没有(一)-源程序
本帖最后由 fivegg 于 2010-12-23 19:48 编辑是否一直期盼着autocad能支持.net开发自定义实体呢。我等了很久一直没有等到。后来我想既然.net可以包裹arx类,那可能编写一个arx代理实体,将所有自定义实体的函数调用转到.net类实现呢。下面我用2007开发了一个代理类,欢迎大家拍砖。
二。使用方法
TomCustomEntityDBX.DBXarx对象
TomCustomEntityMgd.dllarx对象的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
想过使用.net开发自定义实体没有(三) -.net代码分析
.net实现的项目:3.RealDotNetLib:实际的.net实体
我实现的一个简单的实体,这个对象目前必须拷贝到autocad2007目录下,否则它提示找不到。
//
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 成员
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;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
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的代码,另外显示一个属性面板。
共享就是伟大,感谢,学习中
想过使用.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;
//pts = *(new AcGePoint3d(0,0,0));
//pts = *(new AcGePoint3d(100,0,0));
//pts = *(new AcGePoint3d(100,200,0));
//pts = *(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
{
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();
};
}
第三个问题能解决最好
这应该是Arx和NetApi结合的标准方式
但还有很多问题需要解决:)
1、需要C++功底,业余的开发者很难解决
2、自定义开发现在还只是ObjectArx的禁区
3、是否有更好的解决方案? 本帖最后由 fivegg 于 2010-12-23 19:50 编辑
lzh741206 发表于 2010-12-23 19:07 http://bbs.mjtd.com/static/image/common/back.gif
第三个问题能解决最好
这应该是Arx和NetApi结合的标准方式
但还有很多问题需要解决:)
我的目的就是以后都使用这个代理对象,用户实现不同的.net类。使用了我的C++模块TomCustomEntityDBX.DBX,用户只需要自己用.net实现IRealEntity接口就可以了。我给出C++代码只是用于高级用户的研究。过两天给出一个例子。
想过使用.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请使用我的源程序编译
下来学习一下!谢谢。 要点时间慢慢研究了
为了查找方便,我直接把这几个相关的帖子合并了
望见谅 本帖最后由 fivegg 于 2010-12-24 16:08 编辑
lzh741206 发表于 2010-12-24 11:59 static/image/common/back.gif
要点时间慢慢研究了
为了查找方便,我直接把这几个相关的帖子合并了
望见谅
谢谢版主,我赶出一个2011的源程序。其中C++代码中的list,worlddraw等几个函数变成了subList,subWorldDraw。.net代码不影响
由于使用civil 3d2011开发,路径请大家自己修改。
SimpleCase目录是(四)部分例子的2011代码,由于使用.net开发,没有任何改动,只是引用改了一下
要是能有原理的解释就更好了
页:
[1]
2