利用Html文件生成chm文件
文章目录
对个人使用HTML网页生成CHM格式说明手册的使用经验进行简单的记录与分享。
背景
CHM(Microsoft Compiled HTML Help)是微软公司开发的文件帮助格式,包含了由一系列的HTML页面、目录菜单、索引和其它导航工具,在Windows环境下可方便的打开与查阅。
由于其使用的便利性(Windows环境下可直接打开,无须各种依赖),故相同当多的软件在Windows环境下都提供了CHM格式的说明手册,出于此考虑个人想将部门的部分使用软件整合为CHM格式,在此过程中发现网络上关于此方面的资料较少,故简单记录下。
软件安装
说明
由于CHM是微软开发的,其自家的操作系统为Windows,故本文的操作环境也为Windows。
点击此链接下载名为htmlhelp.exe的文件,双击安装完毕后其目录结构类似如下

从图中可看出部分文件的日期相当老旧,事实上自从2009年起微软官方便计划不在提供新版本的CHM1,尽管如此但并不影响CHM的正常使用。
将安装路径添加到系统环境变量后,可采用类似如下方式验证安装是否成功

CHM生成
环境准备好之后,可以通过下述步骤实现将1个简单的HTML文件生成CHM文件:
1.编写一个简单的HTML文件,假设其名称为index.html,内容如下
<!DOCTYPE html>
<html>
<head>
<title>CHM测试</title>
<meta charset="utf-8">
<style type="text/css">
.content {
background-color: powderblue;
width:80%;
margin-left:auto;
margin-right:auto;
padding: 10px;
min-height:100px;
}
.content:hover {
background-color: #3e8e41;
color: white;
}
</style>
</head>
<body>
<p class="content">测试生成简单的<strong>CHM</strong>文件</p>
</body>
</html>
该文件的显示效果如下

2.编写一个扩展名为hhp(全称为HTML Help Project)的文件,文件名称不限制,内容如下
[OPTIONS]
Compatibility=1.1 or later
Compiled file=help.chm
Default topic=index.html
Display compile progress=Yes
Language=0x804 中文(简体,中国)
[FILES]
index.html
关于上述文件中的属性具体说明可参见此链接或此链接,也可查看老外写的更加详细的说明或在线文档。
3.假设前述步骤中的文件名为chm-test.hhp,在命令行执行如下命令
hhc chm-test.hhp
若环境配置正确,则输出类似如下

4.若一切正常,则会在当前目录生成一个名为help.chm的文件,打开后其展示效果如下,可看出其展示效果和步骤1中的HTML页面直接展示类似

中文文件名
若想将生成的CHM文件改为中文名称,可将前面的hhp文件内容修改如下
[OPTIONS]
Compatibility=1.1 or later
Compiled file=帮助手册.chm
Default topic=index.html
Display compile progress=Yes
Language=0x804 中文(简体,中国)
[FILES]
index.html
执行编译命令的输出类似如下,可看出输出过程中的中文显示乱码,实际生成的CHM文件名称也确实是乱码。

此问题一般是由编码问题造成的,需要将hhp文件的编码从UTF-8修改为ANSI

重新执行构建命令后可发现能正常生成中文文件

中文标题支持
如下图所示,默认情况下生成的CHM文件标题在中文环境为帮助,在英文环境下为Help,看起来不太直观。

可通过此说明在hhp文件中设置Title属性来实现,根据说明可修改为如下
[OPTIONS]
Compatibility=1.1 or later
Compiled file=帮助手册.chm
Default topic=index.html
Display compile progress=Yes
Language=0x804 中文(简体,中国)
Title=简单的说明文档
[FILES]
index.html
此时如果执行构建指令,会发现CHM文件的标题还是没有变化,网络上这方面的资料较少,经过自己的一番对比与尝试后,发现Title属性必须与其它功能结合后才生效,如搜索功能、菜单目录等,原因暂时不明。
假设要添加搜索功能,将hhp文件修改如下
[OPTIONS]
Compatibility=1.1 or later
Compiled file=帮助手册.chm
Default topic=index.html
Display compile progress=Yes
Language=0x804 中文(简体,中国)
Title=简单的说明文档
;支持搜索功能
Full-text search=Yes
[FILES]
index.html
重新执行构建指令,并打开生成的CHM文件,可发现其标题已经改变。

菜单目录支持
前述的内容都是基于单个HTML页面,实际使用中肯定会涉及多个文件,尤其是使用手册等说明类的文档,通常需要添加菜单目录来进行合适的分类与快速导航定位。
可通过在编译时提供hhc(全称为HTML Help Contents)文件来生成带有菜单目录的CHM文件,相关操作步骤如下:
1.为了便于管理,将相关的文件都放到一个文件夹下,其层级结构如下所示,其中包含多个HTML文件和图片等文件

