技术开发 频道

SAP 2007创新技术论坛于本月25日在京举行

  6. 其它源代码例子
  6.1 说明

在此章节中,您将学习如何在设计资源管理器平台上来创建四个原理图编辑器的服务器,所有这些例子都将使用强大的原理图API,例子中按部就班地解释每一个服务器的功能,并说明如何使用原理图API函数,此章节的基础是知识是如何在设计资源管理器应用程序中有效地使用原理图API。

  6.2 原理图库编辑器的全局设置例子

此例子显示如何来提取原理图库编辑器的全局设置。请见SDK例子\SAMPLES\NO3\API\Sch\Get Library Options。

{....................................................................................}

Procedure ObtainGlobalSettings;

Var

SchLibHandle : Tobjecthandle;

SchLibOptions: TschLibraryOptions;

ShowBorderString : String;

ShowHiddenPinsString : String;

UseCustomSizeString: String;

SnapGridOnString : String;

VisibleGridOnString: String;

Begin

If MessageRouter_GetState_WindowKind(SchAPI_GetCurrentEditorWindow) <> 'SchLib' Then Exit;

//以当前编辑器窗体类型句柄作为参数来取得窗体类型,即文档类型,如果不为“SchLib”退出。

SchLibHandle:= SchAPI_GetCurrentSheetHandle;//取得当前库图表句柄。

SchLibOptions := TSchLibraryOptions.Create(SchLibHandle);

//根据库图表句柄创建环境库选项。

SchLibOptions.Querydatabase(eGetState);//同内部数据库同步外部数据库。

If SchLibOptions <> Nil Then//原理图库选项建立成功。

With SchLibOptions Do

Begin

QueryDatabase(eGetState);

If Not(ShowBorder) ThenShowBorderString := 'ShowBorder=False'

Else ShowBorderString := 'ShowBorder=True';

//根据选项的属性“ShowBorder”属性值,对字符串变量ShowBorderString赋值。

If Not(ShowHiddenPins) Then ShowHiddenPinsString := 'ShowHiddenPin = False'

Else ShowHiddenPinsString := 'ShowHiddenPin = True';

//根据选项的属性“ShowHiddenPins”属性值,对字符串变量ShowHiddenPinsString赋值。

If Not(UseCustomSize)ThenUseCustomSizeString := 'UseCustomSize = False'

Else UseCustomSizeString := 'UseCustomSize = True';

//根据选项的属性“UseCustomSize”属性值,对字符串变量UseCustomSizeString赋值。

If Not(SnapGridOn) Then SnapGridOnString := 'SnapGridOn = False'

Else SnapGridOnString := 'SnapGridOn = True';

//根据选项的属性“SnapGridOn”属性值,对字符串变量SnapGridOnString赋值。

If Not(VisibleGridOn)Then VisibleGridOnString := 'VisibleGridOn = False'

Else VisibleGridOnString := 'VisibleGridOn = True';

//根据选项的属性“VisibleGridOn”属性值,对字符串变量VisibleGridOnString赋值。

ShowInfo(

'Style= ' + IntToStr(Ord(Style))+ #13 +

'Size= ' + IntToStr(Ord(Size))+ #13 +

'Orientation= ' + IntToStr(Ord(Orientation)) + #13 +

ShowBorderString+ #13 +

ShowHiddenPinsString+ #13 +

UseCustomSizeString+ #13 +

'CustomXSize= ' + IntToStr(CustomXSize)+ #13 +

'CustomYSize= ' + IntToStr(CustomYSize)+ #13 +

'BorderColor= ' + IntToStr(BorderColor)+ #13 +

'WorkspaceColor= ' + IntToStr(WorkspaceColor)+ #13 +

SnapGridOnString+ #13 +

'SnapGridSize= ' + IntToStr(SnapGridSize)+ #13 +

VisibleGridOnString+ #13 +

'VisibleGridSize= ' + IntToStr(VisibleGridSize)+ #13 +

'Description= ' + StrPas(Description));

End;

SchLibOptions.Free;//释放库选项对象。

End;

此段代码片段所使用了下列的重要的函数和过程。

MessageRouter_GetState_WindowKind

SchAPI_GetCurrentSheetHandle

SchAPI_GetCurrentEditorWindow

Querydatabase

这段代码做什么?

设计资源管理器的运行时间库提供的函数MessageRouter_GetState_WindowKind返回当前被使用的文档编辑器的类型,此函数的参数从SchAPI_GetCurrentEditorWindow函数获得,SchAPI_GetCurrentEditorWindow函数得到在设计资源管理器中的当前文档的窗体句柄,如果返回字符串是“SchLib”,原理图库图表句柄被从SchAPI_GetCurrentSheetHandle函数获取并且传递到TSchLibraryOptions.Create构造函数。

