HTMLHelp: Sundry Tips, Trip-Ups & Musings

Helpful script writing tricks and HowTo's
User avatar
lmstearn
Posts: 694
Joined: 11 Aug 2016, 02:32
Contact:

HTMLHelp: Sundry Tips, Trip-Ups & Musings

03 Mar 2017, 08:11

Interested in using HTMLHelp for your own project?
Then read on!
Despite HTMLhelp running remarkably well for it's age in windows 10, can't help wondering why AHK stuck with it when there are good and possibly more user friendly (and free) programs around based on it.
Pity MS never made it open source like they never did with the (possibly superior) original WinHlp32 system.
In reading user comments on HTMLHelp the general consensus appears to be don't bother unless one is not competent in HTML.
TBQH mine own knowledge of HTML isn't great either, which is why using it as the recommended help system presents itself somewhat as a challenge.
The other thing to watch out for is keeping one's code to HTML version 4 or less (edit: unless venturing down this path), and there are not many 3rd party programs today that do it well enough (Bluefish and Dreamweaver come to mind as being useful in that regard). And the dinky (oh so nineties) gui featuring the Notepad-like CTRL-Z undo/redo toggle.

As MS's own riff on how to use HTMLHelp cannot be surpassed, we are not offering a full-blown tutorial,- just a few points on ease of use.

To begin with, download and install it, then run the executable hhw.exe from the install directory- typically Program Files (x86)\HTML Help Workshop.
The in-built help file describes how to start a project and add HTML files to it. It's recommended at some stage decompiling the AHK help file to see how things are setup, so let's do that now.
After decompiling the project to an empty folder, we note there is no hpp file generated so download it from github and copy it to the location where the decompiled AHK chm resides along with the Table of Contents.hhc and index.hhk. Upon closing any current projects in the Help Gui, open the AHK project and double click the windows section in the sidebar pane.
Click the files tab to verify the file layout. Note the settings in the other tabs and that the HTMLHelp WM_Help context question mark doesn't trigger on the controls. Meh. Also note there is no in-house "browser preview" of the content until the project is compiled, which at least has since become an integral part of the Visual Studio environment. Double click on the Options section for the tabbed options dialog- perhaps checking "Support enhanced decompilation" under Compiler generates the above missing hhp?
Click over to the Index tab to view the vast indexed list, then return to the contents tab and double click on Quick Reference. Yep, the layout is as with any other HTML page- the most critical is the following:

Code: Select all

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="static/theme.css" rel="stylesheet" type="text/css" />
<script src="static/content.js" type="text/javascript"></script>
The link href points to the theme.css file and the script source points to content.js where various js constructs reside. Note the above content is found on every page in the project!
The following line of code shows how an image in the project is linked:

Code: Select all

<img src="static/ahk_logo.png" alt="AutoHotkey"></a>
BTW the in-house image editor is still very capable for its age!
Lets now look at the entire stylesheet here with some extra (hopefully explanatory) comments- bearing in mind OP has been using CSS for barely five minutes: :lol:

Code: Select all

