首页  编辑  

合并CHM和从CHM中抽取HHC文件名

Tags: /超级猛料/Format.格式,单位/File.文件格式/   Date Created:

How to extract .HHC filename from .chm file.

Copyright (C) Kingon, 2007

如果要合并CHM文件,一种方式是针对多个CHM文件生成一个总的索引,这个索引中管理了所有的CHM文件,可以支持全文检索,目录结构;另外一种方式是反编译CHM,然后把所有的反编译的CHM文件的结果文件重新编译一次,生成新CHM文件。第一种方式速度快,但缺点是必须分发新的CHM文件和老的CHM文件,第二种方式优点是只要分发一个文件,可以独立原来的chm文件,缺点是速度慢。

采用第一个方式合并CHM的时候,需要从每个CHM中抽取其hhc文件名并用Merge方式合并到新的hhc当中,请参考附件的hhc和hhp文件。

下面的代码可以抽取CHM中的HHC文件名:

function ExtractHHCFileNameFromCHM(const CHMFileName: string): string;

var

 ItsStorage: IItsStorage;

 storage: IStorage;

 Stream: IStream;

 Positon, Size: Largeint;

 R : LongInt;

 Buff: PChar;

 p : PChar;

begin

 // [2007-2-13]Kingron: 创建流对象

 OleCheck(CoCreateInstance(CLSID_ITStorage, nil, CLSCTX_INPROC_SERVER, IID_ITStorage, ItsStorage));

 OleCheck(ItsStorage.StgOpenStorage(PWideChar(WideString(CHMFileName)), nil, STGM_READ or STGM_SHARE_DENY_WRITE, nil, 0, storage));

 OleCheck(Storage.OpenStream('#STRINGS', nil, STGM_READ or STGM_SHARE_EXCLUSIVE, 0, Stream));

 // [2007-2-13]Kingron: 提取#STRINGS整个数据的大小

 Stream.Seek(0, soFromEnd, Positon);

 Size := Positon;

 // [2007-2-13]Kingron: 重新定位到开头

 Stream.Seek(0, soFromBeginning, Positon);

 // [2007-2-13]Kingron: 申请内存并读取到缓冲区

 GetMem(Buff, Size);

 try

   Stream.Read(PChar(Buff), Size, @R);

   // [2007-2-13]Kingron: 提取HHC信息,HHC是第3个字符串

   R := 0;

   p := Buff;

   while R < 3 do

   begin

     if p^ = #0 then Inc(R);

     Inc(P);

   end;

   Result := StrPas(p);

 finally

   FreeMem(Buff);

 end;

end;

注意处理没有HHC的情况

没有HHC,需要结合其他的数据来处理的。

CHM有一些格式,可以参考网络上面的相关文档。

推荐hhcode.zip,可以去yahoo下载相关代码,其中Example 10,就可以提取CHM中的数据,非常有用,上面的代码也是参考了它的。

http://tech.groups.yahoo.com/group/DelphiHHKit/files/