课程设计-CHM电子书生成软件制作实例
发布时间:2011-03-16 00:31:12
发布时间:2011-03-16 00:31:12
CHM电子书生成软件制作实例
CHM格式的电子书是网上用得比较多的一种,特别是计算机类的电子书几乎都用CHM格式。CHM格式的电子书简单易用,只要是Windows 98以上的操作系统都能直接使用,免去了安装阅读器的麻烦。同时CHM格式已经成为微软产品的标准帮助文件格式,而且不少基于Windows平台的软件也适用该格式作为其帮助文件的格式。所以,CHM格式已经相当普及。
电子书有两个要素,第一点是电子书本身的格式,第二点就是电子书的阅读器。CHM格式的电子书也不例外。CHM格式其实是对 HTML文件打包并压缩的结果。CHM格式的创始者微软提供了一个将HTML文件编译成CHM文件的免费软件hhc.exe,这样CHM的第一个要素就得到了解决。同时Windows 98以上的操作系统都提供了CHM文件的阅读软件hh.exe。hh.exe是Windows操作系统的一部分,这就是CHM格式的文件可以在Windows平台间流传而不需要专门阅读器的原因。
既然微软提供了现成的编译器,那就从它入手来研究CHM生成软件的开发。
首先,我们来看一下CHM文件有哪些元素。如图所示。
图CHM文件的元素
从上图可知,一个CHM文件需要标识三个部分:工具栏,控制面板,和文件显示。那么怎样才能在生成的CHM文件里表示这些元素呢?这就需要了解微软免费软件hhc.exe的用法了。
hhc.exe可以直接编译HTML或HTM格式的文件,但这样生成的CHM文件只有文件显示区,不能实现CHM文件的所有功能。hhc.exe更多的是编译扩展名为hhp的工程文件,该文件就是在总体上标识CHM文件的各元素的关键所在。同时配合扩展名为hhc的主体文件与扩展名为hhk的索引文件就能实现CHM文件的所有元素。
下面将具体解析三种文件的格式。
1)工程文件*.hhp。
工程文件由[OPTIONS],[WINDOWS],[FILES],[INFOTYPES],[MERGE FILES]等几个部分组成。其中[OPTIONS],[WINDOWS]和[FILES]三个部分是主要部分,其余部分一般不用,所以这里只讨论这三部分。
● [OPTIONS]
[OPTIONS]部分描述的是整个工程的宏观信息,它的格式比较固定,它是由许多选项组成的,一般组成如下:
[OPTIONS]
Compatibility=1.1 or later
Compiled file=D:\MYCHM\pp\test.chm
Contents file=test.hhc
Default Window=main
Default topic=D:\MYCHM\pp\042.htm
Default font=幼圆,14,134面板的tag显示字体,大小,语种
Display compile progress=No
Binary Index=Yes
Binary TOC=Yes
Enhanced decompilation=Yes
Flat=Yes
Full-text search=Yes
Index file=test.hhk
Language=0x804 中文(中国)
上面的每一项占据一行,等号左边是每一项的名称,等号右边是每一项的值。
其中每一项的具体意义如下
项目名称 | 项目意义 |
Compatibility | 版本的兼容性,一般为固定值 “1.1 or later” |
Compiled file | 编译后的文件名称及所在目录 |
Contents file | 生成目录所用的目录文件的名称及所在目录 |
Default Window | 描述CHM文件窗体样式的窗体文件名,在[WINDOWS]部分会用到。 |
Default topic | CHM文件启动时首页文件的名称及所在目录 |
Display compile progress | 是否显示编译进程 |
Full-text search | 是否支持全文检索 |
Index file | 生成索引所用的索引文件的名称及所在目录 |
Default font | 控制面板中目录或索引显示的字体,大小及所用的字符集 |
Binary Index | 表示是否创建二进制索引 |
Binary TOC | 表示是否创建二进制目录 |
Enhanced decompilation | 表示是否支持增强反编译 |
Flat | “Yes”表示编译文件中不保存目录信息 |
Language | CHM文件所用的语言 |
● [WINDOWS]
[WINDOWS]部分描述的是CHM文件的窗体样式。这一部分是整个工程文件中最为繁琐也是最为关键的一项,它决定了CHM文件是否能按照正常的方式显示。下面我们就来看看它的结构。
[WINDOWS]部分由一个等式组成。等式的左边是窗体名称,即上面所提到的Default Window的值,等式的右边是由一长串用逗号隔开的值,具体样子如下:
main = "","","","","","","","","", ,, , , , ,,,,,0
可见等式右边是由19个逗号隔开的20个参数。其中前九个参数比较简单其意义如下:
参数位置 | 参数意义 |
1 | chm文件的标题。 |
2 | 目录文件的路径与名称。 |
3 | 索引文件的路径与名称。 |
4 | CHM文件启动时首页文件的名称及所在目录 |
5 | CHM文件主页文件的名称及所在目录 |
6 | 跳转按钮1对应的文件名及所在目录。 |
7 | 跳转按钮1的标题。 |
8 | 跳转按钮2对应的文件名及所在目录。 |
9 | 跳转按钮2的标题。 |
第十个参数表示的是chm控制面板的样式。下表中每一个选项对应一个值,如果要选择多个选项只要把它们对应的值相加再赋给参数就可以了,下面碰到的类似问题都这样解决。该参数的具体意义如下:
面板选项意义 | 对应值 |
初值(表示具有“目录”与“搜索”两项) | 0x20 |
添加搜索项 | 0x400 |
添加高级项 | 0x20000 |
添加书签项 | 0x1000 |
自动显示/隐藏面板 | 0x1 |
隐藏工具栏 | 0x40 |
记录位置和大小 | 0x40000 |
同步 | 0x100 |
第十一个参数表示面板宽度,用十进制数表示。
第十二个参数表示工具栏按钮的定制具体意义如下:
工具栏选项意义 | 对应值 |
初值 | 0x0 |
“隐藏/显示”按钮 | 0x2 |
“后退”按钮 | 0x4 |
“前进”按钮 | 0x8 |
“停止”按钮 | 0x10 |
“刷新”按钮 | 0x20 |
“主页”按钮 | 0x40 |
“字体”按钮 | 0x100000 |
“打印”按钮 | 0x2000 |
“选项”按钮 | 0x1000 |
“定位”按钮 | 0x800 |
“自定义1”按钮 | 0x40000 |
“自定义2”按钮 | 0x80000 |
“”按钮 | |
第十三个参数表示窗体大小与位置,其具体的格式是:[ddd1,ddd2,ddd3,ddd4]。这四个参数都是十进制数字,并且宽度步超过3位。四个参数的具体意义如下:
ddd1 | CHM文件左上角到桌面左边框的距离,单位为像素 |
ddd2 | CHM文件左上角到桌面上边框的距离,单位为像素 |
ddd3 | CHM文件右下角到桌面左边框的距离,单位为像素 |
ddd4 | CHM文件右下角到桌面上边框的距离,单位为像素 |
第十四个参数表示窗体样式,具体意义如下:
窗体样式意义 | 对应值 |
最小化按钮 | 0x10000 |
最大化按钮 | 0x20000 |
厚框架 | 0x40000 |
系统菜单 | 0x80000 |
水平滚动条 | 0x100000 |
垂直滚动条 | 0x200000 |
对话框框架 | 0x400000 |
边框宽度 | 0x800000 |
最大化 | 0x1000000 |
有子窗口 | 0x2000000 |
有同级窗口 | 0x4000000 |
失效 | 0x8000000 |
可视 | 0x10000000 |
最小化 | 0x20000000 |
子窗口(使弹出失效) | 0x40000000 |
弹出(使子窗口失效) | 0x80000000 |
迭交(使最小化有效)或空 | 0x0 |
第十五个参数表示窗体的扩展样式,具体意义如下:
窗体扩展样式意义 | 对应值 |
不通知父母 | 0x4 |
始终最上 | 0x8 |
接受文件 | 0x10 |
透明 | 0x20 |
工具窗口 | 0x80 |
客户区边框 | 0x200 |
上下文帮助 | 0x400 |
右对齐文本 | 0x1000 |
右到左阅读顺序 | 0x2000 |
左滚动条 | 0x4000 |
控制父窗口 | 0x10000 |
静态边框 | 0x20000 |
第十六个参数一般为空。
第十七个参数指示打开时面板是否关闭,若值为1表示启动时面板关闭,否则值为空。
第十八个参数表示启动时控制面板的默认面板。
目录 | 空值 |
索引 | 1 |
第十九个参数表示控制面板上的各面板标题的位置
在上边 | 空值 |
在左边 | 0x1 |
在下面 | 0x2 |
第二十个参数一般为0。
● [FILES]
[FILES]部分最为简单,其下列出了所要编译的全部文件名称及所在目录。
2)目录文件*.hhc
先来看一个目录文件的实例
从上可以看出,目录文件与html文件十分相似,它其实就是一个对象列表文件。第一个对像是:
其中参数"Window Styles"描述的是目录文件的目录树在显示时的样式。具体书值如下:
参数值 | 意义 |
0x0 | 无效果 |
0x20 | 显示选择 |
0x200 | 轨迹 |
0x600 | 链接效果 |
0x1 | 显示[+][-],[+]代表目录下有文件,[-]相反 |
0x2 | 显示虚线,(该选项使“行选”无效) |
0x4 | 显示根 |
0x400 | 展开 |
0x1000 | 行选,(该选项使“显示虚线”无效) |
如果要修改目录文件显示的前景色,背景色,以及字体则要添加下面三个属性:
同时还可以通过添加下面三个属性来指定自己的图标,图标宽度,图标背景色以代替系统图标。
从第二个对象开始,描述的是目录项所对应的文件。它一般有两个参数,PARAM NAME="Name" 和PARAM NAME="Local"。第一个参数对应目录的名称,第二个文件则对应所指向的文件路径。如果要定制目录树节点上的图表,则还要增加一个参数PARAM NAME= "ImageNumber",它的值是从1到42的任意一个数字,每一个数字代表一种图标。
将这些参数设置好之后,只要将所有的文件对象按照html语言的无序列标排列就形成了目录文件。
3)索引文件*.hhk
索引文件和目录文件的格式几乎一样,只是少了第一个对象,同时对象不支持参数PARAM NAME= "ImageNumber"。因为一般情况下索引文件没有对应的目录树显示效果,并且索引的显示也不含图标。
有了上面的知识基础,我们就可以来构建具体的编译软件了。
由于Delphi在开发Windows程序时相当方便,所以我这里就用Delphi6.0作为软件开发工具。下面就来讲解软件的实现过程。
工程文件,目录文件及索引文件的生成都要用到制作电子书所需的HTML文件,所以制作该软件时首先考虑从文件导入入手,即先把制作电子书的HTML文件导入,然后就可以在此基础上进行修改和编译了。
1)导入HTML文件
所谓的导入是把电子书的目录结构用程序获取,以便于以后生成目录及索引之用。在使用软件编译电子书时一般要求将所有要编译的文件放在同一目录下,以便于管理。我这里所制作的软件就有这个要求。这样,程序就可以自动从文件夹中获取目录结构。
我使用TreeView控件来存放目录结构,使用makeTree(curDir:string; topNod:tTreeNode; tree:tTreeView)过程来完成目录获取,具体的程序如下:
procedure makeTree(curDir:string; topNod:tTreeNode; tree:tTreeView);
var
tmpDir:string;
tmpNod:tTreeNode;
sr:tSearchRec;
begin
tmpDir := curDir + '\';
tmpNod := topNod;
if findFirst(tmpDir+'*.*', faAnyFile, sr) = 0 then
begin
repeat
if (sr.name <> '.') and (sr.name <> '..') then
begin
tmpNod := tree.items.addchild(topNod, sr.name);
if (sr.Attr and fadirectory) <> 0 then
begin
makeTree(tmpDir + sr.name, tmpNod, tree);
end;
end;
until FindNext(sr) <> 0;
findClose(sr);
end;
end;
这一过程运行的结果就是将指定目录下的所有文件,子文件夹及其中的文件的目录结构放到TreeView控件中。其中的每个节点的名称为文件或文件夹本身的名称,它是用sr.name来获取的。如果,有兴趣的话,可以不用sr.name,而是从网页中把
有了目录树我们就可以来生成编译所需的三个文件了。
2)工程文件的生成
由上面的知识可知,工程文件主要是实现[OPTIONS],[WINDOWS]和[FILES]三个部分,而[OPTIONS],[WINDOWS]这两个部分只要向用户提供可选的选项,根据用户的选择便可生成。具体实现可用复选框,文本框来收集输入信息,实现并不复杂,所以不再描述。
工程文件中稍微复杂一点的就是[FILES]项。不过,有了目录树作为基础,便可从中获取文件信息了。
我用writeHHP_FILES(topNode:tTreeNode; var f:text; topPath:string)这一过程来实现这一功能,具体代码如下
procedure writeHHP_FILES(topNode:tTreeNode; var f:text; topPath:string);
var
i:integer;
begin
i := 0;
while i < topNode.count do
begin
if topNode[i].Count = 0 then
begin
writeln(f, topPath + '\' + topNode[i].text);
end;
if topNode[i].Count <> 0 then
begin
writeHHP_FILES(topNode[i], f, topPath + '\' + topNode[i].text);
end;
i := i + 1;
end;
end;
需要注意的是,代码中topNode[i].text表示的是节点的名称。由于makeTree(curDir:string; topNod:tTreeNode; tree:tTreeView)过程中给节点命名时用的是文件或文件夹的名称,所以这里可以用topNode[i].text直接生成路径。如果节点的名称不是文件或文件名,则在建立树型目录时,要把每一个文件的路径保存下来,代替这里的topNode[i].text。一个可行的办法就是用tStringList对像,它可以按树型结构保存变量,至于具体实现这里不做讨论。
工程文件完成后,让我们来完成目录文件的生成。
3)目录文件的生成
目录文件的生成可以分成三个部分,头部、中间部分与尾部。目录文件的头部首先是固定部分可以用下面的代码实现。
HhcHead :=‘ ’;
Writeln(f, HhcHead);
接下来头部的可变部分,即目录树对像。首先根据用户的选择确定参数值,然后用writeln()函数写入文件。具体如下:
writeln(f, ‘’);
writeln(f, ‘’);
writeln(f, ‘’);
writeln(f, ‘’);
writeln(f, ‘’);
writeln(f, ‘’);
writeln(f, ‘’);
writeln(f, ‘’);
writeln(f, ‘’);
尾部也比较简单,可用HhcEnd表示,具体如下:
HhcEnd := ‘’;
Writeln(f, HhcEnd);
目录文件的中间部分比较复杂,它要实现的功能是把TreeView中的节点按照HTML语言中的无序列表列出,其实现的本质仍是遍历整个目录树。这里使用了 procedure writeList(topNode:tTreeNode; var f:text; topPath:string);
var
i:integer;
fPath:String;
begin
i:=0;
fPath := topPath + '\' + topNode[i].text;
writeln(f,'');
while i < topNode.count do
begin
if topNode[i].count = 0 then
begin
writeln(f,'
end
else
begin
writeln(f,'
writeList(topNode[i], f, fPath);
end;
i:=i+1;
end;
writeln(f,'');
end;
这里要注意两个问题,第一个问题在生成工程文件时已经介绍过,就是用topNode[i].text来生成路径时有前提的。第二个问题就是在文件列表对像时,对象的参数不是一成不变的,可以根据用户的选择使用不同的参数。
目录文件完成后就只剩索引文件了。
4)索引文件的生成
前面讲过,索引文件的结构与目录文件是一样的,所以只需把目录文件中索引文件不支持的部分去掉就是索引文件了。我们完全可以使用和目录文件一样的程序结构,只需修改两个部分即可。第一,将描述目录树的对象去掉。第二,将在写入文件列表对象时所使用的索引文件不支持的参数去掉。这样,生成的文件就是索引文件了。
有了上面三个文件之后,可谓万事俱备只欠东风,只要调用hhc.exe就可以完成编译了。具体代码如下:
WinExec(PCHAR(‘hhc.exe’+fileName+’.hhp’),SW_SHOW);
其中fileName为工程文件名称及所在目录。
以上就是CHM电子书生成软件的构架与实现,上述的代码知识一个最简单的实现,要想做出功能强大的软件还有很多要做。不过万变不离其中,只要具有上面的知识就一定能做出你想要的CHM电子书生成软件。