通用枚举值…
// 本枚举融合 Autodesk.AutoCAD.Runtime.LispDataType
// Autodesk.AutoCAD.EditorInput.PromptStatus
public enum EnumBufCode
{
// resbuf元素的类型
None = , //没有结果 回车耶
Double = , //实数 Real
Point2d = , //2维点
Int16 = , //短整数 Short
Angle = , //角度
Text = , //字符串 String
ObjectId = , //实体名称 Ename
SelectionSet = , //选择集名 PickSet
Orientation = , //方向
Point3d = , //3维点
Int32 = , //长整数 Long
Void = , //空白符号
ListBegin = , //list begin
ListEnd = , //list end
DottedPair = , //点对
Nil = , //nil(空表)
Dxf0 = , //DXF代码0仅适用于ads\_bListldlist
T\_atom = , //T(原子)
Resbuf = , //resbuf
Modeless = , //被无模式对话中断
Other = ,
// 错误返回代码
OK = , //请求成功,用户输入值有效 Norm
Error = -,//其他一些错误
Cancel = -,//用户取消请求-Ctl-C
RejectRequest = -,//AutoCAD拒绝请求-无效
FailureLink = -,//链接失败-Lisp可能已经死了
Keyword = -,//从getxxx()例程返回的关键字
Inputtruncated = -,//输入并不都适合缓冲区
}
首先是传参型lisp的定义,它在低版本有个问题,就是所有的返回值都要用表包裹着,而高版本就修复了这个问题.
为了所有版本统一,返回值应该统一成 ResultBuffer ,在lisp再(car 返回值)…. 我这里既有 ResultBuffer,又有object返回,供各位参考.
//传参型lisp的定义:传点
//复制到命令栏运行: (Test\_AddLine (getpoint))
\[LispFunction("Test\_AddLine")\] //注意: 这里不是command!
public static ResultBuffer AddLine(ResultBuffer rbArgs)
{
Database db = Acap.DocumentManager.MdiActiveDocument.Database;
Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;
Point3d p1 = Point3d.Origin;
Point3d p2 = Point3d.Origin;
if (rbArgs != null)
{
foreach (TypedValue rb in rbArgs)
{
try
{
//ed.WriteMessage(Environment.NewLine + "rb.ToString()=" + rb.ToString());
//ed.WriteMessage(Environment.NewLine + "rb.TypeCode.ToString()=" + rb.TypeCode.ToString());
//ed.WriteMessage(Environment.NewLine + "rb.Value.ToString()=" + rb.Value.ToString());
var str = rb.Value.ToString();
str = str.Substring().Substring(, str.Length - );
var pts = str.Split(',');
p2 = new Point3d(double.Parse(pts\[\]), double.Parse(pts\[\]), double.Parse(pts\[\]));
}
catch
{ }
}
}
var line = new Line(p1, p2);
using (Transaction tr = db.TransactionManager.StartTransaction())
{
var acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
var acBlkTblRec = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
// line.SetDatabaseDefaults();设置数据库默认值
acBlkTblRec.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
tr.Commit();
}
var rbrtn = new ResultBuffer(new TypedValue\[\]
{
new TypedValue((int)EnumBufCode.ObjectId, line.ObjectId),
new TypedValue((int)EnumBufCode.Point3d, p1),
new TypedValue((int)EnumBufCode.Point3d, p2)
});
ed.WriteMessage(Environment.NewLine + " rbrtn=" + rbrtn.ToString());
ed.WriteMessage(Environment.NewLine);
return rbrtn; //返回值此处有图元名
}
//传参型lisp的定义:加法
//复制到命令栏运行: (Test\_MyAdd 1 2 3)
\[LispFunction("Test\_MyAdd")\] //注意: 这里不是command!
public static object Test\_MyAdd(ResultBuffer args) //高版本这里可以返回double,但是08只能返回ResultBuffer
{
var ds = new List<double>();
if (args != null)
{
foreach (TypedValue rb in args)
{
try
{
var a = double.Parse(rb.Value.ToString());
ds.Add(a);
}
catch
{ }
}
}
double number = ;
foreach (var item in ds)
{
number += item;
}
//08只能返回ResultBuffer 会返回表内数字(6.0)
//高版本可以返回其他的
var rbrtn = new ResultBuffer(new TypedValue\[\]
{
new TypedValue((int)EnumBufCode.Double, number),
});
var dotPair = new ResultBuffer(new TypedValue\[\] {
new TypedValue((int)EnumBufCode.ListBegin, -),
new TypedValue((int)EnumBufCode.Int16, ),
new TypedValue((int)EnumBufCode.Int16, ),
new TypedValue((int)EnumBufCode.DottedPair, -),
});
#if AC2008
return rbrtn; //但是08只能返回ResultBuffer 会返回(6.0)
#else
return number; //高版本这里可以返回double 会返回6.0
#endif
}
//传参型lisp的定义:选择集
//复制到命令栏运行: (Test\_ssget (ssget))
\[LispFunction("Test\_ssget")\] //注意: 这里不是command!
public static object Test\_ssget(ResultBuffer args)
{
//var dt = new List<object>();
var ds = new List<object>();
if (args != null)
{
foreach (TypedValue rb in args)//{((5007,(((-2181752),Crossing,0,)((-2181760),Crossing,0,))))}
{
try
{
//dt.Add(rb.TypeCode);
ds.Add(rb.Value);
}
catch
{ }
}
}
var tl = new List<TypedValue>();
foreach (var item in ds)
{
tl.Add(new TypedValue((int)EnumBufCode.SelectionSet, item));
}
var rbrtn = new ResultBuffer(tl.ToArray());
return rbrtn;
}
//传参型lisp的定义:点对
//复制到命令栏运行: (Test\_dotPair 0 100)
\[LispFunction("Test\_dotPair")\] //注意: 这里不是command!
public static object Test\_dotPair(ResultBuffer args)
{
var ds = new List<object>();
if (args != null)
{
foreach (TypedValue rb in args)//{((5007,(((-2181752),Crossing,0,)((-2181760),Crossing,0,))))}
{
try
{
ds.Add(rb.Value);
}
catch
{ }
}
}
var ls = new List<TypedValue>();
ResultBuffer dotPair = null;
if (ds.Count == )
{
ls.Add(new TypedValue((int)EnumBufCode.ListBegin, -));
ls.Add(new TypedValue((int)EnumBufCode.Int16, ds\[\]));
if (short.TryParse(ds\[\].ToString(), out short num))
{
ls.Add(new TypedValue((int)EnumBufCode.Int16, num));
ls.Add(new TypedValue((int)EnumBufCode.DottedPair, -));
dotPair = new ResultBuffer(ls.ToArray());
}
}
return dotPair; //返回点对表
}
在c#读取和赋值lisp变量的值 ,测试命令: Test_setLisp
#if !HC2020
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.EditorInput;
using GrxCAD.Geometry;
using GrxCAD.ApplicationServices;
using GrxCAD.Runtime;
using GrxCAD.Colors;
using GrxCAD.GraphicsInterface;
using Viewport = GrxCAD.DatabaseServices.Viewport;
using Application = GrxCAD.ApplicationServices.Application;
#endif
using System.Runtime.InteropServices;
using System;
namespace JoinBox.CommandLisp
{
// 操作lisp赋值
// https://blog.csdn.net/qq_21489689/article/details/80630817
// 我验证了2008和2019,32位 DllImport("accore.dll" 好像不对,没有环境验证
public static class LStructure
{
//LSP变量的写入-64位
\[System.Security.SuppressUnmanagedCodeSecurity\]
\[DllImport("accore.dll", EntryPoint = "acedPutSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)\]
extern static private int AcedPutSym64(string args, IntPtr result);
#if AC2008
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acad.exe", EntryPoint = "acedPutSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedPutSym32(string args, IntPtr result);
#else
//没有环境验证
//LSP变量的写入-32位
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", EntryPoint = "_acedPutSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedPutSym32(string args, IntPtr result);
#endif
/// <summary>
/// 设置Lisp变量值
/// </summary>
/// <param name="name">变量名</param>
/// <param name="rb">变量值</param>
static int SetLispSym(string name, ResultBuffer rb)
{
int ret = ;
//判断系统是32位还是64位
switch (Marshal.SizeOf(typeof(IntPtr)))
{
case :
{
ret = AcedPutSym32(name, rb.UnmanagedObject);
}
break;
case :
{
ret = AcedPutSym64(name, rb.UnmanagedObject);
}
break;
}
return ret;
}
//LSP变量的读取-64位
\[System.Security.SuppressUnmanagedCodeSecurity\]
\[DllImport("accore.dll", EntryPoint = "acedGetSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)\]
extern static private int AcedGetSym64(string args, out IntPtr result);
#if AC2008
//LSP变量的读取-32位
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acad.exe", EntryPoint = "acedGetSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedGetSym32(string args, out IntPtr result);
#else
//没有环境验证
//LSP变量的读取-32位
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", EntryPoint = "_acedGetSym", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static private int AcedGetSym32(string args, out IntPtr result);
#endif
/// <summary>
/// 获取Lisp变量值
/// </summary>
/// <param name="name">变量名</param>
/// <returns>变量值,如果失败则为空</returns>
static ResultBuffer GetLispSym(string name)
{
IntPtr ip;
//判断系统是32位还是64位
switch (Marshal.SizeOf(typeof(IntPtr)))
{
case :
{
int status = AcedGetSym32(name, out ip);
if (status == (int)EnumBufCode.OK && ip != IntPtr.Zero)
{
return ResultBuffer.Create(ip, true);
}
}
break;
case :
{
int status = AcedGetSym64(name, out ip);
if (status == (int)EnumBufCode.OK && ip != IntPtr.Zero)
{
return ResultBuffer.Create(ip, true);
}
}
break;
}
return null;
}
/// <summary>
/// lisp变量赋值
/// </summary>
/// <param name="varName">变量名</param>
/// <param name="varValue">变量值</param>
/// <param name="cEnumRes">变量值类型,原子,字符串等等</param>
public static void SetLspVar(EnumBufCode cEnumRes, string varName, object varValue = null)
{
using (var rb = new ResultBuffer())
{
rb.Add(new TypedValue((int)cEnumRes, varValue));
SetLispSym(varName, rb);
}
}
/// <summary>
/// 读取LSP变量
/// </summary>
/// <param name="varName">变量名</param>
/// <returns></returns>
public static object GetLspVar(string varName)
{
object varValue = null;
ResultBuffer rb = GetLispSym(varName);
if (rb != null)
{
foreach (var val in rb)
{
varValue = val.Value;
}
}
return varValue;
}
\[CommandMethod("Test\_setLisp")\]
public static void Test\_setLisp()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
string varName = "a";
object v;
// 赋值例子
// (setq a "35432")
SetLspVar(EnumBufCode.Text, varName, ""); //返回 "3543252351515"
v = GetLspVar(varName);
ed.Princ(v);
// (setq a 35432)
SetLspVar(EnumBufCode.Double, varName, ""); //返回 3543252351515
v = GetLspVar(varName);
ed.Princ(v);
// (setq a T)
SetLspVar(EnumBufCode.T\_atom, varName, true); //返回 T
SetLspVar(EnumBufCode.T\_atom, varName, false); //返回 T
v = GetLspVar(varName);
ed.Princ(v);
// (setq a nil)
SetLspVar(EnumBufCode.Nil, varName); //返回 nil
v = GetLspVar(varName);
ed.Princ(v);
}
static void Princ(this Editor ed, object var)
{
string varString = "";
if (var == null)
{
varString = "nil";
}
else
{
string type = var.GetType().Name;
switch (type)
{
case "String":
{
varString = var.ToString();
varString = "\\"" + varString + "\\"";
}
break;
case "Double":
{
varString = var.ToString();
}
break;
case "Boolean":
{
varString = "T"; //返回布尔值都是为true的,不返回才是nil
}
break;
}
}
ed.WriteMessage("\\n" + varString);
}
}
}
再来是通过接口发送lisp,这个可以避免用明文方式发送到命令栏,而且它在自动执行函数上面也是同步发送的,很有趣哟: testLisp
#if AC2008 || AC2012
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acad.exe", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acedEvaluateLisp@@YAHPB_WAAPAUresbuf@@@Z")]
private static extern int AcedEvaluateLisp(string lispLine, out IntPtr result);
\[DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")\]
private static extern int AcedInvoke(IntPtr args, out IntPtr result);
#else
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z")]
private static extern int AcedEvaluateLisp(string lispLine, out IntPtr result);
\[DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedInvoke")\]
private static extern int AcedInvoke(IntPtr args, out IntPtr result);
#endif
/// <summary>
/// 定义lisp
/// </summary>
/// <param name="arg">lisp语句</param>
/// <returns>缓冲结果,返回值</returns>
public static ResultBuffer RunLisp(string arg)
{
AcedEvaluateLisp(arg, out IntPtr rb);
if (rb != IntPtr.Zero)
{
try
{
var rbb = DisposableWrapper.Create(typeof(ResultBuffer), rb, true) as ResultBuffer;
return rbb;
}
catch
{
return null;
}
}
return null;
}
/// <summary>
/// c#发送lisp,这个同步方式可以在自动运行函数上跑,也是同步的
/// </summary>
/// <returns></returns>
\[CommandMethod("testLisp")\]
public void Cmdtest()
{
string Strlisp = "(setq a 10)";
var res = RunLisp(Strlisp); //有lisp的返回值
}
最后是提供一些发送命令的函数,这里有些备注,他们可以异步发送lisp,有些会导致自动执行时候发送lisp出错,但是却是异步发送的必需品.
public partial class SendToCad
{
#if AC2006 || AC2007 || AC2008 || AC2009 || AC2010 || AC2011 || AC2012
///
///
///
[DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ads_queueexpr")]
private static extern int Ads_queueexpr(string strExpr);//非同步,这个在08/12发送lisp不会出错,但是发送bo命令出错了..
/// <summary>
/// 发送命令,设置CommandFlags.Session可以同步,
/// 发送lisp也可以,但是非同步,在自动执行函数上面会非同步
/// </summary>
/// <param name="str"></param>
public static void SendLisp(string str)
{
try
{
Ads\_queueexpr(str + "\\n");
}
catch (Exception ee)
{
//自执行发送lisp都是在最后的(异步执行)
var ed = Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage(Environment.NewLine + "发送命令失败,导致加载失败!");
ed.WriteMessage(Environment.NewLine + "" + ee.Message + Environment.NewLine);
}
}
/// <summary>
/// 发送命令
/// </summary>
/// <param name="strExpr"></param>
/// <returns></returns>
\[DllImport("acad.exe", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedPostCommand@@YAHPB\_W@Z")\]
private static extern int AcedPostCommand(string strExpr);
#else
///
/// 发送lisp加载命令
///
public static void SendLisp(string str)
{
Document dc = Application.DocumentManager.MdiActiveDocument;
string commands = str + "\n";
try
{
dc.SendStringToExecute(commands, false, false, false);//08所有都flase会有问题,出现报错
}
catch (System.Exception ee)
{
//自执行发送lisp都是在最后的(异步执行)
var ed = dc.Editor;
ed.WriteMessage(ee.Message);
ed.WriteMessage(Environment.NewLine + "发送命令失败,导致加载失败!");
ed.WriteMessage(Environment.NewLine + ee.Message);
}
}
#endif
///
/// 命令
///
public static bool SendCommand(string str) //非同步,这里加载lisp第二个文档有问题…
{
object ActiveDocument = Com.App.GetType().InvokeMember("ActiveDocument", BindingFlags.GetProperty, null, Com.App, null);
object[] commandArray = { str + "\n" };
ActiveDocument.GetType().InvokeMember("SendCommand", BindingFlags.InvokeMethod, null, ActiveDocument, commandArray);
return true;
}
}
最后的最后是一个发送esc的操作,我也不知道为什么要放这里,可能他存在的价值不高…
//http://www.tiancao.net/blogview.asp?logID=1871&cateID=3&tdsourcetag=s\_pcqq\_aiomsg
/\*
我想从我的非模态对话框的按钮中启动一些命令。我已经发现,对于SendStringToExecute,我应该使用‘\\x03’字符而不是^C。
我唯一的问题是,在这种情况下,如果没有运行命令,那么我将在命令窗口,如果单击菜单项时没有运行命令,则菜单的^C^C不会导致\* Cancel\*出现。
我怎样才能达到同样的目的呢?
解:
你可以查帐CMDNAMES系统变量,根据当前运行的命令数量,可以在命令字符串的开头添加许多转义字符。
这里有一个样本这表明:
\*/
\[CommandMethod("sendEsc")\]
public void SendEsc()
{
//c#非模态窗体发命令
string esc = "";
string cmds = CadSystem.Getvar("CMDNAMES");
if (cmds.Length > )
{
int cmdNum = cmds.Split(new char\[\] { '\\'' }).Length;
for (int i = ; i < cmdNum; i++)
esc += '\\x03';
}
Document doc = Application.DocumentManager.MdiActiveDocument;
doc.SendStringToExecute(esc + "\_.LINE ", true, false, true);
//设置cad窗口的焦点激活绘图区
//acApp.MainWindow.Focus();
}
最最后,写一下com接口的新旧版本写法:
public static class Com
{
#if AC2006 || AC2007 || AC2008 || AC2009 || AC2010 || AC2011 || AC2012
public static AcadDocument Adm { get; } = Application.DocumentManager.MdiActiveDocument.AcadDocument as AcadDocument;
#else
public static AcadDocument Adm { get; } = Application.DocumentManager.MdiActiveDocument.GetAcadDocument() as AcadDocument;
#endif
#if !HC2020
public static AcadApplication App { get; } = Application.AcadApplication as AcadApplication;
#else
public static GcadApplication App { get; } = Application.AcadApplication as GcadApplication;
#endif
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章