HTML Help alternative via Internet Explorer

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

HTML Help alternative via Internet Explorer

29 Dec 2017, 22:49

- Here is a prototype, 2 windows: a treeview and Internet Explorer, as an alternative to HTML Help.
- At the moment it displays the Contents, I might try and add in support for the Index, Search (a superior search, equivalent to FileRead and InStr) and Favorites.
- I'm also going to incorporate support for switching between the AHK v1/v2 help pages.
- To view the contents of a chm file, you can decompile it using HTML Help or 7-Zip. The older version of the AutoHotkey.chm file has 'Table of Contents.hhc' (the basis of the Contents list). Both the new and old versions have 'Index.hhk' (the basis of the Index list). The Favorites are stored in %AppData%\Microsoft\HTML Help\hh.dat, which contains information for all of the chm files that have ever been run, back it up if you intend to edit it. (It's a binary file so you can't edit it in Notepad, use HxD or some other program.)
- The best current workaround is to use an old version of the contents list, and the new version of the index list. The Search would search for text within any pages listed in either the old contents list or the new index list. The Favorites would be based on an ini file, and/or a hardcoded template in the script.
- Btw a new version of 'Table of Contents.hhc' is ideally needed, otherwise the Contents would be missing a few pages. Newer pages would still be accessible by clicking hyperlinks.
[EDIT:] It appears that the data is stored here in the new version:
docs\static\source\data_index.js and docs\static\source\data_toc.js

- I first worked on this at the beginning of the year, in January. I wanted to retrieve the contents of the Contents table directly from the .hhc file (retrieved by decompiling the chm), rather than by getting text via a treeview control.
- At the time, I wanted to combine the benefits of Internet Explorer with the benefits of the HTML Help treeview control.
- What's changed now is that I've figured out a way to get the contents of the .hhc/.hhk files, direct from the chm file, without decompiling it, but to do this you must already know the relative paths of those 2 files. (I found that out by decompiling.)

Code: Select all

;HTML Help alternative via Internet Explorer by jeeswg

;settings
vFontSize := 20
vFontName := "Verdana"

;older chm containing contents information:
vPath1Old := "C:\Program Files\AutoHotkey\AutoHotkey.chm"
;up-to-date chm:
vPath1 := "C:\Program Files\AutoHotkey\AutoHotkey.chm"
;vPath1 := "https://autohotkey.com"

;==================================================

OnExit("ExitFunc")

;e.g. https://autohotkey.com/docs/commands/SubStr.htm
;e.g. mk:@MSITStore:C:\Program%20Files\AutoHotkey\AutoHotkey.chm::/docs/commands/SubStr.htm
;e.g. its:C:\Program%20Files\AutoHotkey\AutoHotkey.chm::/docs/commands/SubStr.htm

;e.g. https://autohotkey.com/Table of Contents.hhc
;e.g. mk:@MSITStore:C:\Program%20Files\AutoHotkey\AutoHotkey.chm::Table of Contents.hhc
;e.g. its:C:\Program%20Files\AutoHotkey\AutoHotkey.chm::Table of Contents.hhc

if (SubStr(vPath1, 1, 4) = "http")
	vPath1X := vPath1 "/"
else
	vPath1X := "its:" vPath1 "::/"

oWB := ComObjCreate("InternetExplorer.Application")
;oWB.Navigate("its:" vPath1Old "::Index.hhk")
oWB.Navigate("its:" vPath1Old "::Table of Contents.hhc")
;oWB.Visible := True
vHtml := oWB.document.documentElement.innerText
;MsgBox, % vHtml
oWB.Quit()
oWB := ""

oHTML := ComObjCreate("HTMLFile")
oHTML.write(vHtml)
vOutput := ""
VarSetCapacity(vOutput, 1000000*2)

Loop, % oHTML.getElementsByTagName("object").length
{
	oElt := oHTML.getElementsByTagName("object")[A_Index-1]
	if (oElt.type = "text/site properties")
		continue
	vTitle := vUrl := ""
	if (oElt.childNodes.length > 0)
		vTitle := oElt.childNodes[0].getAttribute("value")
	if (oElt.childNodes.length > 1)
		vUrl := oElt.childNodes[1].getAttribute("value")
	vIndent := ""
	Loop
	{
		oElt := oElt.parentNode.parentNode.parentNode.childNodes[0]
		vTitle2 := oElt.childNodes[0].getAttribute("value")
		if !(vTitle2 = "") && !(oElt.type = "text/site properties")
			vIndent .= "`t"
		else
			break
	}
	vOutput .= vIndent vTitle "`t" vUrl "`r`n"
}

;trim trailing tabs
vOutput := RegExReplace(vOutput, "m)`t+$")
;MsgBox, % "done"
;return
Clipboard := vOutput

;==================================================

vText := vOutput
oWB := ComObjCreate("InternetExplorer.Application")
oWB.Navigate(vPath1X "docs/AutoHotkey.htm")
oWB.Visible := True

DetectHiddenWindows, On

vCtlW := 280
vCtlW := 480
;vCtlW := 680

Gui, +HwndhGui
Gui, Font, % "s" vFontSize, % vFontName

Gui, +Resize
Gui, Add, TreeView, % "vMyTreeView x0 y0 w" vCtlW " gMyTreeView ImageList" ImageListID " AltSubmit +HwndhLV"
Gui, Add, Button, Hidden Default, OK

ImageListID := IL_Create(5)
Loop, 5
	IL_Add(ImageListID, "shell32.dll", A_Index)

