此示例演示如何获取DWG图纸的信息,如符号表(块表、层表、文字样式表、线型表、点样式表)、字典、图元对象坐标等数据。点击下载演示实例。
DWG文件是一种数据库结构,所有图形信息都储存在该数据库中,掌握对该数据库的操作后也就会控件开发了。数据库对象包括实体、块表记、符号表记录和字典等。数据库的结构如下图:
DWG数据库中存储了构成图形的对象和实体,图形是存储在数据库中对象的集合,基本的数据库对象包括实体、符号表和字典。实体是一种指定类型的数据库对象,实体的可以直线、圆、圆弧、文字、曲线和椭圆等。用户在屏幕上可以看见实体并且可以对它进行操作。
符号表和字典是用来存储数据库对象的容器对象,这两种对象都可以将一个符号名映射到一个数据库对象。数据库包括固定数目的符号表,每一个符号表包含了一种特定类的实例作为符号表记录。符号表的例子如层表(MxDrawLayerTable,包含层表记录)和块表(MxDrawBlockTable,包含块表记录),所有实体都属于块表记录。
字典提供了一个比符号表更加通用的容器对象来存储对象,一个字典可以包含任何MxDrawMcDbObject类或其他子类的对象。
在一个使用控件过程中,可以装入多个数据库,其中每一个对象都有自己的句柄和对象ID。句柄和ID都可以唯一表示一个对象,名柄可以保存到图形中,下次打不会发生成变化,ID只是当前内存地址,它比句柄更能快速找到对象,但是它不随图保存,下次打开会发生变化。
通过对象ID,用户可以获得一个实际数据库对象,这样用户就可以对对象执行操作
数据库对象类名:MxDrawDatabase,它的详细接口说明参考:http://www.mxdraw.com/help/frames.htm?frmname=topic&frmfile=IMxDrawDatabase.htm
控件对象都内带一个数据库对象,调用ocx.GetDatabase()函数,得到数据库对象
例如得到当前控件数据库对象,C#语言
MxDrawDatabase databse = (MxDrawDatabase)axMxDrawX1.GetDatabase();
或者这样:
// 创建一个当前应用实体对象。
MxDrawApplication app = new MxDrawApplication();
//得到当前数据库对象
MxDrawDatabase database = app.WorkingDatabase();
也可以临时定义数据库对象,然后用它打开DWG文件,如C#语言
MxDrawDatabase databae = new MxDrawDatabase();
if(databae.ReadDwgFile("d:\\1.dwg","") )
{
MessageBox.Show("读取DWG文件成功");
}DWG数据库中,图层存放在图层层表中,层表类名:MxDrawLayerTable,它的详细接口说明参考:http://www.mxdraw.com/help/frames.htm?frmname=topic&frmfile=IMxDrawLayerTable.htm
层表中每一条记录称为层表记录,类名:MxDrawLayerTableRecord,它的详细接口说明参数:http://www.mxdraw.com/help/frames.htm?frmname=topic&frmfile=IMxDrawLayerTableRecord.htm
每一个层,有颜色,线型,关闭/打开,冻结等属性,DWG数据库默认总是有一个"0"层,该层不能被删除。
视频演示:
A. 当前层
当前层表示DWG数据库默认层,向数据库中添加一个对象时,默认放到该层上,该属性随图存放,通过系统变量CLAYER操作,系统变量设置参考:http://www.mxdraw.com/help_2_48.html
设置当前层代码C#:
// 新建一个图层
axMxDrawX1.AddLayer("MyLayerName");
// 设置当前层
axMxDrawX1.SetSysVarString("CLAYER", "MyLayerName");
// 设置控件Draw函数使得的层
axMxDrawX1.LayerName = "MyLayerName";
或者这样:
// 添加层
axMxDrawX1.AddLayer("aaaa");
// 得到当前数据库
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 设置当前层
database.CurrentlyLayerName = "aaaa";
取当前层代码:
String sName = "";
if(axMxDrawX1.GetSysVarString("CLAYER", ref sName))
{
MessageBox.Show("当前层名:" + sName);
}
B.添加图层
调用控件AddLayer方法添加图层,详细接口说明见:http://www.mxdraw.com/help/frames.htm?frmname=topic&frmfile=MxDrawXLib___DMxDrawX__AddLayer@BSTR.htm
例如C#代码:
// 新建一个图层
axMxDrawX1.AddLayer("MyLayerName");
// 设置控件Draw函数使得的层
axMxDrawX1.LayerName = "MyLayerName";
或使用层表Add方法来添加一个图层
private void CreateLayer()
{
// sNewLayerName新创建的图层名
string sNewLayerName = "TestNewLayer";
MxDrawApplication app = new MxDrawApplication();
// 得到当前数据为的层表对象
MxDrawLayerTable layerTable = app.WorkingDatabase().GetLayerTable();
// 向层表中新增一个层表记录
MxDrawLayerTableRecord layerTableRec = layerTable.Add(sNewLayerName);
// 设置新图层的颜色。SetRGB
MxDrawMcCmColor color = new MxDrawMcCmColor();
color.SetRGB(255, 0, 0);
layerTableRec.Color = color;
// 把新建的层设置成当前层
app.WorkingDatabase().CurrentlyLayerName = sNewLayerName;
}
文章例子运行效果:
C.遍历所有图层
下面代码是遍历层表中所有层表记录,并得到所有图层名,在遍历的循环中,得到每个层表记录对象,可以去修改它的属性
private void GetAllLayer()
{
MxDrawApplication app = new MxDrawApplication();
//返回数据库中的层表对象
MxDrawLayerTable layerTable = app.WorkingDatabase().GetLayerTable();
//创建一个遍历层表中所有图层的遍历器
MxDrawLayerTableIterator iter = layerTable.NewIterator();
if (iter == null)
return;
//所有图层名
string sRet = null;
//移动当前遍历器位置
for (; !iter.Done(); iter.Step(true, true))
{
//返回遍历器当前位置的记录
MxDrawLayerTableRecord layerTableRec = iter.GetRecord();
sRet = sRet + ',' + layerTableRec.Name;
}
MessageBox.Show(sRet);
}
文章例子运行效果:
D. 隐藏图层
隐藏一个图层的实现思路,得到数据库层表对象,然后根据层名得到层表记录对象,设置层表记录IsOff属性值。
例如代码,让用户在CAD图上选择一个对象,然后隐藏对象所在的图层C#:
private void HideLayer()
{
// 隐藏选择实体的层。
MxDrawUtility mxUtility = new MxDrawUtility();
// 当用户在图上选择一个对象。
MxDrawPoint getPt;
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "\n 选择要关闭图层的实体:");
if (ent == null)
{
return;
}
// 该对象层属性。
string sLayerName = ent.Layer;
MxDrawApplication app = new MxDrawApplication();
//返回数据库中的层表对象
MxDrawLayerTable layerTable = app.WorkingDatabase().GetLayerTable();
//关闭指定图层
MxDrawLayerTableRecord layerTableRec = layerTable.GetAt(sLayerName, false);
//返回图层是否处于关闭状态
layerTableRec.IsOff = true;
}
文章例子运行效果:
隐藏图层前:
隐藏图层后:
E. 显示图层
如下例子,得到层表,然后循环得到所有层表记录,并打开图层显示
例如代码 C#:
private void ShowLayer()
{
MxDrawApplication app = new MxDrawApplication();
//返回数据库中的层表对象
MxDrawLayerTable layerTable = app.WorkingDatabase().GetLayerTable();
//创建一个遍历层表中所有图层的遍历器
MxDrawLayerTableIterator iter = layerTable.NewIterator();
if (iter == null)
return;
//移动当前遍历器位置
for (; !iter.Done(); iter.Step(true, false))
{
//返回遍历器当前的层表记录
MxDrawLayerTableRecord layerTableRec = iter.GetRecord();
//设置图层关闭属性为false
layerTableRec.IsOff = false;
}
}
文章例子运行效果:
显示隐藏图层前:
显示隐藏图层后:
F. 锁定图层
锁定后的图层上的实体不能编辑,但可以选择,如果想也不能选择,设置控件InitSet属性值为:SelectLockLayer=N
下面演示,遍历所有图层表记录,并设置图层为锁定状态,
例如代码 C#:
private void LockeAllLayer()
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的层表对象
MxDrawLayerTable layerTable = database.GetLayerTable();
//创建一个遍历层表中所有图层的遍历器
MxDrawLayerTableIterator iter = layerTable.NewIterator();
if (iter == null)
return;
//移动当前遍历器位置
for (; !iter.Done(); iter.Step(true, false))
{
//返回遍历器当前位置的记录
MxDrawLayerTableRecord layerTableRec = iter.GetRecord();
//返回图层是否处于锁定状态
layerTableRec.IsLocked = true;
}
MessageBox.Show("锁定所有图层成功!");
}
效果展示:
F. 冻结图层
被冻结上的图层实体,不会参显示数据的生成,这样可以加快显示速度,和打开图纸的速度,它与关闭属性相比,冻结后的图层不但看不见,并且在内存中也不参加显示。
private void FrozenLayer()
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的层表对象
MxDrawLayerTable layerTable = database.GetLayerTable();
// 由层名得到层表记录。
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "n 选择要关闭图层的实体:");
if (ent == null)
{
return;
}
string sLayerName = ent.Layer;
MxDrawLayerTableRecord rec = layerTable.GetAt(sLayerName);
if (rec != null)
{
rec.IsFrozen = true;
MessageBox.Show("冻结图层成功");
}
}
G.调用图层管理界面
例如代码 C#:
axMxDrawX1.SendStringToExecute("MxLayerManager");
H.得到图层上所有对象
我们通过构造选择集,使用图层名过虑来得到某个层上所有对象,关于选择集的类说明参考:http://www.mxdraw.com/help/frames.htm?frmname=topic&frmfile=IMxDrawSelectionSet.htm
例如代码 C#:
private List<Int64> GetAllObjectsOnLayer(String sLayerName)
{
// 创建一个过滤数据连表对象。
MxDrawResbuf filter = new MxDrawResbuf();
// 把层名加入过滤条件,8是DXF组码,它代表sLayerName表示是的是一个层名。
filter.AddStringEx(sLayerName, 8);
//定义选择集对象
MxDrawSelectionSet ss = new MxDrawSelectionSet();
// 选择图上的所有对象。
ss.Select(MCAD_McSelect.mcSelectionSetAll, null, null, filter);
int i = 0;
List<Int64> listId = new List<Int64>();
// 遍历所有对象,得到对象id.
for (; i < ss.Count;i++)
{
MxDrawEntity e = ss.Item(i);
listId.Add(e.ObjectID);
}
return listId;
}
I. 设置指定图层上的实体不能选择
通过控件InitSet属性,来设置特定图层上的实体不能选择,有关IniSet的详细说明,参考:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__Iniset.htm
比如 C#:
// 设置Layer1,Layer2,Layer3图层上的实体不能选择
axMxDrawX1.Iniset = "DisableSelectLayer=Layer1;Layer2;Layer3";
J. 设置CAD实体对象,到指定层上
实体对象都有一个层属性,可以直接修改该属性。
比如 C#:
private void SetEntityToLayer()
{
// 隐藏选择实体的层。
MxDrawUtility mxUtility = new MxDrawUtility();
// 当用户在图上选择一个对象。
MxDrawPoint getPt;
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "\n 选择实体对象:");
if (ent == null)
{
return;
}
// 得到数据库对象.
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 得到层表.
MxDrawLayerTable layerTable = database.GetLayerTable();
string sLayerName = "layer";
// 得到层。
MxDrawLayerTableRecord layer = layerTable.GetAt(sLayerName, true);
if (layer == null)
{
// 如果没有层,就新建一个层。
axMxDrawX1.AddLayer(sLayerName);
}
else
{
// 如果层被删除,就反删除。
layer.SetProp("unErase", null);
}
// 设置实体层名到指定层上。
ent.Layer = sLayerName;
MessageBox.Show("已将该实体设置到指定图层");
}
K.判断该层上是否有对象,是不是一个 无用 的层。
在CAD图上,一般需要遍历所有块表记录中的实体对象,才判断某个图层上是有对象实体,然后才能放心删除一个图层,因为一个图层上如果有实体对象,你删除该图层时,实体对象就会引用一个无效的图层。
所以控件专门提供一个定制函数,用来判断该图上是否有实体对象:
比如 C#:
MxDrawResbuf param = (MxDrawResbuf)axMxDrawX1.Call("ExApp_isUselessLayer", "图层1");
if(param.AtLong(1) == 1)
{
MessageBox.Show("该图层上没有对象");
}
L.删除数据库所有无用的图层
我们提供一个定制函数,来遍历图上的所有对象,判断出图层上没有对象,然后删除。
比如 C#:
axMxDrawX1.Cal("ExApp_DeleteUselessLayer");
M.修改图层亮度
控件提供,让CAD图层上的所有对象,按指定亮度显示功能,比如亮度设置0,表示对象显示成灰色,一般一些背景不让修改的对象放在背景层上,然后把亮度设置成0.
Mx_SetLayerBright函数详细说明,参考:http://www.mxdraw.com/help/MxDrawXCustomFunction__Mx_SetLayerBright@LPCTSTR@DOUBLE@LONG.htm
Mx_SetBright 函数详细说明,参考:http://www.mxdraw.com/help/MxDrawXCustomFunction__Mx_SetBright@IN_LONG@CString.htm
例如设置图层 222按50%显示, C#代码:
MxDrawResbuf param = new MxDrawResbuf();
// 图层名
param.AddString("222");
// 图层亮度.
param.AddDouble(50);
// 不自动调用更新显示函数
param.AddLong(0);
axMxDrawX1.CallEx("Mx_SetLayerBright", param);
N. 删除图层
在删除图层前,最好判断一个该图层上是否有CAD绘图对象,如果有的话就不要删除图层
C#代码:
private bool DeleteLayer(String sLayerName)
{
// 判断图上是否对象。
MxDrawResbuf param = (MxDrawResbuf)axMxDrawX1.Call("ExApp_isUselessLayer", sLayerName);
if (param.AtLong(1) != 1)
{
// 图上还有对象,不能删除。
return false;
}
// 得到数据库对象.
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 得到层表.
MxDrawLayerTable layerTable = database.GetLayerTable();
// 得到层。
MxDrawLayerTableRecord layer = layerTable.GetAt(sLayerName, false);
if (layer == null)
{
// 没有该层
return false;
}
else
{
// 删除图层。
layer.Erase();
return true;
}
}DWG数据库中,文字样式存放在文字样式表中,表类名:MxDrawTextStyleTable,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawTextStyleTable.htm
文字样式表中每一条记录称为一种文字样式,类名:MxDrawTextStyleTableRecord,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawTextStyleTableRecord.htm
文字样式是随图纸保存,不同的图纸使用的文字样式都可能会不一样。
文字样式设置命令:Mx_Style, 比如:
ocx.SendStringToExecute("Mx_Style")调用样式界面,如下图:

