cad.net 定义lisp

时间:2019-09-17
本文章向大家介绍cad.net 定义lisp,主要包括cad.net 定义lisp使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

首先是传参型lisp的定义: (addLine (getpoint))

        //定义lisp传入参数的例子
        //复制到命令栏运行:  (addLine (getpoint))
        [LispFunction("addLine")] //注意: 这里不是command!
        public static ResultBuffer AddLine(ResultBuffer rbArgs)
        {
            Database db = Application.DocumentManager.MdiActiveDocument.Database;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            Point3d p1 = new Point3d(1000, 1000, 0);
            Point3d p2 = new Point3d(2000, 2000, 0);
            if (rbArgs != null)
            {
                foreach (TypedValue rb in rbArgs)
                {
                    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 line = new Line(p1, p2);
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable acBlkTbl = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                BlockTableRecord acBlkTblRec = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                line.SetDatabaseDefaults();
                acBlkTblRec.AppendEntity(line);
                trans.AddNewlyCreatedDBObject(line, true);
                trans.Commit();
            }
            var rbrtn = new ResultBuffer(new TypedValue[]
           {
                new TypedValue((int)LispDataType.ObjectId, line.ObjectId),
                new TypedValue((int)LispDataType.Point3d, p1),
                new TypedValue((int)LispDataType.Point3d, p2)
           });
            ed.WriteMessage(Environment.NewLine + " rbrtn=" + rbrtn.ToString() + Environment.NewLine + "");
            return rbrtn; //返回值此处有图元名
        }
View Code

再来是通过接口发送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的返回值
        }
View Code

最后是提供一些发送命令的函数,这里有些备注,他们可以异步发送lisp,有些会导致自动执行时候发送lisp出错,但是却是异步发送的必需品.

    public partial class SendToCad
    {
#if AC2006 || AC2007 || AC2008 || AC2009 || AC2010 || AC2011 || AC2012
        /// <summary> 
        /// 发送命令
        /// </summary>
        /// <param name="strExpr"></param>
        /// <returns></returns>    
        [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
        /// <summary>
        /// 发送命令
        /// </summary> 
        /// <param name="str">发送lisp加载命令</param>
        /// <param name="activate">命令是否有效</param>
        /// <param name="wrapUpInactiveDoc">是否是当前活动的文档</param>
        /// <param name="echoCommand">发送的命令是否在命令行</param>
        /// <returns></returns>
        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 

        /// <summary>
        /// 发送命令
        /// </summary>
        /// <param name="str">命令</param>
        /// <returns></returns>
        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;
        }
    }
View Code

最后的最后是一个发送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 > 0)
            {
                int cmdNum = cmds.Split(new char[] { '\'' }).Length;
                for (int i = 0; i < cmdNum; i++)
                    esc += '\x03';
            }
            Document doc = Application.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute(esc + "_.LINE ", true, false, true);
            //设置cad窗口的焦点激活绘图区
            //acApp.MainWindow.Focus();
        }
View Code

原文地址:https://www.cnblogs.com/JJBox/p/11532752.html