CAD二次开发 学习笔记(3)


 CAD二次开发 学习笔记(3)

Excel数据存储测试

        /// 
        /// 从database读取直线的数据,并将数据保存到excel表
        /// 
        [CommandMethod("ToExcel")]
        public void ToExcel()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            System.Data.DataTable table = new System.Data.DataTable();
            table.TableName = "直线表";
            table.Columns.Add("操作", typeof(string));
            table.Columns.Add("起点坐标X",typeof(double ));
            table.Columns.Add("起点坐标Y", typeof(double));
            table.Columns.Add("起点坐标Z", typeof(double));
            table.Columns.Add("终点坐标X", typeof(double));
            table.Columns.Add("终点坐标Y", typeof(double)); 
            table.Columns.Add("终点坐标Z", typeof(double));

            using (Transaction tr=db.TransactionManager.StartTransaction())
            {
                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                foreach (ObjectId objectId in btr)
                {
                    Line line = tr.GetObject(objectId,OpenMode.ForRead) as Line;
                    System.Data.DataRow row = table.NewRow();
                    if (line!=null)
                    {
                        row[0] = line.Handle.ToString();
                        row[1] = line.StartPoint.X;
                        row[2] = line.StartPoint.Y;
                        row[3] = line.StartPoint.Z;
                        row[4] = line.EndPoint.X;
                        row[5] = line.EndPoint.Y;
                        row[6] = line.EndPoint.Z;

                    }
                    table.Rows.Add(row);
                }
                tr.Commit();
            }
            SaveTo(table, @"C:\Users\Administrator\Desktop\LineData.xlsx");
        }
        /// 
        /// 将数据保存到excel表格
        /// 
        /// 
        /// 
        private void SaveTo(System.Data.DataTable table, string fileName)
        {
            int columnIndex = 1;
            int rowIndex = 1;

            Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
            excelApp.DefaultFilePath = fileName;
            excelApp.DisplayAlerts = true;
            excelApp.SheetsInNewWorkbook = 1;
            Microsoft.Office.Interop.Excel.Workbook workbook = excelApp.Workbooks.Add(true);

            foreach (System.Data.DataColumn column in table.Columns)
            {
                excelApp.Cells[rowIndex, columnIndex] = column.ColumnName;
                columnIndex++;
            }

            for (int i = 0; i < table.Rows.Count; i++)
            {
                columnIndex = 1;
                rowIndex++;
                for (int j = 0; j < table.Columns.Count; j++)
                {
                    excelApp.Cells[rowIndex, columnIndex] = table.Rows[i][j].ToString();
                    columnIndex++;
                }
            }
            workbook.SaveCopyAs(fileName);
            excelApp = null;
            workbook = null;
        }

运行结果

规则重定义OverRule

注意:该规则重定义不支持Jig绘制直线,只能静态生成,否则会导致CAD崩溃;

AddLine命令就是为了测试OverRule而专门添加的静态画直线方法;

        //-------------规则重定义-------------------

        /// 
        /// 开启规则重定义
        /// 
        [CommandMethod("StartOverRule")]
        public void StartOverRule()
        {
            LineToPipe lineToPipe = new LineToPipe(10);
            Overrule.AddOverrule(RXClass.GetClass(typeof(Line)), lineToPipe, false);
            Overrule.Overruling = true;
        }
        /// 
        /// 结束规则重定义
        /// 
        [CommandMethod("EndOverRule")]
        public void EndOverRule()
        {
            Overrule.Overruling = false;
        }
        /// 
        /// 添加一条直线:测试
        /// 
        [CommandMethod("AddLine")]
        public void AddLine()
        {
            Random r = new Random();
            Database db = HostApplicationServices.WorkingDatabase;
            using (Transaction tr =db.TransactionManager.StartTransaction())
            {
                BlockTable bt = tr.GetObject(db.BlockTableId,OpenMode.ForRead) as BlockTable;
                BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace],OpenMode.ForWrite) as BlockTableRecord;
                
                Line line = new Line(new Point3d(r.Next(0,500), r.Next(0, 200),0), new Point3d(r.Next(0, 500), r.Next(0, 200), 0));
                btr.AppendEntity(line);
                tr.AddNewlyCreatedDBObject(line ,true);
                tr.Commit();
            }
        }