html, body { /*comma applies to both elements*/
	margin: 0;
	padding: 0;
    height: 100%;
}
body {
	margin: 0 8px 0 8px;
	font-size: .875em; /*em is an HTML emphasis phrase tag. Here it is typographic font size with properties overridden below */
	line-height: 1.75;
	background-color: #fefefe;
	padding-bottom: 3em;
}
html {
	font-family: Arial, sans-serif;
}
img {
	border: none;
}
img::selection { /*selects portion selected by user- "selection" is a pseudo-element*/
	background: transparent;
}
img::-moz-selection { /*above for Firefox*/
background: transparent;
}
a { /*a element refers to all hyperlink tags*/
    text-decoration: none;
}
a:link, a:active { /* :link looks to be a class selector, not a pseudo-element*/
    color: #4280CA;
}
a:visited {
    color: #AA00AA;
}
a:hover, a:focus {
    text-decoration: underline;
    color: #2A6496;
}
#MyApp img { /*hash before ID makes it unique*/
    margin: 20px 0 20px 0;
}
input, select {
    border: 1px solid #ccc;
}
pre, code { /*pre is pre-formatted*/
    border-right: solid 1px #C8C8C8;
    border-bottom: solid 1px #C8C8C8;
    background-color: #F6F6E8;
}
pre, .Syntax { /* "Syntax: user defined class with following properties */
	font-family: Consolas, Courier New, monospace;
}
.Syntax {
	background-color: #FFFFAA;
	border: solid 1px #E8E89A;
}
code, span.Syntax { /* span or inline element with class name of Syntax */
	font-family: Consolas, Courier New, monospace;
	padding: 0 1px;
}
pre {
    background-color: #F6F6E8; /*#F3F3FF*/
	margin: 0.7em 1.5em 0.7em 1.5em;
	padding: 0.7em 0 0.7em 0.7em;
	white-space: pre-wrap; /* works in IE8 but apparently not CHM viewer */
	word-wrap: break-word; /* works in CHM viewer */
}
pre.Syntax {
	margin: 0 0 1.0em 0;
	padding: 12px 0 12px 4px;
	line-height: 150%;
}
pre, pre.Short /*used with .Syntax -to enforce make Short a subclass?*/ {
	line-height: 120%;
}
pre em, code em { /* em is a size factor of Font, em is some descendant of both pre and code */
	color: #00A000;
	font-style: normal;
}
.NoIndent {
    margin-left: 0;
}
::selection {
	color: #fff;
	background: #6c7a95;
}
::-moz-selection {
 color: #fff;
 background: #6c7a95;
}
h1 {
    font-size: 2em;
    font-weight: bold;
    border-bottom-color: #FFFFFF;
    border-bottom-width: 2px;
    margin-top: 8px;
    color: #3F5770; /* Well known navy bluish header */
}
.navh1 { /* override of h1 in javascript main.js */
    font-weight: normal;
    background-color: #606060;
    color: #FFF;
    margin: 0px -8px 8px -8px;
    padding: 7px 8px 0px 8px;
    text-overflow: ellipsis;
    overflow: hidden;
    height: 43px;
    border-bottom: 1px solid #ccc;
    font-size: 1.5em;
    white-space: nowrap;
}
.navh1 a {
    color: #CCC !important;
}
h2 {
    color: #A04040;
}
h3 {
    color:  #008800;
}
#headerbar { /* referenced in javascript main.js but not used in help files*/
    background-color: #606060;
    position: absolute;
    top: 108px;
    left: 0px;
    width: 100%;
    height: 50px;
    z-index: -1;
    border-bottom: 1px solid #ccc;
}
a:visited {
	color: #7847b2;
}
h2:first-child {
	margin-top: 0;
}
h4 {
	margin-bottom: 0;
	line-height: 1;
}

h1, h2, h3 {
    border-bottom: 1px solid #ddd;
}
/* table of command parameters */
table {
    margin-bottom: 1em;
}
table.info {
    border: solid 2px #C0C0C0;
	border-collapse: collapse;
	width: 100%;
}
table.info td {
	border: solid 1px #C0C0C0;
	padding: 0.3em 0.5em;
}
table.info th {
	background-color: #F6F6F6;
	padding: 0.3em 0.5em;
}
/* heading note / version number/requirement tag */
.headnote,
h1 .ver, h2 .ver, h3 .ver {
	color: #808080;
    font-size: 65%;
	font-weight: normal;
	margin-left: 1em;
	vertical-align: text-middle;
}
h4 .headnote,
h4 .ver {
    font-weight: normal;
}
.ver, a.ver {
	color: gray;
}
a.ver:hover, a.ver:focus {
	text-decoration: none;
}
.dull {
	color: gray;
}
.red {
	color: red;
} /* used for highlight in various places */
.blue {
	color: blue;
}
/* emphasized note */
.note {
	border-left: 2px solid #99BB99;
	background-color: #E6FFE6;
	color: #005500;
	padding: .5em 1em;
}
.warning {
	border-left: 2px solid #FFA000;
	background-color: #FFF8E6;
	color: #C05500;
	padding: .5em 1em;
}
/* styles for briefly documenting multiple methods on one page: */
.methodShort {
	border: solid thin #C0C0C0;
	padding: 0.5em;
	margin-bottom: 1em;
}
.methodShort h2 {
	margin-top: 0;
  color: black;
  border-bottom: 0px;
}
.methodShort table.info {
	border: none;
}
.methodShort table.info td {
	border: none;
	vertical-align: text-top;
}
.methodShort:target { /* non-essential, but helpful if it works */
	border-color: black;
}

