Главная »Статьи »AutoCAD и Delphi » |
Блок это особый тип объетов AutoCAD, содержимое которого сохраняется в таблице определений блоков файла DWG. Програмный доступ к определениям блоков осуществляется через коллекцию Blocks. Блок в рисунок вставляется в виде ссылки (BlockReference) на его имя в таблице определений и точки вставки. Ниже приведена функция, возвращающая имена всех блоков в документе: function EnumBlockNames(Items: TStrings; IncludeSpecial: Boolean = False): Integer; var i, BlocksCount: Integer; BlkName: string; begin Result:= -1; if not VarIsClear(Acad) then begin with Items do begin BeginUpdate; try Clear; BlocksCount:= Acad.ActiveDocument.Blocks.Count; for i:= 0 to BlocksCount - 1 do begin BlkName:= Acad.ActiveDocument.Blocks.Item(i).Name; if (not IncludeSpecial) and (BlkName[1] <> '*') or IncludeSpecial then Add(BlkName); end; finally EndUpdate; end; Result:= Count; end; end; end; Здесь надо обратить внимание на условие: if (not IncludeSpecial) and (BlkName[1] <> '*') or IncludeSpecial then задающее включить ли в список имена спецблоков, под которыми понимаются коллекции объектов пространства модели (*MODEL_SPACE) и листа (*PAPER_SPACE). Имена спецблоков начинаются с символа *, что и используется в условии. Если блок с именем *MODEL_SPACE может быть только один, то блоков *PAPER_SPACE столько, сколько Layout. Их имена обозначаются по формуле: *PAPER_SPACEn, где n целое, начиная с 0, но для блока, отражающего текущее пространство листа имя всегда *PAPER_SPACE.
Метод создания:
// Возвращаемое значение объект AcadBlock
function Add(InsertionPoint: OleVariant; const Name: WideString): OleVariant;
Пример использования: var BlockName: string; Block, BlkRef: OleVariant; begin if not VarIsClear(Acad) then begin BlockName:= 'New Block'; // Добавить новый блок в коллекцию блоков Block:= Acad.ActiveDocument.Blocks.Add(AcadPoint(0, 0), BlockName); // Добавить во вновь созданный блок графические объекты Block.AddLine(AcadPoint(0, 0), AcadPoint(10, 10)); Block.AddLine(AcadPoint(10, 10), AcadPoint(-10, 10)); Block.AddLine(AcadPoint(-10, 10), AcadPoint(0, 0)); // Отобразить список блоков в lbBlkNames: TListBox EnumBlockNames(lbBlkNames.Items, ckbIncSpecBlocks.Checked); end; end; В результате выполнения приведенного примера в файл будет добавлен новый блок с именем "New Block". Теперь его можно вставить в чертеж с помощью метода:
// Возвращаемое значение объект AcadBlockReference
function InsertBlock(InsertionPoint: OleVariant; const Name: WideString; Xscale, Yscale, Zscale: Double;
Rotation: Double): OleVariant;
Пример использования — вставка блока с именем из списка lbBlkNames: var BlockName: string; BlkRef, InsPnt: OleVariant; begin if not VarIsClear(Acad) and (lbBlkNames.ItemIndex >= 0) then begin InsPnt:= Acad.ActiveDocument.Utility.GetPoint(, 'Укажите первую точку: '); with lbBlkNames do BlockName:= Items[ItemIndex]; BlkRef:= Acad.ActiveDocument.ModelSpace.InsertBlock(InsPnt, BlockName, 1, 1, 1, 0); BlkRef.Update; end; end; Замечательной особенностью блоков является возможность добавлять в них атрибуты, значения которых затем могут быть изменены или извлечены. Атрибут подобен обычному однострочному тексту. Для вставки атрибута в блок используется метод:
// Возвращаемое значение объект AcadAttribute
function AddAttribute(Height: Double; Mode: AcAttributeMode; const Prompt: WideString;
InsertionPoint: OleVariant; const Tag: WideString; const Value: WideString): OleVariant;
Параметры метода в основном аналогичны задаваемым в диалоге Attribute Definition: Чтобы извлечь атрибуты вставленного блока надо для начала узнать есть ли они у него, для чего проверить значение его свойства HasAttributes типа WordBool. Далее вызовом метода GetAttributes получаем ссылку на вариантный массив со всеми атрибутами блока. В приведенном ниже примере после выбора пользователем блока, его атрибуты извлекаются в ini-подобный файл: procedure ExtractBlkRefAttr(ABlkRef: OleVariant; AFileName: string); var AttrArray, AttrRef: OleVariant; i, LBnd, HBnd: Integer; lst: TStringList; begin if ABlkRef.HasAttributes then begin lst:= TStringList.Create; try lst.Add(Format('[%s]', [ABlkRef.Name])); AttrArray:= ABlkRef.GetAttributes; LBnd:= VarArrayLowBound(AttrArray, 1); HBnd:= VarArrayHighBound(AttrArray, 1); for i:= LBnd to HBnd do begin AttrRef:= AttrArray[i]; lst.Add(Format('%s=%s', [AttrRef.TagString, AttrRef.TextString])); end; lst.SaveToFile(AFileName); finally lst.Free; end; end else raise Exception.CreateFmt('Блок "%s" не имеет атрибутов', [ABlkRef.Name]); end; procedure ExtractSameBlockAttr(AFileName: string); Для извлечения атрибутов из всех блоков в чертеже можно использовать такую процедуру: procedure ExtractBlockAttr(AFileName: string; Space: TWorkSpace = wsModelSpace); var BlkRef: OleVariant; BlkName: string; i, ObjCount: Integer; lst: TStringList; begin if not VarIsClear(Acad) then begin lst:= TStringList.Create; try if Space = wsModelSpace then ObjCount:= Acad.ActiveDocument.ModelSpace.Count else ObjCount:= Acad.ActiveDocument.PaperSpace.Count; for i:= 0 to ObjCount - 1 do begin if Space = wsModelSpace then BlkRef:= Acad.ActiveDocument.ModelSpace.Item(i) else BlkRef:= Acad.ActiveDocument.PaperSpace.Item(i); if BlkRef.ObjectName = 'AcDbBlockReference' then begin if BlkRef.HasAttributes then begin ExtractBlkRefAttr(BlkRef, lst); end; end; end; lst.SaveToFile(AFileName); finally lst.Free; end; end; end; Атрибуты извлекаются из блоков в пространстве модели или листа. В цикле перебираются все объкты заданного пространства. Условие if BlkRef.ObjectName = 'AcDbBlockReference' служит для идентификации типа объекта (блок/не блок). Конечно это не идеальное решение, но работает. К статье прилагаются примеры на Delphi 7. Внимание! Запрещается воспроизведение
данной статьи или ее части без согласования с автором. Если вы желаете разместить
эту статью на своем сайте или издать в печатном виде, свяжитесь с автором. |