While looking into DocProject, I wanted to see how easy it would be to add custom topics into a project but didn’t get chance to do it in my original post.
One of the nice features of DocProject is that you can add your own code into the build process. The file BuildProcess.cs has a number of event methods which are called at various points within the build process. In the How To… there is a a guide to creating custom topics for the webpage, however I wanted to use my existing HTML pages within the help file. It would have been nice just to be able to select these from within the options menu – hint hint Dave. I am going to create my own for now.
What I want to do, is take a folder and include it within a CHM/Help 1.0 fie. For this there are two important concepts, one, everything needs to be included in the html folder. Second, the index for the help file is .hhc and .hhk which is loosely based on html file and uses
Firstly, I created a directory structure in my solution which looks like below.
- /Root Folder
- /Custom Topics
- /test
- test.htm
- HtmlPage2.htm
- HTMLPage1.htm
- /test
- /Custom Topics
This is what I want to appear within my CHM file. However, it’s not as simple as it first seems. I included test.htm to be the default page for when a user clicks the Test namespace, as Test is a folder in the structure, it needs a related page.
Firstly, I had to hook into the DocProject build process. This is really nice as Dave has already provided the methods/events there for you, it was just finding where to place the call as when Sandcastle is creating its own files, it will override any changes you have made previously. The method BeforeExecuteStep is called before every step in the build process, so I simply did a check to see if the I was before the step I was interested in:
if (step.Name.Equals(“Compile Help 1.x”))
ProcessHelpCustomTopics(context, “Html”);
Now a method is called just before the help file is about to be compiled, this method writes out some information to the trace and calls CustomTopics.Import. Here, I simply copy all the content from Custom Topics into the html folder, keeping the correct folder structure (Method CopyAllFilesInSourceToTarget). So now all the files are in the correct place, we need to tell the help compiler about them, now this is where it started to get tricky.
There are two important files for the help structure,
<li><object type="text/sitemap"> <param name="Name" value="HTMLPage1"> <param name="Local" value="htmlHTMLPage1.htm"> object> <li><object type="text/sitemap"> <param name="Name" value="Test"> <param name="Local" value="htmltesttest.htm"> object> <ul> <li><object type="text/sitemap"> <param name="Name" value="HTMLPage2"> <param name="Local" value="htmltestHTMLPage2.htm"> object> ul>
It works well, the only problem is that the file format is not the easiest to understand, as its not XML and its not really HTML. But to be fair, Help 1.0 is from 98, and Help 2.0 does have a XML based TOC file.
For a simple file to be displayed in the contents, the file hhc file should have a entry like
<li><object type="text/sitemap"> <param name="Name" value="HTMLPage1"> <param name="Local" value="htmlHTMLPage1.htm"> object>
Notice, li is not closed. If you wanted a page as a child node of another page, underneath an entry like above, you would add
<ul> <li><object type="text/sitemap"> <param name="Name" value="HTMLPage2"> <param name="Local" value="htmltestHTMLPage2.htm"> object> ul>
Adding an entry for each page between the ul tags.
Within hhk you simple just have a single entry for all of the pages, like below
<li><object type="text/sitemap"> <param name="Name" value="HTMLPage2"> <param name="Local" value="html/test/HTMLPage2.htm"> object>
So, its not that difficult, but trying to out it would wasn’t a great experience.
You can download my code BuildProcess.cs and CustomTopics.cs. I have also zipped up the complete project for download here
While, I haven’t implemented the support for Help 2.0, you would simply need to copy all of the html into the Html2 folder and modify the HxT file. Plus, with this solution it also works with the DocSite web applications.
One thing to be aware of was that if I changed BuildProcess.cs without changing the target assembly, then it would never build as there was no point because the the source hadn’t changed. That’s fine, unless BuildProcess.cs changes, but selecting ReBuild gets around this and forces a fresh build.
Another tip, Sandcastle builds a lot quicker when your laptop isn’t on Power Saving mode…
Great work Ben! This is a really nice effort. (and I get the hint 🙂
Others have asked for this functionality too. I’ve already added a work item to DocProject on CodePlex for a “Custom Topic Dialog”. Currently, I’m waiting for Sandcastle to support custom content so that the process is integrated and supported, instead of a hack. In the June ’07 CTP Sandcastle ships with “conceptual” content transformations, which look promising. I’m waiting to here more about them from Anand.
BTW, DocProject has partial-build support (check out the Build Process wiki), which allows you to rebuild only the HTML Help Workshop files instead of running the entire Sandcastle process for when you only make a change to your custom topics. To trigger a partial build, for example, you can just delete the .chm file and then use the “Build” command instead of using the “Rebuild” command.
Hi Ben,
I’ve just created a blog post that provides more information:
Adding Additional Topics Using DocProject