/* sidebar - or navigation pane if you like */

ul.jqtree-tree {
    margin-left: 20px;
}

ul.jqtree-tree,
ul.jqtree-tree ul.jqtree_common {
    list-style: none outside;
    margin-bottom: 0;
    padding: 0;
}

ul.jqtree-tree ul.jqtree_common {
    display: block;
    margin-left: 12px;
    margin-right: 0;
}
ul.jqtree-tree li {
    line-height: 1.5em;
    padding: .2em 0 .2em 0;
}
ul.jqtree-tree li.jqtree-closed > ul.jqtree_common {
    display: none;
}

ul.jqtree-tree li.jqtree_common {
    clear: both;
    list-style-type: none;
}
ul.jqtree-tree .jqtree-toggler {
    display: block;
    position: absolute;
    left: -1.5em;
    top: 30%;
    *top: 0;  /* fix for ie7 */
    font-size: 10px;
    line-height: 12px;
    font-family: arial;  /* fix for ie9 */
    border-bottom: none;
    color: #333;
}

ul.jqtree-tree .jqtree-toggler:hover {
    color: #000;
}

ul.jqtree-tree .jqtree-element {
    cursor: pointer;
}

ul.jqtree-tree .jqtree-title {
    vertical-align: middle;
}

ul.jqtree-tree li.jqtree-folder {
    margin-bottom: 4px;
}

ul.jqtree-tree li.jqtree-folder.jqtree-closed {
    margin-bottom: 1px;
}

ul.jqtree-tree li.jqtree-folder .jqtree-title {
    margin-left: 0;
}

ul.jqtree-tree .jqtree-toggler.jqtree-closed {
    background-position: 0 0;
}

ul.jqtree-tree .jqtree-element {
    width: 100%; /* todo: why is this in here? */
    *width: auto; /* ie7 fix; issue 41 */
    position: relative;
}

ul.jqtree-tree li.jqtree-selected > .jqtree-element
{
    font-weight: bold;
    color: #dd4b39;
}

ul.jqtree-tree li > .jqtree-element:hover
{
    background-color: #eee;
}

.main-content {
	width: 100%;
	min-height: 100%;
	height: auto!important;
	height: 100%;
}
#app-body {
	width: 100%;
}
#app-body .left-col {
	width: 231px;
	float: left;
}
#app-body .right-col {
	margin-left: 231px;
}
#main-content {
	padding-left: 13px;
	padding-right: 26px;
	min-height: 230px;
	max-width: 950px;
}
.right-col #main-content {
	border-left: 1px solid #e5e5e5;
}

/* Header */

.header {
    position: relative;
    background: #333;
    height: 67px;
    padding: 20px 25px;
    margin: 0 -8px 0 -8px;
    border-bottom: 1px solid #e5e5e5;
    z-index: 9999;
    white-space: nowrap;
}

.hdr-table {
width: 100%;
max-width: 1180px;
height: 81px;
}

.hdr-table td {
margin: 0;
padding: 0;
}
.hdr-table .hdr-image, .hdr-table .hdr-image img {
 width: 217px;
}

.hdr-table .hdr-search {
    vertical-align: bottom;
    padding-bottom: 13px;
}

.hdr-table .hdr-search form {
    display: inline-block;
}

.hdr-table .hdr-search input {
    padding-left: 5px;
    font-size: 1em;
    height: 25px;
    font-family: Arial, sans-serif;
    width:210px;
    vertical-align: middle;
    border: 1px solid #999;
    margin-left: 8px;
}

.hdr-table .hdr-search #search-btn {
    display: inline-block;
    height: 27px;
    line-height: 27px;
    width: 70px;
    color: #bbb;
    background: #606060;
    text-align: center;
    vertical-align: middle;
    border: 1px solid #808080;
    text-transform: uppercase;
    cursor: pointer;
    margin: 0px 10px;
}