文字样式主要属性有:字体文件名,大字体文件名,新建文本高度,新建文本宽度缩放比例,文字倾斜角度,TrueType字体数据等
DWG数据库默认总是有一个"Standard"文字样式,该文字样式不能被删除。
视频演示:
A. 当前文字样式
当前文字样式表示向DWG数据库添加一个文字对象时,使用的默认的文字样式,通过系统变量TEXTSTYLE操作,系统变量设置参考:
http://www.mxdraw.com/help_2_48.html
设置当前文字样式C#
// 添加文字样式
axMxDrawX1.AddTextStyle1("MyTextStyle", "txt.shx", "hztxt.shx", 1);
// 得到当前数据库
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 设置当前文字样式
database.CurrentlyTextStyle = "MyTextStyle";取当前文字样式代码:
String sCurrentTextStyle = database.CurrentlyTextStyle;
B. 添加文字样式
下面代码,得到当前数据库中的文字样式表,然后向样式表中添加一个文字样表记录
C#代码:
private void AddTextStyle(String sNewTextStyleName)
{
MxDrawApplication app = new MxDrawApplication();
//返回数据库中的文字样式表对象
MxDrawTextStyleTable txtStyleTable = app.WorkingDatabase().GetTextStyleTable();
MxDrawTextStyleTableRecord txtStyle = txtStyleTable.GetAt(sNewTextStyleName, true);
if(txtStyle != null)
{
// 当前数据已经有该文字样。
// 如果被删除,就反删除。
txtStyle.SetProp("unErase", null);
return;
}
//增加新的文字样式
MxDrawTextStyleTableRecord mxtstr = txtStyleTable.Add(sNewTextStyleName);
//设置样式的属性,如果文字样式设置了TrueType字体,就不会使用前面设置shx字体
//参数一为turetype字体名 参数二为是否粗写 参数三为是否斜写 参数四为windows字符集 参数五暂没使用
mxtstr.SetFont("黑体", false, false, 0, 0);
//设置文字样式的高度
mxtstr.textSize = 5;
}调用上面函数,增加"aa"文字样式
AddTextStyle("aa");或者也可以这样
使用ocx.AddTextStyle1(添加线形字体文字样式),ocx.AddTextStyle2(添加TrueType字体文字样式)添加文字,该函数详细接口说明参考:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__AddTextStyle1@BSTR@BSTR@BSTR@DOUBLE.htm
比如VB代码
MxDrawX1.AddTextStyle1 "MyTextStyle", "italicc.shx", "gbcbig.shx", 0.7 MxDrawX1.TextStyle = "MyTextStyle" MxDrawX1.DrawColor = 255 MxDrawX1.DrawText 0, 3000, "梦想绘图控件3.0 www.mxdraw.com", 100, 0, 0, 1
比如添加一个黑体字体的文字样式
'添加TureType字体 MxDrawX1.AddTextStyle2 "MyTrueTypeStyle", "黑体", 0.7 MxDrawX1.TextStyle = "MyTrueTypeStyle" MxDrawX1.DrawText 0, 3150, "梦想绘图控件3.0 www.mxdraw.com", 100, 0, 0, 1
效果展示:

C. 得到所有文字样式
下面代码是遍历文字样式表中所有文字样式,并得到所有文字样式名,在遍历的循环中,得到每个文字样式记录对象,可以去修改它的属性
private void GetAllTextStyle()
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的文字样式表对象
MxDrawTextStyleTable mxtst = database.GetTextStyleTable();
//创建一个遍历文字样式表中所有文字样式的遍历器
MxDrawTextStyleTableIterator iter = mxtst.NewIterator();
if (iter == null)
return;
string sRet = null;
//移动当前遍历器位置
for (; !iter.Done(); iter.Step(true, false))
{
//返回遍历器当前位置的文字样式
MxDrawTextStyleTableRecord spTextStyleRec = iter.GetRecord();
//得到文字样式名
sRet = sRet + ',' + spTextStyleRec.Name;
}
MessageBox.Show(sRet);
}运行效果如下:

D. 删除文字样式
在删除文字样式前,最好判断图上有没有文字对象正在使用该文字样式,如果有的话就不要删除文字样式
c#代码如下:
private void DelTextStyle(String sTextStyleName)
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的文字样式表表对象
MxDrawTextStyleTable TextStyleTable = database.GetTextStyleTable();
//得到文字样表中的文字样式对象
MxDrawTextStyleTableRecord TextStyleRec = TextStyleTable.GetAt(sTextStyleName, false);
if (TextStyleRec == null)
return;
//删除文字样式
TextStyleRec.Erase();
MessageBox.Show("成功删除文字样式");
}

E.调用文字样式管理界面
Mx_Style是文字样式命令名
例如代码 C#:
axMxDrawX1.SendStringToExecute("Mx_Style");F. 修改文字对象的文字样式
文字对象都一个TextStyle属性,用这个属性可以设置,或取到文字对象的文字样式。
下面代码演示设置一个文字对象的字体为黑体,如果没有文字样式,就添加文字样式。
void SetTextStyle()
{
MxDrawUtility mxUtility = new MxDrawUtility();
// 当用户在图上选择一个对象。
MxDrawPoint getPt;
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "\n 选择实体对象:");
if (ent == null)
{
return;
}
// 得到数据库对象.
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 得到文本式表.
MxDrawTextStyleTable textStyleTable = database.GetTextStyleTable();
string sTextStyleName = "MyTextStyleName";
// 得到文本式
MxDrawTextStyleTableRecord textStyle = textStyleTable.GetAt(sTextStyleName, true);
if (textStyle == null)
{
// 如果没有就新建一个。
axMxDrawX1.AddTextStyle2(sTextStyleName, "黑体", 0.7);
}
else
{
// 如果被删除,就反删除。
textStyle.SetProp("unErase", null);
textStyle.SetFont("黑体", false, false, 0, 0);
}
// 设置实体文字样式。
ent.TextStyle = sTextStyleName;
MessageBox.Show("已将该实体文字样式");
}G. 得到图所有文字对象使用的字体文件
下面代码会遍历图上所有CAD文字对象,然后取它使用的字体信息
void getAllTextFont()
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的文字样式表表对象
MxDrawTextStyleTable textStyleTable = database.GetTextStyleTable();
// 定义选择集对象
MxDrawSelectionSet ss = new MxDrawSelectionSet();
// 全选图上所有对象。
ss.AllSelect();
int i = 0;
// 遍历所有对象
for(;i <ss.Count;i++)
{
MxDrawEntity ent = ss.Item(i);
// 得到对象使用的文字样式记录.
MxDrawTextStyleTableRecord rec = textStyleTable.GetAt(ent.TextStyle);
if (rec == null)
continue;
// 得到TrueType字体属性。
String pTypeface = "";
Boolean bold = false;
Boolean italic = false;
Int32 charset = 0;
Int32 pitchAndFamily = 0;
rec.Font(out pTypeface, out bold, out italic, out charset, out pitchAndFamily);
String sShxFileName;
String sBigShxFileName;
// 如果TrueType字体名为空,表示使用的Shx字体。
if(pTypeface.Length == 0)
{
// 得到西文字体
sShxFileName = rec.fileName;
// 得到中文字体
sBigShxFileName = rec.bigFontFileName;
}
}
}H. 文字显示号问题原因和解决办法
打开DWG时,图纸中使用的shx字体文件在本地电脑不能找到时,控件会默认使用缺省的字体txt.shx,hztxt.shx来代替,这样一般文字不会显示成问号,但是如果文字中的特殊符号在默认字体也一样找不到,这时就会显示成问号。 使用缺省的字体的代替的文字样式,可能会出现文字显示大小,样子不一至的效果。
这时最好的办法是,把需要使用的字体拷到MxDrawX.ocx所在目录的shx目录下,如果不知道当前用的MxDrawX.ocx在位置,可以命令行输入mx_about看到控件安装位置