TSchLibraryOptions对象被创建,并且被检查是否是一个有效的对象。TSchLibraryOptions对象的字段被使用Delphi的ShowMessage对话框显示,请注意字段风格(Style)、大小(Size)和方向(Orientation)-它们的次序值被获得的它们的枚举类型替代。

This code example must have the following units in the Uses clause: The Windows, SysUtils, SchAPITypes, SchProcs and SchClass, Rt_Util, Rt_Types, Rt_Param, and Rt_Forms units.

此代码例子必须在User子句中加入下列单元,Windows、SysUtils、SchAPITypes、SchProcs 、SchClass、Rt_Util、Rt_Types、Rt_Param和Rt_Forms单元。

  6.3 多层对象描述例子

下面的代码例子检查在原理图编辑器中的当前图表是否是一个项目元件,并且接着收集此项目中的所有图表信息,然而,如果图表是单独的文档,服务器仍将收集有关此图表的信息。一个项目中的图表或单独的图表的信息被输出到设计资源管理器的文本文档。

项目统计,请见SDK例子\SAMPLES\NO3\API\Sch\Project Count。

{....................................................................................}

//以下这段代码是根据当前原理图文档来取得其容器对象,代码主要是用在对象发生改变后,刷新容器对象。

Procedure Repopulate;

Var

EntityHandle: ClientTypes.TObjectHandle;

BinderHandle: ClientTypes.TObjectHandle;

Begin

EntityHandle :=ClientAPI_FindEntityByDataHandle(MessageRouter_GetState_CurrentEditorWindow);

//MessageRouter_GetState_CurrentEditorWindow函数返回在项层的文档的窗体句柄。

//ClientApi_FindEntityByDataHandle 函数使用一个编辑器窗体句柄来返回查找返回一个实体的句柄。此实体能表现为设计资源管理器编辑器窗体内的一个文档。您能通过使用ClientAPI_QueryEntity 或ClientAPI_QueryDocumentEntity 查询此实体来检查文档类型,名称等等。

If EntityHandle = 0 Then Exit; //无对象则退出。

BinderHandle := ClientApi_GetDocumentOwnerBinder(EntityHandle);

//ClientApi_GetDocumentOwnerBinder函数获得在其内部存有文档的封装对象的句柄,一个封装对象表现为包含实体的容器,一个实体可为一个设计文档或文件来。

ClientApi_RepopulateDocumentEntity(BinderHandle,False);

//ClientApi_RepopulateDocumentEntity 过程在封装对象中刷新文档实体的内容依赖于Recursive参数值,如果参数为false,当前实体被刷新,否则实体的封装对象被刷新。它在当文档被增加到一个封装对象中您需要刷新封装对象来让设计资源管理器知道有新的文档时情况下很有用。

End;

{....................................................................................}

//以下这段代码是把列表中的字符串输出到文本文档中

Procedure GenerateTextFile(AFileNameList : TStringList);

var

CurrentSheetEntity : ClientTypes.TObjecthandle;

F: TextFile;

S: TString;

I: Integer;

Begin

CurrentSheetEntity:=ClientApi_FindEntityByDataHandle(SchAPI_GetCurrentEditorWindow);

//通过当前原理图编辑器顶层对象取得窗体句柄作为查找实体对象的参数来获得实体对象句柄

ClientApi_GetDocumentEntityAbsoluteAddress(CurrentSheetEntity,S);

//取得实体对象的绝对地址并作为字符串放在S中,绝对地址中有很多标识符,如$RP表示设计数据库Full name, $RN表示设计数据库中的文件Full name,等等。

S := ForceFileNameExtension(S, 'TXT');

//用TXT扩展文件名称代替现有的文件扩展名,即把S扩展名称改为TXT。

//产生并且在当前ddb中放入文件

AssignDDB(F,S,'Admin');

//把文本文件F关联到DDB库,把S中内容放到文件F中,操作用户为“Admin”

Rewrite(F);//建立一个文件

Writeln(F,'Project Hierarchy Report...');

Writeln(F,'===========================');

Writeln(F,'');

For I := 0 to AFileNamelist.Count - 1 Do //按共有多少图表数量建立循环。

Writeln(F,AFileNameList.Strings[I]);

CloseFile(F);

Repopulate;//刷新实体对象

End;

{....................................................................................}

//以下代码计算图表总计,为此小章节例子的主程序。