.hdr-table .hdr-search #search-btn:hover, .hdr-table .hdr-language li:hover {
    color: #FFF;
    background: #808080;
}

.hdr-table .hdr-language {
    vertical-align: bottom;
    text-align: right;
    padding-bottom: 13px;
}

.hdr-table .hdr-language ul {
    display: inline-block;
    padding:0;
    margin:0;
}

.hdr-table .hdr-language li {
    border:1px solid #808080;
    background: #606060;
    color:#bbb;
    cursor:pointer;
    display:block;
    width: 100px;
    text-align: center;
    vertical-align: middle;
    height: 27px;
    line-height: 27px;
    position:relative;
    text-transform: uppercase;
}

.hdr-table .hdr-language .second {
    left:-1px;
    position:absolute;
    top:28px;
    display: none;
}

.hdr-table .hdr-language .second li {
    text-transform: none;
}

/* Footer */

.footer {
    background: #333;
    color: #fff;
    line-height: 44px;
    margin: 0 -8px 0 -8px;
    padding: 0 26px;
}

.footer a {
    color: #CCC;
}

.float-clear {
clear: both;
}

.nav {
    width: 242px;
    float: left;
    margin-top: -2px;
    margin-left: -10px;
    padding: 0;
    list-style: none;
    background-color: #808080;
    border-bottom: 1px solid #ccc;
    border-top: 1px solid #ccc;
}

.nav li {
    float: left;
    width: 50%;
    text-align: center;
    cursor: pointer;
}
.nav .selected {
    background-color: #bbb;
}

.nav .selected span {
    color: #000;
}

.nav li span {
        display: block;
        padding: 8px 15px;
        text-decoration: none;
        color: #FFF;
        border-right: 1px solid #ccc;
        height: 35px;
        text-transform: uppercase;
        font-size: 1.5em;
}

.nav li span:hover {
    color: #000;
    background-color: #bbb;
}

#IndexEntry {
    width: 214px;
    font-size: 1em;
    font-family: helvetica, Arial, sans-serif;
}

#indexcontainer {
    width: 216px;
    font-size: 1em;
    font-family: helvetica, Arial, sans-serif;
    height: 100%;
}

/* command parameters */
dt { /* param name */
	color: #008800;
	margin-left: 0.5em;
}

dd {
    margin-left: 1.5em;
    padding-left: 1.0em;
    border-left: 0.3em solid #e0e0e0;
	margin-bottom: 1em;
}
dd > p:first-child {
    margin-top: 0.3em;
}
So what now? How do we pare down something like the AHK file help for a smaller but fully functional and different help system? A good way is to modify the stylesheet with different font pitch font, colour, padding and so forth, but to aid the beginner with something much less erudite click Tags/Insert from the menu and note the slots are all empty.
Let's populate them, but
note the following
Clicking Tags/Edit and the first empty slot, paste the following into the title edit box:
Standard link to file
And paste this into the Text block:
<a href="Root/File.htm">Link_to_File.htm_text</a>
Slot 2 title:
Metas (used by AHK)
This into the Text block:
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
Slot 3 title:
Java Source
Slot 3 Text:
<script src="static/content.js" type="text/javascript"></script>
Slot 4 title:
Tables
Slot 4 Text:
<h3>Table Title</h3>
<table class="info">
<tr id="Something label">
<td>Something</td>
<td>Info on something</td>
</tr>
</table>
Slot 5 title:
Unordered List
Slot 5 Text:
<ul>
<li>Something</li>
<li><a href="htm file">htm filename</a></li>
</ul>
Slot 6 title:
Span for Color
Slot 6 Text:
<span style="color:red">red</span>
Slot 7 title:
Standard paragraph
Slot 7 Text:
<p>Blah...Paragraph can be broken up with <br> no closing tag required</p>
Slot 8 title:
Description List (From W3 schools)
Slot 8 Text:
<dl>
<dt>Coffee</dt>
<dd>Black hot drink</dd>
<dt>Milk</dt>
<dd>White cold drink</dd>
</dl>
And lastly for slot 9 do something fancy like the well-known Select All/Download routine:
Pre Code AHK style
And paste this into the Text block:
<pre>Some Code like Text</pre>