规则重定义的类

   /// 
    /// 规则重定义的类
    /// 
    public class LineToPipe : DrawableOverrule
    {
        private double r;
        public LineToPipe(double radius)
        {
            r = radius;
        }
        public override bool WorldDraw(Drawable drawable, WorldDraw wd)
        {
            if (drawable is Line)
            {
                Line line = drawable as Line;
                Circle circle = new Circle(line.StartPoint, line.EndPoint - line.StartPoint, r);
                ExtrudedSurface pipe = new ExtrudedSurface();
                pipe.CreateExtrudedSurface(circle, line.EndPoint - line.StartPoint, new SweepOptions());
                pipe.WorldDraw(wd);
                circle.Dispose();
                pipe.Dispose();
            }
            return true;
        }

    }

运行结果

CAD事件Event-EventHandler

 //--------------------事件-----------------------

        /// 
        /// 移除对象删除事件的处理函数/移除事件侦听者
        /// 
        [CommandMethod("RemoveErasedObjectEvent")]
        public void RemoveErasedObjectEvent()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            db.ObjectErased -= new ObjectErasedEventHandler(ObjectErasedEventHandler);
        }

        /// 
        /// 添加对象删除事件的处理函数/添加事件侦听者
        /// 
        [CommandMethod("AddErasedObjectEvent")]
        public void AddErasedObjectEvent()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            //db.ObjectErased += ObjectErasedHandler;//方法一、委托添加方法
            db.ObjectErased += new ObjectErasedEventHandler(ObjectErasedEventHandler);//方法二、委托添加委托
        }
        /// 
        /// 对象删除事件的处理函数
        /// 
        /// 
        /// 
        private void ObjectErasedEventHandler(object sender, ObjectErasedEventArgs e)
        {
            Application.ShowAlertDialog($"删除的对象Id为:{e.DBObject.ObjectId}");
        }

运行结果

交互界面总结

添加右键菜单

        /// 
        /// 添加右键菜单
        /// 
        [CommandMethod("AddContextMenu")]
        public void AddContextMenu()
        {
            ContextMenuExtension contextMenu = new ContextMenuExtension();
            contextMenu.Title = "我的右键菜单";
            MenuItem item1 = new MenuItem("创建直线");
            item1.Click += new EventHandler(item1_Click);
            MenuItem item2 = new MenuItem("创建圆");
            item2.Click += new EventHandler(item2_Click);

            contextMenu.MenuItems.Add(item1);
            contextMenu.MenuItems.Add(item2);
            Application.AddDefaultContextMenuExtension(contextMenu);

        }

        private void item2_Click(object sender, EventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute("\nCircle",true,false,true);
        }

        private void item1_Click(object sender, EventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute("\nLine", true, false, true);
        }

运行结果

添加Ribbon菜单

/// 
        /// 添加菜单命令
        /// 
        [CommandMethod("AddRibbon")]
        public void AddRibbon()
        {
            RibbonControl control = RibbonControl();
            RibbonTab tab = RibbonTab("菜单标签1", "1");
            RibbonTab tab2 = RibbonTab("菜单标签2", "2");
            RibbonTab tab3 = RibbonTab("菜单标签3", "3");
            RibbonPanel panel = RibbonPanel("菜单面板1");
            RibbonPanel panel2 = RibbonPanel("菜单面板2");
            RibbonPanel panel3 = RibbonPanel("菜单面板3");
            RibbonPanel panel4 = RibbonPanel("菜单面板4");
            RibbonButton button = RibbonButton("菜单按钮1", "菜单命令");
            RibbonButton button2 = RibbonButton("菜单按钮2", "菜单命令");
            RibbonButton button3 = RibbonButton("菜单按钮3", "菜单命令");
            RibbonButton button4 = RibbonButton("菜单按钮4", "菜单命令");
            panel.Source.Items.Add(button);
            panel.Source.Items.Add(button2);
            panel.Source.Items.Add(button3);
            panel.Source.Items.Add(button4);

            tab.Panels.Add(panel);
            tab.Panels.Add(panel2);
            tab.Panels.Add(panel3);
            tab.Panels.Add(panel4);

            control.Tabs.Add(tab);
            control.Tabs.Add(tab2);
            control.Tabs.Add(tab3);
        }
        /// 
        /// 获得菜单控制
        /// 
        /// 
        public RibbonControl RibbonControl()
        {
            if (ComponentManager.Ribbon == null)
            {
                ComponentManager.ItemInitialized +=
                    new EventHandler(ComponentManager_ItemInitialized);
            }
            return ComponentManager.Ribbon;
        }
        /// 
        /// 用于激活菜单
        /// 
        /// 
        /// 
        private void ComponentManager_ItemInitialized(object sender, RibbonItemEventArgs e)
        {
            if (ComponentManager.Ribbon != null)
            {
                ComponentManager.ItemInitialized -= new EventHandler(ComponentManager_ItemInitialized);
            }
        }
        /// 
        /// 创建菜单标签
        /// 
        /// 标签名称
        /// 标签Id
        /// 
        public RibbonTab RibbonTab(string name, string id)
        {
            RibbonTab tab = new RibbonTab()
            {
                Title =  "Title:"+name,
                
                Id = id,
                IsActive = true,
            };
            return tab;
        }
        /// 
        /// 创建菜单面板
        /// 
        /// 面板名称
        /// 
        public RibbonPanel RibbonPanel(string title)
        {
            RibbonPanelSource source = new RibbonPanelSource();
            source.Title = title;
            RibbonPanel panel = new RibbonPanel();
            panel.Source = source;
            return panel;

        }
        /// 
        /// 创建按钮
        /// 
        /// 
        /// 
        /// 
        public RibbonButton RibbonButton(string buttonName, string commandName)
        {
            RibbonButton button = new RibbonButton()
            {
                Text = "Text:" + buttonName,
                
                CommandParameter = commandName,
                ShowText = true,
                CommandHandler = new AdCommandHandler(),
            };
            return button;
        }

