Здравствуйте.
Недавно начал заниматься программированием для autocad. Уже написал пару *.dll с командами для autocad и приложение с доступом через com типа “Hello Word”. Объем работ, который приходится выполнять в autocad заставляет писать что-то более практичное и тут возникает множество вопросов и непонимания. Надеюсь, вы поможете разобраться.
Итак, нужно написать *.dll библиотеку, с командой, которая должна считать количество блоков с определённым именем, получать координаты расположения базовой точки каждого блока (относительно оси координат), осуществлять чтение\ запись в атрибуты, которые находятся в блоке и получать состояние видимости каждого блока.
Пока команда умеет находить блоки, проверять имя, и считать их кол-во:
[CommandMethod("MyCommand")]
public void iterateThroughAllObjects()
{
var Editor = Application.DocumentManager.MdiActiveDocument.Editor;
int countOfBlock = 0;
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приведение типов
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
BlockTable blocktab = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
//BlockTableRecord mybtr = (BlockTableRecord)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
if (blocktab.GetType() == typeof(BlockReference))
{
Editor.WriteMessage("typeof(BlockReference");
}
string name= "ABCD";
if (blocktab.Has(name))
{
countOfBlock += 1;
Editor.WriteMessage(blocktab.Id.ToString());
Editor.WriteMessage(blocktab.AcadObject.ToString());
}
}
Editor.WriteMessage("Кол-во =" + countOfBlock.ToString());
tr.Commit();
}
Основная моя проблема в том, что у меня не складывается полного представление о том, что содержится в accoremgd.dll, acdbmgd.dll, acdbmgd.dll, где в них находятся нужные мне параметры и функции, и где какие типы нужно использовать.
Про иерархию читал тут
https://sites.google.com/site/bushmansnetlaboratory/translate-manual/osnovy-autocad-net-api/ponimanie-ierarhii-obektov-autocad и на
http://docs.autodesk.com/ . И используемые *.dll смотрел в object browser.
Вот к примеру:
string name= "ABCD";
if (blocktab.Has(name))
Я так понимаю, что вернется true, если имя блока будет включать себя то, что содержится в переменной name. Т.е. если название блока будет "ABCDF" или "ABCD1" то тоже вернется true. ".Has" я использую т.к. blocktab типа BlockTable не имеет поля "Имя". У типа BlockTableRecord есть поля "Name" и "Origin" (последнее, вроде бы расположение базовой точки блока). Но этот тип используется для записи в чертеж, и при преобразовании:
BlockTableRecord mybtr = (BlockTableRecord)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
выдает ошибку.
Далее. Для загрузки *.dll в autocad используется команду Netload. А какой командой ее выгрузить? Приходится закрывать автокад, для того что бы завершить процесс чтения с *.dll.
Далее. Можно ли использовать пространства имен Autodesk.AutoCAD.ApplicationServices.Core.Application в WindowsForms приложении?
Т.е. есть приложение, которое связывается с автокадом через com:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
using System.Runtime.InteropServices;
//using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using acadCore= Autodesk.AutoCAD.ApplicationServices.Core;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Создаем объект приложения
AcadApplication acadApp = null;
try
{
object obj = Marshal.GetActiveObject("AutoCAD.Application.19");
if (obj != null)
{ MessageBox.Show("ok");
acadCore.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("Test Message");
}
}
catch
{
MessageBox.Show("AutoCAD is not open or version is not right.");
}
finally
{
if (acadApp != null) Marshal.FinalReleaseComObject(acadApp);
}
}
Ругается на
Application.Run(new Form1());
Выдает ошибку: An unhandled exception of type 'System.IO.FileNotFoundException' occurred in System.Windows.Forms.dll
Additional information: Could not load file or assembly 'accoremgd.dll' or one of its dependencies. The specified module could not be found.
Если убрать строчку:
acadCore.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("Test Message");
то, все работает.
Я так понимаю, accoremgd.dll уже занят, и получить к нему доступ не получится? Скопировал этот файл в отдельную папку (что не рекомендуется), результат не изменился.
ps извините что так много букв