在Visual Studio中创建包含窗体的AutoCAD C#项目

发布于:2025-03-30 ⋅ 阅读:(20) ⋅ 点赞:(0)

第一步:创建项目

1. 打开Visual Studio
2. 点击"新建项目"
3. 选择"类库(.NET Framework)" - 注意选择与你的AutoCAD版本兼容的.NET版本
4. 命名项目为`CircleGeneratorPlugin`
5. 点击"创建"
 

第二步:组织项目结构

CircleGeneratorPlugin/
├── Commands/
│   └── CircleCommands.cs
├── Forms/
│   ├── CircleInputForm.cs
│   └── CircleInputForm.Designer.cs
├── Properties/
│   └── Settings.settings
└── CircleGeneratorPlugin.csproj

1. 在解决方案资源管理器中右键项目 → 添加 → 新建文件夹

   - 创建`Commands`文件夹

   - 创建`Forms`文件夹

# 项目文件夹与命名空间的关系详解

在C#项目中,文件夹和命名空间的关系需要明确理解,它们既有关联又有区别。下面我会详细解释,并用你的AutoCAD插件项目作为例子说明。

## 核心结论

**文件夹结构不自动决定命名空间**,但Visual Studio默认会基于文件夹路径生成命名空间建议。

## 详细解释

### 1. 默认行为

当你在Visual Studio中:
1. 创建文件夹(如`Commands`和`Forms`)
2. 在这些文件夹中添加新类文件时

Visual Studio**默认**会:
- 使用"根命名空间.文件夹名"作为新类的命名空间
- 根命名空间就是你在项目属性中设置的"默认命名空间"(项目右键→属性→应用程序→默认命名空间)

### 2. 你的项目具体分析

以你的`CircleGeneratorPlugin`项目为例:

```
CircleGeneratorPlugin/ (默认命名空间: CircleGeneratorPlugin)
├── Commands/
│   └── CircleCommands.cs
├── Forms/
│   └── CircleInputForm.cs
```

- **CircleCommands.cs**的默认命名空间会是:`CircleGeneratorPlugin.Commands`
- **CircleInputForm.cs**的默认命名空间会是:`CircleGeneratorPlugin.Forms`

### 3. 关键注意事项

1. **命名空间可以手动修改**:
   - 即使文件在Commands文件夹中,你也可以手动将命名空间改为任何名称
   - 但保持文件夹和命名空间一致是良好的实践
 

 

## 第三步:添加窗体类

 

1. 右键`Forms`文件夹 → 添加 → 新建项

2. 选择"Windows 窗体" → 命名为`CircleInputForm.cs`

using System;

using System.Windows.Forms;

 

namespace CircleGeneratorPlugin.Forms

{

    public partial class CircleInputForm : Form

    {

        // 公开属性用于获取圆的数量

        public int CircleCount { get; private set; } = 1; // 默认1个圆

 

        public CircleInputForm()

        {

            InitializeComponent();

        }

 

        private void btnOK_Click(object sender, EventArgs e)

        {

            if (int.TryParse(txtCircleCount.Text, out int count) && count > 0)

            {

                CircleCount = count;

                this.DialogResult = DialogResult.OK;

                this.Close();

            }

            else

            {

                MessageBox.Show("请输入有效的正整数!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }

        }

 

        private void btnCancel_Click(object sender, EventArgs e)

        {

            this.DialogResult = DialogResult.Cancel;

            this.Close();

        }

    }

}

 

 

4. 设计窗体界面:
   - 添加一个Label:"请输入要生成的圆的数量:"
   - 添加一个TextBox (命名为`txtCircleCount`)
   - 添加两个Button:"确定"(命名为`btnOK`)和"取消"(命名为`btnCancel`)

## 第四步:添加AutoCAD命令类

1. 右键`Commands`文件夹 → 添加 → 类
2. 命名为`CircleCommands.cs`
3. 修改代码:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using CircleGeneratorPlugin.Forms;
using System;

namespace CircleGeneratorPlugin.Commands
{
    public class CircleCommands
    {
        [CommandMethod("GenerateCircles")]
        public void GenerateCircles()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                // 显示输入窗体
                using (CircleInputForm form = new CircleInputForm())
                {
                    if (Application.ShowModalDialog(form) != DialogResult.OK)
                    {
                        ed.WriteMessage("\n用户取消了操作");
                        return;
                    }

                    int circleCount = form.CircleCount;
                    ed.WriteMessage($"\n将生成 {circleCount} 个圆...");

                    // 开始事务处理
                    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;

                        // 生成指定数量的圆
                        for (int i = 0; i < circleCount; i++)
                        {
                            // 创建圆 (位置按索引排列)
                            Circle circle = new Circle(
                                new Point3d(i * 10, 0, 0),  // X坐标间隔10个单位
                                Vector3d.ZAxis,             // 法向量(Z轴)
                                5);                        // 半径5个单位

                            // 添加到图形数据库
                            btr.AppendEntity(circle);
                            tr.AddNewlyCreatedDBObject(circle, true);
                        }

                        tr.Commit();
                        ed.WriteMessage($"\n成功生成 {circleCount} 个圆!");
                    }
                }
            }
            catch (Exception ex)
            {
                ed.WriteMessage($"\n错误: {ex.Message}");
            }
        }
    }
}

 

