Архив за месяц: Июнь 2014

Единая "точка входа" (DLL файл) в плагин .NET, ARX или VBA, не зависящая от версии AutoCAD

Поскольку .NET плагины AutoCAD (и не только они) имеют зависимость от версий обозначенной САПР, то нередко приходится один и тот же исходный код компилировать отдельно под разные версии AutoCAD. Результаты компиляции я, как правило, размещаю либо в одном и том же каталоге плагина, либо по специальным его подкаталогам, имена которых указывают на целевую версию ядра AutoCAD, а так же зависимость от разрядности приложения (если таковая присутствует). Какой из двух перечисленных вариантов использовать - зависит от конкретного случая.

Т.о. результат может выглядеть, к примеру, либо так:


либо так:


Имена файлов, зависящих от версии AutoCAD, так же содержат в виде суффикса версию ядра приложения, а так же, в случае необходимости, разрядность целевой платформы. Например, согласно обозначенному выше скрину, в подкаталоге .R17.2x64 будет находиться файл RegionTools.17.2x64.dll, а в подкаталоге .R20.0 - файл RegionTools.20.0.dll.

Я использую версию ядра AutoCAD, а не год (2009, 2010, 2011 и т.д.), обозначенный в имени САПР, т.к. программно нужную версию DLL файла удобней находить именно по версии ядра AutoCAD - это наиболее надёжная и точная информация.

Конечно, при такой системе наименований рядовому пользователю может быть сложно понять, какой именно DLL файл из набора имеющихся подкаталогов, ему следует загружать в установленную у него версию AutoCAD. Как вариант: можно в файле readme.txt разместить текстовую информацию о том, для какой версии AutoCAD какой DLL файл следует загружать.

Однако можно эту задачу решить иначе: непосредственно в подкаталоге .bin создавать единственный DLL файл, который предназначен для загрузки в любую версию AutoCAD. Предназначение этого файла заключается в том, чтобы загрузить в AutoCAD наиболее подходящую версию плагина, найдя её либо в текущем каталоге сборки, либо в соответствующих подкаталогах. На скрине показанном выше эта роль возложена на файл RegionTools.dll.

Т.о. Какую бы версию AutoCAD пользователь не имел на своей машине, ему всегда нужно загружать только файл RegionTools.dll

Аналогичная проблема актуальна так же для плагинов ARX и VBA (VBA "хромает" по части разрядности: x86x64). Поэтому было бы вполне логично расширить решение таким образом, чтобы оно работало не только для .NET, но так же и для C++, VBA. Для ARX и VBA плагинов систему наименований, а так же структуру подкаталогов использую такие же, как и для .NET (указана мною выше).

Поскольку данный подход удобно применять во всех плагинах,  то его можно оформить в виде шаблона проекта:



Далее приводится подробно комментированный код обозначенной выше логики. Проект компилирую с опцией AnyCPU под .NET 3.5,  хотя AutoCAD 2009 по умолчанию использует 3.0. Мой выбор обусловлен тем, что AutoCAD 2009 может вместо 3.0 использовать 3.5, в которой присутствует технология LINQ, активно мною используемая. Версии ниже чем AutoCAD 2009 мне не интересны. Однако тут возникает один нюанс: на исходном компьютере так же должен быть установлен .NET Framework 3.5 SP1.

/* EntryPoint.cs
 * © Andrey Bushman, 2014
 * Поиск и загрузка версии плагина .NET, ARX или VBA, наиболее пригодной для 
 * текущей версии AutoCAD.
 * http://bushman-andrey.blogspot.ru/2014/06/dll-autocad.html
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

#if AUTOCAD
using cad = Autodesk.AutoCAD.ApplicationServices.Application;
using Rt = Autodesk.AutoCAD.Runtime;
#endif

[assembly: Rt.ExtensionApplication(typeof(Bushman.CAD.EntryPoint
  .EntryPoint))]

namespace Bushman.CAD.EntryPoint {
  /// <summary>
  /// Задачей данного класса является поиск и загрузка в AutoCAD наиболее 
  /// подходящей для него версии плагина.
  /// </summary>
  public sealed class EntryPoint : Rt.IExtensionApplication {
    const String netPluginExtension = ".dll";
    static readonly String[] extensions = new String[] { ".arx"".dvb" };
    static readonly String[] methodNames = new String[] { "LoadArx""LoadDVB" 
    };

    /// <summary>
    /// Код этого метода будет запущен на исполнение при загрузке сборки в 
    /// AutoCAD. В результате его работы происходит попытка найти и загрузить в
    /// AutoCAD наиболее подходящую версию плагина из имеющихся в наличии.
    /// </summary>
    public void Initialize() {
      // Для начала извлекаем информацию о текущей версии AutoCAD и ищем
      // соответствующую ей версию файла. Имя такого файла должно 
      // формироваться по правилу: 
      //    ИмяТекущейСборки.Major.Minor[x86|x64].(dll|arx|dvb).
      // Где <Major> и <Minor> - это значения одноимённых свойств объекта 
      // Version, полученного из Application.Version.
      Version version = cad.Version;

      String fileFullName = GetType().Assembly.Location;

      Version minVersion = new Version(17, 2);

      FileInfo targetDllFullName = FindFile(fileFullName, version, minVersion);

      if(targetDllFullName == null)
        return;

      // Если найден файл, соответствующий нашей версии AutoCAD, то 
      // загружаем его.
      Assembly asm = null;
      try {
        if(targetDllFullName.Extension.Equals(netPluginExtension,
          StringComparison.CurrentCultureIgnoreCase))
          asm = Assembly.LoadFrom(targetDllFullName.FullName);
        else {
          Int32 index = Array.IndexOf(extensions, targetDllFullName.Extension);

          if(index >= 0) {
            Object application = cad.AcadApplication;

            application.GetType().InvokeMember(methodNames[index], BindingFlags
              .InvokeMethod, null, application, new Object[] { 
                targetDllFullName.FullName });
          }
        }
      }
      catch {
      }
    }

    /// <summary>
    /// Получить имя наиболее подходящего файла, для его последующей загрузки в
    /// AutoCAD. Если такой файл не будет найден, то возвращается null.
    /// </summary>
    /// <param name="fileFullName">"Базовое" имя файла, т.е. полное имя 
    /// файла без указания в нём версий ядра и разрядности платформы.</param>
    /// <param name="expectedVersion">Версия AutoCAD, для которой следует 
    /// выполнить поиск соответствующей версии файла.</param>
    /// <param name="minVersion">Наименьшая версия AutoCAD, ниже которой не 
    /// следует выполнять поиск.</param>
    /// <returns>Возвращается FileInfo наиболее подходящего файла, для его 
    /// последующей загрузки в AutoCAD. Если такой файл не будет найден, то 
    /// возвращается null.</returns>
    private FileInfo FindFile(String fileFullName, Version expectedVersion,
      Version minVersion) {

      if(fileFullName == null)
        throw new ArgumentNullException("fileFullName");

      if(fileFullName.Trim() == String.Empty)
        throw new ArgumentException(
          "fileFullName.Trim() == String.Empty");

      if(expectedVersion < minVersion)
        throw new ArgumentException(
          "expectedVersion < minVersion");

      Int32 major = expectedVersion.Major;
      Int32 minor = expectedVersion.Minor;

      String directory = Path.GetDirectoryName(fileFullName);
      String fileName = Path.GetFileNameWithoutExtension(fileFullName);

      String coreString = String.Format("{0}.{1}", major.ToString(),
        minor.ToString());

      String subDirectoryName = "R" + coreString;
      String subDirectoryName_xPlatform = subDirectoryName + (IntPtr.Size == 4
        ? "x86" : "x64");

      String targetFileName = String.Empty;
      String targetFileName_xPlatform = String.Empty;
      String targetFileFullName = String.Empty;
      String targetFileFullName_xPlatform = String.Empty;

      List<String> items = new List<String>(extensions);
      items.Insert(0, netPluginExtension);

      String name = String.Empty;

      foreach(String extension in items) {

        targetFileName = String.Format("{0}.{1}{2}", fileName, coreString,
          extension);
        targetFileName_xPlatform = String.Format("{0}.{1}{2}{3}", fileName,
          coreString, (IntPtr.Size == 4 ? "x86" : "x64"), extension);

        // Сначала выполняем поиск в текущем каталоге
        targetFileFullName = Path.Combine(directory, targetFileName);
        if(File.Exists(targetFileFullName)) {
          name = targetFileFullName;
          break;
        }
        targetFileFullName_xPlatform = Path.Combine(directory,
          targetFileName_xPlatform);
        if(File.Exists(targetFileFullName_xPlatform)) {
          name = targetFileFullName_xPlatform;
          break;
        }

        // Если в текущем каталоге подходящий файл не найден, то продолжаем
        // поиск по соответствующим подкаталогам
        targetFileFullName = directory + "\" + subDirectoryName +
          "\" + targetFileName;
        if(File.Exists(targetFileFullName)) {
          name = targetFileFullName;
          break;
        }

        targetFileFullName_xPlatform = directory + "\" +
          subDirectoryName_xPlatform + "\" + targetFileName_xPlatform;
        if(File.Exists(targetFileFullName_xPlatform)) {
          name = targetFileFullName_xPlatform;
          break;
        }
      }

      // Если найден файл, соответствующий нашей версии AutoCAD, то возвращаем 
      // соответтствующий ему объект FileInfo.
      if(File.Exists(name)) {
        return new FileInfo(name);
      }
      // Если соответствия не найдено, то продолжаем поиск, последовательно 
      // проверяя наличие подходящего файла для более ранних версий AutoCAD
      else {
        if(minor == 0) {
          minor = 3;
          --major;
        }
        else {
          --minor;
        }

        Version version = new Version(major, minor);
        if(version < minVersion)
          return null;
        FileInfo file = FindFile(fileFullName, new Version(major, minor),
          minVersion);
        return file;
      }
    }

    /// <summary>
    /// Код данного метода выполняется при завершении работы AutoCAD.
    /// </summary>
    public void Terminate() {
    }
  }
}

Без рубрики

OpenOfficeBase custom database combobox

Как я и обещал в одном из самых первых сообщений, собирался реализовать компонент combobox.

Зачем? Если есть встроенный. Встроенный есть и встроенного нет. То есть есть но не совсем тот.

 Встроенный DatabaseList и DatabaseCombobox имеет два очень неприятных ограничения. Первое - количество вывдоимых данных ограничено примерно 30 тас. (2 в степени там сколько-то). Второе - работает только в таблицах но не в диалогах. (А надо бы)

Итак создаем компонент для диалогов неограниченный и удобный навроде Google autocompeet.

Пробовал взять за основу Combobox  с палитры диалогов - не вышло. Там не поддерживается индекс выбранной строки и проблематично хранить суррогатный индекс записи - только текстовое поле. Итак пришлось польоваться обычным текстовым полем. Для автоматизации назовем его с префикса _combo_.

Тогда по-порядку.

Диалог вызываем и закрываем такой процедурой. (Диалоги у нас неасинхронные).

Sub Dogovor_Edit(Event)
Dim oDialog As Object
Dim f_dogovor As Object
f_dogovor = Thiscomponent.DrawPage.Forms.GetByName("f_dogovor")
oDialog = GetDialog("ctl", "dogovor")
'xRay oDialog
CreateDatabaseComboBox(oDialog, "_combo_contragent_id", "contragent",Array("name","uaname","egr"), "name || '(' || uaname || ') ЕГР=' || egr" , "name || '(' || uaname || ') ЕГР=' || egr" , "ID")
CreateDatabaseComboBox(oDialog, "_combo_dogovor_id", "dogovor",Array("nd", "dated", "memo"), "type || ' ' || nd || ' ' || dated || ' ' || memo" , "type || ' ' || nd || ' ' || dated || ' ' || memo" , "ID")
If Event.Source.Model.Tag = "edit" then
ctl.util.FromBaseToDialog(f_dogovor, oDialog)
End If
If oDialog.Execute() = 1 Then
If Event.Source.Model.Tag = "new" Then
f_dogovor.MoveToInsertRow()
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.InsertRow()
Else
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.UpdateRow()
EndIf
Else
End If
End Sub

Создаем комбобокс конструктрором

01Sub CreateDatabaseComboBox(oDialog as Variant, sTextName as String, sTable as String, aFields as Array, sList as String, sText As String, sID As String)
02 Dim oText As Variant
03 Dim oList As Variant
04 Dim oConnection As Variant
05 Dim sProp As String
06 Dim Listener As Object
07 oText = oDialog.GetControl(sTextName)
08 sProp = "ctl.databasecombobox." & oDialog.GetModel.Name & "." & oText.GetModel().Name
09 Listener = createUnoListener("oText_", "com.sun.star.awt.XKeyListener")
10 oText.addKeyListener(Listener)
11 Listener = createUnoListener("ctl.databasecombobox.mText_", "com.sun.star.awt.XMouseListener")
12 oText.addMouseListener(Listener)
13 Dim vList
14 vList=CreateUnoService("com.sun.star.awt.UnoControlListBox")
15 vList.SetModel(CreateUnoService("com.sun.star.awt.UnoControlListBoxModel"))
16 Dim vTextPosSize As Variant
17 vTextPosSize = oText.GetPosSize(15)
18 vList.setDropDownLineCount(15)
19 vList.SetPosSize(vTextPosSize.X,vTextPosSize.Y + vTextPosSize.HEIGHT,vTextPosSize.WIDTH, 250,1+2+4+8)
20 vList.AddItems(Array(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,111111111111111111111111111111111),0)
21 Listener = createUnoListener("ctl.databasecombobox.mList_", "com.sun.star.awt.XMouseListener")
22 vList.addMouseListener(Listener)
23 oDialog.AddControl(sTextName & "_List", vList)
24 vList.SetContext(oText)
25 vList.RemoveItems(0,vList.ItemCount)
26 vList.SetVisible(False)
27 Dim aString(0,1) As String
28 ' 0 1 2 3 4 5-ID 6-IDs 7-Texts
29 ctl.SetUserProperty(sProp, Array(sTable,aFields,sList,sText,sID,Null,Null,Null)
30End Sub

Небольшие разьяснения.
Строка 09+11 слушателей событий создаем по префиксу.
Строка 14+15 программно создаем список и подгоняем его под срез текстового поля (19).
Строка 21 созает запоненный данными список только для того чтобы позиционировать его (в противном случае несть смещениен на величину полосок прокрутки, хотя не олжно быть - непофикшеный баг)
Строка 29 сохраняет в некторой области нужные значения. Функционала такого я не нашел поэтому дописал сам.

Function GetUserProperty(Prop As String) As Variant
Dim Tag As Variant
Tag = ThisComponent.DrawPage.Forms(0).GetByName("Tag")
ON ERROR GOTO ERR
GetUserProperty = Tag.GetPropertyValue(Prop)
EXIT FUNCTION
ERR: GetUserProperty = null
End Function

Sub AddUserProperty(Prop As String, Val)
Dim Tag As Variant
Tag = ThisComponent.DrawPage.Forms(0).GetByName("Tag")
ON ERROR GOTO ERR
Tag.AddProperty(Prop, 0, Val)
EXIT SUB
ERR:
Tag.RemoveProperty(Prop)
Tag.AddProperty(Prop, 0, Val)
End Sub

Sub SetUserProperty(Prop As String, Val)
Dim Tag As Variant
Tag = ThisComponent.DrawPage.Forms(0).GetByName("Tag")
ON ERROR GOTO ERR
Tag.SetPropertyValue(Prop, Val)
EXIT SUB
ERR:
ctl.AddUserProperty(Prop, Val)
End Sub
Довольно мутный код связан с отрабткой ошибок. Не все всегда бывает удобно.
Далее компонент инициируется текущим значением, а затем реализуется поиск по введенному тексту и выбор по мыши.

Из интересных моментов. Поиск реализован по полям от одног и более. Фраза поиска может не соответсововать отображаемому тексту (например может выводиться дополительная информация).

Ну во пока и все.



Без рубрики

OpenOfficeBase custom database combobox

Как я и обещал в одном из самых первых сообщений, собирался реализовать компонент combobox.

Зачем? Если есть встроенный. Встроенный есть и встроенного нет. То есть есть но не совсем тот.

 Встроенный DatabaseList и DatabaseCombobox имеет два очень неприятных ограничения. Первое - количество вывдоимых данных ограничено примерно 30 тас. (2 в степени там сколько-то). Второе - работает только в таблицах но не в диалогах. (А надо бы)

Итак создаем компонент для диалогов неограниченный и удобный навроде Google autocompeet.

Пробовал взять за основу Combobox  с палитры диалогов - не вышло. Там не поддерживается индекс выбранной строки и проблематично хранить суррогатный индекс записи - только текстовое поле. Итак пришлось польоваться обычным текстовым полем. Для автоматизации назовем его с префикса _combo_.

Тогда по-порядку.

Диалог вызываем и закрываем такой процедурой. (Диалоги у нас неасинхронные).

Sub Dogovor_Edit(Event)
Dim oDialog As Object
Dim f_dogovor As Object
f_dogovor = Thiscomponent.DrawPage.Forms.GetByName("f_dogovor")
oDialog = GetDialog("ctl", "dogovor")
'xRay oDialog
CreateDatabaseComboBox(oDialog, "_combo_contragent_id", "contragent",Array("name","uaname","egr"), "name || '(' || uaname || ') ЕГР=' || egr" , "name || '(' || uaname || ') ЕГР=' || egr" , "ID")
CreateDatabaseComboBox(oDialog, "_combo_dogovor_id", "dogovor",Array("nd", "dated", "memo"), "type || ' ' || nd || ' ' || dated || ' ' || memo" , "type || ' ' || nd || ' ' || dated || ' ' || memo" , "ID")
If Event.Source.Model.Tag = "edit" then
ctl.util.FromBaseToDialog(f_dogovor, oDialog)
End If
If oDialog.Execute() = 1 Then
If Event.Source.Model.Tag = "new" Then
f_dogovor.MoveToInsertRow()
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.InsertRow()
Else
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.UpdateRow()
EndIf
Else
End If
End Sub

Создаем комбобокс конструктрором

01Sub CreateDatabaseComboBox(oDialog as Variant, sTextName as String, sTable as String, aFields as Array, sList as String, sText As String, sID As String)
02 Dim oText As Variant
03 Dim oList As Variant
04 Dim oConnection As Variant
05 Dim sProp As String
06 Dim Listener As Object
07 oText = oDialog.GetControl(sTextName)
08 sProp = "ctl.databasecombobox." & oDialog.GetModel.Name & "." & oText.GetModel().Name
09 Listener = createUnoListener("oText_", "com.sun.star.awt.XKeyListener")
10 oText.addKeyListener(Listener)
11 Listener = createUnoListener("ctl.databasecombobox.mText_", "com.sun.star.awt.XMouseListener")
12 oText.addMouseListener(Listener)
13 Dim vList
14 vList=CreateUnoService("com.sun.star.awt.UnoControlListBox")
15 vList.SetModel(CreateUnoService("com.sun.star.awt.UnoControlListBoxModel"))
16 Dim vTextPosSize As Variant
17 vTextPosSize = oText.GetPosSize(15)
18 vList.setDropDownLineCount(15)
19 vList.SetPosSize(vTextPosSize.X,vTextPosSize.Y + vTextPosSize.HEIGHT,vTextPosSize.WIDTH, 250,1+2+4+8)
20 vList.AddItems(Array(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,111111111111111111111111111111111),0)
21 Listener = createUnoListener("ctl.databasecombobox.mList_", "com.sun.star.awt.XMouseListener")
22 vList.addMouseListener(Listener)
23 oDialog.AddControl(sTextName & "_List", vList)
24 vList.SetContext(oText)
25 vList.RemoveItems(0,vList.ItemCount)
26 vList.SetVisible(False)
27 Dim aString(0,1) As String
28 ' 0 1 2 3 4 5-ID 6-IDs 7-Texts
29 ctl.SetUserProperty(sProp, Array(sTable,aFields,sList,sText,sID,Null,Null,Null)
30End Sub

Небольшие разьяснения.
Строка 09+11 слушателей событий создаем по префиксу.
Строка 14+15 программно создаем список и подгоняем его под срез текстового поля (19).
Строка 21 созает запоненный данными список только для того чтобы позиционировать его (в противном случае несть смещениен на величину полосок прокрутки, хотя не олжно быть - непофикшеный баг)
Строка 29 сохраняет в некторой области нужные значения. Функционала такого я не нашел поэтому дописал сам.

Function GetUserProperty(Prop As String) As Variant
Dim Tag As Variant
Tag = ThisComponent.DrawPage.Forms(0).GetByName("Tag")
ON ERROR GOTO ERR
GetUserProperty = Tag.GetPropertyValue(Prop)
EXIT FUNCTION
ERR: GetUserProperty = null
End Function

Sub AddUserProperty(Prop As String, Val)
Dim Tag As Variant
Tag = ThisComponent.DrawPage.Forms(0).GetByName("Tag")
ON ERROR GOTO ERR
Tag.AddProperty(Prop, 0, Val)
EXIT SUB
ERR:
Tag.RemoveProperty(Prop)
Tag.AddProperty(Prop, 0, Val)
End Sub

Sub SetUserProperty(Prop As String, Val)
Dim Tag As Variant
Tag = ThisComponent.DrawPage.Forms(0).GetByName("Tag")
ON ERROR GOTO ERR
Tag.SetPropertyValue(Prop, Val)
EXIT SUB
ERR:
ctl.AddUserProperty(Prop, Val)
End Sub
Довольно мутный код связан с отрабткой ошибок. Не все всегда бывает удобно.
Далее компонент инициируется текущим значением, а затем реализуется поиск по введенному тексту и выбор по мыши.

Из интересных моментов. Поиск реализован по полям от одног и более. Фраза поиска может не соответсововать отображаемому тексту (например может выводиться дополительная информация).

Ну во пока и все.



Без рубрики

Стиль точек в AutoCAD

Задачка, что называется "в два действия", но раз уж стал выкладывать информацию по работе с различными стилями в AutoCAD, то покажу и настройку стиля точек (для полноты картины), хотя, скорее всего, это и без моих заметок ни у кого не должно вызывать трудностей.

Весь код сводится к банальному изменению двух свойств (одноимённых соответствующим системным переменным AutoCAD). Информация об этих переменных присутствует в справочной системе AutoCAD и не должна вызывать каких-либо сложностей в понимании.



/* PointStyleSample.cs
 * © Андрей Бушман, 2014 
 * Пример изменения стиля точек.
 */
