Spaces:
Sleeping
Sleeping
# help.py - help utilities for PythonWin. | |
import os | |
import regutil | |
import win32api | |
import win32con | |
import win32ui | |
htmlhelp_handle = None | |
html_help_command_translators = { | |
win32con.HELP_CONTENTS: 1, # HH_DISPLAY_TOC | |
win32con.HELP_CONTEXT: 15, # HH_HELP_CONTEXT | |
win32con.HELP_FINDER: 1, # HH_DISPLAY_TOC | |
} | |
def FinalizeHelp(): | |
global htmlhelp_handle | |
if htmlhelp_handle is not None: | |
import win32help | |
try: | |
# frame = win32ui.GetMainFrame().GetSafeHwnd() | |
frame = 0 | |
win32help.HtmlHelp(frame, None, win32help.HH_UNINITIALIZE, htmlhelp_handle) | |
except win32help.error: | |
print("Failed to finalize htmlhelp!") | |
htmlhelp_handle = None | |
def OpenHelpFile(fileName, helpCmd=None, helpArg=None): | |
"Open a help file, given a full path" | |
# default help arg. | |
win32ui.DoWaitCursor(1) | |
try: | |
if helpCmd is None: | |
helpCmd = win32con.HELP_CONTENTS | |
ext = os.path.splitext(fileName)[1].lower() | |
if ext == ".hlp": | |
win32api.WinHelp( | |
win32ui.GetMainFrame().GetSafeHwnd(), fileName, helpCmd, helpArg | |
) | |
# XXX - using the htmlhelp API wreaks havoc with keyboard shortcuts | |
# so we disable it, forcing ShellExecute, which works fine (but | |
# doesn't close the help file when Pythonwin is closed. | |
# Tom Heller also points out http://www.microsoft.com/mind/0499/faq/faq0499.asp, | |
# which may or may not be related. | |
elif 0 and ext == ".chm": | |
import win32help | |
global htmlhelp_handle | |
helpCmd = html_help_command_translators.get(helpCmd, helpCmd) | |
# frame = win32ui.GetMainFrame().GetSafeHwnd() | |
frame = 0 # Dont want it overlapping ours! | |
if htmlhelp_handle is None: | |
htmlhelp_hwnd, htmlhelp_handle = win32help.HtmlHelp( | |
frame, None, win32help.HH_INITIALIZE | |
) | |
win32help.HtmlHelp(frame, fileName, helpCmd, helpArg) | |
else: | |
# Hope that the extension is registered, and we know what to do! | |
win32api.ShellExecute(0, "open", fileName, None, "", win32con.SW_SHOW) | |
return fileName | |
finally: | |
win32ui.DoWaitCursor(-1) | |
def ListAllHelpFiles(): | |
ret = [] | |
ret = _ListAllHelpFilesInRoot(win32con.HKEY_LOCAL_MACHINE) | |
# Ensure we don't get dups. | |
for item in _ListAllHelpFilesInRoot(win32con.HKEY_CURRENT_USER): | |
if item not in ret: | |
ret.append(item) | |
return ret | |
def _ListAllHelpFilesInRoot(root): | |
"""Returns a list of (helpDesc, helpFname) for all registered help files""" | |
import regutil | |
retList = [] | |
try: | |
key = win32api.RegOpenKey( | |
root, regutil.BuildDefaultPythonKey() + "\\Help", 0, win32con.KEY_READ | |
) | |
except win32api.error as exc: | |
import winerror | |
if exc.winerror != winerror.ERROR_FILE_NOT_FOUND: | |
raise | |
return retList | |
try: | |
keyNo = 0 | |
while 1: | |
try: | |
helpDesc = win32api.RegEnumKey(key, keyNo) | |
helpFile = win32api.RegQueryValue(key, helpDesc) | |
retList.append((helpDesc, helpFile)) | |
keyNo = keyNo + 1 | |
except win32api.error as exc: | |
import winerror | |
if exc.winerror != winerror.ERROR_NO_MORE_ITEMS: | |
raise | |
break | |
finally: | |
win32api.RegCloseKey(key) | |
return retList | |
def SelectAndRunHelpFile(): | |
from pywin.dialogs import list | |
helpFiles = ListAllHelpFiles() | |
if len(helpFiles) == 1: | |
# only 1 help file registered - probably ours - no point asking | |
index = 0 | |
else: | |
index = list.SelectFromLists("Select Help file", helpFiles, ["Title"]) | |
if index is not None: | |
OpenHelpFile(helpFiles[index][1]) | |
helpIDMap = None | |
def SetHelpMenuOtherHelp(mainMenu): | |
"""Modifies the main Help Menu to handle all registered help files. | |
mainMenu -- The main menu to modify - usually from docTemplate.GetSharedMenu() | |
""" | |
# Load all help files from the registry. | |
global helpIDMap | |
if helpIDMap is None: | |
helpIDMap = {} | |
cmdID = win32ui.ID_HELP_OTHER | |
excludeList = ["Main Python Documentation", "Pythonwin Reference"] | |
firstList = ListAllHelpFiles() | |
# We actually want to not only exclude these entries, but | |
# their help file names (as many entries may share the same name) | |
excludeFnames = [] | |
for desc, fname in firstList: | |
if desc in excludeList: | |
excludeFnames.append(fname) | |
helpDescs = [] | |
for desc, fname in firstList: | |
if fname not in excludeFnames: | |
helpIDMap[cmdID] = (desc, fname) | |
win32ui.GetMainFrame().HookCommand(HandleHelpOtherCommand, cmdID) | |
cmdID = cmdID + 1 | |
helpMenu = mainMenu.GetSubMenu( | |
mainMenu.GetMenuItemCount() - 1 | |
) # Help menu always last. | |
otherHelpMenuPos = 2 # cant search for ID, as sub-menu has no ID. | |
otherMenu = helpMenu.GetSubMenu(otherHelpMenuPos) | |
while otherMenu.GetMenuItemCount(): | |
otherMenu.DeleteMenu(0, win32con.MF_BYPOSITION) | |
if helpIDMap: | |
for id, (desc, fname) in helpIDMap.items(): | |
otherMenu.AppendMenu(win32con.MF_ENABLED | win32con.MF_STRING, id, desc) | |
else: | |
helpMenu.EnableMenuItem( | |
otherHelpMenuPos, win32con.MF_BYPOSITION | win32con.MF_GRAYED | |
) | |
def HandleHelpOtherCommand(cmd, code): | |
OpenHelpFile(helpIDMap[cmd][1]) | |