vParentItemID1 := 0
Loop, Parse, vText, `n, `r
{
	vTemp := A_LoopField
	if (vTemp = "")
		continue
	vGen := 1
	Loop, Parse, vTemp
	{
		if (A_LoopField = "`t")
			vGen++
		else
			break
	}
	vTempX := SubStr(vTemp, vGen)
	vGen2 := vGen+1
	oTemp := StrSplit(vTempX, "`t")

	vParentItemID := vParentItemID%vGen%

	vItemID := TV_Add(oTemp.1, vParentItemID, "Icon4")
	vText%vItemID% := oTemp.2
	vParentItemID%vGen2% := vItemID
}

;WinGetPos,,,, vCtlH, % "ahk_id " hLV
WinGetPos,,,, vTaskbarH, ahk_class Shell_TrayWnd
vCtlH := (A_ScreenHeight-vTaskbarH)
Gui, Show, % "x0 y0 w" vCtlW " h" vCtlH, AutoHotkey Help
WinGetPos,,, vWinW,, % "ahk_id " hGui
vWin2W := (A_ScreenWidth-vWinW)
WinMove, % "ahk_id " oWB.HWND,, % vWinW, 0, % vWin2W, % vCtlH
return

;==================================================

MyTreeView:
if (A_GuiEvent = "DoubleClick")
|| (A_GuiEvent = "Normal")
{
	vItemID := A_EventInfo
	vText := vText%vItemID%

	;if !(vText = "")
	;	ToolTip, % vText
	;else
	;	ToolTip

	if !(vText = "")
		oWB.Navigate(vPath1X vText, hWnd)
	;return
}

;if A_GuiEvent in DoubleClick,Normal
;	ToolTip, % A_GuiEvent " " A_MSec
return

;==================================================

GuiSize:
if (A_EventInfo = 1)
	return
GuiControl, Move, MyTreeView, % "H" (A_GuiHeight - 30) ; -30 for status bar and margins
return

;==================================================

GuiClose:
ExitApp

;==================================================

ButtonOK:
GuiControlGet, vCtlName, FocusV
if !(vCtlName = "MyTreeView")
	return

vItemID := TV_GetSelection()
vText := vText%vItemID%
if !(vText = "")
	oWB.Navigate(vPath1X vText, hWnd)

vState := TV_Get(vItemID, "Expand")
if TV_GetChild(vItemID)
	if (vState := TV_Get(vItemID, "Expand"))
		TV_Modify(vItemID, "-Expand")
	else
		TV_Modify(vItemID, "Expand")
return

;==================================================

ExitFunc()
{
	global oWB
	oWB.Quit()
	oWB := ""
}

;==================================================

;q::
Gui, Show
return

;==================================================
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: HTML Help alternative via Internet Explorer

02 Jun 2018, 18:30