using System;

using cad = Autodesk.AutoCAD.ApplicationServices
.Application;
using Ap = Autodesk.AutoCAD.ApplicationServices;
using Db = Autodesk.AutoCAD.DatabaseServices;
using Rt = Autodesk.AutoCAD.Runtime;

[assembly: Rt.CommandClass(typeof(Bushman.CAD
  .Samples.Styles.PointStyleSample))]

namespace Bushman.CAD.Samples.Styles {

  public sealed class PointStyleSample {

    [Rt.CommandMethod("ChangePointStyle",
      Rt.CommandFlags.Modal)]
    public void ChangePointStyle() {
      Ap.Document doc = cad.DocumentManager
        .MdiActiveDocument;
      if(doc == null)
        return;
      using(doc.LockDocument()) {
        Db.Database db = doc.Database;
        db.Pdmode = 35;
        db.Pdsize = -10;
      }
    }
  }
}

Текстовые стили в AutoCAD

Заметка содержит пример программного создания и детальной настройки текстового стиля в AutoCAD.


В результате работы кода (команда CreateOrEditTextStyle) будет создан и настроен новый текстовый стиль:


В коде каждая изменяемая нами опция настроек помечена комментарием, содержащим наименование этой опции в англоязычной версии AutoCAD.

/* TextStyleSample.cs
 * AutoCAD 2009-2015
 * © Андрей Бушман, 2014 
 * Пример по работе с текстовым стилем. 
 */
using System;

#if AUTOCAD
using cad = Autodesk.AutoCAD.ApplicationServices
.Application;
using Ap = Autodesk.AutoCAD.ApplicationServices;
using Db = Autodesk.AutoCAD.DatabaseServices;
using Rt = Autodesk.AutoCAD.Runtime;
#endif

[assembly: Rt.CommandClass(typeof(Bushman.CAD
  .Samples.Styles.TextStyleSample))]

namespace Bushman.CAD.Samples.Styles {
  public static class TextStyleSample {
    // Наименование группы команд
    const String ns = "Samples";
    /// <summary>
    /// В текущем чертеже данная команда либо 
    /// создаёт новый текстовый стиль и полностью
    /// настраивает его, либо выполняет его 
    /// перенастройку, если нужный стиль уже 
    /// существует.
    /// </summary>
    [Rt.CommandMethod(ns,
      "CreateOrEditTextStyle",
      Rt.CommandFlags.Modal)]
    public static void CreateOrEditTextStyle() {
      Ap.Document doc = cad.DocumentManager
        .MdiActiveDocument;
      if(doc == null)
        return;
      using(doc.LockDocument()) {
        CreateOrEditTextStyle(doc.Database);
      }
    }

    /// <summary>
    /// В указанной базе данных данная команда 
    /// либо создаёт новый текстовый стиль и 
    /// полностью настраивает его, либо выполняет
    /// его перенастройку, если нужный стиль уже 
    /// существует.
    /// </summary>
    /// <param name="db">База данных, подлежащая 
    /// обработке</param>
    private static void CreateOrEditTextStyle(
      Db.Database db) {
      if(db == null)
        throw new ArgumentNullException("db");
      using(Db.Transaction tr =
        db.TransactionManager.StartTransaction()) 
        {
        Db.TextStyleTable tst =
          (Db.TextStyleTable)tr.GetObject(
          db.TextStyleTableId, Db.OpenMode
          .ForWrite);

        String textStyleName = "Курсив";
        Db.TextStyleTableRecord rec = null;

        // Если нужного текстового стиля нет, то 
        // создаём его
        if(!tst.Has(textStyleName))
          rec = new Db.TextStyleTableRecord();
        else // Если стиль существует, то 
          // открываем его для редактирования.
          rec = tr.GetObject(tst[textStyleName],
            Db.OpenMode.ForWrite)
            as Db.TextStyleTableRecord;

        // ttf или, к примеру, "txt.shx".
        String fontName = "Times New Roman.ttf";
        String bigFontName = String.Empty;
        FillTextStyle(rec, textStyleName,
          fontName, bigFontName,
          Db.AnnotativeStates.NotApplicable, 0,
          0.8, 15, falsefalsefalsefalse);

        // Если это новый текстовый стиль, то не 
        // забываем добавить его в базу данных 
        // чертежа.
        if(rec.Database == null) {
          tst.Add(rec);
          tr.AddNewlyCreatedDBObject(rec, true);
        }
        tr.Commit();
      }
    }

