2.2. Программный код

Для работы кода требуется .Net Framework 3.5 SP1

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Xml.Linq;
   6:  using System.Globalization;
   7:  using System.ComponentModel;
   8:  using System.IO;
   9:  //Acad namespaces
  10:  using acad = Autodesk.AutoCAD.ApplicationServices.Application;
  11:  using Autodesk.AutoCAD.ApplicationServices;
  12:  using Autodesk.AutoCAD.DatabaseServices;
  13:  using Autodesk.AutoCAD.EditorInput;
  14:  using Autodesk.AutoCAD.Runtime;
  15:  using Autodesk.AutoCAD.Colors;
  16:  //http://www.caddzone.com/CommandLine.cs
  17:  using CaddZone.ApplicationServices;
  18:  using System.Reflection;
  19:  using Autodesk.AutoCAD.Windows;
  20:   
  21:  namespace TextGost
  22:  {
  23:      /// <summary>
  24:      /// Класс, содержащий команды создания текстовых объектов по ГОСТ 2.304-81
  25:      /// </summary>
  26:      public sealed class HwdCommands
  27:      {
  28:          const string ns = "hwd";//Пространство имён
  29:          bool xc = false; //Метка о запуске текстовой команды
  30:          XElement doc; //Корневой элемент документа Settings.xml
  31:          XElement paramsGroup;//Группа параметров команд по работе с текстом
  32:          Document dwg;
  33:          Database db;
  34:          Editor ed;
  35:          string justification;
  36:          string xmlFileName;
  37:          //Кэш значений текущих слоя, толщины линии, высоты шрифта и текстового стиля (чтобы восстановить их значения в исходное состояние после выполнения команды)
  38:          ObjectId oldLayer;
  39:          LineWeight oldLineWeight;
  40:          double oldHeight;
  41:          ObjectId oldTextStyle;
  42:   
  43:          /// <summary>
  44:          /// Конструктор по умолчанию. В нём производится начальная инициализация внутренних полей объекта.
  45:          /// </summary>
  46:          public HwdCommands()
  47:          {            
  48:              dwg = acad.DocumentManager.MdiActiveDocument;
  49:              db = dwg.Database;
  50:              ed = dwg.Editor;            
  51:              justification = "_BL";//Выравнивание текста по умолчанию
  52:              xmlFileName = "Settings.xml";
  53:              LoadXmlData();
  54:              dwg.CommandEnded += new CommandEventHandler(dwg_CommandEnded);
  55:              dwg.CommandFailed += new CommandEventHandler(dwg_CommandEnded);
  56:              dwg.CommandCancelled += new CommandEventHandler(dwg_CommandEnded);            
  57:          }
  58:   
  59:          private void LoadXmlData()
  60:          {
  61:              try
  62:              {
  63:                  //Получаем XML-объект, инкапсулирующий в себе информацию файла настроек
  64:                  string settPath = new FileInfo(Assembly.GetAssembly(this.GetType()).Location).DirectoryName;
  65:                  doc = XElement.Load(Path.Combine(settPath, xmlFileName));
  66:   
  67:                  //Группа команд создания объектов однострочного текста
  68:                  paramsGroup = doc.Element("CommandParameters");
  69:              }
  70:              catch (System.Exception ex)
  71:              {
  72:                  ed.WriteMessage(ex.Message);
  73:              }
  74:          }
  75:   
  76:          void dwg_CommandEnded(object sender, CommandEventArgs e)
  77:          {
  78:              if (xc)
  79:              {
  80:                  //Возвращаем изменённые нами параметры в их первоначальное состояние
  81:                  db.Clayer = oldLayer;
  82:                  db.Textstyle = oldTextStyle;
  83:                  db.Textsize = oldHeight;
  84:                  db.Celweight = oldLineWeight;
  85:                  xc = false;
  86:              }            
  87:          }
  88:   
  89:          /// <summary>
  90:          /// Создание однострочного текста по ГОСТ 2.304-81
  91:          /// </summary>
  92:          [CommandMethod(ns, "dt", CommandFlags.Modal)]
  93:          [Description("Создание однострочного текста по настройкам, хранящимся в файле Settings.xml")]
  94:          public void GostDText()
  95:          {
  96:              LoadXmlData();
  97:              if (doc != null && paramsGroup != null)
  98:              {
  99:                  xc = true;
 100:                  CreateText(AcadText.DText);                  
 101:              }                   
 102:          }
 103:   
 104:          /// <summary>
 105:          /// Создание многострочного текста по ГОСТ 2.304-81
 106:          /// </summary>
 107:          [CommandMethod(ns, "mt", CommandFlags.Modal)]
 108:          [Description("Создание многострочного текста по настройкам, хранящимся в файле Settings.xml")]
 109:          public void GostMText()
 110:          {
 111:              LoadXmlData();
 112:              if (doc != null && paramsGroup != null)
 113:              {
 114:                  xc = true;
 115:                  CreateText(AcadText.MText);
 116:              } 
 117:          }
 118:   
 119:          private void CreateText(AcadText textType)
 120:          {
 121:              //*******************************
 122:              //Запоминаем начальные значения текущего слоя, текстового стиля, высоты шрифта и толщины линий
 123:              oldLayer = db.Clayer;
 124:              oldTextStyle = db.Textstyle;
 125:              oldHeight = db.Textsize;
 126:              oldLineWeight = db.Celweight;
 127:              //*******************************
 128:   
 129:              PromptKeywordOptions keys = new PromptKeywordOptions("Укажите вариант настроек, или способ выравнивания текста:");
 130:              string justif = "Justify";
 131:              keys.Keywords.Add(justif);
 132:              foreach (string item in paramsGroup.Elements().Where(n => Boolean.Parse(n.Attribute("Use").Value)).Select(n => n.Attribute("ParameterName").Value))
 133:              {
 134:                  keys.Keywords.Add(item);
 135:              }
 136:              PromptResult result = ed.GetKeywords(keys);
 137:              if (result.Status == PromptStatus.OK && result.StringResult.Equals(justif, StringComparison.CurrentCultureIgnoreCase))
 138:              {
 139:                  string jres = "_" + GetJustification();
 140:                  justification = jres == null ? justification : jres;
 141:                  keys = new PromptKeywordOptions("Укажите вариант настроек текстового объекта:");
 142:                  foreach (string item in paramsGroup.Elements().Where(n => Boolean.Parse(n.Attribute("Use").Value)).Select(n => n.Attribute("ParameterName").Value))
 143:                  {
 144:                      keys.Keywords.Add(item);
 145:                  }
 146:                  result = ed.GetKeywords(keys);
 147:              }
 148:              if (result.Status == PromptStatus.OK)
 149:              {
 150:                  try
 151:                  {
 152:                      //Получаю запись с настройками команды
 153:                      XElement cmdRecord = paramsGroup.Elements().Where(n => n.Attribute("ParameterName").Value == result.StringResult).First();
 154:   
 155:                      //Высота текста для команды
 156:                      double txtHeightValue = double.Parse(cmdRecord.Attribute("Height").Value.Replace(",", "."));
 157:   
 158:                      //Получаю параметры текстового стиля
 159:                      //Сначала получаю имя ключа, по которому нужно будет искать текстовый стиль
 160:                      string txtStyleKey = cmdRecord.Attribute("TextStyleKey").Value;
 161:                      //Получаю объект текстового стиля
 162:                      XElement xTextStyle = doc.Element("TextStyles").Elements("TextStyle").Where(n => n.Attribute("Key").Value == txtStyleKey).First();
 163:   
 164:                      //Извлекаю информацию о текстовом стиле:
 165:   
 166:                      //1. Имя текстового стиля
 167:                      string txtStyleName = xTextStyle.Attribute("TextStyleName").Value;
 168:                      //2. Имя файла шрифта
 169:                      string fileFontName = xTextStyle.Attribute("FileFontName").Value;
 170:                      //Проверяю, имеется ли на самом деле такой файл шрифта
 171:                      string[] fileSearchPaths = (acad.GetSystemVariable("ACADPREFIX") as string).Split(';');
 172:   
 173:                      bool fileFontPresent = false;//Метка наличия нужного файла шрифта
 174:   
 175:                      foreach (string item in fileSearchPaths.Where(n => n.Trim() != string.Empty))
 176:                      {
 177:                          DirectoryInfo dir = new DirectoryInfo(item);
 178:                          if (dir.Exists && File.Exists(Path.Combine(dir.FullName, fileFontName)))
 179:                          {
 180:                              fileFontPresent = true;
 181:                              break;
 182:                          }
 183:                      }
 184:                      //Если указанный файл шрифта не найден - заменяем его альтернативным (тем, который указан к использованию по умолчанию)
 185:                      if (!fileFontPresent)
 186:                      {
 187:                          fileFontName = acad.GetSystemVariable("FONTALT") as string;
 188:                      }
 189:   
 190:                      //3. Значение свойства аннотативности
 191:                      bool isAnnotative = Boolean.Parse(xTextStyle.Attribute("Annotative").Value);
 192:                      //4. Коэффициент сжатия
 193:                      double xScale = Double.Parse(xTextStyle.Attribute("XScale").Value.Replace(",", "."));
 194:                      //5. Угол наклона шрифта
 195:                      double obliqueAngle = Double.Parse(xTextStyle.Attribute("ObliqueAngle").Value) * Math.PI / 180;
 196:   
 197:                      ///Проверяю, имеется ли в файле чертежа нужный мне текстовый стиль. Если стиль отсутствует, создаю его. Если стиль присутствует, но 
 198:                      ///его настройки отличаются от тех, что установлены в файле Settings.xml - исправляю их в соответствии с теми, что прописаны в Settings.xml.
 199:   
 200:                      //Метка о наличии нужного текстового стиля в чертеже
 201:                      bool presence = false;
 202:                      TextStyleTableRecord txtStyleRecord = null;//В эту переменную буду сохранять существующий текстовый стиль (если он будет найден)
 203:   
 204:                      //Ищем нужный текстовый стиль в базе данных чертежа
 205:                      using (Transaction trs = db.TransactionManager.StartTransaction())
 206:                      {
 207:                          TextStyleTable txtStyleTable = trs.GetObject(db.TextStyleTableId, OpenMode.ForRead) as TextStyleTable;
 208:                          foreach (ObjectId txtStyleId in txtStyleTable)
 209:                          {
 210:                              TextStyleTableRecord txtStyle = trs.GetObject(txtStyleId, OpenMode.ForRead) as TextStyleTableRecord;
 211:                              if (txtStyle.Name == txtStyleName)
 212:                              {
 213:                                  presence = true;
 214:                                  txtStyleRecord = txtStyle;
 215:                                  break;
 216:                              }
 217:                          }
 218:                          //Если нужный текстовый стиль существует, но имеет другие настройки - привожу их в соответствие с настройками файла Settings.xml.
 219:                          bool isEqual = presence &&
 220:                              txtStyleRecord != null &&
 221:                              txtStyleRecord.Name == txtStyleName &&
 222:                              txtStyleRecord.Annotative == (AnnotativeStates)Enum.Parse(typeof(AnnotativeStates), isAnnotative.ToString()) &&
 223:                              txtStyleRecord.FileName == fileFontName &&
 224:                              txtStyleRecord.XScale == xScale &&
 225:                              txtStyleRecord.ObliquingAngle == obliqueAngle;
 226:                          if (presence && !isEqual)
 227:                          {
 228:                              txtStyleRecord.UpgradeOpen();
 229:                              txtStyleRecord.Name = txtStyleName;
 230:                              txtStyleRecord.Annotative = (AnnotativeStates)Enum.Parse(typeof(AnnotativeStates), isAnnotative.ToString());
 231:                              txtStyleRecord.FileName = fileFontName;
 232:                              txtStyleRecord.XScale = xScale;
 233:                              txtStyleRecord.ObliquingAngle = obliqueAngle;
 234:                              txtStyleRecord.DowngradeOpen();
 235:                          }
 236:   
 237:                          //Если нужный текстовый стиль не найден - создаю его и добавляю в базу данных чертежа
 238:                          if (!presence)
 239:                          {
 240:                              txtStyleRecord = new TextStyleTableRecord
 241:                              {
 242:                                  Name = txtStyleName,
 243:                                  Annotative = (AnnotativeStates)Enum.Parse(typeof(AnnotativeStates), isAnnotative.ToString()),
 244:                                  FileName = fileFontName,
 245:                                  XScale = xScale,
 246:                                  ObliquingAngle = obliqueAngle,
 247:                              };
 248:                              txtStyleTable.UpgradeOpen();
 249:                              txtStyleTable.Add(txtStyleRecord);
 250:                              trs.AddNewlyCreatedDBObject(txtStyleRecord, true);
 251:                          }
 252:                          trs.Commit();
 253:                      }//Здесь транзакция по работе с текстовым стилем завершается
 254:   
 255:                      //Извлекаю из Settings.xml информацию о нужном слое:
 256:   
 257:                      //Сначала получаю имя ключа, по которому нужно будет искать слой
 258:                      string txtLayerKey = cmdRecord.Attribute("LayerKey").Value;
 259:   
 260:                      //Теперь по ключу извлекаю нужную запись...
 261:                      XElement layerRecord = doc.Element("Layers").Elements("LayerRecord").Where(n => n.Attribute("Key").Value == txtLayerKey).First();
 262:   
 263:                      string layerName = layerRecord.Attribute("LayerName").Value;
 264:                      Color color = new Color();
 265:   
 266:                      ObjectId txtLayerId = ObjectId.Null;
 267:                      //Проверяем, имеется ли в чертеже нужный нам слой. Если не имеется - создаём его.
 268:                      using (Transaction trans = dwg.TransactionManager.StartTransaction())
 269:                      {
 270:                          LayerTable layerTable = trans.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
 271:                          bool layerIsExist = false;//Метка о наличии искомого слоя
 272:   
 273:                          foreach (ObjectId layerId in layerTable)
 274:                          {
 275:                              LayerTableRecord layer = trans.GetObject(layerId, OpenMode.ForRead) as LayerTableRecord;
 276:                              if (layer.Name == layerName)
 277:                              {
 278:                                  layerIsExist = true; txtLayerId = layer.ObjectId;
 279:                                  break;
 280:                              }
 281:                          }
 282:                          if (!layerIsExist)
 283:                          {
 284:                              layerTable.UpgradeOpen();
 285:                              LayerTableRecord txtLayer = new LayerTableRecord();
 286:                              txtLayer.Name = layerName;
 287:                              txtLayer.Color = color;
 288:                              layerTable.Add(txtLayer);
 289:                              trans.AddNewlyCreatedDBObject(txtLayer, true);
 290:                              txtLayerId = txtLayer.ObjectId;
 291:                          }
 292:                          trans.Commit();
 293:                      }//Здесь транзакция по работе с слоем завершается
 294:   
 295:                      //Изменяем настройки
 296:                      db.Clayer = txtLayerId;
 297:                      db.Textstyle = txtStyleRecord.ObjectId;
 298:                      db.Textsize = Double.Parse(cmdRecord.Attribute("Height").Value);
 299:                      db.Celweight = (LineWeight)Convert.ToInt32(cmdRecord.Attribute("LineWeight").Value);
 300:   
 301:                      if (textType == AcadText.DText)
 302:                      {
 303:                          //Запускаем команду создания текстового объекта:
 304:                          PromptPointResult point = ed.GetPoint("Укажите базовую точку вставки текста");
 305:                          if (point.Status == PromptStatus.OK)
 306:                          {
 307:                              CommandLine.Command("_.DText", "_j", justification, point.Value, db.Textsize );
 308:                          }
 309:                      }
 310:                      else
 311:                      {
 312:                          //Запускаем команду создания текстового объекта:
 313:                          PromptPointResult point1 = ed.GetPoint("Укажите первый угол объекта многострочного текста");
 314:                          if (point1.Status == PromptStatus.OK)
 315:                          {
 316:                              PromptPointOptions options = new PromptPointOptions("\nУкажите противоположный по диагонали угол многострочного текста");
 317:                              options.BasePoint = point1.Value;
 318:                              options.UseBasePoint = true;
 319:                              options.UseDashedLine = true;
 320:                              options.LimitsChecked = true;
 321:                              PromptPointResult point2 = ed.GetPoint(options);
 322:                              if (point2.Status == PromptStatus.OK)
 323:                              {
 324:                                  CommandLine.Command("_.MTEXT", point1.Value, "_J", justification, point2.Value, "", "", "_.DDEDIT", "_L", "\\");
 325:                              }
 326:                          }
 327:                      }
 328:                  }
 329:                  catch (System.Exception ex)
 330:                  {
 331:                      ed.WriteMessage(ex.Message);
 332:                  }
 333:              }           
 334:          }
 335:          private string GetJustification()
 336:          {
 337:              ///Варианты "Align" и "Fit" исключаю из перечисления, т.к. они создают текстовый объект, шрифт которого не соответствует ГОСТ.
 338:              string[] list = {"Center", "Middle", "Right", "TL", "TC", "TR", "ML", "MC", "MR", "BL", "BC", "BR" };
 339:              PromptKeywordOptions options = new PromptKeywordOptions("Укажите способ выравнивания текста");            
 340:              foreach (string item in list)
 341:              {
 342:                  options.Keywords.Add(item);
 343:              }
 344:              PromptResult result = ed.GetKeywords(options);
 345:              if (result.Status == PromptStatus.OK)
 346:              {
 347:                  return result.StringResult;
 348:              }
 349:              return null;
 350:          }
 351:      }
 352:   
 353:      /// <summary>
 354:      /// Тип текстового объекта
 355:      /// </summary>
 356:      public enum AcadText
 357:      {
 358:          /// <summary>
 359:          /// Однострочный текст
 360:          /// </summary>
 361:          DText,
 362:          /// <summary>
 363:          /// Многострочный текст
 364:          /// </summary>
 365:          MText
 366:      }
 367:  }


Comments