cad.net 仿猫老师的vlisp小助手

说明

本功能就是直接点击cad图元获取vla函数,快速知道图元对应的方法和属性(存在可用的).

小贱贱他复刻了一个高版本用的vlisp小助手,
因为他调用了高版本函数,没有Acad08版,我很郁闷,
然后就在他的基础上造了一个net全版本通用的...

至于猫老师曾经实现过的,通过帮助文件实现参数获取,
我懒得做了,要新建数据库做索引才行,还要对数据库整理...

动图演示

image

乱码问题

Acad08测试时候:
以下操作不加T表示仅看vlisp支持的属性,
加T表示加看vlisp支持的方法,而加T时候会有乱码信息.

(if (setq ent (entsel))(progn (vlax-dump-object (vlax-ename->vla-object(car ent))T)))

它会将";支持的方法:" 会随机变成 ";?С值姆椒?"
直接使用Acad08获取都有,所以这无法通过改变字符串编码修改,
这可能仅发生在Acad08或者net35,
怀疑是Win10系统中文和Acad08编译环境不同导致.
因为我用Acad21测试并没有这样的问题.
处理方法详情见代码SplitMethod内

如果是用Lisp制作小助手,恐怕每次获取都是不一样的码值(lisp的解释器有bug),
无法用eq/equal对比,因为图层乱码是导致我学c#原因之一...
这可能就是不死猫老师vlisp小助手会出现有的能用,有的不能用的问题.

对话框模式和发送命令

代码同时支持调用winform的模态窗口和非模态窗口两种方式,可自己修改为自己喜欢的.

首先要说明:
先要发送复制命令历史命令,再从剪贴板获取历史.

1: 当发送命令时,此时要同步处理剪贴板,那么需要同步命令,
但是非模态不能发送同步命令,
否则出现Acap.DocumentManager.IsApplicationContext == true
命令上下文的报错.

2: 异步命令会导致先获取剪贴板,之后才发送了复制命令历史.
而cad异步命令又没有执行完成后的回调.

在我一筹莫展的时候,edata给了我个建议:
写一个自己的同步命令,在命令内发送复制命令历史命令,
再在剪贴板获取命令,并且修改窗体信息.
然后点击图元时候发送异步命令,调用这个自写的同步命令,
这样执行顺序就是正常的,窗体也能得到信息.

简直妙到不行,有一种用魔法打败魔法的感觉.

代码

调用命令

using Autodesk.AutoCAD.Runtime;

namespace JoinBox.CommandLisp.Vlisp
{
    public class VlispCmd
    {
        public VlispForm vlisp = null;

        [CommandMethod(nameof(Lisp))]
        public void Lisp()
        {
            if (vlisp == null || vlisp.IsDisposed)
            {
                vlisp = new VlispForm();
            }
#if true  //两种模式我都调整好了
            vlisp.Show();
            Win32API.WinApi.SetFocus(vlisp.Handle);
#else
            vlisp.ShowDialog();
#endif
        }

        /* 此命令并不是由用户调用,而是点选的时候自动调用.
           因为在非模态窗口发送同步命令会失败.
           所以制作了一个同步命令来
           进行获取命令历史,加入剪贴板.
        */
        [CommandMethod(nameof(Cmd_Copyhist), CommandFlags.NoHistory)]
        public void Cmd_Copyhist()
        {
            VlispTool.SendCmd();
            if (vlisp == null) return;
            
            VlispTool.ClipboardData(cmdLines =>
            {
                // 发送的最后一行是发送的命令,移除掉
                cmdLines.Remove(nameof(Cmd_Copyhist));
                vlisp.SplitMethod(cmdLines);
            });
            
        }
    }
}

剪贴板

using Autodesk.AutoCAD.DatabaseServices;
using System.Diagnostics;
using System.Windows.Forms;
using System;
using System.Collections.Generic;

namespace JoinBox.CommandLisp.Vlisp
{
    public static class VlispTool
    {
        /// <summary>
        /// 发送命令获取剪贴板历史
        /// </summary>
        public static void SendCmd()
        {
            const string cps = "_.copyhist";
            var rb = new ResultBuffer
            {
                new TypedValue((int)EnumBufCode.Text, cps)
            };
            int cnum = CSendSynchronization.AcedCmd(rb);
            if (cnum == 0)
            { 
                Debug.WriteLine($"{cps}发送命令失败!");
            }
        }