Procedure RunCountSubSheets;

Var

Sheet: TSchSheetOptions;

J: Integer;

SheetHandle: SchAPITypes.TObjectHandle;

CurrentSheet : SchAPITypes.TObjectHandle;

TopSheet : SchAPITypes.TObjectHandle;

SheetCount : Integer;

FileNameList : TStringList;

Begin

If MessageRouter_GetState_WindowKind(SchAPI_GetCurrentEditorWindow) <> 'Sch' Then Exit;

//检查当前的文档类型是否是Sch,即原理图,如果不是则退出。

//SchAPI_GetCurrentEditorWindow是返回当前文档对象的窗体句柄。

//MessageRouter_GetState_WindowKind函数使用编辑器窗体句柄返回表示编辑器窗体类型的字符串值。例如,Advanced PCB 编辑器返回“PCB”字符串,并且TextEdit服务器返回“TEXT” 字符串。

SheetHandle := SchAPI_GetCurrentSheetHandle;

SheetCount:= SchAPI_GetDocumentCountInProject(SheetHandle);

//SchAPI_GetDocumentCountInProject调用仅统计在设计资源管理器中打开的图表。。

If SheetCount = 0 Then Exit;

FileNameList := TStringList.Create;

If SheetCount = 1 Then //仅有一个原理图图表。

Begin

Sheet := TSchSheetOptions.Create(SheetHandle);//创建原理图图表对象。

Sheet.QueryDatabase(SchAPITypes.eGetState);//同步内外部数据库。

FileNameList.Add(ConvertToNormalFilePath(Sheet.DocumentName) +

' is the only one open schematic document.');

//显示文档文件名称。

GenerateTextFile(FileNameList);

Sheet.Free;

End

Else

Begin //多图表项目。

SheetCount := SchAPI_GetDocumentCountInProject(SheetHandle);

//在当前项目中统计打开的原理图图表

For J := 1 to SheetCount Do

Begin

CurrentSheet := SchAPI_GetDocumentHandleByIndex(J-1, SheetHandle, False);

//返回给定索引对象的句柄。

Sheet:= TSchSheetOptions.Create(CurrentSheet);

Sheet.Querydatabase(SchAPITypes.eGetState);

FileNameList.Add(ConvertToNormalFilePath(Sheet.DocumentName));

Sheet.Free;

End;

//以下代码在文件名称列表第三行插入抬头,第一行为图表总数,第二行为文件说明,第三行为空。

FileNameList.Insert(0,'The multi level Project consists of ' + IntToStr(SheetCount) + ' open sheets.');

FileNameList.Insert(1,'The schematic documents'' filenames are : ');

FileNameList.Insert(2,'');

GenerateTextFile(FileNameList);

End;

FileNameList.Free;

End;

此段代码片段所使用了下列的重要的函数和过程。

MessageRouter_GetState_WindowKind

SchAPI_GetDocumentHandleByIndex

SchAPI_GetCurrentEditorWindow

Querydatabase

SchAPI_GetCurrentSheetHandle

SetState_Parameter

SchAPI_GetDocumentCountInProject

MessageRouter_SendCommandToModule

这段代码做什么?

MessageRouter_GetState_WindowKind返回一个当前被使用的文档编辑器类型字符串描述,如果此字符串不是一个“Sch”格式,服务器停止,否则,通过SchAPI_GetDocumentCountInProject函数获得图表总计,SchAPI_GetCurrentSheetHandle函数得到当前原理图文档句柄,句柄被传递到SchAPI_GetDocumentCountInProject函数,此函数返回在设计资源管理器打开的原理图图表总计。

接着一个由原理图图表的文档名称组成的字符串和一列描述字符串被输出到文本文档,如果产生的总计是超出一个,那么循环机制被使用,对于每一个参数的传递,函数SchAPI_GetDocumentHandleByIndex接受三个参数,第一个参数J值为循环变量,第二个参数为当前的图表句柄,最后的参数为是否设置项目图表为焦点,此函数返回句柄到一个项目的原理图图表。带有句柄的TSchSheetOptions类在当前原理图编辑器的图表中创建一个图表对象,图表对象被使用来获取它的文件名称和路径。

最后,GenerateText过程被调用,在设计资源管理器中输出数据到一个文本文档,这个文本文档中将有当前打开的多个图表项目图表文件名称或一个打开的原理图图表的文件名称。

  6.4 显示关于原理图元件信息的例子

此例子将示范对象迭代程序和组迭代程序的使用。对象迭代程序收集每一个发现的元件对象句柄,获得元件对象容器并且传递到组迭代程序。