运行结果

添加自定义窗口面板

        /// 
        /// 自定义面板Palette
        /// 
        [CommandMethod("AddPalette")]
        public void AddPalette()
        {
            CustomController controller = new CustomController();
            PaletteSet ps = new PaletteSet("我的自定义面板")
            {
                Visible = true,
                Style = PaletteSetStyles.ShowAutoHideButton,
                Dock = DockSides.None,
                MinimumSize = new Size(200, 100),
                Size = new Size(400,200),
            };
            ps.Add("自定义控件",controller);
            ps.Visible = true;
        }

运行结果

菜单层级结构

基础知识:

嵌入 AutoCAD 的窗体有两种:

ModalDialog(模态对话框), Application.ShowModalDialog(form); 

ModelessDialog(非模态对话框) , Application.ShowModelessDialog(form); 

一、模态对话框

ModalDialog(模态对话框)为不可切换焦点的对话框, 模态窗体显示的时候程序的焦点始终保持在模态窗体上;

如果需要切换到 AutoCAD 环境进行交互的时候需要EditorUserInteraction 类来切换焦点到 AutoCAD 的命令行; 

如果将焦点从CAD切换回窗口,首先需要结束EditorUserInteraction ,然后再用Focus()方法将焦点重新回到窗体;

二、非模态对话框
ModelessDialog(非模态对话框)为活动焦点的对话框,程序焦点可以自由的从 AutoCAD 界面到窗体之间切换,主要用于
用户与
AutoCAD 环境的即时交互操作。 

 using (EditorUserInteraction edUsrInt = ed.StartUserInteraction(this))
{
//交互过程
edUsrInt.End(); //交互结束.
this.Focus();
}
 

交互测试-通过窗口选择点

        /// 
        /// 通过交互窗口选择点
        /// 
        [CommandMethod("SelectPointDialog")]
        public void SelectPointDialog()
        {
            using (SelectPointForm form=new SelectPointForm())
            {
                //像CAD提示窗口一样,不在任务栏显示
                form.ShowInTaskbar = false;
                //将form窗口作为模态窗口进行显示
                Application.ShowModalDialog(form);
                //将textBox1的文本信息,显示到Editor窗口
                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(form.textBox1.Text);
            }    
        
        }
        /// 
        /// 将焦点切换至CAD,以便选择点
        /// 
        /// 
        /// 
        private void button1_Click(object sender, EventArgs e)
        {
            Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;

            using (EditorUserInteraction interaction = ed.StartUserInteraction(this))
            {
                Point3d point = GetPoint3D("\n选择点");
                textBox1.Text = $"选择点的坐标  X:{point.X},Y:{point.Y},Z:{point.Z}";
                interaction.End();
                this.Focus();
            }

        }
        /// 
        /// 提示用户拾取一个点
        /// 
        /// 
        /// 
        public Point3d GetPoint3D(string promptMessage)
        {

            Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            PromptPointResult result = ed.GetPoint(promptMessage);
            if (result.Status == PromptStatus.OK)
            {
                return result.Value;
            }
            else
            {
                return new Point3d();
            }
        }
        /// 
        /// 确认按钮
        /// 
        /// 
        /// 
        private void button2_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
        /// 
        /// 取消按钮
        /// 
        /// 
        /// 
        private void button3_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }
    }

运行结果

打印输出相关类的关系图