如下图,打开图时,在命令行提示找不到字体

修改控件Iniset属性,Iniset="ShxPath=D:/shx"添加一个字体搜索位置,
修改控件Iniset属性, Iniset="DownLoadServerFont=Y",设置打开网络图纸时,自动下载服务器上的字体文件。默认不会下载.,服务器需要 设置MIME,增加shx文件类型支持.
修改控件Iniset属性, Iniset="SHXWEBSITEADDRESS=http://www.mxdraw.com/shx",设置字体下载位置
修改控件Iniset属性, Iniset="DefaultText=txt.shx", 设置缺省的shx文件
修改控件Iniset属性, Iniset="DefaultBigText=hztxt.shx", 设置缺省的big shx文件
iniset属性接口说明,参考:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__Iniset.htm
I. 修改文字样式
下面代码由文字样式名得到文字样字记录,然后它的属性。
c#代码如下:
private void ModifyTextStyle(String sTextStyleName)
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的文字样式表表对象
MxDrawTextStyleTable TextStyleTable = database.GetTextStyleTable();
//得到文字样表中的文字样式对象
MxDrawTextStyleTableRecord TextStyleRec = TextStyleTable.GetAt(sTextStyleName, false);
if (TextStyleRec == null)
return;
//修改文字样式的字体高度
TextStyleRec.textSize = 10;
//修改文字宽度缩放比例
TextStyleRec.xScale = 0.7;
}DWG数据库中,标注样式存放在标注样式表中,表类名:MxDrawDimStyleTable,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawDimStyleTable.htm
标注样式表中每一条记录称为一种标注样式,类名:MxDrawDimStyleTableRecord,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawDimStyleTableRecord.htm
标注样式是随图纸保存,不同的图纸使用的标注样式都可能会不一样。
标注样式设置命令:Mx_Dimstyle, 比如:
mxOcx.SendStringToExecute("Mx_Dimstyle")
调用样式界面,如下图:
标注样式主要属性有:double,int string三个类型标注的变量设置,通过设置三类的变量的值,就能设置标注样式的各种控制值。
比如:GetDimVarDouble,SetDimVarDouble ,设置Double类型属性,可以设置的值有如下:
(m_标注变量名,DXF组码) m_dimaltf,143 m_dimasz , 41 m_dimcen ,141 m_dimdle , 46 m_dimdli , 43; m_dimexe , 44; m_dimexo , 42; m_dimgap ,147; m_dimlfac,144; m_dimrnd , 45; m_dimscale, 40; m_dimtfac,146; m_dimtm , 48; m_dimtp , 47; m_dimtsz ,142; m_dimtvp ,145; m_dimtxt ,140; m_dimaltrnd,148;
因为我们的标注设置和AutoCAD保持一至,所以如果不清楚,标注变量名具体代表什么属性,可以复制标注变量,然后在百度搜索AutocAD 标注变量名,就能看见。
比如,我们搜索 dimaltf,是什么属性,如下图:
比如,我们要修改标注样式中的文字高度,文件高度控制变量是dimtxt,对应的DXF组码是140,所以如下调用,设置文件高度是100, 140是DXF组码。
dimstyle.SetDimVarDouble(140, 100);
GetDimVarInt,SettDimVarInt ,设置Int类型属性,可以设置的值有如下:
m_dimadec,179 m_dimalt ,170 m_dimaltd ,171 m_dimalttd,274 m_dimalttz,286 m_dimaltu ,273 m_dimaltz ,285 m_dimaunit,275 m_dimclrd ,176 m_dimclre ,177 m_dimclrt ,178 m_dimdec ,271 m_dimfit ,287 m_dimjust ,280 m_dimlim , 72 m_dimsah ,173 m_dimsd1 ,281 m_dimsd2 ,282 m_dimse1 , 75 m_dimse2 , 76 m_dimsoxd ,175 m_dimtad , 77 m_dimtdec ,272 m_dimtih , 73 m_dimtix ,174 m_dimtofl ,172 m_dimtoh , 74 m_dimtol , 71 m_dimtolj ,283 m_dimzin , 78 m_dimunit ,270 m_dimupt ,288 m_dimtzin ,284 m_dimfrac ,276 m_dimlunit,277 m_dimatfit,289 m_dimtmove,279 m_dimazin, 79
比如,设置标注中的文字显示小数位,设置不显示小数位,调用如下:
curDimRecord.SetDimVarInt(271, 0);
GetDimVarString,SetDimVarString 设置String类型属性,可以设置的值有如下:
m_dimapost,4 m_dimpost,3 m_dimblk, 342 m_dimblk1, 343 m_dimblk2, 344 m_dimldrblk,341 m_dimtxsty,340 m_dimltype,345 m_dimltex1,346 m_dimltex2,347
如下,设置标注两端使用建筑标注效果
curDimRecord.SetDimVarString(342, "_ARCHTICK");
如下图风格:
视频演示:
A. 当前标注样式
当前标注样式表示向DWG数据库添加一个标注对象时,使用的默认的标注样式,通过系统变量DIMSTYLE操作,系统变量设置参考:
http://www.mxdraw.com/help_2_48.html
设置当前标注样式C#
// 添加一个标注文本使用的文字样式
Int64 idTextStyleId = axMxDrawX1.AddTextStyle1("MyTextStyle", "italicc.shx", "gbcbig.shx", 0.7);
// 文字高度140,2.5
// 标注精度: 271,4
Int64 idDimStyleId = axMxDrawX1.AddDimStyle("MyDimStyle", "41,0.25,141,0.09,40,203,140,2.5", "271,4",
"", string.Format("340,{0}", idTextStyleId) );
MxDrawDimStyleTableRecord dimRec = (MxDrawDimStyleTableRecord)axMxDrawX1.ObjectIdToObject(idDimStyleId);
// 设置小数点分隔符.
dimRec.SetDimVarInt(278, '.');
// 测量比例因子: 144,2
dimRec.SetDimVarDouble(144, 2);
// 设置超出尺寸界线 dimexe , 44
dimRec.SetDimVarDouble(44, 0.01);
// 得到当前数据库
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 设置当前文字样式
database.CurrentlyDimstyleName = "MyDimStyle";
//取当前标注样式代码:
String sCurrentlyDimstyleName = database.CurrentlyDimstyleName;
设置控件Draw函数使用标注式,需要如下:
// 设置axMxDrawX1.Drawxxx函数使用的标注样式 axMxDrawX1.DimStyle = "MyDimStyle";
B. 添加标注样式
下面代码,得到标注样式表,然后向标式表中添一个表记录。
实现c#代码如下:
private void CreateDimStyle()
{
//返回控件的数据库对象
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的标注样式表对象
IMxDrawDimStyleTable mxdim = database.GetDimStyleTable();
//增加新的标注样式
IMxDrawDimStyleTableRecord dimstr = mxdim.Add("mydim");
//设置样式属性,dimscale:标注缩放比例
dimstr.SetDimVarDouble(40, 20.0);
//返回数据库中的标注样式表对象
database.CurrentlyDimstyleName = "mydim";
}
运行效果如下:
也可以使用 AddDimStyle用来增加一个标注样式,详细参考:
http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__AddDimStyle@BSTR@BSTR@BSTR@BSTR@BSTR.htm
比如:
MxDrawX1.AddDimStyle "MyDimStyle2", "41,0.18,141,0.09,40,200", "77,1,271,3", "", "" MxDrawX1.DimStyle = "MyDimStyle2"
C. 得到所有标注样式
下面代码遍历标注样式表,然后得到每个样式名称,c#代码如下:
private void GetAllDimStyle()
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的标注样式表对象
MxDrawDimStyleTable spDimStyleTable = database.GetDimStyleTable();
//创建一个遍历器
var spIter = spDimStyleTable.NewIterator();
// 得到所有标注样式名
string sRet = null;
//移动当前遍历器位置
for (; !spIter.Done(); spIter.Step(true, true))
{
//返回遍历器当前位置的记录
var spDimStyleTableRec = spIter.GetRecord();
//符号表记录名属性
var sName = spDimStyleTableRec.Name;
if (sRet == null)
sRet = sName;
else
{
sRet = sRet + "," + sName;
}
}
MessageBox.Show(sRet);
}
效果展示:
D. 删除标注样式
在删除标注样式前,最好判断图上有没有标注对象正在使用该样式,如果有的话就不要删除文字样式
c#代码如下:
private void DelDimStyle()
{
string txt = textBox2.Text;
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的样式表对象
IMxDrawDimStyleTable DimStyleTable = database.GetDimStyleTable();
//得到样式表表中的样式对象
IMxDrawDimStyleTableRecord DimStyleRec = DimStyleTable.GetAt(txt, false);
if (DimStyleRec == null)
return;
//删除对象
DimStyleRec.Erase();
MessageBox.Show("成功删除标注样式");
}
效果展示:
E.修改标注对象的标注样式
标注对象都一个DimensionStyle属性,用这个属性可以设置或取到标注对象的标注样式。
下面代码演示设置一个标注对象的样式
void SetDimStyle()
{
MxDrawUtility mxUtility = new MxDrawUtility();
// 当用户在图上选择一个对象。
MxDrawPoint getPt;
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "\n 选择标注对象:");
if (ent == null)
{
return;
}
if(ent.ObjectName != "McDbAlignedDimension")
{
return;
}
MxDrawDimAligned dim = (MxDrawDimAligned)ent;
// 得到数据库对象.
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 得到标注样式表.
MxDrawDimStyleTable dimStyleTable = database.GetDimStyleTable();
string sDimStyleName = "MyDimStyleName";
// 得到文本式
MxDrawDimStyleTableRecord dimStyle = dimStyleTable.GetAt(sDimStyleName, true);
if (dimStyle == null)
{
// 如果没有就新建一个。
axMxDrawX1.AddDimStyle("MyDimStyleName", "41,0.18,141,0.09,40,200", "77,1,271,3", "", "");
}
else
{
// 如果被删除,就反删除。
dimStyle.SetProp("unErase", null);
}
// 设置实体文字样式。
dim.DimensionStyle = "MyDimStyleName";
MessageBox.Show("已修改对象标注样式");
}CAD图纸中有个全局字典,用来存放图纸中的全局信息,开发者可以通过在字典存放扩展记录方式存放自己的全局数据,字典已经内置了一些数据,比如:组,多线样式,布局信息,图片定义,Wipout等数据,比如下图:
全局字典类名:MxDrawDictionary,详细信息参考:http://www.mxdraw.com/help/IMxDrawDictionary.htm
得到DWG图的全局字典,c#代码:
// 得到数据库对象. MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase(); // 得到全局字典 MxDrawDictionary dict = database.GetNamedObjectsDictionary();
视频演示:
A. 遍历字典
字典中可以再存放字典(嵌套存放),也可以存一个扩展记录,类名:MxDrawXRecord,详细参考:http://www.mxdraw.com/help/IMxDrawXRecord.htm,
下面代码,演示了,使用递归方式,如果去遍历字典中所有数据,c#如下
// 遍历字典使用的递归函数。
public String GetAllDictionaryDataCall(MxDrawDictionary dict)
{
// 创建一个字典遍历器
MxDrawDictionaryIterator iter = dict.NewIterator();
String sOut = "";
for (; !iter.Done(); iter.Step())
{
// 遍历到每个字典,取出名称.
String sName = iter.Name();
sOut = sOut + "," + sName;
MxDrawMcDbObject obj = iter.GetObject();
if (obj == null)
continue;
if (obj.ObjectName == "McDbDictionary")
{
MxDrawDictionary tmpDict = (MxDrawDictionary)obj;
sOut += "," + GetAllDictionaryDataCall(tmpDict);
}
}
return sOut;
}
public void GetAllDictionaryData()
{
// 得到数据库对象.
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 得到全局字典
MxDrawDictionary dict = database.GetNamedObjectsDictionary();
String sOut = GetAllDictionaryDataCall(dict);
MessageBox.Show(sOut);
}
B. 写扩展记录
用户自定义的全局数据,通过扩展记录方式写到DWG图中
下面代码,取到图纸全局字典,然后在字典中放一个用户自己的字典,在字典写一个扩展记录数据
如下c#代码
public void wirteGlobalVer(String sName, String sVal)
{
// 得到CAD数据库
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 得到全局字典
MxDrawDictionary dict = database.GetNamedObjectsDictionary();
// 得到用户自定义字典,MyExDataDictName是字典名称
MxDrawDictionary myDict = (MxDrawDictionary)dict.GetAt("MyExDataDictName");
if (myDict == null)
{
// 如果没有,就添加一个字典。
myDict = (MxDrawDictionary)dict.AddObject("MyExDataDictName", "McDbDictionary");
}
// 得到字典中的扩展记录数据。
MxDrawXRecord rec = (MxDrawXRecord)myDict.GetAt(sName);
if (rec == null)
{
// 如果没有就,添加一个扩展记录.
rec = myDict.AddXRecord(sName);
}
// 创建数据链表.
MxDrawResbuf res = new MxDrawResbuf();
// 设置值。
res.AddString(sVal);
// 设置扩展记录数据。
rec.SetXRecordData(res);
}
执行
wirteGlobalVer("MyData", "aaaa");
DWG中的数据内容如下:
C. 读扩展记录
上面写的数据,能过如下方式读取,
C#代码:
String readGlobalVar(String sName)
{
// 得到CAD数据库
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 得到全局字典
MxDrawDictionary dict = database.GetNamedObjectsDictionary();
// 得到用户自定义字典,MyExDataDictName是字典名称
MxDrawDictionary myDict = (MxDrawDictionary)dict.GetAt("MyExDataDictName");
if (myDict == null)
{
// 没有数据。
return "";
}
// 得到字典中的扩展记录数据。
MxDrawXRecord rec = (MxDrawXRecord)myDict.GetAt(sName);
if (rec == null)
{
// 没有数据。
return "";
}
// 得到记录中的数据链表。
MxDrawResbuf ret = rec.GetXRecordData();
if (ret == null)
return "";
// 返回写的数据。
return ret.AtString(0);
}
调用代码 :
String sRet = readGlobalVar("MyData");
if (sRet == "")
{
MessageBox.Show("没有数据");
}
else
{
MessageBox.Show(sRet);
}DWG数据库中,所有图块存放在块表中,块表类名:MxDrawBlockTable,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawBlockTable.htm
块表中每一条记录称为块表记录,类名:MxDrawBlockTableRecord,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawBlockTableRecord.htm
块表记录中存放所有实体数据。每个DWG数据库中,到少有一个名为"*Model_Space"的块表记录(模型空间),CAD图纸打开后,默认看到的对象都存放在模型空间,有一种对象是块引用MxDrawBlockReference,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawBlockReference.htm,块引用又可以指向另一个块表记录。
调用MxDrawDatabase::GetBlockTable 得到DWG数据库中块表
// 得到当前数据库。 MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase(); // 得到块表. MxDrawBlockTable blkTable = database.GetBlockTable();
调用MxDrawDatabase::CurrentSpace 得到当前空间(当前显示的块表记录),有了当前空间,就能在CAD图上添加,删除,遍历显示的对象。
得到当前空间:如下代码,
// 得到当前数据库。 MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase(); // 得到当前块表记录. MxDrawBlockTableRecord blkRec = database.CurrentSpace();
A. 得到所有图块
下面代码,遍历块表的每条记录,然后得到块名,C#如下:
MxDrawDatabase databae = (MxDrawDatabase)axMxDrawX1.GetDatabase();
MxDrawBlockTable blkTab = databae.GetBlockTable();
MxDrawBlockTableIterator iter = blkTab.NewIterator();
for (; !iter.Done(); iter.Step())
{
MxDrawBlockTableRecord blkRec = iter.GetRecord();
MessageBox.Show(blkRec.Name);
}B. 判断当前数据库中,是有指定的块名
MxDrawDatabase data = (MxDrawDatabase)axMxDrawX1.GetDatabase();
if (data.GetBlockTable().Has("BlkName"))
{
// 已经插入.
}C. 遍历某名称图块下所有实体
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
MxDrawBlockTableRecord blkRec = database.GetBlockTable().GetAt(sBlkName);
MxDrawBlockTableRecordIterator iter = blkRec.NewIterator();
if (iter == null)
return;
int iNum = 0;
// 循环得到所有实体
for (; !iter.Done(); iter.Step(true, false))
{
// 得到遍历器当前的实体
MxDrawEntity ent = iter.GetEntity();
MessageBox.Show(ent.ObjectName);
iNum++;
}
MessageBox.Show(iNum.ToString());D. 得到当前空间中所有实体
下面代码演示如何得到当前块表记录,然后遍历块表记录,取到每个对象,判断对象类型,然后得到对象的属性数据。
private void GetAllEntity()
{
MxDrawApplication app = new MxDrawApplication();
MxDrawUtility mxUtility = new MxDrawUtility();
// 得到当前图纸空间
MxDrawBlockTableRecord blkRec = app.WorkingDatabase().CurrentSpace();
// 创建一个用于遍历当前图纸空间的遍历器
MxDrawBlockTableRecordIterator iter = blkRec.NewIterator();
if (iter == null)
return;
// 所有实体的id数组。
List<Int32> aryId = new List<Int32>();
int iLineNum = 0;
// 循环得到所有实体
for (; !iter.Done(); iter.Step(true, false))
{
// 得到遍历器当前的实体
MxDrawEntity ent = iter.GetEntity();
if (ent == null)
continue;
// 得到实体的id
aryId.Add((int)ent.ObjectID);
if (ent is MxDrawLine)
{
// 当前实体是一个直线
MxDrawLine line = (MxDrawLine)ent;
iLineNum++;
}
else if (ent is MxDrawBlockReference)
{
// 当前实体是一个块引用
MxDrawBlockReference blkRef = (MxDrawBlockReference)ent;
for (int j = 0; j < blkRef.AttributeCount; j++)
{
// 得到块引用中所有的属性
MxDrawAttribute attrib = blkRef.AttributeItem(j);
mxUtility.Prompt("n Tag: " + attrib.Tag + "Text:" + attrib.TextString);
}
}
// else if (ent is 其它类型)
//{
// ... ....
//}
}
String sT;
sT = "发现" + aryId.Count + "个实体,其中有" + iLineNum + "个直线";
MessageBox.Show(sT);
}E 添加块表记录
下面代码,判断块表中是否有指定名称的块表记录,如果没有就增一个块表记录。
// sName 是新增加的块名。
// blkOriginPoint 是图块的插入基点。
public bool AddBlockRrecord(String sName, MxDrawPoint blkOriginPoint)
{
// 取当前数据库.
MxDrawDatabase curDatabase = (MxDrawDatabase)(axMxDrawX1.GetDatabase());
// 得到块表
MxDrawBlockTable blkTable = curDatabase.GetBlockTable();
// 判断块表是否已经有该名称的块名。
if (blkTable.Has(sName))
{
MxDrawBlockTableRecord blkRec = blkTable.GetAt(sName, true);
// 如果块被删除,就反删除。
blkRec.SetProp("unErase", null);
return true;
}
// 新增一个块表记录.
MxDrawBlockTableRecord blkNewRec = blkTable.Add(sName);
if (blkNewRec == null)
return false;
// 设置块表记录的插入基点
blkNewRec.Origin = blkOriginPoint;
return true;
}调用代码:
MxDrawPoint pt = new MxDrawPoint();
pt.x = 100;
pt.y = 100;
AddBlockRrecord("MyBlkName", pt);运行后块表中多了一个我们添加的块表记录