组迭代程序接着收集此特定的元件的图元,进程继续直到在当前原理图图表中没有更多的元件对象被找到。每一个元件的信息和它的引脚位置被显示在设计资源管理器的文本编辑器中。

此例子代码从当前原理图中查找元件对象,然后再查找此一个元件对象的引用库对象共有多少个元件,可能元件库中包含多个元件,一般是一个元件,对元件库中的每一个元件对象进行组迭代程序查找,找到其下所有的子对象,包含引脚对象和非引脚对象,把引脚对象信息加到列表中,对象引用库的查找直到引用库中所有的元件全部迭代完毕为止,再返回查找当前原理图中下一个元件对象,重复上面的过程,直到把当前原理图中所有的元件对象全部查找完毕为止,最后把列表打印出来。

请见SDK例子\SAMPLES\NO3\API\Sch\Report Sch Parts。

{...............................................................................}

Implementation

Var

Partslist : TStringList;

{...............................................................................}

//以下这段代码是根据当前原理图文档来取得其容器对象,代码主要是用在对象发生改变后,刷新容器对象。

Procedure Repopulate;

Var

EntityHandle: ClientTypes.TObjectHandle;

BinderHandle: ClientTypes.TObjectHandle;

Begin

EntityHandle:=ClientAPI_FindEntityByDataHandle(MessageRouter_GetState_CurrentEditorWindow);

//MessageRouter_GetState_CurrentEditorWindow函数返回在项层的文档的窗体句柄。

//ClientApi_FindEntityByDataHandle 函数使用一个编辑器窗体句柄来返回查找返回一个实体的句柄。此实体能表现为设计资源管理器编辑器窗体内的一个文档。您能通过使用ClientAPI_QueryEntity 或ClientAPI_QueryDocumentEntity 查询此实体来检查文档类型,名称等等。

If EntityHandle = 0 Then Exit;

BinderHandle := ClientApi_GetDocumentOwnerBinder(EntityHandle);

//ClientApi_GetDocumentOwnerBinder函数获得在其内部存有文档的封装对象的句柄,一个封装对象表现为包含实体的容器,一个实体可为一个设计文档或文件来。

ClientApi_RepopulateDocumentEntity(BinderHandle,False);

//ClientApi_RepopulateDocumentEntity 过程在封装对象中刷新文档实体的内容依赖于Recursive参数值,如果参数为false,当前实体被刷新,否则实体的封装对象被刷新。它在当文档被增加到一个封装对象中您需要刷新封装对象来让设计资源管理器知道有新的文档时情况下很有用。

End;

{....................................................................................}

//以下这段代码在给定元件中把元件内引脚对象信息取出来。把元件对象看成一个组件,组件中再包含元件对象即引脚。建立组迭代程序来取得引脚对象的信息。

Procedure IterateInsidePartContainerList(APartContainerList : TObjectHandle; APart : TSchPart);

Var

ObjectKind: TObjectKind;

GroupIterator : TObjecthandle;

Primitive : TObjectHandle;

Pin : TSchPin;

Handle: TObjectHandle;

Begin

GroupIterator:= SchAPI_CreateGroupIterator(APartContainerList);

//创建组迭代程序对象,此代码是从主程序中传入中的引脚对象和非引脚对象建立迭代程序对象

If GroupIterator <> Nil Then //如果组迭代程序对象建立成功

Begin

Partslist.Add('Part Object Information: Library Reference = ' +

StrPas(APart.LibReference) +

' Designator = ' + GetStringFromTextObject(APart.PartDesignator));

//把元件对象的属性“库参照”(LibReference)和“元件流水号”(PartDesignator)和说明字符串一起加到Partslist列表中,作为一行字符串。

Partslist.Add('Pins of this part object:');

Primitive := SchAPI_GetFirstGroupObject(GroupIterator);

//查找第一个组对象。

//以下代码对引脚对象中具体的每一根引脚线进行查询,并把其坐标值放到列表中。

While Primitive <> Nil Do //循环查找引脚对象,直到找完。

Begin

If SchAPI_GetObjectIDFromObjectHandle(Primitive) = ePin Then

//SchAPI_GetObjectIdFromObjectHandle函数通过给定对象句柄参数据返回原理图对象的ID,如果ID是ePin,即表明是引脚对象。

Begin

Handle := SchAPI_ReplicatePartItem(Primitive,APart.Objecthandle);

//根据元件对象句柄和引脚图元对象的句柄返回引脚对象句柄。必须通过单独建立引脚对象方式取得引脚的属性,不能用引用对象句柄直接从元件中读取。

