@版权声明:本文为版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出,
本文链接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托管代码需要特殊处理。会出现 如下问题
- 在c#中不能new托管对象。
- 托管对象插入cad后,操作无反映,比如选择无反应,如果设置了夹点,夹点无显示等。
- 通过选择集选择获取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部分问题处理
该部分内容较多,如有疑问请联系博主。
网友评论