codekingpro/portable-devtools
115k
1# help.py - help utilities for PythonWin.2import os3 4import regutil5import win32api6import win32con7import win32ui8 9htmlhelp_handle = None10 11html_help_command_translators = {12 win32con.HELP_CONTENTS: 1, # HH_DISPLAY_TOC13 win32con.HELP_CONTEXT: 15, # HH_HELP_CONTEXT14 win32con.HELP_FINDER: 1, # HH_DISPLAY_TOC15}16 17 18def FinalizeHelp():19 global htmlhelp_handle20 if htmlhelp_handle is not None:21 import win32help22 23 try:24 # frame = win32ui.GetMainFrame().GetSafeHwnd()25 frame = 026 win32help.HtmlHelp(frame, None, win32help.HH_UNINITIALIZE, htmlhelp_handle)27 except win32help.error:28 print("Failed to finalize htmlhelp!")29 htmlhelp_handle = None30 31 32def OpenHelpFile(fileName, helpCmd=None, helpArg=None):33 "Open a help file, given a full path"34 # default help arg.35 win32ui.DoWaitCursor(1)36 try:37 if helpCmd is None:38 helpCmd = win32con.HELP_CONTENTS39 ext = os.path.splitext(fileName)[1].lower()40 if ext == ".hlp":41 win32api.WinHelp(42 win32ui.GetMainFrame().GetSafeHwnd(), fileName, helpCmd, helpArg43 )44 # XXX - using the htmlhelp API wreaks havoc with keyboard shortcuts45 # so we disable it, forcing ShellExecute, which works fine (but46 # doesn't close the help file when Pythonwin is closed.47 # Tom Heller also points out http://www.microsoft.com/mind/0499/faq/faq0499.asp,48 # which may or may not be related.49 elif 0 and ext == ".chm":50 import win32help51 52 global htmlhelp_handle53 helpCmd = html_help_command_translators.get(helpCmd, helpCmd)54 # frame = win32ui.GetMainFrame().GetSafeHwnd()55 frame = 0 # Dont want it overlapping ours!56 if htmlhelp_handle is None:57 htmlhelp_hwnd, htmlhelp_handle = win32help.HtmlHelp(58 frame, None, win32help.HH_INITIALIZE59 )60 win32help.HtmlHelp(frame, fileName, helpCmd, helpArg)61 else:62 # Hope that the extension is registered, and we know what to do!63 win32api.ShellExecute(0, "open", fileName, None, "", win32con.SW_SHOW)64 return fileName65 finally:66 win32ui.DoWaitCursor(-1)67 68 69def ListAllHelpFiles():70 ret = []71 ret = _ListAllHelpFilesInRoot(win32con.HKEY_LOCAL_MACHINE)72 # Ensure we don't get dups.73 for item in _ListAllHelpFilesInRoot(win32con.HKEY_CURRENT_USER):74 if item not in ret:75 ret.append(item)76 return ret77 78 79def _ListAllHelpFilesInRoot(root):80 """Returns a list of (helpDesc, helpFname) for all registered help files"""81 import regutil82 83 retList = []84 try:85 key = win32api.RegOpenKey(86 root, regutil.BuildDefaultPythonKey() + "\\Help", 0, win32con.KEY_READ87 )88 except win32api.error as exc:89 import winerror90 91 if exc.winerror != winerror.ERROR_FILE_NOT_FOUND:92 raise93 return retList94 try:95 keyNo = 096 while 1:97 try:98 helpDesc = win32api.RegEnumKey(key, keyNo)99 helpFile = win32api.RegQueryValue(key, helpDesc)100 retList.append((helpDesc, helpFile))101 keyNo = keyNo + 1102 except win32api.error as exc:103 import winerror104 105 if exc.winerror != winerror.ERROR_NO_MORE_ITEMS:106 raise107 break108 finally:109 win32api.RegCloseKey(key)110 return retList111 112 113def SelectAndRunHelpFile():114 from pywin.dialogs import list115 116 helpFiles = ListAllHelpFiles()117 if len(helpFiles) == 1:118 # only 1 help file registered - probably ours - no point asking119 index = 0120 else:121 index = list.SelectFromLists("Select Help file", helpFiles, ["Title"])122 if index is not None:123 OpenHelpFile(helpFiles[index][1])124 125 126helpIDMap = None127 128 129def SetHelpMenuOtherHelp(mainMenu):130 """Modifies the main Help Menu to handle all registered help files.131 mainMenu -- The main menu to modify - usually from docTemplate.GetSharedMenu()132 """133 134 # Load all help files from the registry.135 global helpIDMap136 if helpIDMap is None:137 helpIDMap = {}138 cmdID = win32ui.ID_HELP_OTHER139 excludeList = ["Main Python Documentation", "Pythonwin Reference"]140 firstList = ListAllHelpFiles()141 # We actually want to not only exclude these entries, but142 # their help file names (as many entries may share the same name)143 excludeFnames = []144 for desc, fname in firstList:145 if desc in excludeList:146 excludeFnames.append(fname)147 148 helpDescs = []149 for desc, fname in firstList:150 if fname not in excludeFnames:151 helpIDMap[cmdID] = (desc, fname)152 win32ui.GetMainFrame().HookCommand(HandleHelpOtherCommand, cmdID)153 cmdID = cmdID + 1154 155 helpMenu = mainMenu.GetSubMenu(156 mainMenu.GetMenuItemCount() - 1157 ) # Help menu always last.158 otherHelpMenuPos = 2 # cant search for ID, as sub-menu has no ID.159 otherMenu = helpMenu.GetSubMenu(otherHelpMenuPos)160 while otherMenu.GetMenuItemCount():161 otherMenu.DeleteMenu(0, win32con.MF_BYPOSITION)162 163 if helpIDMap:164 for id, (desc, fname) in helpIDMap.items():165 otherMenu.AppendMenu(win32con.MF_ENABLED | win32con.MF_STRING, id, desc)166 else:167 helpMenu.EnableMenuItem(168 otherHelpMenuPos, win32con.MF_BYPOSITION | win32con.MF_GRAYED169 )170 171 172def HandleHelpOtherCommand(cmd, code):173 OpenHelpFile(helpIDMap[cmd][1])174 