Ниже приведен листинг файла /kylix/source/clx/HelpIntfs.pas, который обеспечивает
необходимые интерфейсы файла справки, а также менеджер файлов.
{ ************************************************************************************************}
{ Kylix и Delphi кросс-платформенная библиотека визуальных компонентов }
{ }
{ Copyright (с) 2000, 2001 Borland Software Corporation }
{ }
{ Этот файл может распространяться и/или модифицироваться в соответствии
с условиями GNU General Public License (GPL) версии 2 }
{ http://www.borland.com/kylix/gpl.html. }
{ }
{ Файл лицензии license.txt прилагается к составу данного программного
обеспечения. }
{ }
{*************************************************************************************************}
unit Helplntfs;
{ ************************************************************************************************}
{ }
{ Этот модуль является главным для различных справочных систем VCL/CLX }
{ TApplication содержит указатель на интерфейс IHelpSystem, через }
{ который обеспечиваются вызовы менеджера помощи. Менеджер помощи }
{ содержит список программ, обеспечивающих показ файлов справки, и }
{ реализует поддержку интерфейса ICustomHelpViewer. Программы для }
{ просмотра файлов справки взаимодействуют с менеджером помощи через }
{ интерфейс IHelpManager. }
{ }
{ Такой же механизм применяется при разработке пакетов, которые }
{ интегрируются в систему помощи IDE; вызов HelpIntfs.RegisterViewer(} }
{ внутри процедуры Register() вызовет регистрацию просмотрщика. }
{ }
{*************************************************************************************************}
interface
uses SysUtils, Classes;
type
{ IHelpSelector. IHelpSelector используется системой помощи для того, чтобы
узнать у приложения, какие ключевые слова оно поддерживает. }
IHelpSelector = interface(Ilnterface)
['{BOFC9358-5FOE-11D3-A3B9-OOC04F79AD3A}']
function SelectKeyword(Keywords: TStrings) : Integer;
function TableOfContents(Contents: TStrings); Integer; end;
{ IHelpSystem. IHelpSystem - это интерфейс, с помощью которого приложение
посылает запрос об отображении файла справки. ShowHelp() использует
функциональность, которая гарантированно поддерживается всеми
программами для просмотра файлов справки. ShowContextHelp() и
ShowTopicHelp() поддерживаются только расширенными просмотрщиками
файлов справки. В случае, когда расширенные просмотрищики не
установлены, ShowTableOfContents запрашивает систему об отображении
содержания файла справки и показывает окно диалога, с помощью которого
пользователь может выбрать один из просмотрщиков. Если ни один из
установленных просмотрщиков не поддерживает отображение содержания,
генерируется исключительная ситуация EHelpSystemException. Hook () представляет
собой механизм, с помощью которого приложение запрашивает
систему помощи для упаковки специфичных winhelp-команд в команды,
которые понимают установленные просмотрщики файлов справки.}
IHelpSystem = interface(Ilnterface)
['{BOFC9353-5FOE-11D3-A3B9-OOC04F79AD3A}']
procedure ShowHelp(const HelpKeyword, HelpFileName: String);
procedure ShowContextHelp(const ContextID: Longint; const HelpFileName: String);
procedure ShowTableOfContents;
procedure ShowTopicHelp(const Topic, HelpFileName: String);
procedure AssignHelpSelector(Selector: IHelpSelector);
function Hook(Handle: Longint; HelpFile: String; Comand: Word; Data: Longint):
Boolean;
end;
{ ICustomHelpViewer. Справочная система взаимодействует с просмотрщиками
файлов справки с помощью данного интерфейса. В случае, когда в системе
зарегистрировано более одного просмотрщика, справочная система вызывает
функцию UnderstandsKeyword() для каждого из них. Данная функция
возвращает число доступных ключевых слов. В случае, когда более чем один
просмртрщик может работать с нужными ключевыми словами, эти
просмотрщики запрашиваются на список поддерживаемых ключевых строк
с помощью метода GetHelpStrings();
менеджер помощи предлагает пользователю выбрать один из просмотрщиков
и затем вызывает метод ShowHelpO только для выбранной пользователем
программы просмотра файлов помощи. Во время регистрации менеджер
помощи вызывает метод NotifylD для того, чтобы присвоить просмотрщику
уникальный номер. В случае, когда связь с просмотрщиком по каким-либо
причинам оборвалась, вызывается метод Release () и менеджеру помощи будет
передан этот номер. Если менеджер помощи сам разрывает связь, будет
вызван метод ShutDown() для всех просмотрщиков. Если менеджер помощи
получает просьбу о завершении работы всех просмотрщиков помощи, он
вызывает метод SoftShutDown() для всех просмотрщиков. }
ICustomHelpViewer = interface(Ilnterface)
['{BOFC9364-5FOE-11D3-A3B9-OOC04F79AD3A}']
function GetViewerName : String;
function UnderstandsKeyword(const HelpString: String): Integer;
function GetHelpStrings(const HelpString: String): TStringList;
function CanShowTableOfContents : Boolean;
procedure ShowTableOfContents;
procedure ShowHelp(const HelpString: String);
procedure NotifylD(const ViewerlD: Integer);
procedure SoftShutDown;
procedure ShutDown;
end;
lExtendedHelpViewer = interface(ICustomHelpViewer)
['{BOFC9366-5FOE-11D3-A3B9-OOC04F79AD3A}']
function UnderstandsTopic(const Topic: String): Boolean;
procedure DisplayTopic(const Topic: String);
function UnderstandsContext(const ContextID: Integer;
const HelpFileName: String): Boolean;
procedure DisplayHelpByContext(const ContextID: Integer;
const HelpFileName: String);
end;
ISpecialWinHelpViewer = interface(lExtendedHelpviewer)
['{BOFC9366-5FOE-11D3-A3B9-OOC04F79AD3A}']
function CallWinHelpfHandle: Longlnt; const HelpFile: String; Command:
Word;
Data: Longlnt): Boolean;
end;
IHelpManager = interface
['{BOFC9366-5FOE-11D3-A3B9-OOC04F79AD3A}']
function GetHandle: Longlnt; { sizeof(Longlnt) = sizeof (HWND) }
function GetHelpFile: String;
procedure Release(const ViewerlD: Integer);
end;
EHelpSystemException = class (Exception);
function RegisterViewer(newViewer: ICustomHelpViewer;
out Manager: IHelpManager): Integer;
function GetHelpSystem(out System: IHelpSystem) : Integer;
{$IFDEF LINUX}
const
HELP_CONTEXT = 1;
HELP_QUIT = 2;
HELP_INDEX = 3;
HELP_CONTENTS = HELP_INDEX;
HELP_HELPONHELP = 4;
HELP_SETINDEX = 5;
HELP__SETCONTENTS = HELPJ3ETINDEX;
HELP_CONTEXTPOPUP = 8;
HELP_FORCEFILE = 9;
HELP_CONTEXTMENU = 10;
HELP_FINDER =11;
HELP_WM_HELP = 12;
HELP_SETPOPUP__POS = 13;
HELP_TCARD_OTHER_CALLER = 17;
HELP__KEY = 257;
HELP_COMMAND = 258;
HELP^PARTIALKEY = 261;
HELP^MULTIKEY = 513;
HELP_SETWINPOS = 515;
HELPJICARD_DATA = $10;
HELP TCARD = $8000;
{$ENDIF}
implementation
($IFDEF MSWINDOWS}
uses Contnrs, Windows, RTLConsts;
{$ENDIF}
{$IFDEF LINUX}
uses Libc, Contnrs, RTLConsts;
{$ENDIF}
type
THelpViewerNode = class(TObject)
private
FViewer: ICustomHelpViewer;
FViewerlD: Integer;
public
constructor Create(Viewer: ICustomHelpViewer);
property Viewer: ICustomHelpViewer read FViewer;
property ViewerlD : Integer read FViewerlD write FViewerlD;
end;
THelpManager = class(TInterfacedObject, IHelpSystem, IHelpManager)
private
FHelpSelector: IHelpSelector;
FViewerList: TObjectList;
FExtendedViewerList: TObjectList;
FSpecialWinHelpViewerList: TObj ectList;
FMinCookie : Integer;
FHandle: Longlnt;
FHelpFile: String;
procedure UnloadAllViewers;
procedure DoSoftShutDown;
procedure DoTableOfContents;
function CallSpecialWinHelp(Handle: Longlnt; const HelpFile: String;
Command: Word; Data: Longlnt): Boolean;
public
constructor Create;
function RegisterViewer(newViewer: ICustomHelpViewer): IHelpManager;
{ IHelpSystem }
procedure ShowHelp(const HelpKeyword, HelpFileName: String );
procedure ShowContextHelp(const ContextID: Longint;
const HelpFileName: String);
procedure ShowTableOfContents;
procedure ShowTopicHelp(const Topic, HelpFileName: String);
procedure AssignHelpSelector(Selector: IHelpSelector);
function Hook(Handle: Longint; HelpFile: String;
Command: Word; Data: Longint) : Boolean;
{ IHelpManager }
function GetHandle: Longint;
function GetHelpFile: String;
procedure Release(const ViewerlD: Integer);
property Handle : Longint read FHandle write FHandle;
property HelpFile : String read FHelpFile write FHelpFile;
destructor Destroy; override;
end;
var
HelpManager : THelpManager;
function RegisterViewer(newViewer: ICustomHelpViewer;
out Manager: IHelpManager): Integer;
begin
if not Assigned(HelpManager) then
HelpManager := THelpManager.Create;
Manager := HelpManager.RegisterViewer(newViewer);
Result := 0;
end;
function GetHelpSystem(out System : IHelpSystem) : Integer;
begin
if not Assigned(HelpManager) then
HelpManager := THelpManager.Create;
System := HelpManager as IHelpSystem;
System._AddRef;
Result := 0;
end;
{ THelpViewerNode }
constructor THelpViewerNode.Create(Viewer: ICustomHelpViewer);
begin
FViewer := Viewer;
Viewer._AddRef;
end;
{ THelpManager }
constructor THelpManager.Create;
begin
inherited Create;
FViewerList := TObjectList.Create;
FExtendedViewerList := TObjectList.Create;
FSpecialWinHelpViewerList := TObjectList.Create;
FHelpFile :=
FMinCookie := I;
end;
function THelpManager.RegisterViewer(NewViewer: ICustomHelpViewer): IHelpManager;
var
ExtendedViewer: lExtendedHelpViewer;
SpecialViewer: ISpecialWinHelpViewer;
NewNode: THelpViewerNode;
begin
NewNode := THelpViewerNode.Create(NewViewer);
NewNode.ViewerlD := FMinCookie;
FViewerList.Insert(FViewerList.Count, NewNode);
NewViewer.NotifylD(NewNode.ViewerlD);
if Supports(NewViewer, lExtendedHelpViewer, ExtendedViewer) then
begin
NewNode := THelpViewerNode.Create(ExtendedViewer);
NewNode.ViewerlD := FMinCookie;
FExtendedViewerList.Insert(FExtendedViewerList.Count, NewNode);
end;
if Supports(NewViewer, ISpecialWinHelpViewer, SpecialViewer) then
begin
NewNode := THelpViewerNode.Create(SpecialViewer);
NewNode.ViewerlD := FMinCookie;
FSpecialWinHelpViewerList.Insert(FSpecialWinHelpViewerList.Count, NewNode);
end;
FMinCookie := FMinCookie + 1;
Result := Self as IHelpManager;
end;
procedure THelpManager.UnloadAllViewers;
var
I: Integer;
begin
for I:=0 to FViewerList.Count-1 do
begin
THelpviewerNode(FviewerList[I]).Viewer.ShutDown;
end;
FviewerList.Clear;
FExtendedViewerList.Clear;
FSpecialWinHelpViewerList.Clear;
end;
procedure THelpManager.DoSoftshutDown;
var
I : Integer;
begin
for I := 0 to FviewerList.Count-1 do
begin
THelpviewerNode(FviewerList[I]).Viewer.SoftshutDown;
end;
end;
procedure THelpManager.DoTableOfContents;
var
ViewerNames : TStringList;
I : Integer;
HelpNode : THelpviewerNode;
begin
if FviewerList.Count = 1 then
begin
if THelpviewerNode(FViewerList[0]).Viewer.CanShowTableOfContents then
THelpviewerNode(FViewerList[0]).Viewer.ShowTableOfContents;
end
else if FHelpSelector <> nil then
begin
ViewerNames := TStringList.Create;
try
for I := 0 to FViewerList.Count -1 do
begin
HelpNode := THelpviewerNode(FViewerList[I]);
if HelpNode.Viewer.CanShowTableOfContents then
ViewerNames.AddObject(HelpNode.Viewer.GetviewerName, TObject(HelpNode)) ;
end;
if ViewerNames.Count > 1 then
begin
ViewerNames.Sort;
I := FHelpSelector.TableOfContents(ViewerNames);
THelpviewerNode(ViewerNames.Objects[I]).Viewer.ShowTableOfContents;
end
else begin
THelpviewerNode(ViewerNames.Obj ects[0]).Viewer.ShowTableOfContents;
end;
finally
ViewerNames.Free;
end;
end
else if (FViewerList.Count > 0) and
(THelpviewerNode(FViewerList[0]).Viewer.CanShowTableOfContents) then
begin
THelpviewerNode(FViewerList[0]).Viewer.ShowTableOfContents;
end
else raise EHelpSystemException.CreateRes(ShNoTableOfContents) ;
end;
function THelpManager.CallSpecialWinHelp(Handle: Longlnt;
const HelpFile: String;
Command: Word ;
Data: Longlnt): Boolean;
var
View : ICustomHelpViewer;
begin
Result := false;
if FSpecialWinHelpViewerList.Count > 0 then
begin
if FSpecialWinHelpViewerList.Count = 1 then
begin
View := THelpviewerNode(FSpecialWinHelpViewerList[0]).Viewer;
Result := (View as ISpecialWinHelpViewer).CallWinHelp(Handle, HelpFile, Command,
Data);
end else
begin
View := THelpviewerNode(FSpecialWinHelpViewerList[0]).Viewer;
Result := (View as ISpecialWinHelpViewer).CallWinHelp(Handle, HelpFile, Command,
Data);
end;
end;
end;
{ THelpManager - IHelpSystem }
procedure THelpManager.ShowHelp(const HelpKeyword, HelpFileName :
String);
var
I, J: Integer;
AvailableHelp: Integer;
HelpfulViewerCount : Integer;
Viewerlndex: Integer;
AvailableHelpList: TStringList;
ViewerHelpList: TStringList;
HelpNode : THelpViewerNode;
Keywordlndex : Integer;
Obj: TObject;
ObjString: String
begin
Viewerlndex := 0;
HelpfulViewerCount := 0;
if HelpFileName <> '' then
HelpFile := HelpFileName;
if FViewerList.Count > 0 then
begin
for I := 0 to (FViewerList.Count - 1) do
begin
AvailableHelp := THelpViewer-
Node (FViewerList[I]).Viewer.UnderstandsKeyword(HelpKeyword);
if AvailableHelp > 0 then
begin
Viewerlndex := I;
HelpfulViewerCount := HelpfulViewerCount + 1;
end;
end;
if HelpfulViewerCount = 0 then
raise EHelpSystemException.CreateResFmt(ShNothingFound,
[PChar(HelpKeyword)]);
if HelpfulViewerCount = 1 then
begin
THelpViewerNode(FViewerList[Viewerlndex]).Viewer.ShowHelp(HelpKeyword);
end;
if HelpfulViewerCount > 1 then
begin
AvailableHelpList := TStringList.Create();
for I := 0 to FViewerList.Count -1 do
begin
HelpNode := THelpViewerNode(FViewerList[I]) ;
AvailableHelp := HelpNode.Viewer.UnderstandsKeyword(HelpKeyword);
if AvailableHelp > 0 then
begin
ViewerHelpList := HelpNode.Viewer.GetHelpStrings(HelpKeyword);
for J := 0 to ViewerHelpList.Count - 1 do
begin
AvailableHelpList.Addobject(ViewerHelpList.Strings[J], TOb-ject(HelpNode));
end;
ViewerHelpList.Free;
end;
end;
if FHelpSelector <> nil then
begin
AvailableHelpList.Sort;
Keywordlndex := FHelpSelector.SelectKeyword(AvailableHelpList);
if Keywordlndex >= 0 then begin
Obj := AvailableHelpList.Objects[Keywordlndex];
ObjString := AvailableHelpList.Strings[Keywordlndex]; THelpViewerNode(Obj).Viewer.ShowHelp(ObjString);
end;
end
else begin
Obj := AvailableHelpList.Objects[0];
ObjString := AvailableHelpList.Strings[0]; THelpViewerNode(Obj).Viewer.ShowHelp(ObjString);
end;
AvailableHelpList. Free
end;
end;
end;
procedure THelpManager.ShowContextHelp(const ContextID: Longint; const HelpFileName:
String);
var
I : Integer;
View: ICustomHelpViewer;
begin
if FExtendedViewerList.Count = 0 then
raise EHelpSystemException.CreateRes(ShNoContext)
else begin
for I := 0 to FExtendedViewerList.Count -1 do
begin
View := THelpviewerNode(FExtendedViewerList[I]).Viewer;
if (View as lExtendedHelpviewer).UnderstandsContext(ContextID, HelpFileName
) then
begin
(View as lExtendedHelpviewer).DisplayHelpBycontext(ContextID, HelpFileName)
;
break;
end;
end;
end;
end;
procedure THelpManager.ShowTableOfContents;
begin
DoTableOfContents;
end;
procedure THelpManager.ShowTopicHelp(const Topic, HelpFileName: String);
var
I: Integer;
View: ICustomHelpViewer;
begin
if FExtendedViewerList.Count = 0 then
raise EHelpSystemException.CreateRes(ShNoTopics)
else begin
for I := 0 to FExtendedViewerList.Count - 1 do
begin
View := THelpviewerNode(FExtendedViewerList[I]).Viewer;
if (View as lExtendedHelpviewer).UnderstandsTopic(Topic) then
begin
(View as lExtendedHelpviewer).DisplayTopic(Topic);
break;
end;
end;
end;
end;
procedure THelpManager.AssignHelpSelector(Selector: IHelpSelector)
begin
if FHelpSelector <> nil then FHelpSelector := nil;
FHelpSelector := Selector;
Selector._AddRef;
end;
function THelpManager.Hook(Handle: Longint; HelpFile: String;
Command: Word; Data: Longint): Boolean;
begin
case Command of
HELP_CONTEXT:
begin
ShowContextHelp(Data, HelpFile);
end;
HELP_CONTEXTPOPUP:
begin
ShowContextHelp(Data, HelpFile);
end;
HELP_QUIT:
begin
DoSoftShutDown;
end;
HELP_CONTENTS:
begin
FHelpFile := HelpFile;
DoTableOfContents;
end;
else
CallSpecialWinHelp(Handle, HelpFile, Command, Data) ;
end;
Result := true;
end;
{ THelpManager --- IHelpManager }
function THelpManager.GetHandle: Longint;
begin
Result := Handle;
end;
function THelpManager.GetHelpFile: String
begin
Result := HelpFile;
end;
procedure THelpManager.Release(const ViewerlD: Integer);
var
I : Integer;
begin
for I := 0 to FViewerList.Count-1 do
begin
if THelpviewerNode(FViewerList[I]).ViewerlD = ViewerlD then FViewerList.Delete
(I);
end;
for I := 0 to FExtendedViewerList.Count-1 do
begin
if THelpviewerNode(FExtendedViewerList[I]).ViewerlD = ViewerlD then FExtendedViewerList.Delete(I);
end;
for I := 0 to FSpecialWinHelpViewerList.Count-1 do
begin
if THelpviewerNode(FSpecialWinHelpViewerList[I]).ViewerlD = ViewerlD then FSpecialWinHelpViewerList.Delete(I)
;
end;
end;
destructor THelpManager.Destroy;
begin
if FHelpSelector <> nil then FHelpSelector := nil;
inherited Destroy;
end;
initialization
finalization
if HelpManager <> nil then
begin
HelpManager.UnloadAllViewers;
end;
end.