cad动态编译⽣成命令+获取在位编辑块内图元
⾸先问你⼀个问题,如果你要⽤命令改图元颜⾊,那么cad有256个颜⾊,你需要写256个命令来达到⽬的吗?
答案:不.
程序员都是喜欢偷懒的.那么如何实现呢?看本⽂就知道了.
Lisp和c#的例⼦有点相似,都是利⽤了解释器进⾏动态编译.
由于想要尽可能兼容所有cad版本,就不采⽤AddCommand函数,因为低版本没有.
Arx的例⼦就有点不⼀样了,任何版本都有AddCommand函数,触发命令后在函数做对应的操作即可.
⾄于c#能不能在 [DllImport "" Entpoint ="??"]调⽤内置arx的AddCommand函数,我就不知道了.
有知道的可以留⾔.
那它有什么可拓展的⽅向呢?
可以写⼀个配置⽂件作为快速定义命令的⽂件,例如:
ls1,螺栓1,./标准/模块.dwg,5,10
ls2,螺栓2,./标准/模块.dwg,6,20
ls3,螺栓3,./标准/模块.dwg,
命令,块名,⼯具箱某个⽬录下的dwg⽂件,插⼊时候的颜⾊,动态块拉伸距离(m10螺栓直径)
我们只需要修改这个配置⽂件就可以配置多个插⼊的图块.
Lisp的例⼦
;;;desc:修改对象颜⾊
(apply
'(lambda ( / cishu feilingyanse) ;匿名函数( 传递变量 / 局部变量 )
(setq cishu 0) ;设置循环次数初始值
(repeat 255 ;循环次数代表颜⾊数量
(setq cishu (1+ cishu) ;循环计数
feilingyanse (itoa cishu) ;循环数转化成字符串
)
(eval ;求值运⾏程序
(read ;去掉双引号,返回整个程序
(strcat ;合并多个字符串
"(defun c:"
feilingyanse ;颜⾊
" ()(BF-yansemokuai "
feilingyanse
" ))"
)
;注意反义斜杠能去掉引号作⽤
)
)
)
)
nil ;匿名函数,空参数
)
;;;name:BF-yansemokuai
;;;desc:修改颜⾊的模板
;;;arg:
;;;return:
;
;;example:(BF-yansemokuai 5)
(defun BF-yansemokuai(tuyuanyanse / ss)
;(BF-GO (list 'cmdecho 0) nil 1);出错编组
(if (setq ss (ssget))
(progn
(command "change" ss "" "p" "c" tuyuanyanse "")
;;;现在使⽤命令模式,因vla-put-Color在在位编辑的时候会修改块外.
;;;(setq ss (BF-ss->vlass ss));转为vla对象
;;;(vlax-for ^se ss ;循环体
;;; (vla-put-Color ^se tuyuanyanse) ;修改颜⾊
;;;);这⾥会修改到块外⾯的东西
)
)
;(BF-End);调⽤恢复错误处理
)
c#的例⼦
中间段的命令代码,及命令的实现
#if !HC2020
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Acap = Autodesk.AutoCAD.ApplicationServices.Application;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.EditorInput;
using GrxCAD.Geometry;
using GrxCAD.ApplicationServices;
using Acap = GrxCAD.ApplicationServices.Application;
#endif
using System;
using System.Text;
using JoinBoxCurrency;
//要注意.本cs⽂件的命名空间,类名是和动态编译字符串关联的,要修改的时候记得⼀起改.
//AutoGo.JoinBoxEnName = "JoinBox"
namespace JoinBox
{
public class DynamicEntityColor : IAutoGo
{
const string DynamicStr = nameof(DynamicEntityColor);
public Sequence SequenceId()
{
return Sequence.Last;
}
public void Terminate()
{
try
{
AppDomain.CurrentDomain.AssemblyResolve -= RunTimeCurrentDomain.DefaultAssemblyResolve;
}
catch
{
System.Windows.Forms.MessageBox.Show($"动态编译{DynamicStr}卸载出错", "惊惊连盒");
}
}
// 动态编译命令
public void Initialize()
{
try
{
AppDomain.CurrentDomain.AssemblyResolve += RunTimeCurrentDomain.DefaultAssemblyResolve;
var code = new StringBuilder();
for (int i = 0; i < 256; i++)
{
AddDynamicCommand(i.ToString(), code);
}
DynamicAssembly.Go(code, DynamicStr);
}
catch (Exception e)
{
Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;//命令栏交互
ed.WriteMessage(Environment.NewLine + $"动态编译{DynamicStr}出错::" + e.Message);
}
}
/// <summary>
/// ⽣成编译的命令部分的字符串
/// </summary>
/// <param name="command">命令</param>
private void AddDynamicCommand(string command, StringBuilder code)
{
code.Append("[CommandMethod(\"");
code.Append(command);
code.Append("\", CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw | CommandFlags.DocExclusiveLock)]"); code.Append("public static void ");
code.Append($"{DynamicStr}FuncName" + command);
code.Append("(){");
code.Append(AutoGo.JoinBoxEnName);
code.Append($".{DynamicStr}.CommandChangeEntityColor(\"{command}\");");
code.Append("}");
}
editor版本/// <summary>
/// 选择图元修改颜⾊
/// </summary>
/// <param name="dwgPath"></param>
public static void CommandChangeEntityColor(string colorIndex)
{
Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;//命令栏交互
Database db = HostApplicationServices.WorkingDatabase;//当前的数据库
ed.WriteMessage("\r\n这是动态编译的修改图元颜⾊哟,颜⾊是::" + colorIndex);
var psr = ed.GetSelection();//⼿选
if (psr.Status != PromptStatus.OK)
{
return;
}
db.Action(tr =>
{
foreach (var item in psr.Value.GetObjectIds())
{
var ent = tr.GetObject(item, OpenMode.ForWrite) as Entity;
if (ent != null)
{
ent.ColorIndex = int.Parse(colorIndex);
}
}
});
}
}
}
执⾏动态编译
#if !HC2020
using Autodesk.AutoCAD.EditorInput;
using Acap = Autodesk.AutoCAD.ApplicationServices.Application;
#else
using GrxCAD.EditorInput;
using Acap = GrxCAD.ApplicationServices.Application;
#endif
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Text;
using Microsoft.CSharp;
namespace JoinBox
{
public class DynamicAssembly
{
/// <summary>
/
// 开始进⾏编译
/// </summary>
/// <param name="midCode">中间的代码段</param>
/// <param name="dynamicStr">命名空间的字符串</param>
public static void Go(StringBuilder midCode, string dynamicStr)
{
//⽣成驻留内存的动态程序集
var pars = new CompilerParameters
{
CompilerOptions = "/target:library /optimize", //编译器选项
GenerateExecutable = false, //⽣成可执⾏⽂件
GenerateInMemory = true //在内存中⽣成
};
var acpath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory); //获取当前cad运⾏路径 "C:\\Program Files (x86)\\AutoCAD 2008\\" var asslst = pars.ReferencedAssemblies; //添加引⽤
//获取程序集的位置
string configPathAll = Assembly.GetExecutingAssembly().CodeBase;
configPathAll = codeBase.Substring(8, codeBase.Length - 8); // 8是file:// 的长度
asslst.Add(configPathAll); //当前的dll的路径 "G:/K01.惊惊连盒/net35/JoinBox.dll"
string st = acpath.ToString();
#if !HC2020
asslst.Add(st + @"\acdbmgd.dll");
asslst.Add(st + @"\acmgd.dll");
#else
asslst.Add(st + @"\gmap.dll");
asslst.Add(st + @"\gmdb.dll");
#endif
#if !HC2020 && !AC2008 && !AC2009 && !AC2010 && !AC2011 && !AC2012
asslst.Add(st + @"\accoremgd.dll");
#endif
var code = new StringBuilder();
code.Append("using System;");
code.Append("using System.Reflection;");
code.Append("using System.Collections.Generic;");
code.Append("using System.IO;");
code.Append("using System.Text;");
#if !HC2020
code.Append("using Autodesk.AutoCAD.Runtime;");
code.Append("using Autodesk.AutoCAD.ApplicationServices;");
code.Append("using Autodesk.AutoCAD.DatabaseServices;");
code.Append("using Autodesk.AutoCAD.EditorInput;");
code.Append("using Autodesk.AutoCAD.Geometry;");
#else
code.Append("using GrxCAD.Runtime;");
code.Append("using GrxCAD.ApplicationServices;");
code.Append("using GrxCAD.DatabaseServices;");
code.Append("using GrxCAD.EditorInput;");
code.Append("using GrxCAD.Geometry;");
#endif
code.Append($"using {AutoGo.JoinBoxEnName};");
code.Append($"namespace {AutoGo.JoinBoxEnName + dynamicStr}");//不给插⼊到相同命名空间内 code.Append("{");
code.Append("public partial class " + dynamicStr + "{");
code.Append(midCode);
code.Append("}}");
//编译
using (var comp = new CSharpCodeProvider())
{
var cr = comp.CompileAssemblyFromSource(pars, code.ToString());
if (cr.Errors.HasErrors)
{
Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage(Environment.NewLine + $"动态编译{dynamicStr}错误:");
foreach (CompilerError err in cr.Errors)
{
ed.WriteMessage(Environment.NewLine + err.ErrorText);
}
}
}
}
}
}
⼦函数
RunTimeCurrentDomain.DefaultAssemblyResolve 在:
db.Action 在:
IAutoGo接⼝在:
处理在位编辑块的⽅法
在位编辑块时候,块外的图元(褪⾊的)也可以改到,或许可以通过以下来处理:
var dm = Application.DocumentManager;
var md = dm.MdiActiveDocument;
// 命令反应器命令前触发(全局)
dm.DocumentLockModeChanged += Dc_VetoCommand;
// 命令反应器命令后触发
md.CommandEnded += HatchEvent.Md_CommandEnded;
// 利⽤命令反应器 Refedit 启动之前创建选择集
private static List<ObjectId> _refeditSS_Before = new List<ObjectId>() { };
// 利⽤命令反应器 Refedit 启动之后做差集,就是在位编辑的时候内部的图元
private static List<ObjectId> _refeditSS_Interior = new List<ObjectId>() { };
两个反应器写法
/// <summary>
/
// 反应器->命令否决触发命令前(不可锁⽂档)
/// </summary>
public static void Dc_VetoCommand(object sender, DocumentLockModeChangedEventArgs e)
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
//这⾥不可以声明不然关闭⽂档的时候,再打开会引发致命错误
if (string.IsNullOrEmpty(e.GlobalCommandName) || e.GlobalCommandName == "#")
{
return;
}
switch (e.GlobalCommandName.ToUpper())
{
case "REFEDIT":
{
//在位编辑命令,使⽤前获取当前空间所有图元
PromptSelectionResult prompt = ed.SelectAll(_filter);//全选
if (prompt.Status == PromptStatus.OK)
{
_refeditSS_Before = prompt.Value.GetObjectIds().ToList();
}
}
break;
}
}
/// <summary>
/// 反应器->command命令完成后(内锁⽂档)
/// </summary>
public static void Md_CommandEnded(object sender, CommandEventArgs e)
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
if (string.IsNullOrEmpty(e.GlobalCommandName) || e.GlobalCommandName == "#")
{
return;
}
switch (e.GlobalCommandName.ToUpper())
{
case "REFEDIT":
{
//在位编辑命令,使⽤后获取当前空间所有图元
PromptSelectionResult prompt = ed.SelectAll(_filter);//全选
if (prompt.Status != PromptStatus.OK)
{
return;
}
_refeditSS_Interior = prompt.Value.GetObjectIds().Except(_refeditSS_Before).ToList(); foreach (var item in _refeditSS_Interior)
{
ed.WriteMessage(item.ToString());
}
}
break;
case "REFSET": //加减在位编辑图元
{
//完成后必然有上次选择集
PromptSelectionResult psr = ed.SelectPrevious();//上次选择集
if (psr.Status != PromptStatus.OK)
{
return;
}
var ids = psr.Value.GetObjectIds();
Database db = ids[0].Database;
var haIds = new List<ObjectId>();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (var item in ids)
{
Entity ent = item.ToEntity(tr);
if (ent is Hatch ha)
{
haIds.Add(item);
}
}
}
if (haIds.Count > 0)
{
//获取命令历史,最后⼀⾏看是加还是减
string last = CadSystem.Getvar("lastprompt"); //再获取最后⼀⾏命令
if (last.Contains("添加") || last.Contains("Added"))
{
_refeditSS_Before = _refeditSS_Before.Except(haIds).ToList();//差集
_refeditSS_Interior = _refeditSS_Interior.Union(haIds).ToList();//消重+合并
}
else if (last.Contains("删除") || last.Contains("Removed"))
{
_refeditSS_Interior = _refeditSS_Interior.Except(haIds).ToList();//差集
_refeditSS_Before = _refeditSS_Before.Union(haIds).ToList();//消重+合并
}
}
}
break;
case "REFCLOSE"://保存块,清空集合
{
_refeditSS_Interior.Clear();
}
break;
}
}
Arx的例⼦
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论