我正在尝试从现有的C#桌面应用程序启动AutoCAD 2013,使用数据库值绘制图表,然后将图形保存到数据库中,作为可变位阵列(VARBYTE)。除了将坐标进入现有的AutoCAD编辑器窗口外,我一直都取得了良好的成功。
我已经尝试了Netload,但是我无法通过命令行放置55 AutoCAD数据库对象的列表。试图通过COM Interop通过对象的失败和混乱,与AutoCAD和我的应用程序的64位状态有关。虽然此网站很有帮助,但http://through-theterface.typepad.com/,我无法得到我想要做的事情。
任何建议都将不胜感激。谢谢。
编辑:
我接受了Locke的建议,并在.NET DLL中添加了功能,以根据简单的参数绘制单个项目(例如X,Y坐标,半径,标签等)。这是方法签名的样子:
[CommandMethod("DrawSmallCircle", CommandFlags.Session)]
public static void DrawSmallCircle(double x, double y, double aRadius, string aGuage, string aLabel, string aTitle)
netload the .dll托管上述方法(并且是包含类),我在实例化的Interop Accapplication上使用sendCommand,例如:
acApp.ActiveDocument.SendCommand("DrawSmallCircle " +
circ.circle.Center.X.ToString() + ", " +
circ.circle.Center.Y.ToString() + ", " +
circ.circle.Radius.ToString() + ", " +
circ.guage + ", " +
circ.label + ", " +
circ.title + " "
);
不幸的是,我遇到的错误只是"常见的语言运行时检测到无效程序"。
我不确定在我的.dll中注册命令是否会做任何好处,因为据称"命令方法不能接受争论,但是lispfunctions可以。"
http://forums.autodesk.com/t5/net/commandmethod-with-with-custom-params/td-p/2572973
好吧,因此您遇到了Interop/Interop内部自动化问题。传统上,AutoCAD不想放弃流程模块与进程模块进行交谈,至少在来回发送参数的背景下。涉及注册过程中COM接口的正式方法是要正确行为的挑战,尤其是在X64位的背景下。我还没有看到在多台计算机上一直行事,因此,我倾向于默认使用以下方法。
您是正确的,因为使用[CommandMethod]标志标记的方法无法进行参数,因此显然需要是无效的。在运行时发送IT参数上下文的诀窍是在定义的方法本身中包括参数提示。当您开发命令时,请想一想,以便在AutoCAD中调用用户,并且在命令继续执行命令之前,请提示它们。与其他本机AutoCAD命令一样,可以在单个字符串中与呼叫呼叫一起发送参数数据。
示例:
(命令" ._circle" 0,0" 5")< - 在0,0的半径为5中绘制一个圆圈。
因此,您的命令调用最终可能看起来像这样:
(命令" drawdbcircle" 2.3,56.12"," 7"仪表"标签" title")
过程中代码
[CommandMethod("DRAWDBCIRCLE")]
public void DrawDbCircle()
{
var acDb = HostApplicationServices.WorkingDatabase;
var acEd = Application.DocumentManager.MdiActiveDocument.Editor;
using (var acTrans = acDb.TransactionManager.StartOpenCloseTransaction())
{
var bt = (BlockTable)acTrans.GetObject(acDb.BlockTableId, OpenMode.ForWrite);
var btr = (BlockTableRecord)acTrans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
Point3d centerPoint;
double radius;
string gauge, label, title;
// Prompt for the centerpoint
var pointResult = acEd.GetPoint("ENTER CIRCLE ORIGIN: n");
centerPoint = pointResult.Value;
// Prompt for the radius
var doubleResult = acEd.GetDouble("ENTER CIRCLE RADIUS: n");
radius = doubleResult.Value;
// Prompt for the strings
var stringResult = acEd.GetString("ENTER CIRCLE GAUGE: n");
gauge = stringResult.StringResult;
stringResult = acEd.GetString("ENTER CIRCLE LABEL: n");
label = stringResult.StringResult;
stringResult = acEd.GetString("ENTER CIRCLE TITLE: n");
title = stringResult.StringResult;
// Create the circle
var circ = new Circle(centerPoint, Vector3d.ZAxis, radius);
// <-- Add code for dealing with strings -->
btr.AppendEntity(circ);
acTrans.AddNewlyCreatedDBObject(circ, true);
acTrans.Commit();
}
}
Interop代码
private AcadApplication acApp;
private AcadDocument acDoc;
private void btnRun_Click(object sender, EventArgs e)
{
if (acApp == null) return;
acDoc = acApp.ActiveDocument;
foreach (DataRow row in circleTable.Rows)
DrawDatabaseCircle(row);
}
private void DrawDatabaseCircle(DataRow circRow)
{
var cmdFormat = string.Format(""{0},{1}" "{2}" "{3}" "{4}" "{5}"", circRow.ItemArray);
acDoc.SendCommand(string.Format("(Command "DRAWDBCIRCLE" {0})n", cmdFormat));
}
显然,这或多或少是伪代码。我假设这里有很多事情,例如正确设置的Accorplication和Acadocument字段,即包含定义命令方法的DLL已正确净额,并且数据库圆圈正在数据台上出现。在CommandMethod中需要进行错误处理以检查参数,并且将SendCommand方法封闭在尝试/捕获中是有意义的。
这种技术实际上只有在您具有可以用字符串表示的数据类型的情况下起作用,因此它不会涵盖所有情况。绝对值得尝试使COM注册的界面长期工作,以在内外流程之间进行更强大的沟通。