Pin := TSchPin.Create(Handle);//建立一个新的引脚对象。

Pin.Querydatabase(eGetState);//同步数据库。

Partslist.Add('Pin located at(x=' + IntToStr(Pin.LocationX) +

' ,y= ' + IntToStr(Pin.LocationY) + ')');

//把引脚对象的位置值加到Partslist列表中

Pin.Free;//释放引脚对象

SchAPI_DestroyPartItem(Handle); //释放引脚对象句柄

End;

Primitive := SchAPI_GetNextGroupObject(GroupIterator);//再查找下一个引脚对象。

End;

SchAPI_DestroyGroupIterator(GroupIterator); //释放组迭代程序对象。

End;

End;

{....................................................................................}

//以下代码是此章节例子的主程序。

Procedure GetPinInformationAboutParts;

Var

CurrentSheet: TObjectHandle;

ComponentHandle : TObjectHandle;

PartContainerList : TObjecthandle;

Iterator: TObjectHandle;

PartHandle: TObjectHandle;

I, PartCount: Integer;

SchPart : TSchPart;

F : TextFile;

S : TString;

CurrentSheetEntity: ClientTypes.TObjecthandle;

Begin

If MessageRouter_GetState_WindowKind(SchAPI_GetCurrentEditorWindow) <> 'Sch' Then Exit;

//检查当前的文档类型是否是Sch,即原理图,如果不是则退出。

//SchAPI_GetCurrentEditorWindow是返回当前文档对象的窗体句柄。

//MessageRouter_GetState_WindowKind函数使用编辑器窗体句柄返回表示编辑器窗体类型的字符串值。例如,Advanced PCB 编辑器返回“PCB”字符串,并且TextEdit服务器返回“TEXT” 字符串。

CurrentSheet := SchAPI_GetCurrentSheetHandle;//取当前原理图文档的句柄。

Iterator := SchAPI_CreateIterator(CurrentSheet,ePart);

//创建元件对象迭代程序,对元件对象进行搜索。

If Iterator <> Nil Then //元件对象迭代程序建立成功。

Begin

Partslist := TStringList.Create;//建立存放取出的信息的列表。

PartHandle := SchAPI_GetFirstObject(Iterator); //查到第一个元件对象。

While PartHandle <> Nil Do //循环查找元件对象,直到找不到为止。

Begin

SchPart := TSchPart.Create(Nil);//建立一个空的元件对象。

SchPart.ObjectHandle := PartHandle;

//把找到的元件对象句柄赋予新建元件对象句柄。

SchPart.Querydatabase(eGetState);

//同步内部数据库和外部数据库,用内部数据刷新外部数据库。

ComponentHandle := SchAPI_GetLibraryComponentHandle(

SchPart.LibReference,kShortStringLength);

//取得当前元件对象所在的库组件对象的句柄。库组件中可能包含超过一个以上的元件对象。

//SchAPI_GetLibraryComponentHandle函数用给定的库引用字符串和字符串的长度参数返回一个元件库组件的句柄。kShortStringLength是常量,为256。此处的库引用字符串是元件的库引用字符串,往往与元件名称一样。SchPart.LibReference是指元件在元件库中的名称。

PartCount := SchAPI_GetLibraryPartCount(ComponentHandle);

//统计当前元件所在的库组件中有多少元件对象,库中可能包含超过一个以上的元件。

//SchAPI_GetLibraryPartCount函数返回给定库组件的元件的数量。如果给定的句柄不是一个组件对象句柄,则返回值为0。即在元件库中查此共有多少子元件,即元件库中包括多少元件(可能元件库中包含两个或两个以上元件)。

For I := 1 To PartCount Do

Begin

PartContainerList := SchAPI_GetLibraryPartContainer(

ComponentHandle,I,eCompDisplayNormal);

//SchAPI_GetLibraryPartContainer函数返回一个库组件容器的句柄,在此库中,每一个组件有三个容器,并且每一个容器保存一个组件元件。参数是此库组件的对象句柄,元件ID和组件显示模式(Normal, DeMorgan and IEEE)。

//此代码返回库组件中的第i个元件(库组件中可能有超过一个以上的元件)的句柄。

IterateInsidePartContainerList(PartContainerList,SchPart);

//对元件中每一个子对象(包括引脚对象和非引脚对象进行处理)

//第一个参数是当前元件库组件库中的某个元件的句柄,第二个参数是当前元件的句柄。

End;

SchPart.Free;//释放新建的元件对象

PartHandle := SchApi_GetNextObject(Iterator);//查下一个元件对象

Partslist.Add('');

End;