F. 选择实体做成块
下面代码,让用在图上选择实体,然后把实体做成一个图块,然后插入到图上。
C#代码如下:
// 把aryId中的实体,做成一个图块.
private long MakeEntitysToBlock(
AxMxDrawXLib.AxMxDrawX mxdraw,
List<Int64> aryId
)
{
// 得到当前数据库.
MxDrawDatabase curDatabase = (MxDrawDatabase)(mxdraw.GetDatabase());
// 选择实体的最外矩形外包.
double dMinX = 0, dMinY = 0, dMaxX = 0, dMaxY = 0;
bool isFirstEnt = true;
// 遍历每个实体,计算外包。
for (int l = 0; l < aryId.Count; l++)
{
// 根据id得到实体对象.
MxDrawMcDbObject pObj = curDatabase.ObjectIdToObject(aryId[l]);
if (pObj == null)
continue;
MxDrawEntity pEnt = (MxDrawEntity)pObj;
if (pEnt == null)
continue;
// 得到实体的最小外包.
MxDrawPoint pt1Ob, pt2Ob;
pEnt.GetBoundingBox(out pt1Ob, out pt2Ob);
MxDrawPoint minPt = (MxDrawPoint)pt1Ob;
MxDrawPoint maxPt = (MxDrawPoint)pt2Ob;
if (minPt != null && maxPt != null)
{
if (isFirstEnt)
{
dMinX = minPt.x;
dMinY = minPt.y;
dMaxX = maxPt.x;
dMaxY = maxPt.y;
isFirstEnt = false;
}
else
{
if (dMinX > minPt.x)
dMinX = minPt.x;
if (dMinY > minPt.y)
dMinY = minPt.y;
if (dMaxX < maxPt.x)
dMaxX = maxPt.x;
if (dMaxY < maxPt.y)
dMaxY = maxPt.y;
}
}
}
if (isFirstEnt)
{
// 没有实体
return 0;
}
// 计算外包的中心点。
MxDrawPoint pos = new MxDrawPoint();
pos.x = dMinX + (dMaxX - dMinX) / 2.0;
pos.y = dMinY + (dMaxY - dMinY) / 2.0;
// 检查新创建的块名,在当前数据库是否已经存在.
// 得到块表.
MxDrawBlockTable blkTable = curDatabase.GetBlockTable();
// 得到当前空间的块表记录。
MxDrawBlockTableRecord curSpace = curDatabase.CurrentSpace();
String sNewBlakName;
// 添加一个匿名块,
MxDrawBlockTableRecord blkNewRec = blkTable.Add("");
// 得到系统分配的块名。
sNewBlakName = blkNewRec.Name;
// 修改新增加的块表记录的插入基点,到外包的中心点。
blkNewRec.Origin = pos;
// 遍历所有实体,把实体添加块表记录中。
for (int l = 0; l < aryId.Count; l++)
{
// 复制对象,然后添加块表记录.
blkNewRec.AddCloneEntity(aryId[l]);
// 把以前实体删除 。
MxDrawMcDbObject pObj = curDatabase.ObjectIdToObject(aryId[l]);
if (pObj == null)
continue;
pObj.Erase();
}
if (blkNewRec != null)
{
// 在当前空间中,创建一个块引对象,然后引用刚才创建的块表记录。
MxDrawBlockReference blkRef = curSpace.InsertBlock(pos.x, pos.y, sNewBlakName, 1.0, 0.0);
// 为块引用对象,添加一个属性。
MxDrawAttribute attrib = blkRef.AppendAttribute();
attrib.Position = pos;
attrib.AlignmentPoint = pos;
attrib.Oblique = 0.0;
attrib.Rotation = 0.0;
attrib.Height = 2.0;
attrib.TrueColor.SetRGB(255, 0, 0);
attrib.TextString = "这是一个属性文字的测试";
attrib.Tag = "TestTag";
attrib.IsInvisible = false;
blkRef.Position = blkRef.Position;
// 返回创建 的块引用对象的id.
return blkRef.ObjectID;
}
return 0;
}调用代码:
// 创建一个选择集对象.
MxDrawSelectionSet ss = new MxDrawSelectionSet();
// 让用户在图上选择对象.
ss.Select(MCAD_McSelect.mcSelectionSetUserSelect, null, null, null);
// 得到用户选择的对象,把对象的id放入aryID
List<Int64> aryId = new List<Int64>();
for (Int32 i = 0; i < ss.Count; i++)
{
MxDrawEntity ent = ss.Item(i);
if (ent != null)
{
aryId.Add(ent.ObjectID);
ent.Close();
}
}
// 调用函数,把选择的对象做成一个块。
MakeEntitysToBlock(axMxDrawX1,aryId);G. 把一个DWG文件插入到当前文件
调用控件的InsertBlock函数,把一个DWG文件,插入到图上,指定一个块名,放在块表记录中。InsertBlock的函数详细说明:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__InsertBlock@BSTR@BSTR.htm,
如果给的图块名,当前图上已经有该名称的图块,可以调用Mx_InsertBlockEx 自定义函数,告诉控件是否需要重新定义图块。Mx_InsertBlockEx的详细说明: http://www.mxdraw.com/help/MxDrawXCustomFunction__Mx_InsertBlockEx@CString@CString@INT@CString@bool.htm
然后调用DrawBlockReference函数绘制块引用,引用InsertBlock创建的块表记录。函数详细说明:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__DrawBlockReference@DOUBLE@DOUBLE@BSTR@DOUBLE@DOUBLE.htm
下面代码,演示如何插入DWG.
axMxDrawX1.InsertBlock("G:\pt1000.dwg", "MyBlkName");
axMxDrawX1.DrawBlockReference(0, 0, "MyBlkName", 1.0, 0.0);
axMxDrawX1.ZoomAll();H. 把一个图块插入基出,修正到图块的中心点。
下面,会遍历图块中所有实体,然后求所有实体的最小外包,再计算出外包的中心点,再把块记录的Origin属性修改到中心点。sBlkName是图块名。
private bool ModifyBlockInsertPointToCenter(String sBlkName)
{
//返回控件的数据库对象
MxDrawDatabase databae = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的块表对象
MxDrawBlockTable blkTab = databae.GetBlockTable();
MxDrawBlockTableRecord blkRec = blkTab.GetAt(sBlkName);
if (blkRec == null)
return false;
//创建一个遍历块表中所有记录的遍历器
MxDrawBlockTableRecordIterator mBlockTableReciter = blkRec.NewIterator();
MxDrawPoint mMaxPt = new MxDrawPoint();
MxDrawPoint mMinPt = new MxDrawPoint();
MxDrawPoint mMaxPtTemp = new MxDrawPoint();
MxDrawPoint mMinPtTemp = new MxDrawPoint();
bool isFirstEnt = true;
//移动当前遍历器位置
for (; !mBlockTableReciter.Done(); mBlockTableReciter.Step(true, false))
{
//与用户交互在图面上选择一个实体
MxDrawEntity ent = mBlockTableReciter.GetEntity();
//返回实体的最小矩形框外包
ent.GetBoundingBox(out mMinPtTemp, out mMaxPtTemp);
if ((mMinPtTemp == null) || (mMaxPtTemp == null))
break;
if (isFirstEnt)
{
mMinPt.x = mMinPtTemp.x;
mMinPt.y = mMinPtTemp.y;
mMaxPt.x = mMaxPtTemp.x;
mMaxPt.y = mMaxPtTemp.y;
isFirstEnt = false;
}
else
{
mMaxPt.x = Math.Max(mMaxPt.x, mMaxPtTemp.x);
mMaxPt.y = Math.Max(mMaxPt.y, mMaxPtTemp.y);
mMinPt.x = Math.Min(mMinPt.x, mMinPtTemp.x);
mMinPt.y = Math.Min(mMinPt.y, mMinPtTemp.y);
}
}
if (isFirstEnt)
{
// 没有实体
return false;
}
MxDrawPoint mNewBasePt = new MxDrawPoint();
mNewBasePt.x = mMinPt.x + (mMaxPt.x - mMinPt.x) / 2;
mNewBasePt.y = mMinPt.y + (mMaxPt.y - mMinPt.y) / 2;
//块表记录的插入原点属性
blkRec.Origin = mNewBasePt;
//重新生成图,重新生成所有显示数据
axMxDrawX1.Regen();
return true;
}I. 属性块
下面我们演示如果在AutoCAD中做一个属性块文件,然后在控件中如何插入该属性块,并修改它的属性。
1. 打开AutoCAD软件,画一些图形,比如我画了一个圆,然后用attdef命令,插入一个属性定义,如下图:

插入属性定义,如下图

2. 使用WBLOCK命令,把我们画的图形输入一个块文件,命令界面如下:
基点,选对圆的中心位置,它是图块的插入原点,点选择对象,选择我们刚画的圆和属性定义,目标指定我们的输出文件位置.

这样我们做好图块文件MyBlock.dwg
3. 下面代码,会插入MyBlock.dwg文件,然后绘一个属性块,然后修改图块属性文字,
c#如下:
private void InsertAttribBlock()
{
// 注释文本内容
String sNoteText = "这是属性文字";
// 注释图块名
String sNote = "NoteBlockName";
// 让用点取一个注释插入点。
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint point = (MxDrawPoint)(mxUtility.GetPoint(null, "点取插入点 :"));
if (point == null)
{
MessageBox.Show("用户取消..");
return;
}
// 得到当前应用对象
MxDrawApplication app = new MxDrawApplication();
// 得到当前数据库
MxDrawDatabase curDatabase = app.WorkingDatabase();
// 得到块表对象
MxDrawBlockTable blkTable = curDatabase.GetBlockTable();
// 得到当前空间
MxDrawBlockTableRecord curSpace = curDatabase.CurrentSpace();
// 当前块表中是否已经有名为sNote的块表记录,如有返回
MxDrawBlockTableRecord blkRec = blkTable.GetAt(sNote, true);
if (blkRec == null)
{
// 没有就新插入块表记录
// sBlkFilePath是块文字路径
String sBlkFilePath = "H:\\MyBlock.dwg";
// 把dwg文件导入到当前数据库。
axMxDrawX1.InsertBlock(sBlkFilePath, sNote);
// 得到新插入的块表记录
blkRec = blkTable.GetAt(sNote, true);
}
if (blkRec != null)
{
// 在当前空间中插入一个块引用。
MxDrawBlockReference blkRef = curSpace.InsertBlock(point.x, point.y, sNote, 4.0, 0.0);
// 创建属性块的属性。
MxDrawResbuf param = new MxDrawResbuf();
blkRef.SetProp("createAttribute", param);
// 修改属性文字。
for (int j = 0; j < blkRef.AttributeCount; j++)
{
// 得到块引用中所有的属性
MxDrawAttribute attrib = blkRef.AttributeItem(j);
if (attrib.Tag == "MYATTRIB")
{
attrib.TextString = sNoteText;
}
}
// 修改了属性文字,通知块引用更新显示。
blkRef.AssertWriteEnabled();
}
}运行效果如下图:

J. 得到图上所有属性块的属性文本.
下面代码,得到图上所有图块,然后遍历每个图块,再遍历每个属性块的属性
C#代码:
private void TestGeAlltBlockAttrib()
{
// 构造一个选择集.
MxDrawSelectionSet ss = new MxDrawSelectionSet();
// 创建一个过滤选择条件.
MxDrawResbuf spFilte = new MxDrawResbuf();
// 把块引用对象,当着过滤条件.
spFilte.AddStringEx("INSERT", 5020);
// 得到图上,所有引用对象.
ss.AllSelect(spFilte);
String str = "";
// 遍历所有块引用。
for (var i = 0; i < ss.Count; i++)
{
MxDrawEntity ent = ss.Item(i);
if (ent == null)
continue;
if (ent.ObjectName == "McDbBlockReference")
{
MxDrawBlockReference blkRef = (MxDrawBlockReference)ent;
// 遍历属性块的属性。
for (var j = 0; j < blkRef.AttributeCount; j++)
{
// 得到块引用中所有的属性
MxDrawAttribute attrib = blkRef.AttributeItem(j);
str += attrib.TextString + "---";
}
}
}
MessageBox.Show(str);
}DWG数据库中,线型样式存放在线型样式表中,表类名:MxDrawLinetypeTable,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawLinetypeTable.htm
线型样式表中每一条记录称为一种线型样式,类名:MxDrawLinetypeTableRecord,它的详细接口说明参考:http://www.mxdraw.com/help/IMxDrawLinetypeTableRecord.htm
线型样式是随图纸保存,不同的图纸使用的线型样式都可能会不一样。
文字样式设置命令:Mx_Linetype, 比如:
ocx.SendStringToExecute("Mx_Linetype")
简单线型定义是通一个double数组来表示,大于零表示线型的实线长度,小于零表示线型的虚线长度,比如
1,-1,2,-2定义的线如下
在控件程序所在目录下有个mx.lin线型定义文件,定义了一些常用的线型,线型文件定义格式与AutoCAD线型定义文件一至,可在百度搜索到AutoCAD线型定义文件格式教程。
调用控件函数:LoadLinetypeFromFile从线型文件加载线型,函数详细说明:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__LoadLinetypeFromFile@BSTR@BSTR@VARIANT_BOOL.htm
下面代码,从线型文件加CENTER线型,然使用该线型,画一条直线
Int64 lId = axMxDrawX1.LoadLinetypeFromFile(axMxDrawX1.GetOcxAppPath() + "//mx.lin", "CENTER",true); axMxDrawX1.LineType = "CENTER"; axMxDrawX1.DrawLine(0, 0, 100, 100);
修改全局线型比例代码如下:
//返回控件的数据库对象 MxDrawDatabase databae = (MxDrawDatabase)axMxDrawX1.GetDatabase(); // 设置全局线型比例 databae.LinetypeScale = 2.0;
MxDrawDatabase的CurrentlyLineTypeScale属性,设置新增加到数据库的对象的默认线型缩放比例
MxDrawDatabase的CurrentlyLineTypeName属性,设置新增加到数据库的对象的默认线型
在有些时候,明明一些线有线型,但显示成实线的原因是,线型的中空白长度远远小于或远远大于当前视区显示的范围上长度(不在一个数量级上),此时控件会显示成实线,AutoCAD软件也一样。这时可以通修改对象的线型比例或全局线型比例,让线型的显示大小在一个合理范围内,也可通过放大或缩小视区后,然后使用重新命令重新生成显示。
A. 添加线型
使用控件的AddLinetype,AddLinetypeEx函数,添加一种线型,详细接口说明:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__AddLinetype@BSTR@BSTR.htm
下面代码,添加一个虚线,然后绘制直线使用该线型
//绘制一个虚线
//定义虚线数据据,"MyLineType"是线型名,"6,-8"是虚线的一个单位定义,6是实线长,-8是空格长。
axMxDrawX1.AddLinetype("MyLineType", "6,-10");
//设置当前线型为"MyLineType"
axMxDrawX1.LineType = "MyLineType";
//绘制一个虚线
axMxDrawX1.DrawLine(0, 30, 100, 30);
axMxDrawX1.UpdateDisplay();
下面代码,添加一个带文字的线型,如下:
// 先添加一个线型中使用的文字样式
axMxDrawX1.AddTextStyle1("MyLineTypeTextStyle", "txt.shx", "hztxt.shx", 1);
//增加一个带有形的线型
axMxDrawX1.AddLinetypeEx("MyLineType3", "(12.7,(\"T=MxDraw\",\"S=2.54\",\"L=-5.08\",\"R=0.0\",\"X=-2.54\",\"Y=-1.27\"),-10.08)", "MyLineTypeTextStyle");
// 设置当前绘图函数使用的线型
axMxDrawX1.LineType = "MyLineType3";
axMxDrawX1.LineWidth = 0;
//绘制一个带宽度的红色点划线。
axMxDrawX1.DrawLine(300, 120, 600, 120);
axMxDrawX1.LineWidth = 4;
//绘制一个带宽度红色点划斜线
axMxDrawX1.DrawLine(300, 220, 600, 220);
//更新视区显示
axMxDrawX1.UpdateDisplay();
运行效果如下:
B. 得到图上所有线型
下面C#代码,取到数据库的线型表,然后遍历表中所有线型记录对象,并得到线型名输出
private void GetAllLinetype()
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
//返回数据库中的线型表对象
MxDrawLinetypeTable linetypeTable = database.GetLinetypeTable();
//创建遍历器
MxDrawLinetypeTableIterator iter = linetypeTable.NewIterator();
if (iter == null)
return;
string sRet = null;
//移动当前遍历器位置
for (; !iter.Done(); iter.Step(true, false))
{
//返回遍历器当前位置的线型样式
MxDrawLinetypeTableRecord lineType = iter.GetRecord();
//得到文字样式名
sRet = sRet + ',' + lineType.Name;
}
MessageBox.Show(sRet);
}
C. 修对象的线型
下面代码,让用户在图上选择一个对象,然后新增加一个线型,再把对象的线型改成新增加的线型。
private void SetEntityLineType()
{
MxDrawUtility mxUtility = new MxDrawUtility();
// 当用户在图上选择一个对象。
MxDrawPoint getPt;
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "\n 选择实体对象:");
if (ent == null)
{
return;
}
axMxDrawX1.AddLinetype("MyLineType", "6,-10");
// 设置实体线型。
ent.LineType = "MyLineType";
MessageBox.Show("已经修改线型");
axMxDrawX1.UpdateDisplay();
}图纸所有对象都是从类MxDrawMcDbObject继承,该 类的详细参考:http://www.mxdraw.com/help/IMxDrawMcDbObject.htm,该类提供得到对象句柄,ID,对象类型信息等函数。
图上可见的对象是从 MxDrawEntity继承,该 类的详细参考:http://www.mxdraw.com/help/IMxDrawEntity.htm,该类提供可见实体的通用属性操作,如线型,图层,文字样式,颜色等函数。
它们在类继承图中位置如下:
类继承关系详细 PDF格式图:http://www.mxcad.net:2080/class.pdf
A. 实体ID和句柄
ID和句柄都用来标识一个对象,ID是一个64位长整型变量,是一个内存地址,访问速度最快,但它每次打开都不一样,如果需要把一个对象的标识存起来,下次又能找到对象,就需要使用句柄,句柄是一个字符串变量,它保证不管什么时候总是不会变化,句柄在DWG图纸中是唯一存在,ID是内存中唯一存在。
如下代码,得到id,句柄,如下:
// 创建一个工具对象。
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
// 让用户在图上选择一个对象。
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体");
if (ent == null)
return;
// 得到对象id;
Int64 id = ent.ObjectID;
// 得到对象句柄
String sHandle = ent.handle;
通过 id得到对象,c#代码如下:
MxDrawMcDbObject obj = (MxDrawMcDbObject)axMxDrawX1.ObjectIdToObject(id);
// 或
// 创建一个当前应用实体对象。
MxDrawApplication app = new MxDrawApplication();
//得到当前数据库对象
MxDrawDatabase database = app.WorkingDatabase();
MxDrawMcDbObject obj = database.ObjectIdToObject(id);
通过 Handle得到对象,c#代码如下:
MxDrawMcDbObject obj = (MxDrawMcDbObject)axMxDrawX1.HandleToObject(sHandle);
// 或
// 创建一个当前应用实体对象。
MxDrawApplication app = new MxDrawApplication();
//得到当前数据库对象
MxDrawDatabase database = app.WorkingDatabase();
MxDrawMcDbObject obj = database.HandleToObject(sHandle);
B. 实体的类型信息
调用ObjectName函数得到对象的类型名,有了类型名就能判断实体具体是一个什么对象,调用Dxf0函数,得到对象的DXF组码的类型名,这个和AutoCAD中的DXF组码是一样,比如直线的类型名为:McDbLine,DXF0组码值: LINE,DXF0组码值可以用来构造集时的类型过滤。
如下C#代码,
// 创建一个工具对象。
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
// 让用户在图上选择一个对象。
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体");
if (ent == null)
return;
// 得到Dxf0的值。
String sDxfType = ent.Dxf0;
if (ent.ObjectName == "McDbLine")
{
// ent是一个直线。
MxDrawLine line = (MxDrawLine)ent;
// 得到直线开始点。
MxDrawPoint pt1 = line.StartPoint;
// 得到直线结束点.
MxDrawPoint pt2 = line.EndPoint;
}
/*
else if(...)
{
// 其它类型.
}*/
C. 可见实体属性
图上可见实体的主要属性,有线型,图层,文字样式,颜色,是否可见,显示顺序,详细参见:http://www.mxdraw.com/help/!!MEMBERTYPE_Properties_IMxDrawEntity.htm
我们可以提取,和修改这些属性,如下图:
修改Visible属性,可让实体是否可见,比如:
// 隐藏实体
ent.Visible = false;
比如修改对象颜色:
如C#代码:
// -------------------------------------------------------------------------
// Summary:
// 改变实体颜色
// Parameters:
// id - 实体的id.
// iR, iG,iB - 实体的颜色
// Returns:
// 成功返回true
// -------------------------------------------------------------------------
bool ChangeColor(Int64 id,int iR,int iG,int iB)
{
// 由id得到实体对象.
MxDrawEntity ent = (MxDrawEntity)axMxDrawX1.ObjectIdToObject(id);
if (ent == null)
return false;
MxDrawMcCmColor color = new MxDrawMcCmColor();
color.SetRGB(iR, iG, iB);
// 设置实体颜色。
ent.TrueColor = color;
return true;
}
注意:由于COM对象的特性,不能这样直接修改颜色,是不起作用,例如下:
ent.TrueColor.SetRGB(iR, iG, iB);
MxDrawModifyTheColor: 用来批量修改图上所有对象的颜色,详细参见:http://www.mxdraw.com/help/IMxDrawModifyTheColor.htm,可以在打印图纸前,用该接口把图纸所有颜色设黑白色,这样打印出来更清晰。
比如下面C#代码,把所有实体颜色修改成灰色:
MxDrawModifyTheColor changeColor = new MxDrawModifyTheColor();
MxDrawApplication app = new MxDrawApplication();
changeColor.Do(app.WorkingDatabase(), 0x010101);
在修改颜色后调用Restore 恢复对象颜色。
修改显示顺序
在用户绘图时,在默认情况下,重叠对象(例如文字、宽多段线和实体填充多边形)通常按其创建次序显示:新创建的对象显示在现有对象前面。本实例演示了如何控制显示顺序,具体实现c#代码如下:
private void MxOrder()
{
MxDrawDatabase database = (MxDrawDatabase)axMxDrawX1.GetDatabase();
// 得到当前图上,最小的显示顺序
MxDrawResbuf ret = database.GetProp("getMinDrawOrder");
int lMin = ret.AtLong(0);
// 得到当前图上,最大的显示顺序
MxDrawResbuf ret2 = database.GetProp("getMaxDrawOrder");
int lMax = ret2.AtLong(0);
// 绘一个图片对象,得到它的id.
long sTemp = axMxDrawX1.DrawImage(0, 0, 0, 0, "D:\\mxcad.jpg");
// 根据id得到图片对象.
MxDrawMcDbObject ent = database.ObjectIdToObject(sTemp);
// 准备调用参数。
MxDrawResbuf param = new MxDrawResbuf();
param.AddLong(lMin + 2);
// 设置显示顺序
ent.SetProp("drawOrder", param);
// 把图上所有图形,放到当前显示范围内。
axMxDrawX1.ZoomAll();
}
由上述设置的c#代码可以将我们插入的图片显示到最开始绘制的两个实体之上,之后绘制的实体之下。效果如下图所示:
E. 扩展数据
用户可给图纸上的对象设置扩展数据,这些扩展数据可以是用户实际需求的专业数据,扩展数据支持字符串,double,int,等类型。每个扩展数据都一个扩展数据名称,每个名称下也可能有多个扩展数据,一个实体可以有多个扩展数据名称,这些扩展数据在内存中是一个链表来存放的,每个链结代表一个数据,每个链结中字符串数据长度不超过200(DWG图纸格式确定了),链表类MxDrawResbuf详细说明参考:
http://www.mxdraw.com/help/IMxDrawResbuf.htm
关于扩展数据的详细教程:
http://www.mxdraw.com/help_4_95.html
F. 编辑实体
我们提供了,复制,移动,缩放,变换,镜向等编辑实体函数,详细如下图:
下面C#代码,把实体从一个点,移到另一个点.
// 创建一个工具对象。
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
// 让用户在图上选择一个对象。
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体");
if (ent == null)
return;
// 移动实体
// 移动基点
MxDrawPoint ptBase = new MxDrawPoint();
ptBase.x = 0;
ptBase.y = 0;
// 移动到点.
MxDrawPoint ptMoveTo = new MxDrawPoint();
ptMoveTo.x = 100;
ptMoveTo.y = 100;
ent.Move(ptBase, ptMoveTo);
调用TransformBy函数,可以构建一个坐标变换矩阵,然后对实体进行变换。
下面C#代码,选对实体进行缩放,然后再移动:
// 创建一个工具对象。
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
// 让用户在图上选择一个对象。
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体");
if (ent == null)
return;
// 创建一个移动矩阵
MxDrawMatrix3d movdMat = new MxDrawMatrix3d();
// 移动向量。,100,100相当于向右,向上移动100.
MxDrawVector3d offset = new MxDrawVector3d();
offset.x = 100;
offset.y = 100;
// 设置移动矩阵.
movdMat.Translation(offset);
// 创建一个缩放矩阵.
MxDrawMatrix3d scale = new MxDrawMatrix3d();
// 设置缩放基点是0,0.
MxDrawPoint scaleBasePoint = new MxDrawPoint();
scaleBasePoint.x = 0;
scaleBasePoint.y = 0;
// 设置缩放比例为 2.
scale.Scaling(2, scaleBasePoint);
// 把两矩阵相乘.PostMultBy是右乘。
// movdMat = movdMat * scale;
// 控件的矩阵坐标变换是从表达式的右往左变换
// 所以下面这句的意思,先进行缩放,然后再进行移动变换。
movdMat.PostMultBy(scale);
// 变换实体.
ent.TransformBy(movdMat);
G. 删除实体
删除实体,直接调用控件Erase函数删除,该函数传一个实体id.
比如 :
axMxDrawX1.Erase(lId);
或都调用对象的删除函数也行,比如:
// 创建一个工具对象。
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
// 让用户在图上选择一个对象。
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体");
if (ent == null)
return;
// 删除对象。
ent.Erase();
H. 扩展记录
在CAD中,对象上面不但可以存放扩展数据,还可以存放扩展记录,在对象上可创建一个字典(这个字典和前面说到的全局字典类似),字典中存放扩展记录,这样可以存放更多的数据,调用GetExtensionDictionary函数得到字典。
下面C#代码演示如何读取对象扩展记录:
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
// 让用户在图上选择一个对象。
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体");
if (ent == null)
return;
// 得到实体扩展字典
MxDrawDictionary dict = ent.GetExtensionDictionary();
if (dict == null)
return;
// 得到字典下自己写数据的字典
MxDrawDictionary myDict = (MxDrawDictionary)dict.GetAt("MyDict");
if (myDict == null)
{
return;
}
// 得到字典内扩展记录.
MxDrawXRecord rec = (MxDrawXRecord)myDict.GetAt("MyGlobalData");
if (rec == null)
{
return;
}
// 输出扩展记录中的数据.
MxDrawResbuf data = rec.GetXRecordData();
data.PrintData();
下面C#代码演示如何写入扩展记录:
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
// 让用户在图上选择一个对象。
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体");
if (ent == null)
return;
// 写扩展字典
MxDrawResbuf param = new MxDrawResbuf();
//创建扩展字典,如果对象已经有扩展字典,该函数什么都不做。
ent.SetProp("createExtensionDictionary", param);
// 得到扩展字典
MxDrawDictionary dict = ent.GetExtensionDictionary();
if (dict == null)
return;
// 向扩展字典中增加一个自己的字典,用于写自己的数据.
MxDrawDictionary myDict = (MxDrawDictionary)dict.AddObject("MyDict", "McDbDictionary");
// 向字典中增加一个扩展记录。
MxDrawXRecord xRecord = (MxDrawXRecord)myDict.AddXRecord("MyGlobalData");
if (xRecord == null)
return;
// 做准备写入的扩展记录数据.
MxDrawResbuf xData2 = new MxDrawResbuf();
xData2.AddLong(99999);
xData2.AddDouble(666);
MxDrawPoint ptTest = new MxDrawPoint();
ptTest.x = 77;
ptTest.y = -100;
xData2.AddPoint(ptTest);
xData2.AddString("TestApp2");
// 写入数据.
xRecord.SetXRecordData(xData2);
I. 得到实体的坐标
不同的实体它的坐标属性不一样,比如直线就是开始点,和结束点属性,圆的就是中心点坐标和半径属性。所以要得实体的坐标,需要判断对象类型,然后再转换成具体的对象,再读取它的坐标。
控件提供的计算对象最小外包的函数:GetBoundingBox,详见:http://www.mxdraw.com/help/IMxDrawEntity__GetBoundingBox@[out]_IMxDrawPoint__@[out]_IMxDrawPoint__.htm
下面C#代码,得到对象最小外包矩形框坐标:
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体:");
if (ent == null)
return;
MxDrawPoint pt1Ob, pt2Ob;
// 得到最小外包。
ent.GetBoundingBox(out pt1Ob,out pt2Ob);
ent.Close();
MxDrawPoint pt1 = (MxDrawPoint)pt1Ob;
MxDrawPoint pt2 = (MxDrawPoint)pt2Ob;
if(pt1 != null && pt2 != null)
{
// 成功得到。
MxDrawApplication app = new MxDrawApplication();
app.ZoomWindow(pt1.x,pt1.y, pt2.x,pt2.y);
}
J. 实体的选择
调用控件的AddCurrentSelect函数,把实体设置成选中状,函数详见:
调用控件的ClearCurrentSelect函数清除当前选择
调用IMxDrawSelectionSet::CurrentSelect 得到当前选择的实体,详见:
下面代码,得到当前选择的实体:
MxDrawSelectionSet ss = new MxDrawSelectionSet();
MxDrawResbuf filter = new MxDrawResbuf();
ss.CurrentSelect(filter);
int i = 0;
for (; i < ss.Count; i++)
{
MxDrawEntity ent = ss.Item(i);
if (ent.ObjectName == "McDbLine")
{
// 是个直线。
MxDrawLine line = (MxDrawLine)ent;
MxDrawPoint spt = line.StartPoint;
MxDrawPoint ept = line.EndPoint;
}
else if (ent.ObjectName == "McDbPolyline")
{
// 是个多义线.
MxDrawPolyline pl = (MxDrawPolyline)ent;
int j = 0;
// 循环,得到端点坐标
for (j = 0; j < pl.NumVerts; j++)
{
MxDrawPoint pt = pl.GetPointAt(j);
}
}
}
响应控件的SelectModified事件,实时得到被选择的实体,详细接口见:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawXEvents__SelectModified@IDispatch_@IDispatch_@VARIANT_BOOL.htm
K. 闪烁实体
我们控件可以对实体进行一个动画的闪烁,这样可以更方便提示用户。
调用控件函数:TwinkeEnt,StopTwinkeEnt,StopAllTwinkeEnt,SetTwinkeTime,SetTwinkeColor ,实现实体的闪烁控制。
如下代码,让用户在图上选择一个对象,然后闪烁
MxDrawUtility mxUtility = new MxDrawUtility();
MxDrawPoint getPt;
// 让用户在图上选择一个对象。
MxDrawEntity ent = mxUtility.GetEntity(out getPt, "选择实体");
if (ent == null)
return;
// 准备闪烁颜色.
MxDrawResbuf colors = new MxDrawResbuf();
colors.AddLong(255);
colors.AddLong(65280);
axMxDrawX1.SetTwinkeColor(colors);
// 设置闪烁间隔的时间
axMxDrawX1.SetTwinkeTime(2000);
// 开始闪烁
axMxDrawX1.TwinkeEnt(ent.ObjectID);
控件DrawImageMark函数,在图上绘制一个图片标记,该标记可以是一组的图片组成,如果闪烁这样的图片标记对象,就可以做出一个图片动画效果。
例如下:
// 创建一个取点对象.
MxDrawUiPrPoint getPt =new MxDrawUiPrPoint();
getPt.message = "点取图片的插入中点";
if (getPt.go() != MCAD_McUiPrStatus.mcOk)
{
return;
}
// 得到在图上点取的点.
MxDrawPoint frstPt = getPt.value();
if (frstPt == null)
{
return;
}
// 准备一组闪烁的图片.
String sImageFile1 = axMxDrawX1.GetOcxAppPath() + "\\1.png";
String sImageFile2 = axMxDrawX1.GetOcxAppPath() + "\\2.png";
String sImageFile3 = axMxDrawX1.GetOcxAppPath() + "\\3.png";
// 绘制一个图片标记对象。
Int64 lId = axMxDrawX1.DrawImageMark(frstPt.x, frstPt.y, -20, 0, sImageFile1,
sImageFile1 + "," + sImageFile2 + "," + sImageFile3, true);
// 开始闪烁实体,运行动画。
axMxDrawX1.TwinkeEnt(lId);
L 得到鼠标左键点击下的实体
可以响应控件的鼠标左键按下事件,然后用我们FindEntAtPoint,或MxDrawSelectionSet::SelectAtPoint函数,得到鼠标坐标下面的实体。
例如
private void axMxDrawX1_MouseEvent(object sender, AxMxDrawXLib._DMxDrawXEvents_MouseEventEvent e)
{
//"lType 是事件类型,1鼠标移动,2是鼠标左键按下,3是鼠标右键按下,4是鼠标左键双击.lRet 返回非0,消息将不在往下传递"
if(e.lType == 4)
{
// 判断当前是否正在运行选择命令。
MxDrawResbuf ret = (MxDrawResbuf)axMxDrawX1.Call("Mx_IsRuningCommand", "");
if ((ret.AtString(0) == "Ok")
&& ret.AtString(1) != "intellisel"
)
return;
// 鼠标左键双击.
// 构建选择集,找到鼠标左建双击下的实体。
MxDrawSelectionSet ss = new MxDrawSelectionSet();
MxDrawResbuf filter = new MxDrawResbuf();
//filter.AddString("LINE",5020);
MxDrawPoint point = new MxDrawPoint();
point.x = e.dX;
point.y = e.dY;
// 得到点击对象。
ss.SelectAtPoint(point,filter);
if(ss.Count > 0)
{
MxDrawEntity ent = ss.Item(0);
MessageBox.Show("点击了" + ent.ObjectName + "对象");
/*
if (ent is MxDrawLine)
{
MxDrawLine line = (MxDrawLine)ent;
}
*/
}
e.lRet = 1;
// 取消后面的命令,不让鼠标事件再往下传递.
axMxDrawX1.SendStringToExecute("");
}
else if(e.lType == 3)
{
// MessageBox.Show("右键按下");
}
}
M. 动态提示
鼠标移动到实体上后,停留一会,控件可能得到该实体对象,然后能动态提示一些信息。响应控件事件:DMxDrawXEvents::InputPointToolTipEvent,详细说明参考:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawXEvents__InputPointToolTipEvent@IDispatch_@BSTR_.htm,调用函数SetDynToolTipPopTime设置动态提示时间。
在C#中,如下图,增加对该事件的响应 ,
在事件代码里,把对象类型名提示出来
private void axMxDrawX1_InputPointToolTipEvent(object sender, AxMxDrawXLib._DMxDrawXEvents_InputPointToolTipEventEvent e)
{
MxDrawDatabase databse = (MxDrawDatabase)(axMxDrawX1.GetDatabase() );
// 得到鼠标下面的对象
MxDrawMcDbObject obj = (MxDrawMcDbObject)e.pEntity;
if(obj != null)
{
// 返回提示信息
e.pToolTip = obj.ObjectName;
}
}
动态提示效果如下:
N. 其它
调用控件PutEntityInView函数,可以把实体放到视区中间,详细说明参考:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__PutEntityInView@LONGLONG@DOUBLE.htm
调用控件 DrawEntityToJpg函数,可以把实体显示输出到一个jpg文件,详细说明参考:
http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__DrawEntityToJpg@LONGLONG@BSTR@LONG@LONG@LONG.htm
我们控件提供一些打开,保存图纸的函数,下面详细说明一下:
A. 在软件启动时,自动打开图纸
调用控件函数:OpenDwgFile,详细说明参考:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__OpenDwgFile@BSTR.htm
该函数支持打开dxf,dwg,dwf,png,jpg,bmp,mxg文件
比如C#语言:
首先响应控件初始化完成事件,在控件初化完成后,调用OpenDwgFile打开图纸