功能增强版

using System;
using System.Drawing;
using System.Windows.Forms;
using CircleGeneratorPlugin.Properties;

namespace CircleGeneratorPlugin.Forms
{
    public partial class CircleInputForm : Form
    {
        // 公开属性用于获取所有参数
        public int CircleCount { get; private set; }
        public double CircleRadius { get; private set; }
        public double CircleSpacing { get; private set; }
        public Color CircleColor { get; private set; }
        public bool ExportToTxt { get; private set; }
        public string ExportPath { get; private set; }

        public CircleInputForm()
        {
            InitializeComponent();
            LoadSettings();
        }

        private void LoadSettings()
        {
            // 加载上次的设置作为默认值
            numCircleCount.Value = Settings.Default.LastCircleCount;
            numRadius.Value = (decimal)Settings.Default.LastRadius;
            numSpacing.Value = (decimal)Settings.Default.LastSpacing;
            colorDialog.Color = Settings.Default.LastColor;
            btnColor.BackColor = colorDialog.Color;
            chkExport.Checked = Settings.Default.LastExportEnabled;
            txtExportPath.Text = Settings.Default.LastExportPath;
            radUniform.Checked = Settings.Default.LastDistributionType == 0;
            radRandom.Checked = Settings.Default.LastDistributionType == 1;
        }

        private void SaveSettings()
        {
            // 保存当前设置
            Settings.Default.LastCircleCount = (int)numCircleCount.Value;
            Settings.Default.LastRadius = (double)numRadius.Value;
            Settings.Default.LastSpacing = (double)numSpacing.Value;
            Settings.Default.LastColor = colorDialog.Color;
            Settings.Default.LastExportEnabled = chkExport.Checked;
            Settings.Default.LastExportPath = txtExportPath.Text;
            Settings.Default.LastDistributionType = radUniform.Checked ? 0 : 1;
            Settings.Default.Save();
        }

        private void btnColor_Click(object sender, EventArgs e)
        {
            if (colorDialog.ShowDialog() == DialogResult.OK)
            {
                btnColor.BackColor = colorDialog.Color;
            }
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            using (SaveFileDialog sfd = new SaveFileDialog())
            {
                sfd.Filter = "文本文件|*.txt";
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    txtExportPath.Text = sfd.FileName;
                }
            }
        }