- After various recent queries and posts, you may have guessed that I'd come back to this project.
send keys to a GUI window/control without causing beeps (+ the standard way to define an AHK GUI hotkey) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=29940
chm file: get internal file contents (navigate to js file, don't download it) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=49643
smart ComboBox that updates as you type (HTML Help-style ComboBox) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=49927
GUI: getting controls to respond to Enter (including controls within tab controls) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=49932
HTML Help file/folder icons - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=49983
- In the next post is my recreation of HTML Help.
- I would still like to resolve: setting the focused item to be the first item in a listbox, and finding out where the default HTML Help icons are kept (at the moment my script doesn't change open/closed folder icons).
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: HTML Help alternative via Internet Explorer

02 Jun 2018, 18:47

The idea is as follows:
- You use a tool like 7-Zip to decompile (extract) a chm file to a folder, and you specify that folder's path in the script.
- You can specify folders for both AHK v1 and AHK v2.
- The script then works much like HTML Help does.
- It also has Ctrl+1/Ctrl+2 hotkeys to switch between AHK v1/v2 pages.
- It also has Ctrl+Shift+1/Ctrl+Shift+2 hotkeys to open AHK v1/v2 pages in a new window.
- There is an option to create a TSV txt file, to specify a custom Favorites list.

Code: Select all

;==================================================

;HTML Help alternative via Internet Explorer by jeeswg
;AHK v1.1

;settings:
vFontSize := 20
vFontName := "Verdana"
;vDir1 := "C:\Program Files\AutoHotkey\AutoHotkey.chm"
;vDir2 := "C:\Program Files\AutoHotkey\AutoHotkey.chm"
vDir1 := A_Desktop "\AutoHotkey_1.1.29.00\AutoHotkey"
vDir2 := A_Desktop "\AutoHotkey_2.0-a096-2ad11cb\AutoHotkey"
;vDir1 := "https://autohotkey.com"
;vDir2 := "https://lexikos.github.io/v2"
;vDir1 := A_Desktop "\AutoHotkey_1.1.25.00\AutoHotkey"

;specify 1 or 2 to determine which version is used for the Contents/Index/Search
vVersion := 1

;an optional TSV file as a Favorites list
SplitPath, A_ScriptFullPath, vName, vDir, vExt, vNameNoExt, vDrive
vPathFav := vDir "\" vNameNoExt "-FAV.txt"

;==================================================

;description:
;an alternative to HTML Help
;2 windows: a treeview and Internet Explorer
;Contents, Index, Search, Favorites
;option to switch between AHK v1/v2 help pages
;option to specify a TSV file as a Favorites list

;key files (older versions):
;'Table of Contents.hhc' (Contents)
;'Index.hhk' (Index)
;%AppData%\Microsoft\HTML Help\hh.dat (Favorites)

;key files (newer versions):
;'data_toc.js' (Contents)
;'data_index.js' [also: 'Index.hhk'] (Index)
;%AppData%\Microsoft\HTML Help\hh.dat (Favorites)

;key files (examples 1)
;e.g. https://autohotkey.com/docs/commands/SubStr.htm
;e.g. mk:@MSITStore:C:\Program%20Files\AutoHotkey\AutoHotkey.chm::/docs/commands/SubStr.htm
;e.g. its:C:\Program%20Files\AutoHotkey\AutoHotkey.chm::/docs/commands/SubStr.htm

;key files (examples 2)
;e.g. https://autohotkey.com/Table of Contents.hhc
;e.g. mk:@MSITStore:C:\Program%20Files\AutoHotkey\AutoHotkey.chm::Table of Contents.hhc
;e.g. its:C:\Program%20Files\AutoHotkey\AutoHotkey.chm::Table of Contents.hhc

;==================================================

#SingleInstance force
ListLines, Off
#KeyHistory 0
Menu, Tray, Click, 1
#NoEnv
AutoTrim, Off
#UseHook

SplitPath, A_ScriptName,,,, vScriptNameNoExt
Menu, Tray, Tip, % vScriptNameNoExt

;==================================================

;tabs + controls
;C: SysTreeView32
;I: Edit, ListBox
;S: Edit/ComboBox, SysListView32, Button, Button
;F: Edit, Listbox

;==================================================

;LIST FOR SWITCHING BETWEEN AHK V1/V2 HELP PAGES

;'~ ' indicates near equivalents
;AHK v1 to v2
vList12 := " ;continuation section
(
AHKL_ChangeLog.htm	ChangeLog.htm
AHKL_Features.htm	_
ChangeLogHelp.htm	_
commands\_AllowSameLineComments.htm	_
commands\_CommentFlag.htm	_
commands\_EscapeChar.htm	_
commands\_IfWinActive.htm	commands\_If.htm
commands\_MaxMem.htm	_
commands\_NoEnv.htm	_
commands\Asc.htm	commands\Ord.htm
commands\AutoTrim.htm	~ commands\Trim.htm
commands\ControlGet.htm	commands\Control.htm
commands\DriveSpaceFree.htm	commands\DriveGet.htm
commands\EnvAdd.htm	~ commands\DateAdd.htm
commands\EnvDiv.htm	~ Variables.htm
commands\EnvMult.htm	~ Variables.htm
commands\EnvSub.htm	~ commands\DateDiff.htm
commands\EnvUpdate.htm	~ Variables.htm
commands\FileCopyDir.htm	commands\DirCopy.htm
commands\FileCreateDir.htm	commands\DirCreate.htm
commands\FileMoveDir.htm	commands\DirMove.htm
commands\FileReadLine.htm	commands\FileRead.htm
commands\FileRemoveDir.htm	commands\DirDelete.htm
commands\FileSelectFile.htm	commands\FileSelect.htm
commands\FileSelectFolder.htm	commands\DirSelect.htm
commands\Gui.htm	objects\Gui.htm
commands\GuiControl.htm	objects\GuiControl.htm
commands\GuiControlGet.htm	objects\GuiControl.htm
commands\IfBetween.htm	~ Variables.htm
commands\IfEqual.htm	~ Variables.htm
commands\IfExist.htm	commands\FileExist.htm
commands\IfIn.htm	_
commands\IfInString.htm	commands\InStr.htm
commands\IfIs.htm	commands\is.htm
commands\IfMsgBox.htm	commands\MsgBox.htm
commands\LoopFile.htm	commands\LoopFiles.htm
commands\LoopReadFile.htm	commands\LoopRead.htm
commands\Menu.htm	objects\Menu.htm
commands\MenuGetHandle.htm	_
commands\MenuGetName.htm	_
commands\OnError.htm	_
commands\Progress.htm	~ misc\Colors.htm
commands\RegisterCallback.htm	commands\CallbackCreate.htm
commands\SetBatchLines.htm	_
commands\SetEnv.htm	~ Variables.htm
commands\SetFormat.htm	commands\Format.htm
commands\SoundGetWaveVolume.htm	commands\SoundGet.htm
commands\SoundSetWaveVolume.htm	commands\SoundSet.htm
commands\SplashTextOn.htm	_
commands\StringGetPos.htm	commands\InStr.htm
commands\StringLeft.htm	commands\SubStr.htm
commands\StringLen.htm	commands\StrLen.htm
commands\StringLower.htm	commands\StrLower.htm
commands\StringMid.htm	commands\SubStr.htm
commands\StringReplace.htm	commands\StrReplace.htm
commands\StringSplit.htm	commands\StrSplit.htm
commands\StringTrimLeft.htm	commands\SubStr.htm
commands\Transform.htm	_
commands\URLDownloadToFile.htm	commands\Download.htm
commands\WinGetActiveStats.htm	~ commands\WinGetPos.htm
commands\WinGetActiveTitle.htm	commands\WinGetTitle.htm
commands\WinMenuSelectItem.htm	commands\MenuSelect.htm
misc\AutoIt2Compat.htm	_
Welcome.htm	_
)"
vList12 := StrReplace(vList12, "`t~ ", "`t")
oList12 := Object(StrSplit(vList12, ["`t", "`n"])*)

;'~ ' indicates near equivalents
;AHK v2 to v1
vList21 := " ;continuation section
(
ChangeLog.htm	AHKL_ChangeLog.htm
commands\_SuspendExempt.htm	~ commands\Suspend.htm
commands\CallbackCreate.htm	commands\RegisterCallback.htm
commands\CaretGetPos.htm	~ docs/Variables.htm
commands\ComObject.htm	~ commands\ComObjActive.htm
commands\DateAdd.htm	commands\EnvAdd.htm
commands\DateDiff.htm	commands\EnvSub.htm
commands\DirCopy.htm	commands\FileCopyDir.htm
commands\DirCreate.htm	commands\FileCreateDir.htm
commands\DirDelete.htm	commands\FileRemoveDir.htm
commands\DirMove.htm	commands\FileMoveDir.htm
commands\DirSelect.htm	commands\FileSelectFolder.htm
commands\Download.htm	commands\URLDownloadToFile.htm
commands\FileSelect.htm	commands\FileSelectFile.htm
commands\Float.htm	_
commands\GuiCreate.htm	_
commands\GuiCtrlFromHwnd.htm	_
commands\GuiFromHwnd.htm	_
commands\Integer.htm	_
commands\is.htm	commands\IfIs.htm
commands\LoopFiles.htm	commands\LoopFile.htm
commands\LoopRead.htm	commands\LoopReadFile.htm
commands\MenuBarCreate.htm	_
commands\MenuCreate.htm	_
commands\MenuFromHandle.htm	_
commands\MenuSelect.htm	commands\WinMenuSelectItem.htm
commands\MonitorGet.htm	commands\SysGet.htm
commands\String.htm	_
commands\StrLen.htm	commands\StringLen.htm
commands\StrLower.htm	commands\StringLower.htm
commands\StrReplace.htm	commands\StringSplit.htm
commands\StrSplit.htm	commands\StringReplace.htm
commands\TraySetIcon.htm	~ commands/Menu.htm
commands\Type.htm	_
commands\WinGetClientPos.htm	_
misc\Colors.htm	~ commands\Progress.htm
misc\EscapeChar.htm	_
objects\Gui.htm	commands\Gui.htm	_
objects\GuiControl.htm	commands\GuiControls.htm	_
objects\GuiOnCommand.htm	_
objects\GuiOnEvent.htm	_
objects\GuiOnNotify.htm	_
objects\Menu.htm	commands\Menu.htm
)"
vList21 := StrReplace(vList21, "`t~ ", "`t")
oList21 := Object(StrSplit(vList21, ["`t", "`n"])*)

;==================================================

OnExit("ExitFunc")

vTextC1 := AhkHtmlHelpGet(vDir1, "Contents")
vTextC2 := AhkHtmlHelpGet(vDir2, "Contents")
vTextI1 := AhkHtmlHelpGet(vDir1, "Index")
vTextI2 := AhkHtmlHelpGet(vDir2, "Index")

oTabNum := StrSplit("Contents,Index,Search,Fav", ",") ;tab number to tab name
oTabHotkey := {c:1, n:2, s:3, i:4} ;tab hotkey letter to tab number
oTabNumHotkey := []
for vKey, vValue in oTabHotkey
	oTabNumHotkey[vValue] := vKey

oWB := ComObjCreate("InternetExplorer.Application")
oWB.Navigate(vDir%vVersion% "\docs\AutoHotkey.htm")
oWB.Visible := True
GroupAdd, WinGroupGui, % "ahk_id " oWB.HWND

;==================================================

;ACCELERATOR KEYS

oAccTable := [], oHotkeyName := [], oID := []
vIndex := 12000
for _, vValue in oTabNumHotkey
{
	vIndex++
	oHotkeyName[vIndex] := "!" vValue
	oAccTable.Push(["!" vValue, vIndex])
	oID[vIndex] := "SubTabFocus" A_Index
}
vListTabSwitch := "^1,^2,^+1,^+2"
for _, vValue in StrSplit(vListTabSwitch, ",")
{
	vIndex++
	oHotkeyName[vIndex] := vValue
	oAccTable.Push([vValue, vIndex])
	oID[vIndex] := "SubTabSwitch" A_Index
}
OnMessage(0x111, "OnCommand") ;WM_COMMAND := 0x111
OnMessage(0x100, "OnKeyDown") ;WM_KEYDOWN := 0x100
OnMessage(0x104, "OnKeyDown") ;WM_SYSKEYDOWN := 0x104

;Virtual-Key Codes (Windows)
;https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
;FCONTROL := 0x8 ;FSHIFT := 0x4
;FALT := 0x10 ;FVIRTKEY := 0x1
vCount := oAccTable.Length()
VarSetCapacity(ACCEL, 6*vCount, 0)
vOffset := 0
for _, oValue in oAccTable
{
	vKey := oValue.1, vID := oValue.2
	vMod := 0x1 | 0x8*!!InStr(vKey, "^") | 0x4*!!InStr(vKey, "+") | 0x10*!!InStr(vKey, "!")
	vKeyTemp := RegExReplace(vKey, "[\^!+]")
	vVK := GetKeyVK(vKeyTemp)
	NumPut(vMod, &ACCEL, vOffset, "UChar") ;fVirt
	NumPut(vVK, &ACCEL, vOffset+2, "UShort") ;key
	NumPut(vID, &ACCEL, vOffset+4, "UShort") ;cmd
	vOffset += 6
}

hAccel := DllCall("user32\CreateAcceleratorTable", Ptr,&ACCEL, Int,vCount, Ptr)

;==================================================

;GUI

DetectHiddenWindows, On

vCtlW := 280
vCtlW := 480
;vCtlW := 680

Gui, +Resize +HwndhGui
Gui, Font, % "s" vFontSize, % vFontName
GroupAdd, WinGroupGui, % "ahk_id " hGui

;add ampersands based on hotkeys defined above
;e.g. &Contents|I&ndex|&Search|Favor&ites
vList := "Contents|Index|Search|Favorites"
Loop, Parse, vList, |
	vList2 .= (A_Index=1?"":"|") RegExReplace(A_LoopField, "i)^.*?\K(?=" oTabNumHotkey[A_Index] ")", "&")
;MsgBox, % vList "`r`n" vList2
Gui, Add, Tab3, x0 y0 h800 +HwndhTab, % vList2

hIL := IL_Create(5)
Loop, 5
	IL_Add(hIL, "shell32.dll", A_Index)

;WinGetPos,,,, vTaskbarH, ahk_class Shell_TrayWnd
SysGet, vMon, MonitorWorkArea
vTaskbarH := A_ScreenHeight - vMonBottom
vWinH := A_ScreenHeight - vTaskbarH
vCtlH := vWinH - 20
vCtlY := 50

;==================================================

;GUI TAB - CONTENTS

Gui, Add, TreeView, % "vMyTreeView x0 y" vCtlY " w" vCtlW " gSubContents ImageList" hIL " +AltSubmit +HwndhTV"

vTextC := vTextC%vVersion%
vParentItemID1 := 0
oLVText := []
oArray := StrSplit(vTextC, "`n", "`r")
for vKey, vValue in oArray
{
	vTemp := vValue
	if (vTemp = "")
		continue
	;if item has children, give it a folder icon, else a file icon
	StrReplace(vTemp, "`t",, vCount1)
	StrReplace(oArray[A_Index+1], "`t",, vCount2)
	vIconNum := (vCount2 > vCount1) ? 4 : 2
	vGen := 1
	Loop, Parse, vTemp
	{
		if (A_LoopField = "`t")
			vGen++
		else
			break
	}
	vTempX := SubStr(vTemp, vGen)
	vGen2 := vGen+1
	oTemp := StrSplit(vTempX, "`t")

	vParentItemID := vParentItemID%vGen%

	hItem := TV_Add(oTemp.1, vParentItemID, "Icon" vIconNum)
	oLVText[hItem] := oTemp.2
	vParentItemID%vGen2% := hItem
}

;==================================================

;GUI TAB - INDEX

Gui, Tab, 2
;separate Edit control and ListBox

oIndex := {}
vTextI := vTextI%vVersion%
vTextIList := ""
Loop, Parse, vTextI, `n, `r
{
	vTemp := A_LoopField
	if (vTemp = "")
		continue
	oTemp := StrSplit(vTemp, "`t")
	if (oTemp.1 ~= "\Q()\E$") ;e.g. 'Trim()' to 'Trim'
	&& !(oTemp.1 ~= "i)^(GetKeyState|OnExit|Trim)\Q()\E$")
		oTemp.1 := SubStr(oTemp.1, 1, -2)
	oIndex["z" oTemp.1] := oTemp.2
	vTextIList .= (A_Index=1?"":"|") oTemp.1
}
;MsgBox, % vTextIList
vLbxH := vCtlH - 120
Gui, Add, Edit, % "gSubIndexEdit x0 y" vCtlY " w" vCtlW " +HwndhEditI"
Gui, Add, ListBox, % "gSubIndex w" vCtlW " h" vLbxH " +HwndhLbxI", % vTextIList

;==================================================

;GUI TAB - SEARCH

Gui, Tab, 3
;ComboBox (with drop-down menu) (ComboBox + Edit)
Gui, Add, ComboBox, % "x0 y" vCtlY " w" vCtlW " gSubSearch +AltSubmit +HwndhCbxS"
Gui, Add, ListView, % "w" vCtlW " r10 +HwndhLV gSubSearch", Title
Gui, Add, Checkbox, Checked +HwndhBtnT, Search titles
Gui, Add, Checkbox, Checked +HwndhBtnC, Search contents

;==================================================

;GUI TAB - FAVORITES

if (vTextF = "")
&& FileExist(vPathFav)
	FileRead, vTextF, % vPathFav
else
	vTextF = ;continuation section
	(LTrim
		functions	commands/index.htm
		variables	Variables.htm
		continuation sections	Scripts.htm#continuation
	)

Gui, Tab, 4
;separate Edit control and listbox
;ComboBox + ComboLBox + Edit

oFav := {}
vTextFList := ""
Loop, Parse, vTextF, `n, `r
{
	vTemp := A_LoopField
	if (vTemp = "")
		continue
	oTemp := StrSplit(vTemp, "`t")
	if (oTemp.1 ~= "\Q()\E$") ;e.g. 'Trim()' to 'Trim'
	;&& !(oTemp.1 ~= "i)^(GetKeyState|OnExit|Trim)\Q()\E$")
		oTemp.1 := SubStr(oTemp.1, 1, -2)
	vTextFList .= (A_Index=1?"":"|") oTemp.1
	oFav["z" oTemp.1] := oTemp.2
}
;MsgBox, % vTextFList
vCbxH := vCtlH - 100
Gui, Add, Edit, % "gSubFavEdit x0 y" vCtlY " w" vCtlW " +HwndhEditF"
Gui, Add, ListBox, % "gSubFav w" vCtlW " h" vLbxH " +HwndhLbxF", % vTextFList

;==================================================

Gui, Tab ;future controls are not part of any tab control
Gui, Add, Button, Hidden Default gSubBtnHidden, % "Hidden`r`nButton"

Gui, Show, % "x0 y0 w" vCtlW " h" vWinH, AutoHotkey Help
WinGetPos,,, vWinW,, % "ahk_id " hGui
vWin2W := A_ScreenWidth - vWinW
WinMove, % "ahk_id " hGui,,,,, % vWinH
WinMove, % "ahk_id " oWB.HWND,, % vWinW, 0, % vWin2W, % vWinH
return

;==================================================

;HTML Help: get Contents/Index text
AhkHtmlHelpGet(vDir, vType)
{
	if (SubStr(vType, 1, 1) = "i") ;Index
		vPath := vDir "\docs\static\source\data_index.js"
	else ;Contents
		vPath := vDir "\docs\static\source\data_toc.js"

	if FileExist(vPath)
	{
		FileRead, vText, % vPath
		vPfx := ""
		VarSetCapacity(vOutput, 100000*2)
		Loop, Parse, vText, `n, `r
		{
			vTemp := Trim(A_LoopField)
			if (vTemp = "[")
				vPfx .= "`t"
			else if InStr(vTemp, "]]")
				vPfx := SubStr(vPfx, 1, -1)
			oTemp := StrSplit(vTemp, Chr(34))
			;if !(oTemp.Length() ~= "^(0|1|5)$")
			;	MsgBox, % vTemp "`r`n`r`n" oTemp.Length()
			if !(oTemp.Length() = 5)
				continue
			vOutput .= vPfx oTemp.2 "`t" oTemp.4 "`r`n"
		}
		;vOutput := RegExReplace(vOutput, "m)`t+$") ;trim trailing tabs
		return vOutput
	}

	if (SubStr(vType, 1, 1) = "i") ;Index
		vPath := vDir "\Index.hhk"
	else ;Contents
		vPath := vDir "\Table of Contents.hhc"
	if !FileExist(vPath)
		return

	FileRead, vHtml, % vPath
	oHTML := ComObjCreate("HTMLFile")
	oHTML.write(vHtml)
	VarSetCapacity(vOutput, 100000*2)

	if (SubStr(vType, 1, 1) = "i") ;Index
	{
		Loop, % oHTML.getElementsByTagName("param").length
		{
			oElt := oHTML.getElementsByTagName("param")[A_Index-1]
			if (A_Index & 1)
				vTitle := oElt.getAttribute("value")
			else
			{
				vUrl := oElt.getAttribute("value")
				vOutput .= vTitle "`t" vUrl "`r`n"
			}
			continue
		}
	}

	if !(SubStr(vType, 1, 1) = "i") ;not Index: Contents
	{
		Loop, % oHTML.getElementsByTagName("object").length
		{
			oElt := oHTML.getElementsByTagName("object")[A_Index-1]
			if (oElt.type = "text/site properties")
				continue
			if (oElt.childNodes.length > 0)
				vTitle := oElt.childNodes[0].getAttribute("value")
			if (oElt.childNodes.length > 1)
				vUrl := oElt.childNodes[1].getAttribute("value")
			vIndent := ""
			Loop
			{
				oElt := oElt.parentNode.parentNode.parentNode.childNodes[0]
				vTitle2 := oElt.childNodes[0].getAttribute("value")
				if !(vTitle2 = "") && !(oElt.type = "text/site properties")
					vIndent .= "`t"
				else
					break
			}
			vOutput .= vIndent vTitle "`t" vUrl "`r`n"
		}
	}

	vOutput := StrReplace(vOutput, "`tdocs/", "`t")
	;vOutput := RegExReplace(vOutput, "m)`t+$") ;trim trailing tabs
	oHTML := ""
	return vOutput
}

;==================================================

JEE_HtmlGetTitle(ByRef vHtml)
{
	if (vHtml = "")
		return
	vPos1 := InStr(vHtml, "<title>")
	if !vPos1
		vPos1 := InStr(vHtml, "<title")
	vPos2 := InStr(vHtml, "</title>", 0, vPos1) + 7
	if vPos1 && !(vPos2 = 7)
		vHtml2 := SubStr(vHtml, vPos1, vPos2-vPos1+1)
	else
		return

	oHTML := ComObjCreate("HTMLFile")
	oHTML.Write(vHtml2)
	try vText := oHTML.getElementsByTagName("title")[0].innerText
	oHTML := ""

	vText := StrReplace(vText, "`r", " ")
	vText := StrReplace(vText, "`n", " ")
	vText := StrReplace(vText, "`t", " ")
	vText := Trim(vText, " ")
	vText := RegExReplace(vText, " {2,}", " ")
	return vText
}

;==================================================

OnCommand(wParam, lParam, uMsg, hWnd)
{
	global oID
	wParam2 := 0xFFFF & wParam
	if oID.HasKey(wParam2)
		Gosub, % oID[wParam2]
}

OnKeyDown(wParam, lParam, uMsg, hWnd)
{
	global hAccel
	global hEditI, hLbxI, hEditF, hLbxF
	;special handling for Up/Down keys
	;if press Up/Down while Edit control is focused on Index/Favorites tab
	;then the listview is notified
	if (wParam = 0x26) || (wParam = 0x28) ;VK_UP := 0x26 ;VK_DOWN := 0x28
	{
		if (hWnd = hEditI)
		{
			vKey := (wParam = 0x28) ? "{Down}" : "{Up}"
			ControlSend,, % vKey, % "ahk_id " hLbxI
			return 0
		}
		else if (hWnd = hEditF)
		{
			vKey := (wParam = 0x28) ? "{Down}" : "{Up}"
			ControlSend,, % vKey, % "ahk_id " hLbxF
			return 0
		}
		else
			return
	}
	VarSetCapacity(MSG, A_PtrSize=8?48:28, 0)
	NumPut(hWnd, &MSG, 0, "Ptr") ;hwnd
	NumPut(uMsg, &MSG, A_PtrSize=8?8:4, "UInt") ;message
	NumPut(wParam, &MSG, A_PtrSize=8?16:8, "UPtr") ;wParam
	NumPut(lParam, &MSG, A_PtrSize=8?24:12, "Ptr") ;lParam
	if DllCall("user32\TranslateAccelerator", Ptr,A_ScriptHwnd, Ptr,hAccel, Ptr,&MSG)
		return 0
}

;==================================================

ExitFunc()
{
	global oWB, hAccel
	ComObjError(False)
	oWB.Quit()
	ComObjError(True)
	DllCall("user32\DestroyAcceleratorTable", Ptr,hAccel)
	oWB := ""
}

;==================================================

GuiSize:
if (A_EventInfo = 1)
	return
GuiControl, Move, MyTreeView, % "H" (A_GuiHeight - 30) ; -30 for status bar and margins
return

;==================================================

GuiClose:
ExitApp

;==================================================

SubContents:
SubContentsEnter:
if (A_GuiEvent = "DoubleClick")
|| InStr(A_ThisLabel, "Enter")
{
	if (A_GuiEvent = "DoubleClick")
		hItem := A_EventInfo
	else
		hItem := TV_GetSelection()

	vText := oLVText[hItem]
	vText := StrReplace(vText, "/", "\")
	if !(vText = "")
		oWB.Navigate(vDir%vVersion% "\docs\" vText, hWnd)
}
if InStr(A_ThisLabel, "Enter")
{
	vState := TV_Get(hItem, "Expand")
	if TV_GetChild(hItem)
		if (vState := TV_Get(hItem, "Expand"))
			TV_Modify(hItem, "-Expand")
		else
			TV_Modify(hItem, "Expand")
}
return

;==================================================

SubIndex:
SubFav:
SubIndexEnter:
SubFavEnter:
;MsgBox, % A_ThisLabel "`r`n" A_Gui "`r`n[" A_GuiEvent "/" A_GuiControlEvent "]`r`n" A_GuiControl "`r`n" A_EventInfo
vLetter := InStr(A_ThisLabel, "Index") ? "I" : "F"
if InStr(A_ThisLabel, "Enter")
|| (A_GuiEvent = "DoubleClick")
	ControlGet, vLabel, Choice,,, % "ahk_id " hLbx%vLetter%
else
	return
if InStr(A_ThisLabel, "Index")
	vArray := "oIndex"
else
	vArray := "oFav"
;MsgBox, % vArray
if !%vArray%.HasKey("z" vLabel)
	return
vText := %vArray%["z" vLabel]
vText := StrReplace(vText, "/", "\")
;MsgBox, % vText
if !(vText = "")
	oWB.Navigate(vDir%vVersion% "\docs\" vText, hWnd)
return

;==================================================

SubIndexEdit:
;note: SubIndexEdit/SubFavEdit: not an ideal solution: A_GuiControl shows the text of the Edit control or the text of the hidden button
;MsgBox, % A_ThisLabel "`r`n" A_Gui "`r`n[" A_GuiEvent "/" A_GuiControlEvent "]`r`n" A_GuiControl "`r`n" A_EventInfo
if (A_GuiControl = "Hidden`r`nButton")
{
	Gosub, SubIndexEnter
	return
}
ControlGetText, vText,, % "ahk_id " hEditI
;'Control, ChooseString' is interpreted as a double-click
;so we use 'GuiControl, ChooseString' instead
;Control, ChooseString, % vText,, % "ahk_id " hLbxI
GuiControl, ChooseString, % hLbxI, % vText
return

SubFavEdit:
if (A_GuiControl = "Hidden`r`nButton")
{
	Gosub, SubFavEnter
	return
}
ControlGetText, vText,, % "ahk_id " hEditF
;Control, ChooseString, % vText,, % "ahk_id " hLbxF
GuiControl, ChooseString, % hLbxF, % vText
return

;==================================================

SubSearchEdit:
;ToolTip, % A_GuiEvent " " A_GuiControl
ControlGet, vDoSearchContents, Checked,,, % "ahk_id " hBtnC
ControlGet, vDoSearchTitles, Checked,,, % "ahk_id " hBtnT
;MsgBox, % vDoSearchContents vDoSearchTitles

;vNeedle := "DriveSpaceFree"
ControlGetText, vNeedle,, % "ahk_id " hCbxS

;update search history list
;from the help: To replace (overwrite) the list instead, include a pipe as the first character
vSearchHist := StrReplace(vSearchHist, "||", "|")
vSearchHist := "|" vNeedle "||" Trim(StrReplace("|" vSearchHist "|", "|" vNeedle "|"), "|")
GuiControl,, % hCbxS, % vSearchHist

if !IsObject(oSearchPath) ;keys are paths
	oSearchPath := {}
if !IsObject(oSearchTitle) ;keys are titles
	oSearchTitle := {}
if !IsObject(oSearchTitleUnique) ;keys are titles
	oSearchTitleUnique := {}

vTextS := ""
Loop, Files, % vDir%vVersion% "\*.htm", FR
{
	vPath := A_LoopFileFullPath
	SplitPath, vPath, vName, vDir, vExt, vNameNoExt, vDrive
	vIsRead := 0
	if (oSearchPath[vPath] = "")
	{
		vIsRead := 1
		FileRead, vText, % vPath
		vTitleOrig := JEE_HtmlGetTitle(vText)
		Loop
		{
			vTitle := vTitleOrig (A_Index=1?"":" (" (A_Index-1) ")")
			if !oSearchTitleUnique.HasKey("z" vTitle)
				break
		}
		oSearchTitleUnique["z" vTitle] := ""
		oSearchPath[vPath] := vTitle
		oSearchTitle[vTitle] := vPath
	}
	if (vDoSearchTitles && InStr(oSearchPath[vPath], vNeedle))
	{
		vTextS .= oSearchPath[vPath] "`t" vPath "`r`n"
		continue
	}
	if !vDoSearchContents
		continue
	if !vIsRead
		FileRead, vText, % vPath
	if InStr(vText, vNeedle)
		vTextS .= oSearchPath[vPath] "`t" vPath "`r`n"
}

LV_Delete()
;Gui, % hGui ":ListView", % hLV ;not needed as there's only one listview
Loop, Parse, vTextS, `n, `r
{
	vTemp := A_LoopField
	if (vTemp = "")
		continue
	oTemp := StrSplit(vTemp, "`t")
	;LV_Add((A_Index=1)?"Select":"", oTemp.1, oTemp.2)
	LV_Add((A_Index=1)?"Select":"", oTemp.1)
}
return

;==================================================

SubSearch:
SubSearchEnter:
if !(A_GuiEvent = "DoubleClick")
&& !InStr(A_ThisLabel, "Enter")
	return
ControlGetFocus, vCtlClassNN, % "ahk_id " hGui
if InStr(vCtlClassNN, "Button")
	return
ControlGet, vLabel, List, Focused Col1,, % "ahk_id " hLV
;MsgBox, % oSearchTitle[vLabel]
oWB.Navigate(oSearchTitle[vLabel], hWnd)
return

;==================================================

SubBtnHidden:
;MsgBox, % A_ThisLabel "`r`n" A_Gui "`r`n[" A_GuiEvent "/" A_GuiControlEvent "]`r`n" A_GuiControl "`r`n" A_EventInfo
ControlGetFocus, vCtlClassNN, % "ahk_id " hGui
;MsgBox, % vCtlClassNN
ControlGet, vTabNum, Tab,,, % "ahk_id " hTab
;MsgBox, % vTabNum
if (vTabNum = 3) && InStr(vCtlClassNN, "Button")
	Gosub, SubSearchEdit
if InStr(vCtlClassNN, "Edit")
	Gosub, % "Sub" oTabNum[vTabNum] "Edit"
else
	Gosub, % "Sub" oTabNum[vTabNum] "Enter"
return

;==================================================

;q::
Gui, Show
return

;==================================================

#IfWinActive, ahk_group WinGroupGui
;!c:: ;focus tab
;!n:: ;focus tab
;!s:: ;focus tab
;!i:: ;focus tab
;&Contents|I&ndex|&Search|Favor&ites
vLetter := SubStr(A_ThisHotkey, StrLen(A_ThisHotkey))
PostMessage, 0x1330, % oTabHotkey[vLetter]-1,,, % "ahk_id " hTab ;TCM_SETCURFOCUS := 0x1330
return
#IfWinActive

;==================================================

#IfWinActive, ahk_group WinGroupGui
;^1:: ;switch to AHK v1 page
;^2:: ;switch to AHK v2 page
;^+1:: ;open AHK v1 page
;^+2:: ;open AHK v2 page
SubTabSwitch1:
SubTabSwitch2:
SubTabSwitch3:
SubTabSwitch4:
;MsgBox, % A_ThisLabel
vThisHotkey := A_ThisHotkey
if InStr(A_ThisLabel, "Sub")
	vThisHotkey := StrSplit(vListTabSwitch, ",")[SubStr(A_ThisLabel, StrLen(StrSplit(vListTabSwitch, ",")))]
vNumD := InStr(vThisHotkey, "1") ? 1 : 2 ;destination
vNumS := (vNumD = 1) ? 2 : 1 ;source
vUrl := oWB.document.url
vPathPart := StrReplace(vUrl, "/", "\")
vPathPart := StrSplit(vPathPart, "\docs\")[2]
vPath := vDir%vNumD% "\docs\" vPathPart
if !FileExist(vPath)
	vPath := vDir%vNumD% "\docs\" oList%vNumS%%vNumD%[vPathPart]
;MsgBox, % vPath
if FileExist(vPath)
	if !InStr(vThisHotkey, "+")
		oWB.Navigate(vPath)
	else
		Run, % vPath
return
#IfWinActive

;==================================================

SubTabFocus1:
SubTabFocus2:
SubTabFocus3:
SubTabFocus4:
vIndex := SubStr(A_ThisLabel, StrLen(A_ThisLabel))
PostMessage, 0x1330, % vIndex-1,,, % "ahk_id " hTab ;TCM_SETCURFOCUS := 0x1330
return

;==================================================
- [EDIT:] Added one line to the script:
vSearchHist := StrReplace(vSearchHist, "||", "|")
The script was searching for the correct term, but the ComboBox was displaying an old search term.
- Note: the search can be slow, the first time it's used, but is lightning quick after that.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
lmstearn
Posts: 694
Joined: 11 Aug 2016, 02:32
Contact:

Re: HTML Help alternative via Internet Explorer

29 Mar 2021, 04:26

This is amazing.
- You use a tool like 7-Zip to decompile (extract) a chm file to a folder, and you specify that folder's path in the script.
Or devise an alternative compression method to chm to make it a viable replacement for AHK's help system. :)
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 167 guests