    /// <summary>
    /// Настройка текстового стиля.
    /// </summary>
    /// <param name="rec">Текстовый стиль, 
    /// подлежащий обработке.</param>
    /// <param name="styleName">Имя текстового 
    /// стиля.</param>
    /// <param name="fontName">Наименование 
    /// используемого шрифта: Font Name в 
    /// диалоговом окне Text Style.</param>
    /// <param name="fontStyle">Наименование 
    /// большого шрифта: Font Style в 
    /// диалоговом окне Text Style. Если этому 
    /// свойству назначить непустое 
    /// значение, то в диалоговом окне Text Style 
    /// будет включена опция Use Big 
    /// Font.</param>
    /// <param name="annotativeStatus">Должен ли 
    /// текстовый стиль быть 
    /// аннотативным: True - аннотативен, False 
    /// или NotApplicable - не 
    /// аннотативен. Опция Annotative в 
    /// диалоговом окне Text Style.</param>
    /// <param name="textHeight">Высота текста: 
    /// Paper Text Height в диалоговом 
    /// окне Text Style.</param>
    /// <param name="widthFactor">Коэффициент 
    /// сжатия текста по горизонтали: 
    /// Width Factor в диалоговом окне Text Style
    /// </param>
    /// <param name="obliquingAngle">Угол наклона
    /// текста. Указывается в градусах и 
    /// отсчитывается от вертикали по часовой 
    /// стрелке. Oblique Angle в диалоговом окне 
    /// Text Style.</param>
    /// <param name="setPaperOrientation">Опция 
    /// Match text orientation to layout в 
    /// диалоговом окне Text Style.</param>
    /// <param name="upsideDown">
    /// Опция Upside down в диалоговом окне Text 
    /// Style.</param>
    /// <param name="backwards">
    /// Опция Backwards в диалоговом окне Text 
    /// Style.</param>
    /// <param name="vertical">
    /// Опция Vertical в диалоговом окне Text 
    /// Style.</param>
    private static void FillTextStyle(
      Db.TextStyleTableRecord rec,
      String styleName, String fontName,
      String fontStyle,
      Db.AnnotativeStates annotativeStatus,
      Double textHeight,
      Double widthFactor, Double obliquingAngle,
      Boolean setPaperOrientation,
      Boolean upsideDown, Boolean backwards,
      Boolean vertical) {

      if(rec == null)
        throw new ArgumentNullException("rec");

      if(styleName == null)
        throw new ArgumentNullException(
          "styleName");
      if(fontName == null)
        throw new ArgumentNullException(
          "fontName");
      if(fontStyle == null)
        throw new ArgumentNullException(
          "fontStyle");

      if(styleName.Trim() == String.Empty)
        throw new ArgumentException("styleName");
      if(fontName.Trim() == String.Empty)
        throw new ArgumentException("fontName");
      if(fontStyle.Length > 0 &&
        fontStyle.Trim() == String.Empty)
        throw new ArgumentException("fontStyle");

      rec.Name = styleName;
      rec.Annotative = annotativeStatus;
      rec.FileName = fontName;
      rec.XScale = widthFactor;
      // Переводим градусы в радианы
      rec.ObliquingAngle = obliquingAngle *
        Math.PI / 180;
      rec.SetPaperOrientation(
        setPaperOrientation);

      // Если мы назначаем значение свойству 
      // BigFontFileName, то в диалоговом окне 
      // Text Style автоматически включается 
      // галочка "Use Big Font"
      rec.BigFontFileName = fontStyle;

      // эти флаги хранят значения опций "Upside 
      // down" и "Backwards"
      rec.FlagBits = (Byte)0;

      rec.FlagBits += upsideDown ? (Byte)2 :
        (Byte)0; // Upside down      
      rec.FlagBits += backwards ? (Byte)4 :
        (Byte)0; // Backwards

      rec.TextSize = textHeight;
      rec.IsVertical = vertical;
    }
  }
}

Стили мультилиний в AutoCAD

Заметка содержит пример программного создания и детальной настройки стиля мультилиний в AutoCAD.

В результате работы кода (команда CreateMultilineStyle) будет создан новый стиль мультилиний:



В коде каждая изменяемая нами опция настроек помечена комментарием, содержащим наименование этой опции в англоязычной версии AutoCAD.

/* MultilineStyleSample.cs
 * © Андрей Бушман, 2014 
 * Пример создания стиля мультилиний.
 */
using System;

using cad = Autodesk.AutoCAD.ApplicationServices
.Application;
using Ap = Autodesk.AutoCAD.ApplicationServices;
using Db = Autodesk.AutoCAD.DatabaseServices;
using Ed = Autodesk.AutoCAD.EditorInput;
using Rt = Autodesk.AutoCAD.Runtime;
using Clr = Autodesk.AutoCAD.Colors;

[assembly: Rt.CommandClass(typeof(Bushman.CAD
  .Samples.Styles.MultilineStyleSample))]

namespace Bushman.CAD.Samples.Styles {

  public class MultilineStyleSample {

    [Rt.CommandMethod("CreateMultilineStyle"
      Rt.CommandFlags.Modal)]
    public void createmlinestyle() {

      Ap.Document doc = cad.DocumentManager
        .MdiActiveDocument;
      if(doc == null)
        return;
      Ed.Editor ed = doc.Editor;
      Db.Database db = doc.Database;

      using(doc.LockDocument()) {
        using(Db.Transaction tr =
        db.TransactionManager.StartTransaction()) 
        {

          Db.DBDictionary mlDict =
            (Db.DBDictionary)tr.GetObject(
            db.MLStyleDictionaryId,
            Db.OpenMode.ForWrite);

          String mlineStyleName = "Пример";

          if(!mlDict.Contains(mlineStyleName)) {

            Db.MlineStyle mlineStyle =
              new Db.MlineStyle();
            // Multiline Style name
            mlineStyle.Name = mlineStyleName;
            mlineStyle.Description =
              "Некоторое описание";

            mlDict.SetAt(mlineStyleName,
              mlineStyle);
            tr.AddNewlyCreatedDBObject(
              mlineStyle, true);

            Double angleGrad = 90.0;
            Double angleRadian = angleGrad
              * Math.PI / 180; // angle

            // Start line
            mlineStyle.StartSquareCap = true;
            // Start Outer arcs
            mlineStyle.StartRoundCap = true;
            // Start Inner arcs
            mlineStyle.StartInnerArcs = true;
            // Start angle
            mlineStyle.StartAngle = angleRadian;

            // End line
            mlineStyle.EndSquareCap = true;
            // End Outer arcs
            mlineStyle.EndRoundCap = true;
            // End Inner arcs
            mlineStyle.EndInnerArcs = true;
            // End angle
            mlineStyle.EndAngle = angleRadian;

            Clr.Color color = Clr.Color.FromRgb(
              255, 0, 0);

            // Fill color
            mlineStyle.Filled = true;
            mlineStyle.FillColor = color;

            // Display joints
            mlineStyle.ShowMiters = true;

            Db.MlineStyleElement element =
              new Db.MlineStyleElement(0.15, 
                color, db.Celtype);
            // First element
            mlineStyle.Elements.Add(element, true
              );

            element = new Db.MlineStyleElement(
              -0.15, color, db.Celtype);

            mlineStyle.Elements.Add(element, 
              false); // Second element
          }
          tr.Commit();
        }
      }
    }
  }
}

Стили мультивыносок в AutoCAD

В заметке показан пример программного создания и детальной настройки стиля мультивыносок в AutoCAD. В коде каждая изменяемая нами опция настроек помечена комментарием, содержащим наименование этой опции в англоязычной версии AutoCAD.
В результате работы кода будет создан и настроен новый стиль мультивыноски:



В коде определена команда CreateMultileaderStyle, выполняющая всю необходимую процедуру.

/* MLeaderStyleSample.cs
 * © Андрей Бушман, 2014 
 * Пример создания и настройки стиля мультивыно-
 * сок.
 */
using System;
using cad = Autodesk.AutoCAD.ApplicationServices
.Application;
using Ap = Autodesk.AutoCAD.ApplicationServices;
using Db = Autodesk.AutoCAD.DatabaseServices;
using Ed = Autodesk.AutoCAD.EditorInput;
using Gm = Autodesk.AutoCAD.Geometry;
using Rt = Autodesk.AutoCAD.Runtime;
using Clr = Autodesk.AutoCAD.Colors;

[assembly: Rt.CommandClass(typeof(Bushman.CAD
  .Samples.Styles.MLeaderStyleSample))]

