第一步:创建项目
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;
}