Flier's Sky

天空,蓝色的天空,眼睛看不到的东西,眼睛看得到的东西

导航

编译 CHM 项目的 API 接口

Posted on 2004-07-08 10:07  Flier Lu  阅读(3177)  评论(7编辑  收藏  举报
编译 CHM 项目的 API 接口

http://www.blogcn.com/user8/flier_lu/index.html?id=1196784&run=.04005F8

    Microsoft 提供的HTML Help Workshop只支持在GUI界面或者使用其自带的HCC.exe程序编译CHM项目文件(.hpp),并不直接提供API供第三方软件使用。而实际上其CHM项目编译器的HHA.DLL中提供了名为HHA_CompileHPP的导出函数,实现了对.hpp的CHM项目文件直接进行编译,并通过两个回调函数通知用户当前编译进度。
 
以下为引用:

   BOOL WINAPI HHA_CompileHHP(PCSTR pszHhpFile, FARPROC pLogString, FARPROC pProgress);
 


     参数pszHhpFile传入要编译的CHM项目工程文件文件(.hhp);pLogString和pProgress分别执行两个回调函数,向用户报告当前编译进度。
 
以下为引用:

   typedef void (CALLBACK *LOGSTRINGPROCA)(PCSTR pszMsg);
   typedef BOOL (CALLBACK *PROGRESSPROCA)(PCSTR pszFile);
 


     使用时只需要载入动态链接库HHA.DLL,并通过函数名字(HHA_CompileHHP)或序号(0x13F)获得函数入口即可。

 btw: CHM的文件格式好些也被搞定了,Code Project上有一个支持Pocket PC 2003的开源CHM阅读器

     下面HHA_CompileHHP的一个Delphi移值版本:

以下为引用:

 unit ChmCompiler;

 interface

 uses
   Windows, SysUtils;

 type
   TChmCompileFunc = function(pszHhpFile: PChar; pLogString: Pointer; pProgress: Pointer): Bool; stdcall;

   TLogMessageEvent = procedure(Msg: string) of object;
   TProgressEvent = function(FileName: string): Boolean of object;

   TChmCompiler = class
   private
     FDll: HMODULE;
     FProc: TChmCompileFunc;

     FOnLogMessage: TLogMessageEvent;
     FOnProgress: TProgressEvent;
   protected
     constructor Create;
   public
     destructor Destroy; override;

     class function Default: TChmCompiler;

     function Compile(FileName: TFileName): Boolean;

     property OnLogMessage: TLogMessageEvent read FOnLogMessage write FOnLogMessage;
     property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
   end;

 implementation

 uses
   ActiveX;

 var
   GChmCompiler: TChmCompiler;

 procedure LogMessageFunc(pszMsg: PChar); stdcall;
 begin
   Assert(Assigned(GChmCompiler));

   if Assigned(GChmCompiler.OnLogMessage) then
     GChmCompiler.OnLogMessage(pszMsg);
 end;

 function ProgressFunc(pszFile: PChar): Bool; stdcall;
 begin
   Assert(Assigned(GChmCompiler));

   if Assigned(GChmCompiler.OnProgress) then
     Result := GChmCompiler.OnProgress(pszFile)
   else
     Result := True;
 end;

 { TChmCompiler }

 constructor TChmCompiler.Create;
 begin
   FDll := SafeLoadLibrary('HHA.DLL');

   if FDll = 0 then RaiseLastOSError;

   FProc := TChmCompileFunc(GetProcAddress(FDll, 'HHA_CompileHHP'));
   //FProc := TChmCompileFunc(GetProcAddress(FDll, PChar($13F)));

   if @FProc = nil then RaiseLastOSError;

   CoInitialize(nil);
 end;

 destructor TChmCompiler.Destroy;
 begin
   CoUninitialize();
   
   FProc := nil;

   if FDll <> 0 then
     Win32Check(FreeLibrary(FDll));

   inherited;
 end;

 class function TChmCompiler.Default: TChmCompiler;
 begin
   if not Assigned(GChmCompiler) then
     GChmCompiler := TChmCompiler.Create;

   Result := GChmCompiler;
 end;

 function TChmCompiler.Compile(FileName: TFileName): Boolean;
 var
   szFileName: PChar;
   LogMessageProc, ProgressProc, CompileProc: Pointer;
   Ret: BOOL;
 begin
   szFileName := PChar(FileName);
   LogMessageProc := @LogMessageFunc;
   ProgressProc := @ProgressFunc;
   CompileProc := @FProc;
   asm
     XOR EAX, EAX
     PUSH EAX
     MOV EAX, ProgressProc
     MOV ECX, LogMessageProc
     MOV EDX, szFileName;
     PUSH EAX
     PUSH ECX
     PUSH EDX
     CALL CompileProc
     MOV Ret, EAX
   end;
   Result := Ret;
 end;

 initialization
   GChmCompiler := nil;

 finalization
   if Assigned(GChmCompiler) then FreeAndNil(GChmCompiler);

 end.