namespace Bushman.CAD.Samples.Styles {
  public class MLeaderStyleSample {
    [Rt.CommandMethod("CreateMultileaderStyle",
      Rt.CommandFlags.Modal)]
    public void CreatingMleaderStyle() {
      Ap.Document doc = cad.DocumentManager
        .MdiActiveDocument;
      if(doc == null)
        return;
      Ed.Editor ed = doc.Editor;
      Db.Database db = doc.Database;

      using(Db.Transaction tr =
        db.TransactionManager.StartTransaction()) {
        Db.DBDictionary mleaderStylesDict =
          tr.GetObject(
          db.MLeaderStyleDictionaryId,
            Db.OpenMode.ForRead) as
            Db.DBDictionary;

        const String mleaderStyleName = "Точка";

        Db.MLeaderStyle mleaderStyle;
        if(mleaderStylesDict.Contains(
          mleaderStyleName))
          mleaderStyle = (Db.MLeaderStyle)tr
            .GetObject(
            (Db.ObjectId)mleaderStylesDict[
            mleaderStyleName],
            Db.OpenMode.ForWrite);
        else {
          mleaderStyle = new Db.MLeaderStyle();
          Db.ObjectId mleaderStyleId =
            mleaderStyle.PostMLeaderStyleToDb(db,
            mleaderStyleName);
          tr.AddNewlyCreatedDBObject(
            mleaderStyle, true);
        }

        // Ниже рассмотрены все настройки 
        // диалогового окна "Modify Multileader 
        // Style". Все наименования соответствуют
        // английской версии AutoCAD.

        // "Вкладка Leader Format" ***

        // Группа "General":

        mleaderStyle.LeaderLineType =
          Db.LeaderType.StraightLeader; // Type
        mleaderStyle.LeaderLineColor =
          Clr.Color.FromColorIndex(
          Clr.ColorMethod.ByLayer, 256); // Color
        mleaderStyle.LeaderLineTypeId =
          db.ByBlockLinetype; // Linetype

        // Lineweight
        mleaderStyle.LeaderLineWeight =
          Db.LineWeight.LineWeight025;

        // Группа "Arrowhead":

        Db.BlockTable blockTable = tr.GetObject(
          db.BlockTableId, Db.OpenMode.ForRead)
          as Db.BlockTable;
        if(!blockTable.Has("_DOT")) {
          // Загружаем определение блока "_DOT"
          cad.SetSystemVariable("DIMBLK""_DOT")
            ;
        }
        mleaderStyle.ArrowSymbolId = blockTable[
          "_DOT"]; // Symbol
        mleaderStyle.ArrowSize = 1; // Size

        // Группа "Leader break":

        // Break size
        mleaderStyle.BreakSize = 2;

        // Вкладка "Leader Structure" ***

        // Группа "Constrains":

        // Maximum leader points
        mleaderStyle.MaxLeaderSegmentsPoints = 2;

        // First segment angle
        mleaderStyle
          .FirstSegmentAngleConstraint =
          Db.AngleConstraint.DegreesAny;

        // Примечание для First segment angle:

        // Опция выбрана и значение равно 0:
        // mleaderStyle        
        //  .FirstSegmentAngleConstraint = 
        //  Db.AngleConstraint.DegreesHorz; 

        // Опция не выбрана и значение равно 0:
        // mleaderStyle        
        //  .FirstSegmentAngleConstraint = 
        //  Db.AngleConstraint.DegreesAny; 

        // Second segment angle
        mleaderStyle
          .SecondSegmentAngleConstraint =
          Db.AngleConstraint.DegreesAny;

        // Примечание для Second segment angle:

        // Опция выбрана и значение равно 0:
        // mleaderStyle
        //  .SecondSegmentAngleConstraint = 
        //  Db.AngleConstraint.DegreesHorz;

        // Опция не выбрана и значение равно 0:
        // mleaderStyle
        //  .SecondSegmentAngleConstraint = 
        //  Db.AngleConstraint.DegreesAny; 

        // Группа "Landing settings":

        // Автору кода не удалось добраться до 
        // опций "Automatically include landing" 
        // и "Set landing distance", а так же до
        // его значения ни через .NET, ни через 
        // COM.             

        // Группа "Scale":

        // Annotative
        mleaderStyle.Annotative =
          Db.AnnotativeStates.True;

        // Scale multileaders to layout
        // mleaderStyle.Scale = 0; 

        // Specify scale
        mleaderStyle.Scale = 1;


        // Вкладка "Content" ***               

        // *** Если для "Multileader type" выбран
        // вариант "MText": ***

        // Multileader type
        mleaderStyle.ContentType =
          Db.ContentType.MTextContent;

        // Создадим новый текстовый стиль для
        // использования его в нашем стиле
        // мультивыноски
        Db.TextStyleTable tst =
          (Db.TextStyleTable)tr.GetObject(
          db.TextStyleTableId,
          Db.OpenMode.ForWrite);
        Db.TextStyleTableRecord textStyle =
          new Db.TextStyleTableRecord();
        textStyle.Name = "Тип А прямой";
        textStyle.FileName = "Arial.ttf";
        textStyle.XScale = 0.75;
        tst.Add(textStyle);
        tr.AddNewlyCreatedDBObject(textStyle,
          true);

        // Группа "Text options":
        Db.MText defaultMText = new Db.MText();
        defaultMText.SetDatabaseDefaults();

#if AUTOCAD_2009
        defaultMText.TextStyle = 
          textStyle.ObjectId;
#else
        defaultMText.TextStyleId =
          textStyle.ObjectId;
#endif

        defaultMText.Contents = String.Empty;
        // Default text
        mleaderStyle.DefaultMText = defaultMText;

        // Text style
        mleaderStyle.TextStyleId =
          textStyle.ObjectId;
        // Text angle
        mleaderStyle.TextAngleType =
          Db.TextAngleType.HorizontalAngle;
        // Text color
        mleaderStyle.TextColor =
          Clr.Color.FromColorIndex(
          Clr.ColorMethod.ByBlock, 256);
        // Text height
        mleaderStyle.TextHeight = 3.5;
        // Alwais left justify
        mleaderStyle.TextAlignAlwaysLeft = false;
        // Frame text
        mleaderStyle.EnableFrameText = false;

        // Группа "Leader connection":
        mleaderStyle.TextAttachmentType =
          Db.TextAttachmentType.AttachmentMiddle;

        // Left attachment
        mleaderStyle.SetTextAttachmentType(
          Db.TextAttachmentType
          .AttachmentBottomOfTopLine,
          Db.LeaderDirectionType.LeftLeader);

        // Right attachment
        mleaderStyle.SetTextAttachmentType(
          Db.TextAttachmentType
          .AttachmentBottomOfTopLine,
            Db.LeaderDirectionType.RightLeader);

        // Landing gap 
        mleaderStyle.LandingGap = 1;

#if !AUTOCAD_2009
        // AutoCAD 2009 не имеет следующих 
        // свойств:

        // Horisontal attachment:
        mleaderStyle.TextAttachmentDirection =
         Db.TextAttachmentDirection
         .AttachmentHorizontal;

        // Внимание! если в настройках мы 
        // устанавливаем вариант "Horisontal 
        // attachment", то для установки опций
        // "Left attachment" и "Right attachment"
        // нужно методу SetTextAttachmentType
        // вторым аргументом передавать значения
        // LeftLeader и RightLeader 
        // сооветственно:

        // Left attachment
        mleaderStyle.SetTextAttachmentType(
          Db.TextAttachmentType
          .AttachmentBottomOfTopLine,
          Db.LeaderDirectionType.LeftLeader);
        // Right attachment
        mleaderStyle.SetTextAttachmentType(
          Db.TextAttachmentType
          .AttachmentBottomOfTopLine,
          Db.LeaderDirectionType.RightLeader);

        // или:
        // Vertical attachment:
        // mleaderStyle.TextAttachmentDirection =
        // Db.TextAttachmentDirection
        // .AttachmentVertical;

        // Внимание! если в настройках мы 
        // устанавливаем вариант "Vertical 
        // attachment", то для установки опций
        // "Top attachment" и "Bottom attachment"
        // нужно методу SetTextAttachmentType
        // вторым аргументом передавать значения
        // TopLeader и BottomLeader 
        // сооветственно:

        // Top attachment
        // mleaderStyle.SetTextAttachmentType(
        //  Db.TextAttachmentType
        //  .AttachmentCenter,
        //  Db.LeaderDirectionType.TopLeader);

        // Bottom attachment
        // mleaderStyle.SetTextAttachmentType(
        //  Db.TextAttachmentType
        //  .AttachmentCenter,
        //  Db.LeaderDirectionType.BottomLeader);

        // Extend leader to text
        mleaderStyle.ExtendLeaderToText = false;
#endif

        // В этом блоке показаны варианты "Block"
        // и "None": 
#if OTHER_VARIANTS_OF_MULTILEADER_TYPE
        // *** Если для "Multileader type" выбран
        // вариант "Block" ***

        // Multileader type
        mleaderStyle.ContentType =
          Db.ContentType.BlockContent;

        // Группа "Block options":     

        // Создаём нужное нам определение блока
        String blockName = "Блок выноски";
        try {
          Db.SymbolUtilityServices
            .ValidateSymbolName(blockName, false)
            ;
          Db.BlockTable bt = tr.GetObject(
            db.BlockTableId,
            Db.OpenMode.ForWrite) as
            Db.BlockTable;

          Db.ObjectId blockId = Db.ObjectId.Null;

          if(bt.Has(blockName))
            blockId = bt[blockName];
          else {
            Db.BlockTableRecord block =
              new Db.BlockTableRecord();
            block.Name = blockName;
            block.Annotative =
              Db.AnnotativeStates.True;
            bt.Add(block);
            tr.AddNewlyCreatedDBObject(block,
              true);
            // Пусть наш блок выноски будет пред-
            // ставлен окружностью с текстовым
            // атрибутом

            // Окружность
            Db.Circle circle = new Db.Circle();
            circle.Center = new Gm.Point3d(0, 0,
              0);
            circle.Radius = 10.0;
            circle.SetDatabaseDefaults();
            block.AppendEntity(circle);
            tr.AddNewlyCreatedDBObject(circle,
              true);

            // Определение атрибута
            Db.AttributeDefinition attDef =
              new Db.AttributeDefinition();
            attDef.Position = new Gm.Point3d(0,
              0, 0);
            attDef.Tag = "Текст выноски";
#if AUTOCAD_2009
            attDef.TextStyle = db.Textstyle;
#else
            attDef.TextStyleId = db.Textstyle;
#endif
            attDef.Prompt = "Значение атрибута";
            attDef.Preset = true;
            attDef.TextString = String.Empty;
            attDef.Justify = Db.AttachmentPoint
              .MiddleCenter;
            attDef.Height = 5;
            attDef.Annotative =
              Db.AnnotativeStates.True;
            block.AppendEntity(attDef);
            tr.AddNewlyCreatedDBObject(attDef,
              true);
            blockId = block.ObjectId;
          }
          // Source block
          mleaderStyle.BlockId = blockId;
          Gm.Scale3d scale3d = new Gm.Scale3d(
            3.35, 3.35, 3.35);
          // Scale
          mleaderStyle.BlockScale = scale3d;
          // Attachment       
          mleaderStyle.BlockConnectionType =
            Db.BlockConnectionType.ConnectBase;
          // Block color
          mleaderStyle.BlockColor = Clr.Color
            .FromColorIndex(Clr.ColorMethod
            .ByBlock, 256);

          // ***
        }
        catch(Exception ex) {
          ed.WriteMessage("Exception: {0}n",
            ex.Message);
        }

        // *** Если для "Multileader type" выбран
        // вариант "None" ***

        // Multileader type
        mleaderStyle.ContentType =
          Db.ContentType.NoneContent;

        // Вариант "None" не содержит никаких 
        // дополнительных настроек.
#endif
        tr.Commit();
      }
    }
  }
}

Табличные стили в AutoCAD

В заметке показан пример создания и детальной настройки базового табличного стиля. Затем, на его основе создан производный табличный стиль к которому применён пользовательский шаблон таблиц (так же созданный нами в коде). После создания и настройки табличных стилей, в коде продемонстрированы примеры создания таблиц на основе обозначенных выше стилей.

В результате работы кода будут созданы два табличных стиля:


В составе базового стиля создаётся дополнительный набор стилей ячеек и происходит подробная настройка каждой опции стиля:


На основе базового стиля создаётся производный стиль и к нему применяется шаблон:


В коде так же определены две команды (CreateTable и CreateTable2), при помощи которых создаются таблицы на основе созданных нами табличных стилей. При запуске этих команд необходимые стили создаются автоматически, если они ещё отсутствуют в базе данных чертежа. Помимо этого, в коде определено две команды, создающие наши стили: BaseTableStyle и TableStyleWithTemplate.