        /// <summary>
        /// 获取剪贴板数据
        /// </summary>
        /// <param name="action"></param>
        public static void ClipboardData(Action<List<string>> action)
        {
            // 此处还需要保存原来的剪贴板,再进行获取,再还原.
            // 剪贴板内容
            var iData = Clipboard.GetDataObject();
            if (!iData.GetDataPresent(DataFormats.Text)) return;    
            string clipboardText = (string)iData.GetData(DataFormats.Text);
            if (string.IsNullOrEmpty(clipboardText.Trim())) return;     

            // 将剪贴板的东西赋值给窗体   
            var cmdLines = clipboardText.Split(new[] { '\r', '\n' },
                             StringSplitOptions.RemoveEmptyEntries)
                             .ToList();
            action(cmdLines);
        }
    }
}

发送命令

/// <summary>
/// 非模态对话框切换焦点回cad
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "SetFocus")]
public static extern int SetFocus(IntPtr hWnd);

public partial class CSendSynchronization
{
        //发送同步命令
        //由于cad2016里AcedCmd改成了AcedCmdS,Accore.dll也是2013版本后才开始改的。
        //调用AutoCAD命令,ARX原型:int acedCmdS(const struct resbuf * rbp);
#if NET35 || NET40
        [DllImport("acad.exe", EntryPoint = "acedCmd", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
#else
        [DllImport("accore.dll", EntryPoint = "acedCmdS", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
#endif
        private static extern int AcedCmd(IntPtr rbp);

        /// <summary>
        /// 调用C++的acedCmdS函数
        /// </summary> 
        /// <param name="args">命令参数列表</param>
        /// <returns>返回命令执行的状态</returns>
        public static int AcedCmd(ResultBuffer args)
        {
            if (!Acap.DocumentManager.IsApplicationContext)
                return AcedCmd(args.UnmanagedObject);  
            return 0;
        }
}

窗体

窗体前台

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Acap = Autodesk.AutoCAD.ApplicationServices.Application;
using static JoinBox.CommandLisp.LSend;
using JoinBox.CommandLisp.Vlisp;

namespace JoinBox
{
    public partial class VlispForm : Form
    {
        // 最高命令行数,用于清空历史记录,再获取历史时候就很干净
        string _clear = new string('\n', 2048);

        const string _entsel = "(Vlax-Ename->Vla-Object (Car (Entsel)))";
        const string _dump = "(if (setq ent (entsel))(progn (vlax-dump-object (vlax-ename->vla-object(car ent))T)))";

        public VlispForm()
        {
            InitializeComponent();

            // 载入COM接口
            RunLisp("(vl-load-com)");
        }

        /// <summary>
        /// 点击图元按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button3_Click(object sender, EventArgs e)
        {
            ModalAction(ed =>
            {
                ed.WriteMessage(_clear); //清空命令历史

                ResultBuffer dump = null;
                dump = RunLisp(_dump);
                if (dump == null || !dump.AutoDelete)
                    return; 
                ed.WriteMessage("\n");
                SendCmdGetClipboard();
            });
        }

        /// <summary>
        /// 判断模态和非模态进入不同的处理
        /// </summary>
        /// <param name="action"></param>
        private void ModalAction(Action<Editor> action)
        {
            var doc = Acap.DocumentManager.MdiActiveDocument;
            if (doc is null) return;
            var ed = doc.Editor;

            if (this.Modal)
            {
                // 模态要启用用户交互
                using ed.StartUserInteraction(this);              
                action.Invoke(ed);          
                return;
            }

            // 非模态设置焦点,并锁定文档才能执行修改数据库
            Win32API.WinApi.SetFocus(Acap.MainWindow.Handle);
            using (doc.LockDocument()) {
                    action.Invoke(ed);
            }
            Win32API.WinApi.SetFocus(this.Handle);   
        }

        /// <summary>
        /// 发送命令及获取剪贴板
        /// </summary>
        private void SendCmdGetClipboard()
        {
            // 仿照Acad2016函数让Acad2008用
            // _cmdLines = Autodesk.AutoCAD.Internal.Utils.GetLastCommandLines(500, false);           
            if (this.Modal)
            {
                // 同步命令
                VlispTool.SendCmd(); 
                VlispTool.ClipboardData(cmdLines =>
                {
                    SplitMethod(cmdLines);
                });
                return;
            }      
            // 异步命令
            string cmd = nameof(VlispCmd.Cmd_Copyhist) + "\n";
            var doc = Acap.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute(cmd, false, true, true);
        }

        /// <summary>
        /// 切割字符串加入对话框
        /// </summary>
        /// <param name="cmdLines"></param>
        public void SplitMethod(List<string> cmdLines)
        {
            // 由于只有方法和属性,它们就存在互斥关系.
            // 网友建议用";"和其后一个空格来判断分类行,这样即使乱码也不怕.
            int a = cmdLines.FindIndex(s => s.Contains(";")
                && s.Length > s.IndexOf(';')+1 
                && s[s.IndexOf(';')+1] != ' '); //返回行号
            if (a < 0) return;

            ListBox lb = MethodList; // 加入函数:_dump有T参数
            if (cmdLines[a] == ";特性值:") {
                lb = AttributesList; // 加入属性:_dump没有T参数
            }
            this.BeginInvoke(new Action(() => {
                lb.Items.Clear();
                for (int i = a + 1; i < cmdLines.Count; i++) {    
                    lb.Items.Add(cmdLines[i].Replace(";   ", ""));
                }
                lb.TopIndex = lb.Items.Count - 1;
            }));
        }

        /// <summary>
        /// 属性值单击显示 Vlax-Get
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AttributesList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                var text = AttributesList.Text.Split(" ".ToCharArray()).GetValue(0);
                CodeText.Text = $"(Vlax-Get {_entsel} '{text} )";
            }));
        }

        /// <summary>
        /// 属性值双击显示 Vlax-Put
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AttributesList_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                var text = AttributesList.Text.Split(" ".ToCharArray()).GetValue(0);
                CodeText.Text = $"(Vlax-Put {_entsel} '{text} 参数)";
            }));
        }

        /// <summary>
        /// 方法选择动作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MethodList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                var text = MethodList.Text.Split(' ');
                var t1 = text.GetValue(0).ToString();
                var t2 = text.GetValue(1).ToString().Split((new char[] { '(', ')' }));
                int num = 1;
                if (t2.GetValue(1).ToString() != "")
                {
                    num = Convert.ToInt16(t2.GetValue(1));
                }
                StringBuilder canshu = new();
                for (int i = 0; i < num; i++)
                {
                    canshu.Append("参数 ");  // ????这是什么?我当时为什么这样写?
                }
                CodeText.Text = $"(Vlax-Invoke-Method {_entsel} '{t1} {canshu})";
            }));
        }

        /// <summary>
        /// 数据复制到粘贴板
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button2_Click(object sender, EventArgs e)
        {
            Clipboard.SetDataObject(CodeText.Text);
        }

        /// <summary>
        /// 自动拷贝
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CodeText_TextChanged(object sender, EventArgs e)
        {
            Clipboard.SetDataObject(CodeText.Text);
        }

        /// <summary>
        /// 变量赋值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TextBox2_Leave(object sender, EventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                CodeText.Text = $"(setq {VariableText.Text} {CodeText.Text})";
            }));
        }

        /// <summary>
        /// 加载按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button1_Click(object sender, EventArgs e)
        {
            ModalAction(ed =>
            {
                ed.WriteMessage("\n\n");
                ed.WriteMessage(CodeText.Text + "\n");
                ResultBuffer aa = RunLisp(CodeText.Text);
                var bb = aa.AsArray();
                ed.WriteMessage(bb[0].Value.ToString() + "\n");
            });
        }

    }
    public static class LResultBufferTool
    {
        public static object GetValue(this ResultBuffer res)
        {
            var arr = res.AsArray();
            object ret = arr[0].Value;
            return ret;
        }
    }
}

