![]() |
| Главная »Статьи »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. Внимание! Запрещается воспроизведение
данной статьи или ее части без согласования с автором. Если вы желаете разместить
эту статью на своем сайте или издать в печатном виде, свяжитесь с автором. |