SchAPI_DestroyIterator(Iterator);//销毁对象迭代程序对象

Partslist.Add('Report created on '+ DateToStr(Date) + ' ' + TimeToStr(Time));

End;

CurrentSheetEntity :=ClientApi_FindEntityByDataHandle(SchAPI_GetCurrentEditorWindow);

//ClientApi_FindEntityByDataHandle 函数使用一个编辑器窗体句柄来返回查找返回一个实体的句柄。此实体能表现为设计资源管理器编辑器窗体内的一个文档。您能通过使用ClientAPI_QueryEntity 或ClientAPI_QueryDocumentEntity 查询此实体来检查文档类型,名称等等。

ClientApi_GetDocumentEntityAbsoluteAddress(CurrentSheetEntity,S);

//ClientApi_GetDocumentEntityAbsoluteAddress在关联的设计数据文档内获得一个文档实体的绝对地址。

S := ForceFileNameExtension(S, 'TXT');

//ForceFileNameExtension函数用新的扩展名称替代已存在的文件扩展名称。

//产生并且放入文件到当前DDB中

AssignDDB(F,S,'Admin');//在当前DDB中建立输出文件S

Rewrite(F);

Writeln(F,'Schematic Parts Report...');

Writeln(F,'=========================');

Writeln(F,'');

Writeln(F,'');

For I := 0 To PartsList.Count - 1 Do

Writeln(F,PartsList.Strings[I]);

//把列表中数据输出到输出文件S

Writeln(F,'');

CloseFile(F);

Repopulate;//刷新实体对象

Partslist.Free;//释放列表对象

End;

此段代码片段所使用了下列的重要的函数和过程。

MessageRouter_GetState_WindowKind

SchApi_GetFirstIterator

SchAPI_GetCurrentEditorWindow

SchApi_GetNextIterator

SchAPI_GetCurrentSheetHandle

SchApi_CreateGroupIterator

SchAPI_CreateIterator

SchApi_DestroyGroupIterator

SchAPI_GetLibraryComponentHandle

SchApi_GetFirstGroupIterator

SchAPI_GetLibraryPartCount

SchApi_GetNextGroupIterator

SchAPI_GetLibraryPartContainer

Querydatabase

SchApi_CreateIterator

SetState_Parameter

SchApi_DestroyIterator

SchAPI_ReplicatePartItem

SchAPI_DestroyPartItem

这段代码做什么?

在此代码例子中,一个新的具有关于一个原理图图表中的所有元件的信息的文本文档被创建,此文档通过迭代机制提取的所有元件的图元。代码中使用两个迭代程序类型,对象迭代程序和组迭代程序。外循环使用对象迭代程序,迭代程序搜索元件对象,内循环使用组迭代程序,组迭代程序搜索内置在元件对象的图元。

迭代程序句柄被传递到SchAPI_GetFirstIterator函数,SchAPI_GetFirstIterator返回在数据库中第一个发现的元件的句柄,通过SchAPI_GetNextIterator来约束一个While Do语句,SchAPI_GetNextIterator读取下一个元件的句柄,直到没有更多元件被查找到为止。在While Do语句内,每一个查找到的元件有它的容器,被传递到一个组迭代程序,此组迭代程序从此元件对象中读取图元。

在内循环中,组件句柄被使用SchAPI_GetLibraryComponentHandle函数从元件对读取,函数使用元件对象的LibReference字段(即元件在元件库中的名称)和此字段的字符串长度参数。一个元件仅是在库组件的一个表示,唯一的在原理图图表中编辑元件图元的方法是从元件库中获取此组件的句柄。

应用库组件句柄,使用SchAPI_GetLibraryPartCount函数读取子元件的总数。子元件的总数被使用,来重复读取一个库元件中所有的子元件信息,子元件总数循环值被传递到SchAPI_GetLibraryPartContainer函数,SchAPI_GetLibraryPartContainer函数读取子元件对象的容器句柄,一个元件对象有三个容器,一般DeMorgan 和 IEEE,在此例子中,我们仅对一般的元件图形表示感兴趣,因此,eCompDisplayNormal值被随着元件总数和组件句柄传递到SchAPI_GetLibraryPartContainer函数。

