help.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. # help.py - help utilities for PythonWin.
  2. import win32api
  3. import win32con
  4. import win32ui
  5. import string
  6. import sys
  7. import regutil
  8. import string, os
  9. htmlhelp_handle = None
  10. html_help_command_translators = {
  11. win32con.HELP_CONTENTS : 1, # HH_DISPLAY_TOC
  12. win32con.HELP_CONTEXT : 15, # HH_HELP_CONTEXT
  13. win32con.HELP_FINDER : 1, # HH_DISPLAY_TOC
  14. }
  15. def FinalizeHelp():
  16. global htmlhelp_handle
  17. if htmlhelp_handle is not None:
  18. import win32help
  19. try:
  20. #frame = win32ui.GetMainFrame().GetSafeHwnd()
  21. frame = 0
  22. win32help.HtmlHelp(frame, None, win32help.HH_UNINITIALIZE, htmlhelp_handle)
  23. except win32help.error:
  24. print("Failed to finalize htmlhelp!")
  25. htmlhelp_handle = None
  26. def OpenHelpFile(fileName, helpCmd = None, helpArg = None):
  27. "Open a help file, given a full path"
  28. # default help arg.
  29. win32ui.DoWaitCursor(1)
  30. try:
  31. if helpCmd is None: helpCmd = win32con.HELP_CONTENTS
  32. ext = os.path.splitext(fileName)[1].lower()
  33. if ext == ".hlp":
  34. win32api.WinHelp( win32ui.GetMainFrame().GetSafeHwnd(), fileName, helpCmd, helpArg)
  35. # XXX - using the htmlhelp API wreaks havoc with keyboard shortcuts
  36. # so we disable it, forcing ShellExecute, which works fine (but
  37. # doesn't close the help file when Pythonwin is closed.
  38. # Tom Heller also points out http://www.microsoft.com/mind/0499/faq/faq0499.asp,
  39. # which may or may not be related.
  40. elif 0 and ext == ".chm":
  41. import win32help
  42. global htmlhelp_handle
  43. helpCmd = html_help_command_translators.get(helpCmd, helpCmd)
  44. #frame = win32ui.GetMainFrame().GetSafeHwnd()
  45. frame = 0 # Dont want it overlapping ours!
  46. if htmlhelp_handle is None:
  47. htmlhelp_hwnd, htmlhelp_handle = win32help.HtmlHelp(frame, None, win32help.HH_INITIALIZE)
  48. win32help.HtmlHelp(frame, fileName, helpCmd, helpArg)
  49. else:
  50. # Hope that the extension is registered, and we know what to do!
  51. win32api.ShellExecute(0, "open", fileName, None, "", win32con.SW_SHOW)
  52. return fileName
  53. finally:
  54. win32ui.DoWaitCursor(-1)
  55. def ListAllHelpFiles():
  56. ret = []
  57. ret = _ListAllHelpFilesInRoot(win32con.HKEY_LOCAL_MACHINE)
  58. # Ensure we don't get dups.
  59. for item in _ListAllHelpFilesInRoot(win32con.HKEY_CURRENT_USER):
  60. if item not in ret:
  61. ret.append(item)
  62. return ret
  63. def _ListAllHelpFilesInRoot(root):
  64. """Returns a list of (helpDesc, helpFname) for all registered help files
  65. """
  66. import regutil
  67. retList = []
  68. try:
  69. key = win32api.RegOpenKey(root, regutil.BuildDefaultPythonKey() + "\\Help", 0, win32con.KEY_READ)
  70. except win32api.error as exc:
  71. import winerror
  72. if exc.winerror!=winerror.ERROR_FILE_NOT_FOUND:
  73. raise
  74. return retList
  75. try:
  76. keyNo = 0
  77. while 1:
  78. try:
  79. helpDesc = win32api.RegEnumKey(key, keyNo)
  80. helpFile = win32api.RegQueryValue(key, helpDesc)
  81. retList.append((helpDesc, helpFile))
  82. keyNo = keyNo + 1
  83. except win32api.error as exc:
  84. import winerror
  85. if exc.winerror!=winerror.ERROR_NO_MORE_ITEMS:
  86. raise
  87. break
  88. finally:
  89. win32api.RegCloseKey(key)
  90. return retList
  91. def SelectAndRunHelpFile():
  92. from pywin.dialogs import list
  93. helpFiles = ListAllHelpFiles()
  94. if len(helpFiles)==1:
  95. # only 1 help file registered - probably ours - no point asking
  96. index = 0
  97. else:
  98. index = list.SelectFromLists("Select Help file", helpFiles, ["Title"])
  99. if index is not None:
  100. OpenHelpFile(helpFiles[index][1])
  101. helpIDMap = None
  102. def SetHelpMenuOtherHelp(mainMenu):
  103. """Modifies the main Help Menu to handle all registered help files.
  104. mainMenu -- The main menu to modify - usually from docTemplate.GetSharedMenu()
  105. """
  106. # Load all help files from the registry.
  107. global helpIDMap
  108. if helpIDMap is None:
  109. helpIDMap = {}
  110. cmdID = win32ui.ID_HELP_OTHER
  111. excludeList = ['Main Python Documentation', 'Pythonwin Reference']
  112. firstList = ListAllHelpFiles()
  113. # We actually want to not only exclude these entries, but
  114. # their help file names (as many entries may share the same name)
  115. excludeFnames = []
  116. for desc, fname in firstList:
  117. if desc in excludeList:
  118. excludeFnames.append(fname)
  119. helpDescs = []
  120. for desc, fname in firstList:
  121. if fname not in excludeFnames:
  122. helpIDMap[cmdID] = (desc, fname)
  123. win32ui.GetMainFrame().HookCommand(HandleHelpOtherCommand, cmdID)
  124. cmdID = cmdID + 1
  125. helpMenu = mainMenu.GetSubMenu(mainMenu.GetMenuItemCount()-1) # Help menu always last.
  126. otherHelpMenuPos = 2 # cant search for ID, as sub-menu has no ID.
  127. otherMenu = helpMenu.GetSubMenu(otherHelpMenuPos)
  128. while otherMenu.GetMenuItemCount():
  129. otherMenu.DeleteMenu(0, win32con.MF_BYPOSITION)
  130. if helpIDMap:
  131. for id, (desc, fname) in helpIDMap.items():
  132. otherMenu.AppendMenu(win32con.MF_ENABLED|win32con.MF_STRING,id, desc)
  133. else:
  134. helpMenu.EnableMenuItem(otherHelpMenuPos, win32con.MF_BYPOSITION | win32con.MF_GRAYED)
  135. def HandleHelpOtherCommand(cmd, code):
  136. OpenHelpFile(helpIDMap[cmd][1])