然后在该事件函数中,加入打开文件代码:
private void axMxDrawX1_InitComplete(object sender, EventArgs e)
{
axMxDrawX1.OpenDwgFile("E:\\1111.dwg");
}B. 打开网络路径图纸
使用控件 OpenWebDwgFile函数,打一个http://开头网络图纸。
比如:
axMxDrawX1.OpenWebDwgFile("http://www.mxcad.net:2080/test.dwg");C. 把DWG图纸当着背景图打开
使用控件 OpenBackgroundFile函数,详细:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__OpenBackgroundFile@BSTR@VARIANT_BOOL@LONG@VARIANT_BOOL@VARIANT_BOOL.htm
该函数把dwg图纸变灰显示,图纸不能选中编辑。
D.二制流数据中加载图形
使用控件 ReadBinStream函数,可以加载二进制流形式的DWG图纸。
例如C#:
string sFileName = "G:\12345.dwg"; FileStream fileStream = new FileStream(sFileName, FileMode.Open, FileAccess.Read); BinaryReader binaryReader = new BinaryReader(fileStream); byte[] mybyte = binaryReader.ReadBytes((int)fileStream.Length); axMxDrawX1.NewFile(); axMxDrawX1.ReadBinStream(mybyte, "", 16777215);
E. 最快方式 加载图纸
DWG图纸中有很多看不见的数据,控件打开文件时,可以设置那些内容不让加载,来提高打开文件速度。
比如, 设置控件的Iniset属性的值 READCONTENT=132440最快方式打开图纸, 132440就一个位运算出来的数值,每个二进位代表是需要加那些内容,
c#设置如下:

每个二进制位代表含义:
enum ReadContent
{
kReadAllDefault = 0xFFF9FFFF,//0xFFFDFFFF=~kFastRelease & ~kReadProxyEntGet
kReadAllProxyEntGet = 0xFFFDFFFF,//0xFFFDFFFF=~kFastRelease
kReadNull = 0x0,// 下面数据都不读取
kReadExData= 0x1,
kReadHandle= 0x2,
kReadBlockRefPreviewIcon= 0x4,
kReadBlockLayoutName= 0x8,
kNamedObjectsDictionary= 0x10,// 是否读对象字典,如果不读,字典下所有数据都不会读取.
kReadGroupDict = 0x20,// 是否读取组字典
kReadLayoutDict = 0x40,
kReadMlineStyleDict = 0x80,
kReadImageDict= 0x100,
kReadXrecord= 0x200,
kReadDrawOrder= 0x400,
kReadxData= 0x800,
kReadExRecord = 0x1000,
kReadExternalReference = 0x2000,
kReadCustomEntity = 0x4000,// 是否读取自定义实体,如果该为项为真,则自动让kReadHandle值也为真,因为自定义实体需要名柄支持.
kReComputeDimBlock = 0x8000,// 是否重新生成标注块 。
kReadUserDictionary = 0x10000,// 读取命名字典下的用户字典.
kFastRelease = 0x20000,
kReadProxyEntGet = 0x40000,// 是否读取代理实体的entget.
kFastRead= kReadBlockLayoutName|kNamedObjectsDictionary|kReadLayoutDict|kReadImageDict|kFastRelease|Mcad::kReadDrawOrder
};F. 打开有密码的DWG函数
调用我们的自定义打开文件函数,Mx_OpenDwgEx,该函数可以输入DWG文件密码,和控制那些内容加载,详细参考:
http://www.mxdraw.com/help/MxDrawXCustomFunction__Mx_OpenDwgEx@IN_CString@IN_LONG@IN_CString.htm
比如打文件,传入密码,C#代码:
MxDrawXLib.MxDrawResbuf param = new MxDrawResbuf();
param.AddString("H:\20150208214210.dwg");
param.AddLong(0);
// dwg文件密码
param.AddString("password");
axMxDrawX1.CallEx("Mx_OpenDwgEx", param);G. 直接修改属性DwgFilePath打开DWG文件
如下图设置,在界面启动,自动打开111.dwg:

H. 清空当前打开内容
调用控件NewFile函数,清空所有内容,比如c#
axMxDrawX1.NewFile();
I. 图纸打开完成事件
控件打开图纸完成后,会触发该事件,用户可以在该事件里面做一些加载图纸后的一些工作。
MxDrawXEvents::OpenFileComplete,详细参考:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawXEvents__OpenFileComplete.htm
如下图,添加事件响应,c#:

J. 保存图纸
调用控件SaveDwgFile保存DWG,详细说明:http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__SaveDwgFile@BSTR.htm
该函数可以传不同的扩展名,然保存不同类型的文件,它支持保存dxf,dwf,mxg,pdf等文件格式
如下保存111.dwg:
axMxDrawX1.SaveDwgFile("e:\\111.dwg");调用扩展函数Mx_SetDefaultDwgVersion设置保存函数默认保存的dwg文件版本
如设置成默认保存为CAD2007文件格式的文件:
axMxDrawX1.CallLongParam1("Mx_SetDefaultDwgVersion", 31);函数的详细帮助如下图:

K. 保存DWG文件到服务器上
调用控件的SaveDwgToURL函数,把DWG文件提交到服务器上保存,详细说明:
http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__SaveDwgToURL@BSTR@BSTR@BSTR@BSTR.htm
该函数会把当前图纸保存到一个临时文件中,然后模拟一个文件表单提交给服务器。
例如:
if (!MxDrawXCtrl_Obj.SaveDwgToURL("http://127.0.0.1.", "/Save.aspx", "ComponentName", "6046")) {
var ret = MxDrawXCtrl_Obj.Call("Mx_GetLastError","");
alert(ret.AtString(0));
}
else {
alert("成功");
}L. 保存pdf
调用控件ExprotPdf函数,把当前图纸保存为pdf文件,详细说明:
http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__ExprotPdf@BSTR@DOUBLE@DOUBLE@BSTR@VARIANT_BOOL.htm
J. 保存JPG
调用控件SaveJpgFile函数,把当前图纸保存为jpg文件,详细说明:
http://www.mxdraw.com/help/MxDrawXLib___DMxDrawX__SaveJpgFile@BSTR@LONG@LONG@LONG.htm
调用控件DrawToJpg函数,把当前显示的指定区域内的图形输出到jpg文件,详细说明:
调用控件自定义函数:Mx_WriteJpgToURL,把控前图形保存为jpg文件,并当着一个文件表单提交给服务器,详细说明: