- •Глава 1. Аналитическая часть 5
- •Глава 2. Практическая часть 11
- •Введение
- •Глава 1. Аналитическая часть
- •1.1 Анализ предметной области
- •1.2 Система автоматизированного проектирования AutoCad
- •1.3 Технология AutoCad .Net
- •Глава 2. Практическая часть
- •2.1 Проектирование бд
- •2.2 Разработка плагина
- •Заключение
- •Список литературы
2.2 Разработка плагина
Проектировать плагин будем в Microsoft Visual Studio 2017. За отладку и тестирование работоспособности плагина будет отвечать AutoCAD 2018.
В процессе создание плагина нам понадобятся следующие dll-файлы. Добавляем их в наш проект:
accoremgd.dll;
AcCui.dll;
acdbmgd.dll;
acmgd.dll;
AdWindows.dll.
Плагин будет связующим элементом между базой данных и AutoCAD. Он должен уметь просматривать файлы чертежей в БД, скачивать их и сохранять в виде новых записей. Так же он должен уметь выполнять деталировку чертежа (полный листинг плагина смотрите в приложении 1).
Для начала создадим внешний вид вкладки плагина. Пример кода создания первой кнопки представлен ниже:
// создание первой кнопки
RibbonButton rb1 = new RibbonButton();
// задаем ее ориентацию
rb1.Orientation = System.Windows.Controls.Orientation.Vertical;
// указываем размер картинки
rb1.Size = RibbonItemSize.Large;
// задаем айди кнопки
rb1.Id = "btn1";
// задаем название кнопки
rb1.Text = "Войти в КБ";
// включаем отображение текста
rb1.ShowText = true;
// присваиваем кнопке картинку
rb1.LargeImage = LoadImage("icon_1");
// включаем отображение картинки
rb1.ShowImage = true;
// всплывающая подсказка
rb1.ToolTip = "Авторизация в системе СУБД для конструкторского бюро";
// включаем отображение подсказки
rb1.IsToolTipEnabled = true;
// обработчик кнопки
rb1.CommandHandler = new CH_rb1();
После, нужно поместить все кнопки в контейнеры. Фрагмент кода представлен ниже:
// создаем контейнер
RibbonPanelSource rbs1 = new RibbonPanelSource();
rbs1.Title = "Авторизация";
// добавляем в контейнер кнопку
rbs1.Items.Add(rb1);
Дальше нужно поместить контейнеры в панели. Фрагмент кода представлен ниже:
// создание панели
RibbonPanel rp1 = new RibbonPanel();
// помещаем контейнер в панель
rp1.Source = rbs1;
Последнее, нужно создать вкладку, поместить в нее панель. А вкладку поместить в ленту. Пример кода представлен ниже:
// создаем вкладку
RibbonTab rt = new RibbonTab();
// присваиваем айди
rt.Id = "rtable";
// задаем заголовок
rt.Title = "Плагин";
// добавляем на вкладку панель
rt.Panels.Add(rp1);
// переменная обеспечивающая связь с лентой
RibbonControl rc = ComponentManager.Ribbon;
// добавляем на ленту вкладку
rc.Tabs.Add(rt);
Рис 2. Внешний дизайн плагина
Следующей частью будет создание обработчика кнопок. Каждый обработчик открывают windows форму. Пример создания обработчика для первой кнопки:
public class CH_rb1 : ICommand {
public event EventHandler CanExecuteChanged;
public bool CanExecute(object param)
{ return true; }
public void Execute(object parameter) {
// открытие формы авторизации
Authorization author = new Authorization();
Application.ShowModalDialog(author);}
Строка подключения к БД будет хранится в отдельном файле Settings.xml, который находиться рядом с dll-файлом плагина. В любой windows формы плагина будет метод, который считывает строку и подключается к БД. Пример кода представлен ниже:
private void LoadDbConn() {
string name = "";
// объект хмл документа
XmlDocument xDoc = new XmlDocument();
// читаем файл с настройками
xDoc.Load("Settings.xml");
// ищем нужную строку, читаем атрибут, присваиваем к переменной
foreach (XmlNode node in xDoc.DocumentElement) {
name = node.Attributes[0].Value; }
conn = new SqlConnection(name);
// открываем подключение
conn.Open(); }
Так же во время открытия любой из форм, будет проверяется подключение к БД. Пример кода представлен ниже:
private void TestDbConn() {
string name = "";
// объект хмл документа
XmlDocument xDoc = new XmlDocument();
// читаем файл с настройками
xDoc.Load("Settings.xml");
// ищем нужную строку, читаем атрибут, присваиваем к переменной
foreach (XmlNode node in xDoc.DocumentElement) {
name = node.Attributes[0].Value; }
// создаем подключение
conn = new SqlConnection(name);
try {
// открываем
conn.Open(); }
catch {
// иначе открываем форму настройки подключения к бд
SettingDB dB = new SettingDB();
dB.ShowDialog(); }}
В случае неудачи установления соединения с БД, отобразится форма настройки подключения (рис. 3).
Рис 3. Форма настройки подключения к БД
В зависимости от выбора проверки подключения скроются/покажутся дополнительные настройки.
Фрагмент кода формирования строки подключения для windows проверки представлен ниже:
if (txt_ds.Text != "" && txt_ic.Text != "") {
// собираем данные и присваиваем переменной строки подключения
conn = "Data Source=" + txt_ds.Text + ";Initial Catalog=" + txt_ic.Text + ";Integrated Security=True"; }
Фрагмент кода записи строки подключения в файл:
// объект хмл-документа
XmlDocument xDoc = new XmlDocument();
// читаем файл с настройками
xDoc.Load("Settings.xml");
// получим корневой элемент
XmlElement xRoot = xDoc.DocumentElement;
// получаем первый дочерний узел
XmlNode firstNode = xRoot.FirstChild;
// удаляем дочерний узел
xRoot.RemoveChild(firstNode);
// сохраняем хмл документ
xDoc.Save("Settings.xml");
// создаем новый узел
XmlElement userElem = xDoc.CreateElement("connectionString");
// создаем атрибут
XmlAttribute nameAttr = xDoc.CreateAttribute("name");
// создаем текстовые значения для элементов и атрибута
XmlText nameText = xDoc.CreateTextNode(conn);
//добавляем узлы
nameAttr.AppendChild(nameText);
userElem.Attributes.Append(nameAttr);
xRoot.AppendChild(userElem);
// сохраняем хмл документ
xDoc.Save("Settings.xml");
В плагине будет форма авторизации (рис. 4).
Рис 4. Форма авторизации
Рис 5. Успешная авторизация
В БД хранятся учетные записи пользователей. Помимо логина и пароля, у учетной записи есть поле места работы. По нему плагин и будет решать авторизовать пользователя или нет. Фрагмент кода авторизации представлен ниже:
// если текстовые поля не пустые
if (txt_log.Text != "" && txt_pass.Text != "") {
// переменная места работы
string factory = "";
// запрос о пользователи в системе
SqlCommand cmd = new SqlCommand("SELECT MUser FROM Users WHERE Ulogin=@Ulogin AND Upassword=@Upassword", conn);
cmd.Parameters.AddWithValue("Ulogin", txt_log.Text);
cmd.Parameters.AddWithValue("Upassword", txt_pass.Text);
try {
sqlReader = await cmd.ExecuteReaderAsync();
while (await sqlReader.ReadAsync()) {
// присваиваем результат
factory = Convert.ToString(sqlReader["MUser"]); }}
Форма предусматривает скачку чертежа. Для этого достаточно выбрать запись и нажать кнопку «открыть чертеж». Фрагмент кода представлен ниже:
// если выбрана запись
if (lv_data.SelectedItems.Count > 0) {
string path = "";
string id = Convert.ToString(lv_data.SelectedItems[0].SubItems[0].Text);
if (count == 1) {
// создаем коллекцию
List<Draw_obj> cherteg = new List<Draw_obj>();
// запрос о чертеже и его названии
SqlCommand cmd4 = new SqlCommand("SELECT OName, ODrawing FROM Object WHERE OName=@Oname", conn);
cmd4.Parameters.AddWithValue("Oname", id);
try {
sqlReader = await cmd4.ExecuteReaderAsync();
while (await sqlReader.ReadAsync()){
string filename = sqlReader.GetString(0);
byte[] data = (byte[])sqlReader.GetValue(1);
// формируем объект коллекции из результата
Draw_obj drawfile = new Draw_obj(filename, data);
// помещаем объект в коллецию
cherteg.Add(drawfile); }
if (cherteg.Count > 0) {
// создаем файл
using (FileStream fs = new FileStream("E:\\MyPlagin\\Originaldraw\\" + cherteg[0].OName + ".dwg", FileMode.OpenOrCreate)) {
fs.Write(cherteg[0].ODrawing, 0, cherteg[0].ODrawing.Length); }
path = "E:\\MyPlagin\\Originaldraw\\" + cherteg[0].OName + ".dwg";}}
Плагин сможет осуществить детализацию чертежа. Для этого достаточно выделить объект на чертеже и нажать кнопку «копировать». Отобразиться форма выбора ГОСТ рамки (рис. 6).
Рис 6. Форма выбора рамки
После выбора создастся новый чертеж и на него скопируется объект. Фрагмент кода работы копирования объектов:
// ссылка на открытый документ в автокаде
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
// ссылка на базу данных открытого документа в автокаде
Database acCurDb = acDoc.Database;
// ссылка на редактор открытого документа в автокаде
Editor acEd = acDoc.Editor;
// создание коллекции для объектов чертежа
ObjectIdCollection acObjIdColl = new ObjectIdCollection();
// блокируем чертеж
using (DocumentLock acLckDocCur = acDoc.LockDocument()) {
// создаем транзакция для выполнения операций
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()) {
// пользовательский выбор объектов чертежа
PromptSelectionResult acSSPrompt = acEd.GetSelection();
// если статус запроса равен ОК
if (acSSPrompt.Status == PromptStatus.OK) {
// выбираем объекты
SelectionSet acSSet = acSSPrompt.Value;
// перебор объектов в наборе
foreach (SelectedObject acSSObj in acSSet) {
// если объект получен правильно
if (acSSObj != null) {
// открываем объект для записи
Entity acEnt = acTrans.GetObject(acSSObj.ObjectId, OpenMode.ForWrite) as Entity;
// если объект открылся
if (acEnt != null) {
// помещаем в коллекцию
acObjIdColl.Add(acEnt.ObjectId); }}}}
// фиксируем изменения
acTrans.Commit(); }}
Фрагмент кода выбора шаблона для чертежа:
// переменная пути к шаблону
string strTemplatePath = "";
// если пользователь выбрал шаблон без рамки
if (rb_1.Checked == true) {
// грузим стандартный шаблон
strTemplatePath = "acad.dwt"; }
Фрагмент кода копирования объекта на новый чертеж:
// создаем чертеж
Document acNewDoc = acDocMgr.Add(strTemplatePath);
// получаем его базу данных
Database acDbNewDoc = acNewDoc.Database;
// переменная хранящая имя чертежа
string strDWGName = acNewDoc.Name;
// объект, который запрашивает названия чертежа
object obj = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("DWGTITLED");
// блокируем документ
using (DocumentLock acLckDoc = acNewDoc.LockDocument()) {
// открываем транзакцию для операций
using (Transaction acTrans = acDbNewDoc.TransactionManager.StartTransaction()) {
// открываем таблицу блоков для чтения
BlockTable acBlkTblNewDoc;
acBlkTblNewDoc = acTrans.GetObject(acDbNewDoc.BlockTableId, OpenMode.ForRead) as BlockTable;
// открытие записи таблицы блоков для внесения изменений
BlockTableRecord acBlkTblRecNewDoc;
acBlkTblRecNewDoc = acTrans.GetObject(acBlkTblNewDoc[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
// копируем коллекцию с объектами в базу данных нового чертежа
IdMapping acIdMap = new IdMapping();
acCurDb.WblockCloneObjects(acObjIdColl, acBlkTblRecNewDoc.ObjectId, acIdMap, DuplicateRecordCloning.Ignore, false);
// фиксируем изменения
acTrans.Commit(); }}
В плагине будут предусмотрены две формы сохранения чертежа в БД. Первая форма для сотрудников конструкторского бюро (рис. 7). С помощью нее можно сохранить составную часть чертежа. Вторая форма для технологов цехов (рис. 8). С помощью этой формы можно сохранить результат детализации.
Рис 7. Форма для сотрудников КБ
Рис 8. Форма для технологов
Фрагмент кода для сохранения чертежа в БД для сотрудников конструкторского бюро:
// поиск файла чертежа
foreach (string file in Directory.GetFiles(path, "*.dwg")){
// создаем объект найденого файла
FileInfo fileInf = new FileInfo(file);
// присваиваем переменной название файла
string tempnamedraw = fileInf.Name;
// присваиваем переменной полный путь к файлу
string filename = path + tempnamedraw;
// создаем объект активного документа в автокаде
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
// закрываем активный документ
acDoc.CloseAndSave(filename);
// создаем поток байтов
byte[] fileData;
// получаем файл чертежа
using (FileStream fs = new FileStream(filename, FileMode.Open)) {
// преобразуем и записываем поток байтов
fileData = new byte[fs.Length];
fs.Read(fileData, 0, fileData.Length); }
// запрос о добавление детали в бд
SqlCommand cmd = new SqlCommand("INSERT INTO SplittingDraw (SDUOName, SDOName, SDDrawing, SDMName) VALUES (@SDUOName, @SDOName, @SDDrawing, @SDMName)", conn);
// собираем информацию
cmd.Parameters.AddWithValue("SDUOName", cb_unitobj.Text);
cmd.Parameters.AddWithValue("SDOName", cb_obj.Text);
cmd.Parameters.AddWithValue("SDDrawing", fileData);
cmd.Parameters.AddWithValue("SDMName", cb_fctr.Text);
try {
await cmd.ExecuteNonQueryAsync();
Последняя форма для просмотра деталей в системе (рис. 9). Она позволит найти или отсортировать нужные детали. В отличии от форм авторизации эта форма сможет не только скачивать чертежи, но и добавлять дополнительную информацию на чертеж в виде таблицы. Дополнительную информацию тоже можно отредактировать (рис. 10).
Рис 8. Форма просмотра деталей в БД
Рис 9. Всплывающая форма добавления дополнительной информации
Фрагмент кода сортировки по материалу:
// очищаем листвью
lv_data.Items.Clear();
// сортировка по конкретному материалу
SqlCommand cmd5 = new SqlCommand("SELECT * FROM Details WHERE DeMaterial=@DeMaterial", conn);
cmd5.Parameters.AddWithValue("DeMaterial",cb_mat.SelectedItem.ToString());
sqlReader = await cmd5.ExecuteReaderAsync();
Фрагмент кода запроса о количестве записей дополнительной информации у чертежа:
// если пользователь поставил галку загрузку доп. инфу
if (cb_othinf.Checked == true) {
int rows = 0;
// запрос о кол-ве записей
SqlCommand cmd9 = new SqlCommand("SELECT COUNT(*) FROM DetailsAddInfo WHERE IdDetal=@IdDetal", conn);
cmd9.Parameters.AddWithValue("IdDetal", id);
sqlReader = await cmd9.ExecuteReaderAsync();
while (await sqlReader.ReadAsync()) {
// присваиваем результат
rows = sqlReader.GetInt32(0); }
Фрагмент кода загрузки дополнительной информации из БД:
// создаем массив
string[] dopinfo = new string[rows];
// запрос о записей доп.инфы.
SqlCommand cmd10 = new SqlCommand("SELECT DAIName FROM DetailsAddInfo WHERE IdDetal=@IdDetal", conn);
cmd10.Parameters.AddWithValue("IdDetal", id);
sqlReader = await cmd10.ExecuteReaderAsync();
int i = 0;
// помещаем результат запроса в массив
while (await sqlReader.ReadAsync()) {
dopinfo[i] = Convert.ToString(sqlReader["DAIName"]);
i++; }
Фрагмент кода переноса информации из массива в таблицу:
// создаем таблицу
Autodesk.AutoCAD.DatabaseServices.Table acTb = new Autodesk.AutoCAD.DatabaseServices.Table();
// стиль таблицы
acTb.TableStyle = acCurDb.Tablestyle;
// кол-во строк в таблице
acTb.NumRows = rows;
// кол-во столбцов в таблице
acTb.NumColumns = 1;
// высота и ширина ячеек
acTb.SetRowHeight(30);
acTb.SetColumnWidth(150);
// размер текста
acTb.SetTextHeight(5, (int)RowType.TitleRow);
acTb.SetTextHeight(5, (int)RowType.HeaderRow);
acTb.SetTextHeight(5, (int)RowType.DataRow);
// цикл записи информации из массива в таблицу
for (int k = 0; k < rows; k++) {
acTb.Cells[k, 0].TextString = dopinfo[k].ToString(); }
Получившуюся таблицу (рис. 11) на чертеже можно двигать, изменять размеры, форматировать стиль.
Рис 11. Получившаяся таблица с дополнительной информации на чертеже
Подведем итоги. Результатом второй главы стало дерево папок (рис. 12). Рассмотрим подробнее:
Originaldraw – папка. в которую скачиваются чертежи из БД;
Plagin – папка, в которой находится сам файл плагина и его файл с настройками (рис. 13);
Tempdraw – папка, в которой хранится временный чертеж, ждущий сохранения в БД;
Template – последняя папка, в ней хранятся шаблоны ГОСТ рамок;
Рис 12. Структура папок проекта
Рис 13. Файл плагина с файлом настроек