2.建议一个如下图所示的hhp文件,可发现其与前面的hhp文件有一定差异,通过Contents file文件来配置菜单目录,同时无需在FILES下面指定具体的文件列表(因为在hhc文件中已经包含了相关的文件)
[OPTIONS]
Compatibility=1.1 or later
Compiled file=帮助手册.chm
;此处用于设置菜单目录
Contents file=contents.hhc
Default topic=doc/ch1/index.html
Display compile progress=Yes
Language=0x804 中文(简体,中国)
Title=简单的说明文档
3.对应的contents.hhc(文件名可任意起名)文件内容如下,可发现其本质上是HTML文件,其中的UL相关的嵌套代码即为最终要展示的层级结构
+点击以展开/折叠
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
<!-- Sitemap 1.0 -->
</HEAD>
<BODY>
<OBJECT type="text/site properties">
<param name="ImageType" value="Folder">
</OBJECT>
<UL>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="第1章节">
<param name="Local" value="doc/ch1/index.html">
<param name="ImageNumber" value="1">
</OBJECT>
<UL>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="功能1">
<param name="ImageNumber" value="0">
</OBJECT>
<UL>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="页面1">
<param name="Local" value="doc/ch1/func1/page1.html">
</OBJECT>
</LI>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="页面2">
<param name="Local" value="doc/ch1/func1/page2.html">
</OBJECT>
</LI>
</UL>
</LI>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="About">
<param name="Local" value="doc/ch1/about.html">
</OBJECT>
</LI>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="Menu">
<param name="Local" value="doc/ch1/menu.html">
</OBJECT>
</LI>
</UL>
</LI>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="第2章节">
<param name="ImageNumber" value="1">
</OBJECT>
<UL>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="功能1">
<param name="ImageNumber" value="0">
</OBJECT>
</LI>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="概览">
<param name="Local" value="doc/ch2/func1.html">
</OBJECT>
</LI>
<LI>
<OBJECT type="text/sitemap">
<param name="Name" value="具体说明">
<param name="Local" value="doc/ch2/具体说明.html">
</OBJECT>
</LI>
</UL>
</LI>
</UL>
</BODY>
</HTML>
4.构建过程如下,由于其包含的文件较多,故构建过程中输出的日志也更加详细

5.打开生成的文件,展示效果类似如下,可看出左侧出现了我们基于hhc文件设置的菜单,且能够正常的点击切换

文件图标修改
前述的菜单目录实现的核心为<OBJECT>对象,其中包含一个或多个<param>对象,通过键值对的方式设置相关参数值,可选的参数如下:
| 参数 | 说明 |
|---|---|
Name |
用于设置在菜单目录中的显示名称(即文件名和显示名称可不相同) |
Local |
该对象对应的HTML文档,采用相对路径设置 |
ImageNumber |
该对象在菜单目录中使用何种图标 |
其中ImageNumber的值可以设置为从1到42(若超过42不会报错且用默认值替代),分别对应如下图标
![]()
可通过如下代码来修改其值
<OBJECT type="text/sitemap">
<param name="Name" value="第1章节">
<param name="Local" value="doc/ch1/index.html">
<param name="ImageNumber" value="3">
</OBJECT>
基于上述说明修改前面的hhc文件,展示效果如下
![]()
下述内容来源于此文章,个人并未做实际验证
如果
<OBJECT>中没有ImageNumber项时,如果hhp文件中的ImageType为Picture(默认是Picture),如果有子目录,就显示,否则显示
,如果
ImageType为Folder,如果有子目录,就显示,否则显示
中文搜索支持
可通过在hhp文件中添加Full-text search来添加搜索功能
[OPTIONS]
Compatibility=1.1 or later
Compiled file=帮助手册.chm
;此处用于设置菜单目录
Contents file=contents.hhc
Default topic=doc/ch1/index.html
Display compile progress=Yes
Language=0x804 中文(简体,中国)
Title=简单的说明文档
;支持搜索功能
Full-text search=Yes
但个人在实际使用中遇到了中文搜索的一些坑,需要将文件编码设置为ANSI 且在HTML文件中去掉显示的文件编码才能正常支持中文搜索。
演示说明如下:
1.假设所有的HTML文件编码均为UTF-8且在文件源码中也通过如下代码进行显示声明
<!--设置为utf-8编码 -->
<meta charset="utf-8">
2.在生成的CHM文件中搜索中文关键字,可看出虽然实际有内容,但检索结果为空

3.切换为英文单词搜索后,结果如下,虽然有结果,但是显示为乱码,同样无法使用

4.将对应的HTML文件以ANSI编码格式保存,重新生成CHM文件,发现其中文直接显示乱码,此时进行搜索已经无意义

5.基于前述步骤,将对应HTML文件源码中的编码类型去掉,然后重新生成CHM文件
<!--设置为utf-8编码
<meta charset="utf-8">-->
6.对重新生成的CHM文件进行中文检索,此时结果正常,如下图所示

从上图的搜索结果可发现其展示的检索结果为HTML文件的title属性值而非实际的文件名称,故建议在生成hhc文件时,<OBJECT>对象下的Name属性值要和HTML页面的title值保持一致,避免使用上引起歧义,可通过代码脚本来达到此目的。
遗留问题
前述生成CHM文件的操作适用于简单的HTML文件,若HTML文件本身内容很复杂(如基于GitBook生成),则生成的CHM文件打开后可能会报错,原因尚未找出。