In the CSS
pre, code {
border-right: solid 1px #C8C8C8;
border-bottom: solid 1px #C8C8C8;
background-color: #F6F6E8;
}

In the js file

// Show select and download buttons in lower right corner of a pre box

var divStyle = {fontSize: "11px", float: "right"};
var aStyle = {cursor: "pointer", color: $("a:not([href=])").css("color")};
var selectLink = $('<a id="selectCode"></a>').text(translate.cdSelectBtn).css(aStyle);
var downloadLink = $('<a id="downloadCode"></a>').text(translate.cdDownloadBtn).css(aStyle);

$('pre').each(function(index) {
if ($(this).is(".Syntax")) {
$.extend(divStyle, {marginTop: "-32px", marginRight: "7px"});
$(this).after($('<div>').css(divStyle).prepend(selectLink.clone()));
}
else {
$.extend(divStyle, {marginTop: "-28px", marginRight: "28px"});
$(this).after($('<div>').css(divStyle).prepend(selectLink.clone(), [' | ', downloadLink.clone()]));
}
});

// Select complete code when clicking

$('a#selectCode').each(function(index) {
$(this).on('click', function(e) {
var doc = document
, text = $(this).parent().prev('pre')[0]
, range, selection
;
if (doc.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(text);
range.select();
} else if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(text);
selection.removeAllRanges();
selection.addRange(range);
}
});
});

// Download complete code when clicking

$('a#downloadCode').each(function(index) {
$(this).on('click', function(e) {
var textToWrite = '\ufeff' + $(this).parent().prev('pre').text().replace(/\n/g, "\r\n");
var textFileAsBlob = new Blob([textToWrite], {type:'text/csv'});
var fileNameToSaveAs = location.pathname.match(/([^\/]+)(?=\.\w+$)/)[0] + "-Script.ahk";

var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";

if (window.webkitURL != null) {
// Chrome
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
downloadLink.click();
}
else if (navigator.userAgent.indexOf("Trident")>-1) {
// IE 10+
navigator.msSaveBlob(textFileAsBlob, fileNameToSaveAs)
}
else {
// Firefox
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();
}
});
});
}
Well not all that for Slot #9 really, but it's there if you wanted to know how it all works - or want to do something similar. :P

And the spanning tag can also be expanded to the following item via another element: e.g.h2
<li><a href="#Something">Something</a></li>
<span id="Something"></span><h2 id="Description_of_Something">Something</h2>
with
h2 {
color: #A04040; /* red */
in the css file
Take care if updating HHW for any reason as these, and other settings will be reset. To preserve the settings, backup the reg key:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\HTML Help Workshop\Settings

Inserting these blocks into the help pages saves a little bit of extra work:- evidenced when only one project can be loaded in one time. Sure other files from other projects can be loaded, but in doing so leaves one prone to errors or unwanted files in the project as it evolves.

To create a search tab include this line in the hpp file:

Code: Select all

Full-text search=Yes
Generating an Index is a lot more work, there used to be free tools to assist, and no mean task of writing code to pick up the text in all the tags in the project htm files, retaining the most "relevant" ones and then adding them to the index. Cross references would make it interesting.
Historical note

The info at chmspec is very useful.
So there we have it- if there is anything amiss with a project the compiler will let you know. To actually link the files into an application refer to WM_Help Context IDs for GUI Controls and chm invocation. Using Anchors with the hidden attribute for topic section jumps is a good idea as well.
Finally, the HelpWare group tabulates a history of Microsoft Help programs.
The AHK help file itself has been taken care of over the years by many hands, but some components still remain a mystery. e.g. the Footer. It doesn't use anything like a (floating) footer, yet the CSS definitions remain for it.
Good idea then to only keep the elements & classes that will be actually used in the chm.
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

Return to “Tutorials (v1)”

Who is online

Users browsing this forum: No registered users and 28 guests