        private void chkExport_CheckedChanged(object sender, EventArgs e)
        {
            txtExportPath.Enabled = btnBrowse.Enabled = chkExport.Checked;
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if (!ValidateInput())
                return;

            // 保存用户输入的值
            CircleCount = (int)numCircleCount.Value;
            CircleRadius = (double)numRadius.Value;
            CircleSpacing = (double)numSpacing.Value;
            CircleColor = colorDialog.Color;
            ExportToTxt = chkExport.Checked;
            ExportPath = txtExportPath.Text;

            SaveSettings();
            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        private bool ValidateInput()
        {
            if (numCircleCount.Value <= 0)
            {
                MessageBox.Show("圆的数量必须大于0!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            if (numRadius.Value <= 0)
            {
                MessageBox.Show("半径必须大于0!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            if (numSpacing.Value < 0)
            {
                MessageBox.Show("间距不能为负数!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            if (chkExport.Checked && string.IsNullOrWhiteSpace(txtExportPath.Text))
            {
                MessageBox.Show("请选择导出文件路径!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            return true;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }
    }
}

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using CircleGeneratorPlugin.Forms;
using System;
using System.IO;
using System.Windows.Forms;
using Color = Autodesk.AutoCAD.Colors.Color;

namespace CircleGeneratorPlugin.Commands
{
    public class CircleCommands
    {
        [CommandMethod("GENCIRCLES")]
        public void GenerateCircles()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                // 显示输入窗体
                using (CircleInputForm form = new CircleInputForm())
                {
                    if (Application.ShowModalDialog(form) != DialogResult.OK)
                    {
                        ed.WriteMessage("\n操作已取消");
                        return;
                    }

                    // 开始事务处理
                    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;

                        // 准备导出数据
                        System.Text.StringBuilder exportData = null;
                        if (form.ExportToTxt)
                        {
                            exportData = new System.Text.StringBuilder();
                            exportData.AppendLine("Index,X,Y,Radius");
                        }

                        // 生成指定数量的圆
                        for (int i = 0; i < form.CircleCount; i++)
                        {
                            double xPos = i * form.CircleSpacing;
                            double radius = form.CircleRadius;
                            
                            // 创建圆
                            Circle circle = new Circle(
                                new Point3d(xPos, 0, 0),  // 位置
                                Vector3d.ZAxis,           // 法向量
                                radius);                  // 半径

                            // 设置颜色
                            circle.Color = Color.FromColor(form.CircleColor);

                            // 添加到图形数据库
                            btr.AppendEntity(circle);
                            tr.AddNewlyCreatedDBObject(circle, true);

                            // 记录导出数据
                            if (form.ExportToTxt)
                            {
                                exportData.AppendLine($"{i + 1},{xPos},0,{radius}");
                            }
                        }

                        // 导出到文件
                        if (form.ExportToTxt && exportData != null)
                        {
                            try
                            {
                                File.WriteAllText(form.ExportPath, exportData.ToString());
                                ed.WriteMessage($"\n圆数据已导出到: {form.ExportPath}");
                            }
                            catch (Exception ex)
                            {
                                ed.WriteMessage($"\n导出失败: {ex.Message}");
                            }
                        }

                        tr.Commit();
                        ed.WriteMessage($"\n成功生成 {form.CircleCount} 个圆!");
                    }
                }
            }
            catch (Exception ex)
            {
                ed.WriteMessage($"\n错误: {ex.Message}\n{ex.StackTrace}");
                try
                {
                    // 尝试记录错误到文件
                    string errorLogPath = Path.Combine(
                        Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                        "CircleGenerator_ErrorLog.txt");
                    File.AppendAllText(errorLogPath, $"{DateTime.Now}: {ex}\n\n");
                }
                catch { }
            }
        }
    }
}

5. 设置文件 (Settings.settings)

 

在设置设计器中添加以下设置项:

- LastCircleCount (int, 默认1)

- LastRadius (double, 默认5.0)

- LastSpacing (double, 默认10.0)

- LastColor (System.Drawing.Color, 默认Red)

- LastExportEnabled (bool, 默认false)

- LastExportPath (string, 默认空)

- LastDistributionType (int, 默认0)

 

 

增强:

using System;

using System.Drawing;

using System.Windows.Forms;

 

namespace EnhancedCirclePlugin

{

    public partial class InputForm : Form

    {

        public int CircleCount { get; private set; } = 5;

        public double Radius { get; private set; } = 10.0;

        public double Spacing { get; private set; } = 30.0;

        public int ArrangementMode { get; private set; } = 0; // 0=直线, 1=矩形, 2=圆形

        public string LayerName { get; private set; } = "0";

        public Color CircleColor { get; private set; } = Color.Black;

 

        public InputForm()

        {

            InitializeComponent();

        }

 

        private void btnOK_Click(object sender, EventArgs e)

        {

            if (!ValidateInputs()) return;

            

            DialogResult = DialogResult.OK;

            Close();

        }

 

        private bool ValidateInputs()

        {

            // 验证圆数量

            if (!int.TryParse(txtCount.Text, out int count) || count < 1)

            {

                MessageBox.Show("请输入有效的正整数", "圆数量错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return false;

            }

            CircleCount = count;

 

            // 验证半径

            if (!double.TryParse(txtRadius.Text, out double radius) || radius <= 0)

            {

                MessageBox.Show("请输入有效的正数", "半径错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return false;

            }

            Radius = radius;

 

            // 验证间距

            if (!double.TryParse(txtSpacing.Text, out double spacing) || spacing <= 0)

            {

                MessageBox.Show("请输入有效的正数", "间距错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return false;

            }

            Spacing = spacing;

 

            // 获取排列模式

            ArrangementMode = cmbArrangement.SelectedIndex;

 

            // 获取图层名称

            LayerName = txtLayer.Text.Trim();

 

            return true;

        }

 

        private void btnColor_Click(object sender, EventArgs e)

        {

            ColorDialog colorDialog = new ColorDialog();

            if (colorDialog.ShowDialog() == DialogResult.OK)

            {

                CircleColor = colorDialog.Color;

           

    btnColor.BackColor = CircleColor;

            }

        }

    }

}

 

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.Colors;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

using System;

 

namespace EnhancedCirclePlugin

{

    public class CircleCommands

    {

        [CommandMethod("ENHANCEDCIRCLES")]

        public void EnhancedCirclesCommand()

        {

            Document doc = Application.DocumentManager.MdiActiveDocument;

            Database db = doc.Database;

            Editor ed = doc.Editor;

 

            try

            {

                // 显示配置对话框

                using (InputForm form = new InputForm())

                {

                    if (Application.ShowModalDialog(form) != DialogResult.OK)

                    {

                        ed.WriteMessage("\n操作已取消");

                        return;

                    }

 

                    // 获取基点

                    PromptPointResult basePointResult = ed.GetPoint("\n指定基点: ");

                    if (basePointResult.Status != PromptStatus.OK) return;

 

                    Point3d basePoint = basePointResult.Value;

 

                    // 开始事务处理

                    using (Transaction tr = db.TransactionManager.StartTransaction())

                    {

                        // 确保图层存在

                        LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);

                        if (!lt.Has(form.LayerName))

                        {

                            LayerTableRecord ltr = new LayerTableRecord

                            {

                                Name = form.LayerName,

                                Color = Color.FromColor(form.CircleColor)

                            };

                            lt.UpgradeOpen();

                            lt.Add(ltr);

                            tr.AddNewlyCreatedDBObject(ltr, true);

                        }

 

                        // 获取模型空间

                        BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

                        BlockTableRecord btr = (BlockTableRecord)tr.GetObject(

                            bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

 

                        // 根据排列模式创建圆

                        switch (form.ArrangementMode)

                        {

                            case 0: // 直线排列

                                CreateLinearArrangement(tr, btr, basePoint, form);

                                break;

                            case 1: // 矩形排列

                                CreateRectangularArrangement(tr, btr, basePoint, form);

                                break;

                            case 2: // 圆形排列

                                CreateCircularArrangement(tr, btr, basePoint, form);

                                break;

                        }

 

                        tr.Commit();

                        ed.WriteMessage($"\n成功创建 {form.CircleCount} 个圆");

                    }

                }

            }

            catch (Exception ex)

            {

                ed.WriteMessage($"\n错误: {ex.Message}");

            }

        }

 

        private void CreateLinearArrangement(Transaction tr, BlockTableRecord btr, Point3d basePoint, InputForm form)

        {

            for (int i = 0; i < form.CircleCount; i++)

            {

                Point3d center = new Point3d(

                    basePoint.X + i * form.Spacing,

                    basePoint.Y,

                    basePoint.Z);

 

                CreateCircle(btr, tr, center, form);

            }

        }

 

        private void CreateRectangularArrangement(Transaction tr, BlockTableRecord btr, Point3d basePoint, InputForm form)

        {

            int cols = (int)Math.Ceiling(Math.Sqrt(form.CircleCount));

            int rows = (int)Math.Ceiling((double)form.CircleCount / cols);

 

            for (int i = 0; i < rows; i++)

            {

                for (int j = 0; j < cols && (i * cols + j) < form.CircleCount; j++)

                {

                    Point3d center = new Point3d(

                        basePoint.X + j * form.Spacing,

                        basePoint.Y - i * form.Spacing,

                        basePoint.Z);

 

                    CreateCircle(btr, tr, center, form);

                }

            }

        }

 

        private void CreateCircularArrangement(Transaction tr, BlockTableRecord btr, Point3d basePoint, InputForm form)

        {

            double angleIncrement = 2 * Math.PI / form.CircleCount;

            for (int i = 0; i < form.CircleCount; i++)

            {

                double angle = i * angleIncrement;

                Point3d center = new Point3d(

                    basePoint.X + form.Spacing * Math.Cos(angle),

                    basePoint.Y + form.Spacing * Math.Sin(angle),

                    basePoint.Z);

 

                CreateCircle(btr, tr, center, form);

            }

        }

 

        


        private void CreateCircle(BlockTableRecord btr, Transaction tr, Point3d center, InputForm form)
        {
            Circle circle = new Circle(center, Vector3d.ZAxis, form.Radius);
            circle.Layer = form.LayerName;
            circle.Color = Color.FromColor(form.CircleColor);

            btr.AppendEntity(circle);
            tr.AddNewlyCreatedDBObject(circle, true);
        }
    }
}
```

partial class InputForm

{

    private System.ComponentModel.IContainer components = null;

 

    protected override void Dispose(bool disposing)

    {

        if (disposing && (components != null))

        {

            components.Dispose();

        }

        base.Dispose(disposing);

    }

 

    private void InitializeComponent()

    {

        this.label1 = new Label();

        this.txtCount = new TextBox();

        this.label2 = new Label();

        this.txtRadius = new TextBox();

        this.label3 = new Label();

        this.txtSpacing = new TextBox();

        this.label4 = new Label();

        this.cmbArrangement = new ComboBox();

        this.label5 = new Label();

        this.txtLayer = new TextBox();

        this.label6 = new Label();

        this.btnColor = new Button();

        this.btnOK = new Button();

        this.btnCancel = new Button();

        this.SuspendLayout();

        

        // label1

        this.label1.AutoSize = true;

        this.label1.Location = new Point(12, 15);

        this.label1.Name = "label1";

        this.label1.Size = new Size(65, 12);

        this.label1.TabIndex = 0;

        this.label1.Text = "圆的数量:";

        

        // txtCount

        this.txtCount.Location = new Point(100, 12);

        this.txtCount.Text = "5";

        this.txtCount.Size = new Size(100, 21);

        

        // label2

        this.label2.AutoSize = true;

        this.label2.Location = new Point(12, 45);

        this.label2.Text = "半径:";

        

        // txtRadius

        this.txtRadius.Location = new Point(100, 42);

        this.txtRadius.Text = "10.0";

        

        // label3

        this.label3.AutoSize = true;

        this.label3.Location = new Point(12, 75);

        this.label3.Text = "间距:";

        

        // txtSpacing

        this.txtSpacing.Location = new Point(100, 72);

        this.txtSpacing.Text = "30.0";

        

        // label4

        this.label4.AutoSize = true;

        this.label4.Location = new Point(12, 105);

        this.label4.Text = "排列方式:";

        

        // cmbArrangement

        this.cmbArrangement.Items.AddRange(new object[] { "直线排列", "矩形排列", "圆形排列" });

        this.cmbArrangement.SelectedIndex = 0;

        this.cmbArrangement.Location = new Point(100, 102);

        

        // label5

        this.label5.AutoSize = true;

        this.label5.Location = new Point(12, 135);

        this.label5.Text = "图层:";

        

        // txtLayer

        this.txtLayer.Location = new Point(100, 132);

        this.txtLayer.Text = "0";

        

        // label6

        this.label6.AutoSize = true;

        this.label6.Location = new Point(12, 165);

        this.label6.Text = "颜色:";

        

        // btnColor

        this.btnColor.BackColor = Color.Black;

        this.btnColor.Location = new Point(100, 162);

        this.btnColor.Size = new Size(75, 23);

        this.btnColor.Click += new EventHandler(this.btnColor_Click);

        

        // btnOK

        this.btnOK.Location = new Point(40, 200);

        this.btnOK.Text = "确定";

        this.btnOK.Click += new EventHandler(this.btnOK_Click);

        

        // btnCancel

        this.btnCancel.Location = new Point(125, 200);

        this.btnCancel.Text = "取消";

        this.btnCancel.Click += new EventHandler(this.btnCancel_Click);

        

        // Form设置

        this.ClientSize = new Size(220, 240);

        this.Controls.AddRange(new Control[] {

            this.label1, this.txtCount,

            this.label2, this.txtRadius,

            this.label3, this.txtSpacing,

            this.label4, this.cmbArrangement,

            this.label5, this.txtLayer,

            this.label6, this.btnColor,

            this.btnOK, this.btnCancel

        });

        this.FormBorderStyle = FormBorderStyle.FixedDialog;

        this.MaximizeBox = false;

        this.Text = "圆绘制设置";

    }

 

    private Label label1, label2, label3, label4, label5, label6;

    private TextBox txtCount, txtRadius, txtSpacing, txtLayer;

    private ComboBox cmbArrangement;

    private Button btnColor, btnOK, btnCancel;

}