窗体设计

namespace JoinBox
{
    partial class VlispForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.AttributesList = new System.Windows.Forms.ListBox();
            this.MethodList = new System.Windows.Forms.ListBox();
            this.label3 = new System.Windows.Forms.Label();
            this.CodeText = new System.Windows.Forms.TextBox();
            this.button1 = new System.Windows.Forms.Button();
            this.button3 = new System.Windows.Forms.Button();
            this.label4 = new System.Windows.Forms.Label();
            this.FeaturesText = new System.Windows.Forms.TextBox();
            this.label5 = new System.Windows.Forms.Label();
            this.MethodText = new System.Windows.Forms.TextBox();
            this.label6 = new System.Windows.Forms.Label();
            this.VariableText = new System.Windows.Forms.TextBox();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.SuspendLayout();
            // 
            // AttributesList
            // 
            this.AttributesList.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.AttributesList.FormattingEnabled = true;
            this.AttributesList.ItemHeight = 12;
            this.AttributesList.Location = new System.Drawing.Point(6, 20);
            this.AttributesList.Name = "AttributesList";
            this.AttributesList.Size = new System.Drawing.Size(546, 424);
            this.AttributesList.TabIndex = 0;
            this.AttributesList.SelectedIndexChanged += new System.EventHandler(this.AttributesList_SelectedIndexChanged);
            this.AttributesList.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.AttributesList_MouseDoubleClick);
            // 
            // MethodList
            // 
            this.MethodList.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.MethodList.FormattingEnabled = true;
            this.MethodList.ItemHeight = 12;
            this.MethodList.Location = new System.Drawing.Point(6, 20);
            this.MethodList.Name = "MethodList";
            this.MethodList.Size = new System.Drawing.Size(256, 424);
            this.MethodList.TabIndex = 2;
            this.MethodList.SelectedIndexChanged += new System.EventHandler(this.MethodList_SelectedIndexChanged);
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Enabled = false;
            this.label3.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label3.Location = new System.Drawing.Point(8, 530);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(29, 12);
            this.label3.TabIndex = 4;
            this.label3.Text = "代码";
            // 
            // CodeText
            // 
            this.CodeText.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.CodeText.Location = new System.Drawing.Point(41, 527);
            this.CodeText.Name = "CodeText";
            this.CodeText.Size = new System.Drawing.Size(800, 21);
            this.CodeText.TabIndex = 5;
            this.CodeText.TextChanged += new System.EventHandler(this.CodeText_TextChanged);
            // 
            // button1
            // 
            this.button1.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.button1.Location = new System.Drawing.Point(416, 552);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(117, 27);
            this.button1.TabIndex = 6;
            this.button1.Text = "加载";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.Button1_Click);
            // 
            // button3
            // 
            this.button3.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.button3.Location = new System.Drawing.Point(293, 552);
            this.button3.Name = "button3";
            this.button3.Size = new System.Drawing.Size(117, 27);
            this.button3.TabIndex = 6;
            this.button3.Text = "选择图元";
            this.button3.UseVisualStyleBackColor = true;
            this.button3.Click += new System.EventHandler(this.Button3_Click);
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Enabled = false;
            this.label4.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label4.Location = new System.Drawing.Point(8, 475);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(29, 12);
            this.label4.TabIndex = 7;
            this.label4.Text = "功能";
            // 
            // FeaturesText
            // 
            this.FeaturesText.Enabled = false;
            this.FeaturesText.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.FeaturesText.Location = new System.Drawing.Point(41, 471);
            this.FeaturesText.Name = "FeaturesText";
            this.FeaturesText.Size = new System.Drawing.Size(800, 21);
            this.FeaturesText.TabIndex = 5;
            this.FeaturesText.Text = "判断是在发生命令之前(先选取再执行)或之后选取对象。";
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Enabled = false;
            this.label5.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label5.Location = new System.Drawing.Point(8, 503);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(29, 12);
            this.label5.TabIndex = 4;
            this.label5.Text = "方法";
            // 
            // MethodText
            // 
            this.MethodText.Enabled = false;
            this.MethodText.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.MethodText.Location = new System.Drawing.Point(41, 499);
            this.MethodText.Name = "MethodText";
            this.MethodText.Size = new System.Drawing.Size(800, 21);
            this.MethodText.TabIndex = 5;
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Enabled = false;
            this.label6.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label6.Location = new System.Drawing.Point(8, 559);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(29, 12);
            this.label6.TabIndex = 4;
            this.label6.Text = "变量";
            // 
            // VariableText
            // 
            this.VariableText.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.VariableText.Location = new System.Drawing.Point(41, 555);
            this.VariableText.Name = "VariableText";
            this.VariableText.Size = new System.Drawing.Size(246, 21);
            this.VariableText.TabIndex = 5;
            this.VariableText.Leave += new System.EventHandler(this.TextBox2_Leave);
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.AttributesList);
            this.groupBox1.Location = new System.Drawing.Point(6, 5);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(561, 456);
            this.groupBox1.TabIndex = 8;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "属性";
            // 
            // groupBox2
            // 
            this.groupBox2.Controls.Add(this.MethodList);
            this.groupBox2.Location = new System.Drawing.Point(573, 5);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(268, 456);
            this.groupBox2.TabIndex = 9;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "方法";
            // 
            // VlispLook
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
            this.ClientSize = new System.Drawing.Size(849, 583);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.button3);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.FeaturesText);
            this.Controls.Add(this.VariableText);
            this.Controls.Add(this.MethodText);
            this.Controls.Add(this.CodeText);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.label3);
            this.Name = "VlispLook";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "Vlisp图元属性查看器";
            this.groupBox1.ResumeLayout(false);
            this.groupBox2.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.ListBox AttributesList;
        private System.Windows.Forms.ListBox MethodList;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.TextBox CodeText;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button3;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.TextBox FeaturesText;
        private System.Windows.Forms.Label label5;
        private System.Windows.Forms.TextBox MethodText;
        private System.Windows.Forms.Label label6;
        private System.Windows.Forms.TextBox VariableText;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.GroupBox groupBox2;
    }
}

后记

反射图元
实际上我们需求是反射图元下面所拥有的东西,那么,我们为什么要靠net调用arx反射?
我们net可是有API的啊!所以只需要反射图元就好了...

Arx制作
由于Arx可以通过重写命令栏的方式拦截命令文本数据,所以不需要像c#一样在那绕圈圈,
便可以导出命令历史到窗体上面,不过实现了功能就好啦

(完)

posted @ 2021-03-13 15:22  惊惊  阅读(1890)  评论(4编辑  收藏  举报