<连载>Protel二次开发从入门到精通
8. 友情提示
8.1 检查编辑器窗体是否为PCB文档类型
然而如果PCB编辑器服务没有安装在设计资源管理器中,并且当一个自定义服务器尝试从PCB编辑器中来请求服务时,设计资源管理器应用程序将会有问题。因而,这里有两个代码片段,您应该在调用任何PCB API前把其插入到您的代码中。
·第一个代码片段检查当前窗体是否是一个PCB文档。
If MessageRouter_GetState_WindowKind(PCBAPI_GetCurrentEditorWindow) <> 'PCB' Then Exit;
//检查当前文档是否是一个印制板文档。
·第二个代码检查当前窗体是否是一个PCB库文档类型。
If MessageRouter_GetState_WindowKind(PCBAPI_GetCurrentEditorWindow) <> 'PCBLIB' Then Exit;
//检查当前文档是否是一个库文档。PcbApi_GetCurrentEditorWindow函数返回文档对象窗体句柄。
·第三个代码片段使用PCB API调用来做一些处理。
If PcbApi_GetCurrentEditorWindow = 0 Then
Begin
ShowMessage('没有PCB文档被在当前设计资源管理器中打开。(No PCB document is currently open in Design Explorer.)');
Exit;
End;
If PcbApi_GetCurrentBoardHandle = 0 Then
Begin
ShowMessage('没有印制板被在当前设计资源管理器中打开。(No PCB is currently open in Design Explorer.)');
Exit;
End;
8.2 产生一个文本文档并且从PCB文档中输出结果
此代码片段使用当前印制板文件名称产生了一个文本文档,把文档扩展名称改为“TXT”,此文本文档报告在PCB文档中查找到的焊盘的数量。
请见SDK例子\SAMPLES\NO4\API\PCB\Generate a Text Document。
{....................................................................................}
Procedure Repopulate;
Var
EntityHandle: TObjectHandle;
BinderHandle: 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 WriteAndEmbedTextFileIntoDDB;
Var
EntityHandle : TObjectHandle;
BinderHandle : TObjectHandle;
BoardHandle: TObjectHandle;
PadHandle: TObjectHandle;
IteratorHandle : TObjectHandle;
PadNumber: Integer;
F: TextFile;
S: TString;
Board: TPCBBoard;
Begin
SetAllPCBProcAddresses;
//SetAllPCBProcAddresses过程初始化并且设置所有PCB编辑器调用。即取得所有AdvPcb.dll中输出的函数和过程的地址指针。
SetAllClientApiProcedures;
//SetAllClientApiProcedures过程初始化并且设置所有客户端API调用。
BoardHandle := PcbApi_GetCurrentBoardHandle;
//PcbApi_GetCurrentBoardHandle函数返回当前在设计资源管理器中的PCB文档的句柄,如果印制板没有找到则返回值是空(nil)。
If BoardHandle = 0 Then
Begin
ShowInfo('没有印制板文档存在…(No PCB document exists...)');
Exit;
End;
PadNumber:= 0;//焊盘数初始值为0
IteratorHandle := PcbApi_CreateIterator(BoardHandle,//印制板句柄。
ePadObject, //要基于的焊盘对象。
eProcessAll,//处理所有层。
eIgnoreLayer);
//PcbApi_CreateIterator函数返回到一个迭代程序对象的对象句柄。创建一个迭代程序对象,在当前PCB文档中处理所有元件对象。
PadHandle := PcbApi_GetFirstObject(IteratorHandle);
//PcbApi_GetFirstObject函数使用给定的迭代程序(iterator)句柄返回第一个发现的PCB对象句柄。此函数在PcbApi_CreateIterator函数后和PcbApi_GetNextObject函数被使用前被立即调用。
While(PadHandle <> 0) Do
Begin
PadNumber := PadNumber + 1;// //查找到的焊盘计数
PadHandle := PcbApi_GetNextObject(IteratorHandle);
//PcbApi_GetNextObject函数使用给定的迭代程序句柄返回下一个查找到的PCB对象的句柄。
End;
PcbApi_DestroyIterator(IteratorHandle);
//PcbApi_DestroyIterator销毁此迭代程序对象。
//以下代码目的是获取当前PCB对象的名称
Board := TPCBBoard.Create(BoardHandle);//创建印制板对象
Board.QueryDatabase(eGetState);//同步数据
//一个印制板实体的抽象的地址扩展名称改变…
S := ForceFileNameExtension(Board.FileName, 'TXT');
//ForceFileNameExtension函数用新的扩展名称替代已存在的文件扩展名称。
Board.Free;
//产生并且放入文件到当前DDB中
AssignDDB(F,S,'Admin');
Rewrite(F);
Writeln(F,'印制板报表(Board Report...)');
Writeln(F,'===========================');
Writeln(F,'');
Writeln(F,'此印制板焊盘数量为(Number of pads on this pcb Board is): ' + IntToStr(PadNumber));
CloseFile(F);
Repopulate;//刷新实体对象
End;
更多有关AssignDDB函数的明细信息请参考客户端API和RTL参考,迭代程序请参见有关迭代程序工作机理章节内容。
8.3 打开想要的文档的程序
如果您想要打开一个指定的文档,但您仅知道设计文档名称,您可以运行这个小规模的附加的服务器,例子在“\SAMPLES\NO2\API\Client\SearchAndOpenDocuments”文件夹下。在您读完客户端API章节后,您将能了解此附加的服务器是如何工作的。
为了使用这个“SearchAndOpen”附加的服务,您只需列出参数“DocumentName1=Value1 | DocumentName2 = Value
8.4 作用域不兼容性
如果您象使用印制板API一样使用客户端API,编译器或许抱怨有不兼容的类型。例如,当您试图在您的源代码中使用客户端API函数“DocumentEntity.QueryDatabase(eGetState)”时,您尝试进行编译,编译器在此误窗体中提示说‘Incompatible types(不兼容的类型).’。
解决方案是使用“DocumentEntity.QueryDatabase(ClientTypes.eGetState);”,这样,编译器就能知道如何解决类型问题。(e-works)