容器句柄被分配到SchAPI_CreateGroupIterator,组迭代程序遍历此元件容器来读取图元(元件子项目,每一根引脚)。在每一次组迭代程序处理时,元件的库引用信息(LibReference)和“元件流水号”(PartDesignator)信息被检索并且插入到此文本文档中。查找到的子元件项目(item)的句柄被组迭代程序传递到SchAPI_ReplicatePartItem函数,此SchAPI函数返回子元件项目item(图元)的一个拷贝,由于返回的元件item仅是此元件item的实际图元的一个拷贝,因而,您仅能调用QueryDatabase(eGetState)来检索关于此元件对象的子元件(即引脚)item的参数。eSetState模式将对子元件item不起作用。一旦您完成上子元件item检索完成,确保必须使用SchAPI_DestroyPartItem来回收分配给此图元的内存。

直到SchAPI_GetNextGroupIterator函数找不到更多的子元件item(引脚),内循环结束并且外循环继续,查找更多的元件直到没有更多的元件来被处理。文本文档被使用了由Protel 强大的RTL库提供的AssignDDB函数创建,显示在一个原理图文档中查找到的每一个元件对象的所有引脚位置,您需一个原理图图表的绝对地址来传递到AssignDDB函数,更多信息请参见客户端API章节。

  6.5 删除错误标记例子

这个例子对进程参数进行检查,判断是否从当前原理图图表中或从一个项目中的所有原理图图表中删除错误标记,如果进程的参数为DocumentLevel = ‘Project’(大小写不敏感)将激活服务器来遍历在项目中的所有原理图图表并且删除所有错误标记,如果字符串不是“Project”,那么错误标记仅从当前原理图图表中被删除。

下面这段代码例子功能主要是删除错误标记。是通过对主程序参数块中的参数DocumentLevel进行判断,判断是否为Project,如果Project则对整个项目中所有原理图图表进行处理,否则仅对当前原理图图表进行处理。收集原理图图表的句柄放在AHandleList中,然后调用CollectErrorMarkers程序来对AHandleList中所存放在原理图图表分别进行处理,检索出所有错误标记对象句柄并放在BagOfErrormarkers列表中,最后调用DeleteErrorMarkerObjects删除错误标记对象。

请见SDK例子\SAMPLES\NO3\API\Sch\Complex Error Marker Eraser。

{....................................................................................}

//这段程序是对AhandleList列表所存放的原理图句柄列表分别进行处理,从每一原理图图表中查找错误标记对象,并且把错误标记对象加到BagOfErrorMarkers列表中,再调用DeleteErrorMarkerObjects来删除这些错误标记对象。

Procedure CollectErrorMarkers(AHandleList : TList);

Var

Iterator: TObjecthandle;//迭代程序对象

J : Integer;

CurrentSheet: TObjecthandle;//当前原理图句柄

Errormarker : TSchErrorMarker;//错误标记对象

BagOfErrormarkers : TList;//存放错误标记对象的句柄

//DeleteErrorMarkerObjects过程销毁BagOfErrormarkers列表中存放在要销毁的错误标记对象。

Procedure DeleteErrorMarkerObjects;

Var

I : Integer;

Begin

If BagOfErrorMarkers <> Nil Then

Begin

For I := 0 To BagOfErrormarkers.Count - 1 Do

SchAPI_DestroyObject(BagOfErrorMarkers.Items[I]);

//SchAPI_DestroyObject过程销毁一个指定的原理图对象,此循环销毁BagOfErrormarkers列表中存放在要销毁的错误标记对象。

End;

End;

Begin

//创建一个列表来收集错误标记对象

BagOfErrormarkers := TList.Create;

//对AHandleList列表中所有原理图进行检索,检索出错误标记对象放到BagOfErrorMarkers列表中。

For J := 0 to AHandleList.Count -1Do

Begin

CurrentSheet := AHandleList.Items[J];

//分别取得要处理的原理图句柄,对AhandleList列表中的原理图进行处理,AhandleList中存放要处理的原理图。

Iterator := SchAPI_CreateIterator(CurrentSheet,eErrorMarker);

//创建一个对象迭代程序,用来查找错误标对象。

If Iterator <> Nil Then //迭代程序对象创建成功。

Begin

ErrorMarker:= TSchErrorMarker.Create(Nil);

//创建错误标记对象。

ErrorMarker.Objecthandle := SchAPI_GetFirstObject(Iterator);

//查找第一个错误标记对象,找到后把其句柄给新建立的错误标记对象。

While ErrorMarker.Objecthandle <> Nil Do //如果有错误标记对象。

Begin

ErrorMarker.QueryDatabase(eGetState);

//用内部服务器数据同步外部服务器数据。

BagOfErrorMarkers.Add(ErrorMarker.Objecthandle);

//把错误标记对象句柄加到错误列表标记对象中,以便对进一步处理。

ErrorMarker.Objecthandle := SchApi_GetNextObject(Iterator);

//查找下一个错误标记对象。