В коде каждая изменяемая нами опция настроек помечена комментарием, содержащим наименование этой опции в англоязычной версии AutoCAD.

   1:  /* TableStyleSample.cs
   2:   * AutoCAD 2009-2015
   3:   * © Андрей Бушман, 2014  
   4:   * Пример создания табличных стилей (с шаблоном и
   5:   * без), а так же таблиц, использующих эти стили.
   6:   * 
   7:   * Команды, определённые в данном коде: 
   8:   * - CreateTable - создать таблицу на основе 
   9:   *    базового табличного стиля.
  10:   *    
  11:   * - CreateTable2 - создать таблицу на основе 
  12:   *    шаблонного табличного стиля.
  13:   *    
  14:   * - BaseTableStyle - создать базовый табличный 
  15:   *    стиль.
  16:   *    
  17:   * - TableStyleWithTemplate - создать табличный 
  18:   *    стиль на основе шаблона таблицы.
  19:   */
  20:  using System;
  21:  using System.Collections.Generic;
  22:  using System.Linq;
  23:  using System.Text;
  24:  using System.Reflection;
  25:   
  26:  #if AUTOCAD
  27:  using cad = Autodesk.AutoCAD.ApplicationServices
  28:  .Application;
  29:  using Ap = Autodesk.AutoCAD.ApplicationServices;
  30:  using Db = Autodesk.AutoCAD.DatabaseServices;
  31:  using Ed = Autodesk.AutoCAD.EditorInput;
  32:  using Rt = Autodesk.AutoCAD.Runtime;
  33:  using Gm = Autodesk.AutoCAD.Geometry;
  34:  using Clr = Autodesk.AutoCAD.Colors;
  35:  using Wn = Autodesk.AutoCAD.Windows;
  36:  using Hs = Autodesk.AutoCAD.DatabaseServices
  37:  .HostApplicationServices;
  38:  using Us = Autodesk.AutoCAD.DatabaseServices
  39:  .SymbolUtilityServices;
  40:  using Int = Autodesk.AutoCAD.Interop;
  41:  using Com = Autodesk.AutoCAD.Interop.Common;
  42:  #endif // #if AUTOCAD
  43:   
  44:  [assembly: Rt.CommandClass(typeof(
  45:    Bushman.CAD.Samples.Styles.TableStyleSample))]
  46:   
  47:  namespace Bushman.CAD.Samples.Styles {
  48:   
  49:    public class TableStyleSample {
  50:      // Наименование группы команд
  51:      const String group = "Samples";
  52:      const String textStyleName = "Текст таблиц";
  53:      const String tableStyleName = "Базовый";
  54:      const String tableStyle2Name =
  55:        "Спецификация металла";
  56:   
  57:      [Rt.CommandMethod(group, "BaseTableStyle",
  58:        Rt.CommandFlags.Modal)]
  59:      public void BaseTableStyle_Command() {
  60:        Ap.Document doc = cad.DocumentManager
  61:          .MdiActiveDocument;
  62:        if(doc == null)
  63:          return;
  64:        Db.Database db = doc.Database;
  65:        Ed.Editor ed = doc.Editor;
  66:        using(doc.LockDocument()) {
  67:          Int.AcadDocument activeDocument =
  68:            default(Int.AcadDocument);
  69:  #if !NEWER_THAN_AUTOCAD_2009
  70:          activeDocument = (Int.AcadDocument)cad
  71:            .DocumentManager.MdiActiveDocument
  72:            .AcadDocument;
  73:  #else
  74:          activeDocument = (Int.AcadDocument)
  75:            Ap.DocumentExtension.GetAcadDocument(
  76:            cad.DocumentManager.MdiActiveDocument);
  77:  #endif
  78:          using(Db.Transaction tr =
  79:            db.TransactionManager.StartTransaction(
  80:            )) {
  81:   
  82:            // Создаём новый текстовый стиль, 
  83:            // который будем использовать в нашем
  84:            // табличном стиле         
  85:            Db.TextStyleTable tst = tr.GetObject(
  86:              db.TextStyleTableId, Db.OpenMode
  87:              .ForWrite) as Db.TextStyleTable;
  88:            Db.ObjectId textStyleId = Db.ObjectId
  89:              .Null;
  90:   
  91:            if(tst.Has(textStyleName)) {
  92:              textStyleId = tst[textStyleName];
  93:            }
  94:            else {
  95:              Db.TextStyleTableRecord textStyle =
  96:                new Db.TextStyleTableRecord();
  97:              textStyle.Name = textStyleName;
  98:              // ttf или, к примеру, shx файл.
  99:              textStyle.FileName = "Arial.ttf";
 100:              textStyle.XScale = 0.75;
 101:              tst.Add(textStyle);
 102:              tr.AddNewlyCreatedDBObject(textStyle,
 103:                true);
 104:              textStyleId = textStyle.ObjectId;
 105:            }
 106:   
 107:            Db.DBDictionary tableStylesDictionary =
 108:              tr.GetObject(
 109:                db.TableStyleDictionaryId,
 110:                Db.OpenMode.ForWrite) as
 111:                Db.DBDictionary;
 112:   
 113:            Db.TableStyle tableStyle;
 114:            Db.ObjectId tableStyleId = Db.ObjectId
 115:              .Null;
 116:   
 117:            // Если табличный стиль с таким именем 
 118:            // уже существует, то завершаем работу 
 119:            // метода.
 120:            if(tableStylesDictionary.Contains(
 121:              tableStyleName)) {
 122:              return;
 123:            }
 124:            // Если нужный нам табличный стиль 
 125:            // отсутствует, то создаём его.
 126:            else {
 127:              tableStyle = new Db.TableStyle();
 128:              tableStyleId = tableStylesDictionary
 129:                .SetAt(tableStyleName, tableStyle);
 130:              tr.AddNewlyCreatedDBObject(
 131:                tableStyle, true);
 132:            }
 133:   
 134:            // Некоторые операции будут выполняться 
 135:            // через COM, т.к. некоторые настройки 
 136:            // автору этого кода удалось выполнить 
 137:            // только через COM.
 138:  #if !NEWER_THAN_AUTOCAD_2009
 139:            Com.IAcadTableStyle2 customTableStyle =
 140:              (Com.IAcadTableStyle2)tableStyle
 141:              .AcadObject;
 142:  #else
 143:            Com.IAcadTableStyle customTableStyle =
 144:              (Com.IAcadTableStyle)tableStyle
 145:              .AcadObject;
 146:  #endif
 147:            // Табличный стиль создан. Теперь нужно
 148:            // выполнить его настройку. Свойство 
 149:            // Table direction в диалоговом окне 
 150:            // Modify Table Style.
 151:            customTableStyle.FlowDirection =
 152:              Com.AcTableDirection
 153:              .acTableTopToBottom;
 154:   
 155:            // Примечание к нашему табличному стилю
 156:            tableStyle.Description =
 157:              "Этот табличный стиль создан " +
 158:              "программно.";
 159:   
 160:            // Большинство настроек табличного 
 161:            // стиля хранятся в настройках стилей 
 162:            // ячеек (Cell styles). Каждый стиль 
 163:            // ячеек содержит настройки, которые в 
 164:            // диалоговом окне Modify Table Style 
 165:            // отображаются на вкладках General, 
 166:            // Text и Borders. 
 167:   
 168:            // Работа с пользовательскими стилями 
 169:            // ячеек выполняется через COM API:
 170:            CreateCustomCellStyles(tableStyle,
 171:              textStyleId, db.ContinuousLinetype);
 172:            // Работа со встроенными стилями ячеек 
 173:            // возможна как через COM API, так и 
 174:            // через .NET API:
 175:            InitializeEmbededCellStyles(tableStyle,
 176:              textStyleId);
 177:            tr.Commit();
 178:          }
 179:        }
 180:      }
 181:   
 182:      [Rt.CommandMethod(group,
 183:        "TableStyleWithTemplate",
 184:        Rt.CommandFlags.Modal)]
 185:      public void TableStyleWithTemplate_Command() {
 186:        Ap.Document doc = cad.DocumentManager
 187:          .MdiActiveDocument;
 188:        if(doc == null)
 189:          return;
 190:        Db.Database db = doc.Database;
 191:        Ed.Editor ed = doc.Editor;
 192:        using(doc.LockDocument()) {
 193:          Int.AcadDocument activeDocument =
 194:            default(Int.AcadDocument);
 195:  #if !NEWER_THAN_AUTOCAD_2009
 196:          activeDocument = (Int.AcadDocument)
 197:            cad.DocumentManager.MdiActiveDocument
 198:            .AcadDocument;
 199:  #else
 200:          activeDocument = (Int.AcadDocument)
 201:            Ap.DocumentExtension.GetAcadDocument(
 202:            cad.DocumentManager.MdiActiveDocument);
 203:  #endif
 204:          using(Db.Transaction tr =
 205:            db.TransactionManager.StartTransaction(
 206:            )) {
 207:            Db.DBDictionary tableStylesDictionary =
 208:              tr.GetObject(
 209:              db.TableStyleDictionaryId,
 210:              Db.OpenMode.ForWrite) as
 211:              Db.DBDictionary;
 212:   
 213:            Db.TableStyle tableStyle = null;
 214:            Db.ObjectId tableStyleId =
 215:              Db.ObjectId.Null;
 216:   
 217:            // Если целевой табличный стиль уже 
 218:            // существует, то завершаем работу 
 219:            // метода
 220:            if(tableStylesDictionary.Contains(
 221:              tableStyle2Name)) {
 222:              return;
 223:            }
 224:   
 225:            // Если базовый табличный стиль с таким 
 226:            // именем отсутствует, то создаём его
 227:            if(!tableStylesDictionary.Contains(
 228:              tableStyleName)) {
 229:              BaseTableStyle_Command();
 230:            }
 231:            tableStyleId = tableStylesDictionary
 232:              .GetAt(tableStyleName);
 233:            tableStyle = tr.GetObject(tableStyleId,
 234:              Db.OpenMode.ForWrite) as
 235:              Db.TableStyle;
 236:   
 237:  #if !NEWER_THAN_AUTOCAD_2009
 238:            Com.IAcadTableStyle2 customTableStyle =
 239:              (Com.IAcadTableStyle2)tableStyle
 240:              .AcadObject;
 241:  #else
 242:            Com.IAcadTableStyle customTableStyle =
 243:              (Com.IAcadTableStyle)tableStyle
 244:              .AcadObject;
 245:  #endif
 246:            // Теперь посмотрим, как табличному 
 247:            // стилю назначать в качестве шаблона 
 248:            // некоторую таблицу. Т.е. как 
 249:            // программно сделать то, что делает 
 250:            // пользователь при помощи кнопки 
 251:            // "select table to start from"
 252:            // в диалоговом окне "Modify Table 
 253:            // Style".
 254:   
 255:            // Шаг 1: Сначала создаём таблицу, 
 256:            // которая должна применяться в 
 257:            // качестве шаблона.
 258:            Db.Table table = new Db.Table();
 259:            table.SetDatabaseDefaults();
 260:            table.TableStyle = tableStyleId;
 261:            table.Position = new Gm.Point3d(0, 0, 0
 262:              );
 263:            const Int32 columnsCount = 8;
 264:            const Int32 rowsCount = 11;
 265:            table.SetSize(columnsCount, rowsCount);
 266:            table.Height = 15;
 267:            table.Width = 20;
 268:            table.ColorIndex = 5;
 269:   
 270:            // Заполняем таблицу...
 271:            String[,] str = new String[
 272:              columnsCount, rowsCount];
 273:            // Для начала инициализируем всё 
 274:            // пустыми значениями, дабы массив в
 275:            // дальнейшем можно было обрабатывать в 
 276:            // цикле
 277:            for(Int32 i = 0; i < columnsCount; i++) {
 278:              for(int j = 0; j < rowsCount; j++) {
 279:                str[i, j] = String.Empty;
 280:              }
 281:            }
 282:   
 283:            // Теперь заполняем конкретные, 
 284:            // интересующие нас ячейки
 285:            str[0, 0] = "Спецификация металла";
 286:            str[1, 0] = "Марка";
 287:            str[1, 1] = "Поз.";
 288:            str[1, 2] = "Наименование";
 289:            str[1, 3] = "Сечение";
 290:            str[1, 5] = "Длина";
 291:            str[1, 6] = "Кол.";
 292:            str[1, 7] = "Масса, кг";
 293:            str[2, 7] = "ед.";
 294:            str[2, 8] = "общ.";
 295:            str[1, 9] = "Материал";
 296:            str[1, 10] = "Приме- чание";
 297:            str[2, 3] = "t";
 298:            str[2, 4] = @"A1;{A, смH0.7x;S2^;}";
 299:   
 300:            for(int i = 0; i < columnsCount; i++) {
 301:              for(int j = 0; j < rowsCount; j++) {
 302:  #if !NEWER_THAN_AUTOCAD_2009
 303:                table.SetColumnWidth(j, 60);
 304:                table.SetTextHeight(i, j, 5);
 305:                table.SetTextString(i, j, str[i, j]
 306:                );
 307:                table.SetAlignment(i, j, 
 308:                Db.CellAlignment.MiddleCenter);
 309:  #else
 310:                // Так можно назначить высоту 
 311:                // текста в конкретной ячейке:
 312:                // table.Cells[i, j].TextHeight = 
 313:                // 5;
 314:   
 315:                // Назначаем значение конкретной 
 316:                // ячейке
 317:                table.Cells[i, j].SetValue(str[
 318:                  i, j],
 319:                  Db.ParseOption.ParseOptionNone);
 320:                // Так можно выровнять содержимое 
 321:                // конкретной ячейки
 322:                // table.Cells[i, j].Alignment = 
 323:                // Db.CellAlignment.MiddleCenter;
 324:  #endif
 325:              }
 326:  #if !NEWER_THAN_AUTOCAD_2009
 327:              table.SetRowHeight(i, 10.0);
 328:   
 329:              table.SetColumnWidth(0, 10);
 330:              table.SetColumnWidth(1, 10);
 331:              table.SetColumnWidth(2, 50);
 332:              table.SetColumnWidth(3, 10);
 333:              table.SetColumnWidth(4, 10);
 334:              table.SetColumnWidth(5, 10);
 335:              table.SetColumnWidth(6, 10);
 336:              table.SetColumnWidth(7, 15);
 337:              table.SetColumnWidth(8, 15);
 338:              table.SetColumnWidth(9, 25);
 339:              table.SetColumnWidth(10, 15);
 340:  #else
 341:              // При желании можно назначать 
 342:              // настройки строкам или столбцам:
 343:              // Наименование таблицы
 344:              // table.Rows[0].TextHeight = 5;
 345:              //Заголовок
 346:              // table.Rows[1].TextHeight = 3.5;
 347:              // table.Rows[2].TextHeight = 3.5;
 348:              // однако предпочтительней 
 349:              // пользоваться настройками стилей 
 350:              // ячеек.
 351:   
 352:              table.Rows[i].Height = 8;
 353:              table.Columns[0].Width = 10;
 354:              table.Columns[1].Width = 10;
 355:              table.Columns[2].Width = 50;
 356:              table.Columns[3].Width = 10;
 357:              table.Columns[4].Width = 10;
 358:              table.Columns[5].Width = 15;
 359:              table.Columns[6].Width = 10;
 360:              table.Columns[7].Width = 15;
 361:              table.Columns[8].Width = 15;
 362:              table.Columns[9].Width = 25;
 363:              table.Columns[10].Width = 15;
 364:  #endif
 365:            }
 366:   
 367:  #if !NEWER_THAN_AUTOCAD_2009
 368:            // Автору кода не удалось найти способ 
 369:            // назначить стиль ячеек строкам, а не 
 370:            // ячейкам для AutoCAD 2009. 
 371:   
 372:            // Автору кода не удалось найти способ 
 373:            // задать выравнивание столбцам для 
 374:            // AutoCAD 2009 
 375:   
 376:            // Дополнительные настройки следует 
 377:            // выполнять после того, как ячейкам, 
 378:            // строкам и столбцам будут назначены 
 379:            // нужные стили. Иначе все изменения 
 380:            // будут переопределены настройками 
 381:            // стилей ячеек.
 382:            // Например, назначаем поворот 
 383:            // содержимого некоторых ячеек в 
 384:            // заголовке таблицы:
 385:            table.SetTextRotation(1, 0, 
 386:              Db.RotationAngle.Degrees090);
 387:            table.SetTextRotation(1, 1, 
 388:              Db.RotationAngle.Degrees090);
 389:  #else
 390:            // Назначаем выравнивание столбцам
 391:            for(Int32 i = 0; i < columnsCount; i++) {
 392:              table.Columns[i].Alignment =
 393:                Db.CellAlignment.MiddleCenter;
 394:            }
 395:   
 396:            // Назначаем выравнивание строкам 
 397:            // (наименованию таблицы и заголовку)
 398:            for(Int32 i = 0; i < 3; i++) {
 399:              table.Rows[i].Alignment =
 400:                Db.CellAlignment.MiddleCenter;
 401:              if(i == 0)
 402:                table.Rows[i].Style = "_TITLE";
 403:              else
 404:                table.Rows[i].Style = "_HEADER";
 405:            }
 406:            // Дополнительные настройки следует 
 407:            // выполнять после того, как
 408:            // ячейкам, строкам и столбцам будут 
 409:            // назначены нужные стили. 
 410:            // Иначе все изменения будут 
 411:            // переопределены настройками стилей 
 412:            // ячеек. Например, назначаем поворот 
 413:            // содержимого некоторых ячеек в 
 414:            // заголовке таблицы:
 415:            table.Cells[1, 0].Contents[0].Rotation
 416:              = 90.0 * Math.PI / 180;
 417:            table.Cells[1, 1].Contents[0].Rotation
 418:              = 90.0 * Math.PI / 180;
 419:  #endif
 420:   
 421:  #if !NEWER_THAN_AUTOCAD_2009
 422:            Db.CellRange rng = new Db.CellRange(2, 
 423:              0, 3, 1);
 424:   
 425:            // Вертикальное объединение ячеек
 426:            Db.CellRange rngMark = new Db.CellRange
 427:              (1, 0, 2, 0);
 428:            Db.CellRange rngPos = new Db.CellRange
 429:              (1, 1, 2, 1);
 430:            Db.CellRange rngName = new Db.CellRange
 431:              (1, 2, 2, 2);
 432:            Db.CellRange rngCount = 
 433:              new Db.CellRange(1, 6, 2, 6);
 434:            Db.CellRange rngMaterial = 
 435:              new Db.CellRange(1, 9, 2, 9);
 436:            Db.CellRange rngDescript = 
 437:              new Db.CellRange(1, 10, 2, 10);
 438:   
 439:            // Горизонтальное объединение ячеек
 440:            Db.CellRange rngSection = 
 441:              new Db.CellRange(1, 3, 1, 4);
 442:            Db.CellRange rngArea = 
 443:              new Db.CellRange(2, 4, 2, 5);
 444:            Db.CellRange rngMass = 
 445:              new Db.CellRange(1, 7, 1, 8);
 446:   
 447:   
 448:  #else
 449:            // Вертикальное объединение ячеек
 450:            Db.CellRange rngMark = Db.CellRange
 451:              .Create(table, 1, 0, 2, 0);
 452:            Db.CellRange rngPos = Db.CellRange
 453:              .Create(table, 1, 1, 2, 1);
 454:            Db.CellRange rngName = Db.CellRange
 455:              .Create(table, 1, 2, 2, 2);
 456:            Db.CellRange rngCount = Db.CellRange
 457:              .Create(table, 1, 6, 2, 6);
 458:            Db.CellRange rngMaterial = Db.CellRange
 459:              .Create(table, 1, 9, 2, 9);
 460:            Db.CellRange rngDescript = Db.CellRange
 461:              .Create(table, 1, 10, 2, 10);
 462:   
 463:            // Горизонтальное объединение ячеек
 464:            Db.CellRange rngSection = Db.CellRange
 465:              .Create(table, 1, 3, 1, 4);
 466:            Db.CellRange rngArea = Db.CellRange
 467:              .Create(table, 2, 4, 2, 5);
 468:            Db.CellRange rngMass = Db.CellRange
 469:              .Create(table, 1, 7, 1, 8);
 470:  #endif
 471:   
 472:            table.MergeCells(rngMark);
 473:            table.MergeCells(rngPos);
 474:            table.MergeCells(rngName);
 475:            table.MergeCells(rngCount);
 476:            table.MergeCells(rngMaterial);
 477:            table.MergeCells(rngDescript);
 478:            table.MergeCells(rngSection);
 479:            table.MergeCells(rngArea);
 480:            table.MergeCells(rngMass);
 481:   
 482:            table.GenerateLayout();
 483:   
 484:            // Шаг 2: Назначаем созданную нами выше 
 485:            // таблицу, шаблоном для табличного 
 486:            // стиля
 487:            Db.TableStyle tableStyle2 =
 488:              new Db.TableStyle();
 489:            tableStyle2.CopyFrom(tableStyle);
 490:   
 491:            Db.ObjectId tableStyle2Id =
 492:              tableStylesDictionary.SetAt(
 493:              tableStyle2Name, tableStyle2);
 494:            tr.AddNewlyCreatedDBObject(tableStyle2,
 495:              true);
 496:   
 497:            Db.TableTemplate template =
 498:              new Db.TableTemplate(
 499:                table, Db.TableCopyOptions
 500:                .TableCopyColumnWidth |
 501:                Db.TableCopyOptions
 502:                .TableCopyRowHeight |
 503:                Db.TableCopyOptions
 504:                .ConvertFormatToOverrides);
 505:            db.AddDBObject(template);
 506:            tr.AddNewlyCreatedDBObject(template,
 507:              true);
 508:   
 509:  #if NEWER_THAN_AUTOCAD_2009
 510:            tableStyle2.Template =
 511:              template.ObjectId;
 512:  #else
 513:            Com.IAcadTableStyle2 customTableStyle2 
 514:            = (Com.IAcadTableStyle2)tableStyle2
 515:            .AcadObject;
 516:  #if PLATFORM_X86
 517:            customTableStyle2.TemplateId = template
 518:            .ObjectId.OldIdPtr.ToInt32();
 519:  #else
 520:            customTableStyle2.TemplateId = template
 521:            .ObjectId.OldIdPtr.ToInt64();
 522:  #endif // #if PLATFORM_X86
 523:  #endif // #if NEWER_THAN_AUTOCAD_2009
 524:            tr.Commit();
 525:          }
 526:        }
 527:      }
 528:   
 529:      /// <summary>
 530:      /// В пространстве модели создать таблицу на 
 531:      /// основе табличного стиля "Базовый". Точка 
 532:      /// вставки таблицы: 0,0,0.
 533:      /// </summary>
 534:      [Rt.CommandMethod(group, "CreateTable",
 535:        Rt.CommandFlags.Modal)]
 536:      public void CreateTable() {
 537:        Ap.Document doc = cad.DocumentManager
 538:          .MdiActiveDocument;
 539:        if(doc == null)
 540:          return;
 541:        Db.Database db = doc.Database;
 542:        using(doc.LockDocument()) {
 543:          using(Db.Transaction tr =
 544:            db.TransactionManager.StartTransaction(
 545:            )) {
 546:            Db.DBDictionary dict = tr.GetObject(
 547:              db.TableStyleDictionaryId,
 548:              Db.OpenMode.ForRead) as
 549:              Db.DBDictionary;
 550:            if(!dict.Contains(tableStyle2Name))
 551:              TableStyleWithTemplate_Command();
 552:            Db.TableStyle ts = tr.GetObject(dict
 553:              .GetAt(tableStyleName),
 554:              Db.OpenMode.ForRead) as Db.TableStyle
 555:              ;
 556:            // Включим отображение толщин линий, 
 557:            // дабы увидеть результат нашей работы
 558:            cad.SetSystemVariable("LWDISPLAY", 1);
 559:            // Создаём новую таблицу, на основе 
 560:            // созданного нами стиля.
 561:            Db.Table tableInstance = new Db.Table()
 562:              ;
 563:            tableInstance.SetDatabaseDefaults();
 564:            tableInstance.TableStyle = ts.ObjectId;
 565:            tableInstance.SetSize(10, 5);
 566:            tableInstance.GenerateLayout();
 567:            tableInstance.Position =
 568:              new Gm.Point3d(0, 0, 0);
 569:            Db.BlockTable bt = tr.GetObject(
 570:              db.BlockTableId, Db.OpenMode.ForRead)
 571:                as Db.BlockTable;
 572:            Db.BlockTableRecord modelSpace =
 573:              tr.GetObject(bt[
 574:              Db.BlockTableRecord.ModelSpace],
 575:              Db.OpenMode.ForWrite) as
 576:              Db.BlockTableRecord;
 577:            modelSpace.AppendEntity(tableInstance);
 578:            tr.AddNewlyCreatedDBObject(
 579:              tableInstance, true);
 580:            tr.Commit();
 581:          }
 582:        }
 583:        Object acadObject = cad.AcadApplication;
 584:        acadObject.GetType().InvokeMember(
 585:          "ZoomExtents", BindingFlags.InvokeMethod,
 586:          null, acadObject, null);
 587:      }
 588:   
 589:      /// <summary>
 590:      /// В пространстве модели создать таблицу на 
 591:      /// основе шаблона, указанного в табличном 
 592:      /// стиле "Спецификация металла". Точка 
 593:      /// вставки таблицы: 50,0,0.
 594:      /// </summary>
 595:      [Rt.CommandMethod(group, "CreateTable2",
 596:        Rt.CommandFlags.Modal)]
 597:      public void CreateTable2() {
 598:        Ap.Document doc = cad.DocumentManager
 599:          .MdiActiveDocument;
 600:        if(doc == null)
 601:          return;
 602:        Db.Database db = doc.Database;
 603:        using(doc.LockDocument()) {
 604:          using(Db.Transaction tr =
 605:            db.TransactionManager.StartTransaction(
 606:            )) {
 607:            Db.DBDictionary dict = tr.GetObject(
 608:              db.TableStyleDictionaryId,
 609:              Db.OpenMode.ForRead) as
 610:              Db.DBDictionary;
 611:            if(!dict.Contains(tableStyle2Name))
 612:              TableStyleWithTemplate_Command();
 613:            Db.TableStyle ts = tr.GetObject(dict
 614:              .GetAt(tableStyle2Name),
 615:              Db.OpenMode.ForRead) as Db.TableStyle
 616:              ;
 617:            Db.TableTemplate template =
 618:              tr.GetObject(ts.Template,
 619:              Db.OpenMode.ForRead) as
 620:              Db.TableTemplate;
 621:            // Включим отображение толщин линий, 
 622:            // дабы увидеть результат нашей работы
 623:            cad.SetSystemVariable("LWDISPLAY", 1);
 624:            // Создаём новую таблицу, на основе 
 625:            // созданного нами шаблона.
 626:            Db.Table tableInstance = new Db.Table()
 627:              ;
 628:            tableInstance.CopyFrom(template,
 629:              Db.TableCopyOptions.FillTarget);
 630:            tableInstance.GenerateLayout();
 631:            tableInstance.Position =
 632:              new Gm.Point3d(50, 0, 0);
 633:            Db.BlockTable bt = tr.GetObject(
 634:              db.BlockTableId, Db.OpenMode.ForRead)
 635:                as Db.BlockTable;
 636:            Db.BlockTableRecord modelSpace =
 637:              tr.GetObject(bt[
 638:              Db.BlockTableRecord.ModelSpace],
 639:              Db.OpenMode.ForWrite) as
 640:              Db.BlockTableRecord;
 641:            modelSpace.AppendEntity(tableInstance);
 642:            tr.AddNewlyCreatedDBObject(
 643:              tableInstance, true);
 644:            tr.Commit();
 645:          }
 646:        }
 647:        Object acadObject = cad.AcadApplication;
 648:        acadObject.GetType().InvokeMember(
 649:          "ZoomExtents", BindingFlags.InvokeMethod,
 650:          null, acadObject, null);
 651:      }
 652:   
 653:      /// <summary>
 654:      /// Настройка встроенных стилей ячеек. 
 655:      /// Встроенными являются стили: _TITLE, 
 656:      /// _HEADER и _DATA.
 657:      /// </summary>
 658:      /// <param name="tableStyle">Табличный стиль, 
 659:      /// подлежащий редактированию.
 660:      /// </param>
 661:      /// <param name="textStyleId">Идентификатор 
 662:      /// текстового стиля, который 
 663:      /// должен использоваться в создаваемых 
 664:      /// стилях ячеек.</param>
 665:      private void InitializeEmbededCellStyles(
 666:        Db.TableStyle tableStyle,
 667:        Db.ObjectId textStyleId) {
 668:        Db.Database db = tableStyle.Database;
 669:        // Некоторые операции будут выполняться 
 670:        // через COM, т.к. некоторые 
 671:        // настройки автору этого кода удалось 
 672:        // выполнить только через COM.
 673:  #if !NEWER_THAN_AUTOCAD_2009
 674:        Com.IAcadTableStyle2 customTableStyle =
 675:          (Com.IAcadTableStyle2)tableStyle
 676:          .AcadObject;
 677:  #else
 678:        Com.IAcadTableStyle customTableStyle =
 679:          (Com.IAcadTableStyle)tableStyle
 680:          .AcadObject;
 681:  #endif
 682:   
 683:        // Большинство настроек табличного стиля 
 684:        // хранятся в настройках стилей ячеек (Cell
 685:        // styles). Каждый стиль ячеек содержит 
 686:        // настройки, которые в диалоговом окне 
 687:        // Modify Table Style отображаются на 
 688:        // вкладках General, Text и Borders.      
 689:   
 690:        //*****************************************
 691:   
 692:        // 1. ВКЛАДКА "GENERAL" ДИАЛОГОВОГО ОКНА 
 693:        // "MODIFY TABLE STYLE":
 694:   
 695:        // В интересующем нас стиле ячеек, 
 696:        // устанавливем цвет фона ячеек (если это 
 697:        // нам нужно). Автор кода не нашёл способа 
 698:        // установить цвет фона для 
 699:        // пользовательских стилей ячеек. Есть 
 700:        // возможность устанавливать фон ячеек для 
 701:        // встроенных стилей Title, Header и Data:          
 702:        String strColor = String.Format(
 703:          "Autocad.AcCmColor.{0}", cad.Version
 704:          .Major);
 705:        Com.AcadAcCmColor color = (
 706:          (Int.AcadApplication)cad.AcadApplication)
 707:            .GetInterfaceObject(strColor) as
 708:            Com.AcadAcCmColor;
 709:        color.SetRGB(250, 0, 0);
 710:   
 711:        // Однако установить и получить фон мы 
 712:        // можем и посредством .NET API:
 713:        // tableStyle.SetBackgroundColor(Clr.Color
 714:        // .FromColorIndex(Clr.ColorMethod
 715:        // .Foreground, 31), (Int32)Db.RowType
 716:        // .DataRow);
 717:   
 718:        // Убираем фон
 719:        tableStyle.SetBackgroundColorNone(true,
 720:          (Int32)Db.RowType.DataRow);
 721:   
 722:        // Получаем фон через .NET API:
 723:        //Clr.Color dataBgColor = tableStyle
 724:        // .BackgroundColor(Db.RowType.DataRow);
 725:   
 726:        // Назначить выравнивание в стиле ячеек 
 727:        // через .NET API
 728:        tableStyle.SetAlignment(
 729:          Db.CellAlignment.TopLeft,
 730:          (Int32)Db.RowType.DataRow);
 731:   
 732:        // Получить выравнивание в стиле ячеек 
 733:        // через .NET API
 734:        // Db.CellAlignment _datAlignment = 
 735:        // tableStyle.Alignment(Db.RowType.DataRow)
 736:        // ;
 737:   
 738:        // Опция 'Format' (кнопка с тремя точками)
 739:        // Если нажать на эту кнопку, то откроется 
 740:        // диалоговое окно "Table Cell Format".
 741:        // Значением 'format' является строковое 
 742:        // значение. Простейший способ получения 
 743:        // этого значения следующий:
 744:        // 1. Установите в диалоговом окне 
 745:        // "Table Cell Format" нужный формат 
 746:        // вручную.
 747:        // 2. Посмотрите значение сгенерированной 
 748:        // строки, воспользовавшись методом 
 749:        // GetFormat2 (см. код ниже). 
 750:   
 751:        // Устанавливаем формат стиля ячеек через 
 752:        // .NET API
 753:        tableStyle.SetFormat("%lu2%pr3%ps[,%]",
 754:          Db.RowType.DataRow);
 755:   
 756:        // Получаем формат стиля ячеек через .NET 
 757:        // API
 758:        // String datFormat = tableStyle.Format(
 759:        // Db.RowType.DataRow);
 760:   
 761:        // Устанавливаем тип данных и единиц 
 762:        // измерения через .NET API
 763:        tableStyle.SetDataType(Db.DataType.Double,
 764:          Db.UnitType.Distance, Db.RowType.DataRow)
 765:          ;
 766:        // Получаем тип данных и единиц измерения 
 767:        // через .NET API
 768:        // Db.DataType _dataType = tableStyle
 769:        // .DataType(Db.RowType.DataRow);
 770:        // Db.UnitType _unitType = tableStyle
 771:        // .UnitType(Db.RowType.DataRow);
 772:   
 773:        // Устанавливаем значения опцииям 
 774:        // 'horizontal margins' и 'vertical 
 775:        // margins'
 776:   
 777:        // Встроенные стили ячеек имеют имена: 
 778:        // _TITLE, _HEADER, _DATA.
 779:        String name = "_HEADER";
 780:  #if !NEWER_THAN_AUTOCAD_2009
 781:        // Мне не удалось получить и назначить 
 782:        // значения опциям 'horizontal 
 783:        // margins' и 'vertical margins' в AutoCAD 
 784:        // 2009 ни через .NET API, ни через COM API
 785:  #else
 786:        tableStyle.SetMargin(Db.CellMargins.Left,
 787:          1.0, name);
 788:        tableStyle.SetMargin(Db.CellMargins.Top,
 789:          1.0, name);
 790:   
 791:        // Получить значения опций 'horizontal 
 792:        // margins' и 'vertical margins'
 793:        // можно так:
 794:        // Double _leftMargin = tableStyle.Margin(
 795:        // Db.CellMargins.Left, name);
 796:        // Double _topMargin = tableStyle.Margin(
 797:        // Db.CellMargins.Top, name);
 798:  #endif
 799:        // Устанавливаем значение свойства 'Merge 
 800:        // cells on row/column creation' через COM 
 801:        // API
 802:        customTableStyle.EnableMergeAll(name, false
 803:          );
 804:   
 805:        // Получаем значение свойства 'Merge cells
 806:        // on row/column creation' через COM API
 807:        // Boolean isMergedCells = customTableStyle
 808:        // .GetIsMergeAllEnabled(name);
 809:   
 810:        //*****************************************
 811:   
 812:        //2. ВКЛАДКА 'TEXT' ДИАЛОГОВОГО ОКНА 
 813:        // "MODIFY TABLE STYLE":
 814:   
 815:        // Получение через COM API текстового 
 816:        // стиля, назначенного стилю ячеек 
 817:        // Db.ObjectId _textStyleId = 
 818:        // new Db.ObjectId(new IntPtr(
 819:        // customTableStyle.GetTextStyleId(name)));
 820:   
 821:        // Назначение текстового стиля стилю ячеек 
 822:        // через .NET API
 823:        tableStyle.SetTextStyle(textStyleId,
 824:          (Int32)Db.RowType.TitleRow);
 825:        tableStyle.SetTextStyle(textStyleId,
 826:          (Int32)Db.RowType.HeaderRow);
 827:        tableStyle.SetTextStyle(textStyleId,
 828:          (Int32)Db.RowType.DataRow);
 829:        // Получение через .NET API текстового 
 830:        // стиля, назначенного стилю ячеек 
 831:        // Db.ObjectId _dataRowTextStyleId = 
 832:        // tableStyle.TextStyle(Db.RowType.DataRow)
 833:        // ;
 834:   
 835:        // Назначение высоты текста через .NET API          
 836:        tableStyle.SetTextHeight(5,
 837:          (Int32)Db.RowType.TitleRow); // TITLE
 838:        tableStyle.SetTextHeight(3.5,
 839:          (Int32)Db.RowType.HeaderRow); // HEADER
 840:        tableStyle.SetTextHeight(3.5,
 841:          (Int32)Db.RowType.DataRow); // DATA
 842:   
 843:        // Получение высоты текста через .NET API
 844:        // Double _dataRowTextHeight = tableStyle
 845:        // .TextHeight(Db.RowType.DataRow);
 846:   
 847:        // Назначение цвета тексту через .NET API      
 848:        Autodesk.AutoCAD.Colors.Color colTitleText
 849:          = Clr.Color.FromColorIndex(
 850:           Clr.ColorMethod.ByColor, 10);
 851:        Autodesk.AutoCAD.Colors.Color colHdText =
 852:          Clr.Color.FromColorIndex(
 853:            Clr.ColorMethod.ByColor, 210);
 854:        Autodesk.AutoCAD.Colors.Color colDataText =
 855:          Clr.Color.FromColorIndex(
 856:           Clr.ColorMethod.ByColor, 10);
 857:   
 858:        tableStyle.SetColor(colTitleText,
 859:          (Int32)Db.RowType.TitleRow);
 860:        tableStyle.SetColor(colHdText,
 861:          (Int32)Db.RowType.HeaderRow);
 862:        tableStyle.SetColor(colDataText,
 863:          (Int32)Db.RowType.DataRow);
 864:   
 865:        // Получение цвета текста через .NET API
 866:        // Clr.Color _textColor2 = tableStyle
 867:        // .Color(Db.RowType.DataRow);
 868:   
 869:        // Назначение угла наклона текста через COM 
 870:        // API
 871:        Double angle = 0; // значение в градусах
 872:        // Градусы необходимо преобразовывать в 
 873:        // радианы
 874:        customTableStyle.SetRotation(name, angle *
 875:          Math.PI / 180);
 876:   
 877:        // Получение угла наклона текста через COM 
 878:        // API
 879:        // Double _angle = customTableStyle
 880:        // .GetRotation(name) * 180.0 / Math.PI;
 881:   
 882:        //*****************************************
 883:   
 884:        // ВКЛАДКА 'BORDERS' ДИАЛОГОВОГО ОКНА 
 885:        // "MODIFY TABLE STYLE":
 886:   
 887:        // Назначение толщин линий границам ячеек 
 888:        // через .NET API
 889:        tableStyle.SetGridLineWeight(Db.LineWeight
 890:          .LineWeight050,
 891:            (Int32)Db.GridLineType.VerticalInside,
 892:            (Int32)Db.RowType.DataRow);
 893:   
 894:        tableStyle.SetGridLineWeight(Db.LineWeight
 895:          .LineWeight018,
 896:            (Int32)Db.GridLineType.HorizontalInside
 897:            , (Int32)Db.RowType.DataRow);
 898:   
 899:        tableStyle.SetGridLineWeight(Db.LineWeight
 900:          .LineWeight050,
 901:            (Int32)Db.GridLineType.OuterGridLines,
 902:            (Int32)Db.RowType.DataRow);
 903:   
 904:        tableStyle.SetGridLineWeight(Db.LineWeight
 905:          .LineWeight050,
 906:            (Int32)Db.GridLineType.AllGridLines,
 907:            (Int32)Db.RowType.HeaderRow);
 908:   
 909:        // Получение толщин линий границам ячеек 
 910:        // через .NET API
 911:        // Db.LineWeight _dataRowLineWeight = 
 912:        //  tableStyle.GridLineWeight(
 913:        //    Db.GridLineType.HorizontalTop, 
 914:        //    Db.RowType.DataRow);
 915:   
 916:        // Получаем идентификатор типа линии, 
 917:        // которая будет использоваться при 
 918:        // прорисовке контура ячеек, использующих 
 919:        // созданный нами стиль ячеек.
 920:        Db.ObjectId linetypeId =
 921:          db.ContinuousLinetype;
 922:   
 923:  #if !NEWER_THAN_AUTOCAD_2009
 924:        // Мне не удалось получить, либо назначить 
 925:        // значение GridLinetype стилю ячеек в 
 926:        // AutoCAD 2009 ни через .NET API, ни через
 927:        // COM API.
 928:  #else
 929:        // Назначаем стилю ячеек нужный тип линии 
 930:        // через .NET API
 931:        tableStyle.SetGridLinetype(linetypeId,
 932:          Db.GridLineType.AllGridLines, name);
 933:   
 934:        // Получаем стиль ячеек нужного нам типа 
 935:        // линии через .NET API
 936:        // Db.GridLineStyle _linestyle = tableStyle
 937:        //  .GridLineStyle(
 938:        // Db.GridLineType.AllGridLines, name);
 939:  #endif
 940:        Autodesk.AutoCAD.Colors.Color
 941:          outerLinesColor =
 942:          Clr.Color.FromColorIndex(
 943:            Clr.ColorMethod.ByColor, 90);
 944:        // Назначаем цвет линиям сетки нашего стиля 
 945:        // ячеек через .NET API
 946:        tableStyle.SetGridColor(outerLinesColor,
 947:          (Int32)(Db.GridLineType.OuterGridLines |
 948:          Db.GridLineType.VerticalGridLines),
 949:          (Int32)Db.RowType.DataRow);
 950:   
 951:        tableStyle.SetGridColor(outerLinesColor,
 952:          (Int32)(Db.GridLineType.AllGridLines),
 953:          (Int32)Db.RowType.HeaderRow);
 954:   
 955:        Autodesk.AutoCAD.Colors.Color
 956:          horInsideLinesColor =
 957:          Clr.Color.FromColorIndex(
 958:          Clr.ColorMethod.ByColor, 130);
 959:   
 960:        tableStyle.SetGridColor(
 961:          horInsideLinesColor,
 962:          (Int32)(Db.GridLineType
 963:          .HorizontalInside), (Int32)Db.RowType
 964:          .DataRow);
 965:   
 966:        // Получаем цвет линий сетки нашего стиля 
 967:        // ячеек через .NET API
 968:        // tableStyle.GridColor((Db.GridLineType
 969:        // .HorizontalInside | Db.GridLineType
 970:        // .VerticalLeft), Db.RowType.DataRow);
 971:   
 972:        // Установка значения опции 'Double line'
 973:  #if !NEWER_THAN_AUTOCAD_2009
 974:        // Мне не удалось получить или назначить в 
 975:        // AutoCAD 2009 значение опции 'Double 
 976:        // line' ни через COM API, ни через .NET 
 977:        // API.
 978:   
 979:        // Мне не удалось получить или назначить в 
 980:        // AutoCAD 2009 значение опции 'Spacing' ни 
 981:        // через COM API, ни через .NET API.            
 982:  #else
 983:        // Установка значения опции 'Double line' 
 984:        // через .NET API
 985:        tableStyle.SetGridLineStyle(
 986:          Db.GridLineStyle.Single,
 987:          Db.GridLineType.AllGridLines, name);
 988:   
 989:        // Получение значения опции 'Double line' 
 990:        // через .NET API
 991:        // Db.GridLineStyle _dataGridLinetypeStyle 
 992:        // = tableStyle.GridLineStyle(
 993:        //    Db.GridLineType.AllGridLines, name);
 994:   
 995:        // Установка значения опции 'Spacing' через
 996:        // .NET API
 997:        tableStyle.SetGridDoubleLineSpacing(3,
 998:          Db.GridLineType.AllGridLines, name);
 999:   
1000:        // Получение значения опции 'Spacing' через
1001:        // .NET API
1002:        // Double _spacing = tableStyle
1003:        // .GridDoubleLineSpacing(
1004:        //  Db.GridLineType.AllGridLines, name);
1005:  #endif
1006:      }
1007:   
1008:      /// <summary>
1009:      /// Создать и настроить дополнительный набор 
1010:      /// стилей ячеек: Группа, Формула и Итого, 
1011:      /// помимо встроенных стилей _TITLE, _HEADER 
1012:      /// и _DATA.
1013:      /// </summary>
1014:      /// <param name="tableStyle">Табличный стиль, 
1015:      /// подлежащий редактированию.
1016:      /// </param>
1017:      /// <param name="textStyleId">Идентификатор 
1018:      /// текстового стиля, который 
1019:      /// должен использоваться в создаваемых 
1020:      /// стилях ячеек.</param>
1021:      /// <param name="linetypeId">Идентификатор 
1022:      /// типа линии, которая должна
1023:      /// использоваться в создаваемых стилях ячеек
1024:      /// </param>
1025:      private void CreateCustomCellStyles(
1026:        Db.TableStyle tableStyle, Db.ObjectId
1027:        textStyleId, Db.ObjectId linetypeId) {
1028:  #if !NEWER_THAN_AUTOCAD_2009
1029:        Com.IAcadTableStyle2 customTableStyle =
1030:          (Com.IAcadTableStyle2)tableStyle
1031:          .AcadObject;
1032:  #else
1033:        Com.IAcadTableStyle customTableStyle =
1034:          (Com.IAcadTableStyle)tableStyle
1035:          .AcadObject;
1036:  #endif
1037:   
1038:        // Имена дополнительных стилей ячеек, 
1039:        // которые мы создадим
1040:        String[] names = new String[] { "Группа", 
1041:          "Формула", "Итого" };
1042:   
1043:        foreach(String name in names) {
1044:          customTableStyle.CreateCellStyle(name);
1045:          //***************************************
1046:   
1047:          // 1. ВКЛАДКА "GENERAL" ДИАЛОГОВОГО ОКНА 
1048:          // "MODIFY TABLE STYLE":
1049:   
1050:          // Установить цвет фона пользовательского 
1051:          // стиля ячеек (опция "Fill color" в 
1052:          // настройках табличного стиля) можно 
1053:          // через COM API. Сначала нужно создать 
1054:          // цвет:
1055:          String strColor = String.Format(
1056:            "Autocad.AcCmColor.{0}",
1057:            cad.Version.Major);
1058:          Com.AcadAcCmColor color = (
1059:            (Int.AcadApplication)cad
1060:            .AcadApplication)
1061:              .GetInterfaceObject(strColor) as
1062:              Com.AcadAcCmColor;
1063:          color.SetRGB(149, 203, 149);
1064:   
1065:          // Теперь пользовательскому стилю ячеек 
1066:          // можно, посредством COM API, установить
1067:          // фон:
1068:          // customTableStyle.SetBackgroundColor2(
1069:          // name, color);
1070:   
1071:          // Сбросить ранее установленный фон можно 
1072:          // следующим образом
1073:          //Int32 cellClass = customTableStyle
1074:          // .GetCellClass(name);
1075:          //Boolean result = false;
1076:          //customTableStyle
1077:          // .SetBackgroundColorNone(cellClass, ref
1078:          // result);
1079:   
1080:          // Получить цвет фона пользовательского 
1081:          // стиля ячеек можно так же посредством 
1082:          // COM API:
1083:          // color = customTableStyle
1084:          // .GetBackgroundColor2(name);
1085:   
1086:          // Назначаем выравнивание             
1087:          customTableStyle.SetAlignment2(name,
1088:            name == "Группа" ?
1089:            Com.AcCellAlignment.acMiddleLeft :
1090:            Com.AcCellAlignment.acMiddleCenter);
1091:   
1092:          // Получить выравнивание в стиле ячеек 
1093:          // через COM API
1094:          // Com.AcCellAlignment alignment = 
1095:          // customTableStyle.GetAlignment2(name);
1096:   
1097:          // Опция 'Format' (кнопка с тремя точками
1098:          // ). Если нажать на эту кнопку, то 
1099:          // откроется диалоговое окно "Table Cell 
1100:          // Format". Значением 'format' является 
1101:          // строковое значение. Простейший способ 
1102:          // получения этого значения следующий:
1103:          // 1. Установите в диалоговом окне "Table 
1104:          // Cell Format" нужный формат вручную.
1105:          // 2. Посмотрите значение сгенерированной 
1106:          // строки, воспользовавшись методом 
1107:          // GetFormat2 (см. код ниже).                
1108:   
1109:          // String _format = null;
1110:          // Устанавливаем нужный нам формат стиля 
1111:          // ячеек через COM API
1112:          customTableStyle.SetFormat2(name,
1113:            "%au0%pr3");
1114:          // Получаем формат стиля ячеек через COM 
1115:          // API
1116:          // customTableStyle.GetFormat2(name, out
1117:          // _format);
1118:   
1119:          // Устанавливем тип данных и единиц 
1120:          // измерения через COM API
1121:          customTableStyle.SetDataType2(name,
1122:            Com.AcValueDataType.acDouble,
1123:            Com.AcValueUnitType.acUnitArea);
1124:          // Получаем тип данных и единиц измерения 
1125:          // через COM API
1126:          // Com.AcValueDataType valueDataType;
1127:          // Com.AcValueUnitType unitType;
1128:          // customTableStyle.GetDataType2(name, 
1129:          // out valueDataType, out unitType);
1130:   
1131:          // Устанавливаем значения опцииям 
1132:          // 'horizontal margins' и 'vertical 
1133:          // margins'
1134:  #if !NEWER_THAN_AUTOCAD_2009
1135:          // Автору кода не удалось получить и 
1136:          // назначить значения опциям 'horizontal
1137:          // margins' и 'vertical margins' в 
1138:          // AutoCAD 2009 ни через .NET API, ни 
1139:          // через COM API.
1140:  #else
1141:   
1142:          tableStyle.SetMargin(Db.CellMargins.Left,
1143:            1, name);
1144:          tableStyle.SetMargin(Db.CellMargins.Top,
1145:            1, name);
1146:   
1147:          // Получить значения опций 'horizontal 
1148:          // margins' и 'vertical margins'
1149:          // можно так:
1150:          // Double _leftMargin = tableStyle
1151:          // .Margin(Db.CellMargins.Left, name);
1152:          // Double _topMargin = tableStyle
1153:          // .Margin(Db.CellMargins.Top, name);
1154:  #endif
1155:          // Устанавливаем значение свойства 'Merge
1156:          // cells on row/column creation' через 
1157:          // COM API
1158:          customTableStyle.EnableMergeAll(name,
1159:            name == "Группа" ? true : false);
1160:          // Получаем значение свойства 'Merge 
1161:          // cells on row/column creation'  через 
1162:          // COM API
1163:          // Boolean isMergedCells = 
1164:          // customTableStyle.GetIsMergeAllEnabled(
1165:          // name);
1166:   
1167:          //***************************************
1168:   
1169:          //2. ВКЛАДКА 'TEXT' ДИАЛОГОВОГО ОКНА 
1170:          // "MODIFY TABLE STYLE":
1171:   
1172:          // Назначение текстового стиля стилю 
1173:          // ячеек через COM API
1174:  #if PLATFORM_X86
1175:          customTableStyle.SetTextStyleId(name,
1176:            textStyleId.OldIdPtr.ToInt32());
1177:  #else
1178:          customTableStyle.SetTextStyleId(name, 
1179:            textStyleId.OldIdPtr.ToInt64());
1180:  #endif
1181:   
1182:          // Получение через COM API текстового 
1183:          // стиля, назначенного стилю ячеек
1184:          // Db.ObjectId _textStyleId = 
1185:          // new Db.ObjectId(new IntPtr(
1186:          // customTableStyle.GetTextStyleId(name))
1187:          // );
1188:   
1189:          // Назначение высоты текста через COM API
1190:          customTableStyle.SetTextHeight2(name,
1191:            name == "Формула" ? 3.5 : 5);
1192:          // Получение высоты текста через COM API
1193:          // Double _textHeight = customTableStyle
1194:          // .GetTextHeight2(name);
1195:   
1196:          // Назначение цвета тексту через COM API
1197:          switch(name) {
1198:            case "Группа":
1199:              color.SetRGB(0, 63, 255);
1200:              break;
1201:            case "Формула":
1202:              color.SetRGB(255, 0, 0);
1203:              break;
1204:            case "Итого":
1205:              color.SetRGB(0, 153, 0);
1206:              break;
1207:            default:
1208:              break;
1209:          }
1210:          customTableStyle.SetColor2(name, color);
1211:          // Получение цвета текста через COM API
1212:          // Com.AcadAcCmColor _textColor = 
1213:          // customTableStyle.GetColor2(name);
1214:   
1215:          // Назначение угла наклона текста через 
1216:          // COM API
1217:          Double angle = 0; // значение в градусах
1218:          // Градусы необходимо преобразовывать в 
1219:          // радианы
1220:          customTableStyle.SetRotation(name, angle
1221:            * Math.PI / 180);
1222:          // Получение угла наклона текста через 
1223:          // COM API
1224:          // Double _angle = customTableStyle
1225:          // .GetRotation(name) * 180.0 / Math.PI;
1226:   
1227:          //***************************************
1228:   
1229:          // ВКЛАДКА 'BORDERS' ДИАЛОГОВОГО ОКНА 
1230:          // "MODIFY TABLE STYLE":
1231:   
1232:          // Назначение толщин линий границам ячеек
1233:          // через COM API
1234:          customTableStyle.SetGridLineWeight2(name,
1235:            Com.AcGridLineType.acHorzTop |
1236:            Com.AcGridLineType.acHorzBottom |
1237:          Com.AcGridLineType.acVertLeft |
1238:          Com.AcGridLineType.acVertRight,
1239:          Com.ACAD_LWEIGHT.acLnWt050);
1240:   
1241:          customTableStyle.SetGridLineWeight2(name,
1242:            Com.AcGridLineType.acVertInside,
1243:            Com.ACAD_LWEIGHT.acLnWt018);
1244:   
1245:          customTableStyle.SetGridLineWeight2(name,
1246:            Com.AcGridLineType.acHorzInside |
1247:            Com.AcGridLineType.acVertInside,
1248:            Com.ACAD_LWEIGHT.acLnWt018);
1249:   
1250:          // Получение толщин линий границам ячеек 
1251:          // через COM API
1252:          // Com.ACAD_LWEIGHT _lineWeight = 
1253:          // customTableStyle.GetGridLineWeight2(
1254:          //  name, Com.AcGridLineType.acHorzTop);
1255:   
1256:  #if !NEWER_THAN_AUTOCAD_2009
1257:          // Автору кода не удалось получить, либо 
1258:          // назначить значение GridLinetype стилю
1259:          // ячеек в AutoCAD 2009 ни через .NET 
1260:          // API, ни через COM API.
1261:  #else
1262:          // Назначаем стилю ячеек нужный тип линии
1263:          // через .NET API
1264:          tableStyle.SetGridLinetype(linetypeId,
1265:            Db.GridLineType.AllGridLines,
1266:            name);
1267:          // Получаем стиль ячеек нужного нам типа 
1268:          // линии через .NET API
1269:          // Db.GridLineStyle _linestyle = 
1270:          // tableStyle.GridLineStyle(
1271:          //  Db.GridLineType.AllGridLines, name);
1272:  #endif
1273:          // Назначаем цвет линиям сетки нашего 
1274:          // стиля ячеек через COM API
1275:          color.SetRGB(70, 158, 250);
1276:   
1277:          customTableStyle.SetGridColor2(name,
1278:            Com.AcGridLineType.acHorzTop |
1279:            Com.AcGridLineType.acHorzBottom |
1280:          Com.AcGridLineType.acVertLeft |
1281:          Com.AcGridLineType.acVertRight,
1282:            color);
1283:   
1284:          color.SetRGB(175, 39, 65);
1285:          customTableStyle.SetGridColor2(name,
1286:            Com.AcGridLineType.acHorzInside |
1287:            Com.AcGridLineType.acVertInside, color)
1288:            ;
1289:   
1290:          // Получаем цвет линий сетки нашего стиля 
1291:          // ячеек через COM API
1292:          // Com.AcadAcCmColor _Clror = 
1293:          // customTableStyle.GetGridColor2(
1294:          //  name, Com.AcGridLineType.acHorzTop);
1295:   
1296:          // Установка значения опции 'Double line'
1297:  #if !NEWER_THAN_AUTOCAD_2009
1298:          // Автору кода не удалось получить или 
1299:          // назначить в AutoCAD 2009 значение 
1300:          // опции 'Double line' ни через COM API, 
1301:          // ни через .NET API.
1302:   
1303:          // Мне не удалось получить или назначить 
1304:          // в AutoCAD 2009 значение опции 'Spacing'
1305:          // ни через COM API, ни через .NET API. 
1306:  #else
1307:          // Установка значения опции 'Double line'
1308:          // через .NET API
1309:          tableStyle.SetGridLineStyle(
1310:            Db.GridLineStyle.Single,
1311:            Db.GridLineType.AllGridLines, name);
1312:          // Получение значения опции 'Double line'
1313:          // через .NET API
1314:          //Db.GridLineStyle _dataGridLinetypeStyle
1315:          // = tableStyle.GridLineStyle(
1316:          // Db.GridLineType.AllGridLines, name);
1317:   
1318:          // Установка значения опции 'Spacing' 
1319:          // через .NET API
1320:          tableStyle.SetGridDoubleLineSpacing(1,
1321:            Db.GridLineType.AllGridLines, name);
1322:          // Получение значения опции 'Spacing' 
1323:          // через .NET API
1324:          // Double _spacing = tableStyle
1325:          // .GridDoubleLineSpacing(
1326:          // Db.GridLineType.AllGridLines, name);
1327:  #endif
1328:        }
1329:      }
1330:    }
1331:  }