End;

SchAPI_DestroyIterator(Iterator);

//销毁迭代程序对象。

End;

End;

If BagOfErrorMarkers.Count > 0 Then DeleteErrorMarkerObjects;

//如果错误标记对象中有超过0的总数,说明收集到错误标记对象,则调用DeleteErrorMarkerObjects过程来在原理图图表中删除这些错误标记。

BagOfErrormarkers.Free;

//列表释放。

End;

{....................................................................................}

//本章节程序的主程序。

Procedure Command_DeleteErrorMarkers(Window : TServerWindow; Parameters : PChar);

var

Value: String;//存放从参数表中检索出的参数值。

J: Integer;

Sheethandle: TObjectHandle;//当前原理图句柄。

HandleList : TList;//存放要处理的原理图句柄。

Begin

If MessageRouter_GetState_WindowKind(SchAPI_GetCurrentEditorWindow) <> 'Sch' Then Exit;

//检查当前的文档类型是否是Sch,即原理图文档,如果不是则退出。

//SchAPI_GetCurrentEditorWindow是返回当前文档对象的窗体句柄。

//MessageRouter_GetState_WindowKind函数使用编辑器窗体句柄返回表示编辑器窗体类型的字符串值。例如,Advanced PCB 编辑器返回“PCB”字符串,并且TextEdit服务器返回“TEXT” 字符串。

//检查进程参数来从一个原理图图表中或项目中删除错误标记。

HandleList := TList.Create;//创建存放要处理的原理图图表的列表。

Value:= '';

GetState_Parameter(Parameters, 'DocumentLevel', Value);

//从参数块“Parameters”中检索“DocumentLevel”参数,找到后放在字符串“Value”中。

If UpperCase(Value) = 'PROJECT' Then //如果参数值是PROJECT,表示对整个项目图表进行。

Begin

SheetHandle := SchAPI_GetCurrentSheetHandle;//取得当前句柄。

For J := 0 to SchAPI_GetDocumentCountInProject(SheetHandle) - 1 Do

HandleList.Add(SchAPI_GetDocumentHandleByIndex(J, SheetHandle, False));

//把整个项目中所有原理图图表中句柄放在列表HandleList中。

//SchAPI_GetDocumentCountInProject函数使用给定的一个原理图文档的句柄返回属于一个项目的子文档数量。

//SchAPI_GetDocumentHandleByIndex使用给定的Index、SchWindow和SetToTop参数返回一个文档的句柄。此函数有三个参数,Index表示一个项目中文档的索引,SchWindow表示一个原理图窗体的对象的句柄,SetToTop设置此文档在其它文档的顶部并且激活。

End

Else HandleList.Add(SchAPI_GetCurrentSheetHandle);

//不是对整个项目处理,而是对当前原理图进行处理。

If HandleList.Count > 0 Then CollectErrorMarkers(HandleList);

//如果在整个项目中有多个原理图或有当前原理图,则调用CollectErrorMarkers(HandleList)来判断这些原理图中是否有错误标记并进行相应的处理。

HandleList.Free;

End;

此段代码片段所使用了下列的重要的函数和过程。

MessageRouter_GetState_WindowKind

SchAPI_GetDocumentCountInProject

SchAPI_GetCurrentEditorWindow

SchAPI_GetDocumentHandleByIndex

GetState_Parameter

Querydatabase

SchAPI_GetCurrentSheetHandle

MessageRouter_SendCommandToModule

这段代码做什么?

过程参数被从设计资源管理器中传递到DeleteErrorMarkers服务器,这种传递参数的能力,表现出了设计资源管理器和它的即插即用服务器具有强大的能力。

这个服务器在设计资源管理器中检查已存在的原理图图表,一旦检查是有效的,全局的变量,如原理图图表总数(Sheet Count)和原理图图表句柄数组被初始化并且和分配值,接着主过程SearchAndCollectErrorMarkers被调用。

在迭代程序循环中,通过把原理图图表句柄分配到存放原理图句柄的列表HandleList中,按索引迭代程序循环变量,也就是说,如果仅有一个原理图图表,那么仅有一个原理图图表句柄被分配到迭代程序函数,否则,对于多个原理图图表,迭代程序将遍历项目中每一个原理图图表,查找并且读取错误标记,把错误标记放到BagOfErrormarkers列表中,一旦所有的原理图图表被处理完成,DeleteErrorMarkerObjects过程将被调用,DeleteErrorMarkerObjects过程从BagOfErrorMarkers列表中,使用SchAPI_DestroyObject函数来删除所有的错误标记。(e-works)

0
相关文章