Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tlbrowse.py 9.3KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. import commctrl
  2. import pythoncom
  3. import win32api
  4. import win32con
  5. import win32ui
  6. from pywin.mfc import dialog
  7. class TLBrowserException(Exception):
  8. "TypeLib browser internal error"
  9. error = TLBrowserException
  10. FRAMEDLG_STD = win32con.WS_CAPTION | win32con.WS_SYSMENU
  11. SS_STD = win32con.WS_CHILD | win32con.WS_VISIBLE
  12. BS_STD = SS_STD | win32con.WS_TABSTOP
  13. ES_STD = BS_STD | win32con.WS_BORDER
  14. LBS_STD = (
  15. ES_STD | win32con.LBS_NOTIFY | win32con.LBS_NOINTEGRALHEIGHT | win32con.WS_VSCROLL
  16. )
  17. CBS_STD = ES_STD | win32con.CBS_NOINTEGRALHEIGHT | win32con.WS_VSCROLL
  18. typekindmap = {
  19. pythoncom.TKIND_ENUM: "Enumeration",
  20. pythoncom.TKIND_RECORD: "Record",
  21. pythoncom.TKIND_MODULE: "Module",
  22. pythoncom.TKIND_INTERFACE: "Interface",
  23. pythoncom.TKIND_DISPATCH: "Dispatch",
  24. pythoncom.TKIND_COCLASS: "CoClass",
  25. pythoncom.TKIND_ALIAS: "Alias",
  26. pythoncom.TKIND_UNION: "Union",
  27. }
  28. TypeBrowseDialog_Parent = dialog.Dialog
  29. class TypeBrowseDialog(TypeBrowseDialog_Parent):
  30. "Browse a type library"
  31. IDC_TYPELIST = 1000
  32. IDC_MEMBERLIST = 1001
  33. IDC_PARAMLIST = 1002
  34. IDC_LISTVIEW = 1003
  35. def __init__(self, typefile=None):
  36. TypeBrowseDialog_Parent.__init__(self, self.GetTemplate())
  37. try:
  38. if typefile:
  39. self.tlb = pythoncom.LoadTypeLib(typefile)
  40. else:
  41. self.tlb = None
  42. except pythoncom.ole_error:
  43. self.MessageBox("The file does not contain type information")
  44. self.tlb = None
  45. self.HookCommand(self.CmdTypeListbox, self.IDC_TYPELIST)
  46. self.HookCommand(self.CmdMemberListbox, self.IDC_MEMBERLIST)
  47. def OnAttachedObjectDeath(self):
  48. self.tlb = None
  49. self.typeinfo = None
  50. self.attr = None
  51. return TypeBrowseDialog_Parent.OnAttachedObjectDeath(self)
  52. def _SetupMenu(self):
  53. menu = win32ui.CreateMenu()
  54. flags = win32con.MF_STRING | win32con.MF_ENABLED
  55. menu.AppendMenu(flags, win32ui.ID_FILE_OPEN, "&Open...")
  56. menu.AppendMenu(flags, win32con.IDCANCEL, "&Close")
  57. mainMenu = win32ui.CreateMenu()
  58. mainMenu.AppendMenu(flags | win32con.MF_POPUP, menu.GetHandle(), "&File")
  59. self.SetMenu(mainMenu)
  60. self.HookCommand(self.OnFileOpen, win32ui.ID_FILE_OPEN)
  61. def OnFileOpen(self, id, code):
  62. openFlags = win32con.OFN_OVERWRITEPROMPT | win32con.OFN_FILEMUSTEXIST
  63. fspec = "Type Libraries (*.tlb, *.olb)|*.tlb;*.olb|OCX Files (*.ocx)|*.ocx|DLL's (*.dll)|*.dll|All Files (*.*)|*.*||"
  64. dlg = win32ui.CreateFileDialog(1, None, None, openFlags, fspec)
  65. if dlg.DoModal() == win32con.IDOK:
  66. try:
  67. self.tlb = pythoncom.LoadTypeLib(dlg.GetPathName())
  68. except pythoncom.ole_error:
  69. self.MessageBox("The file does not contain type information")
  70. self.tlb = None
  71. self._SetupTLB()
  72. def OnInitDialog(self):
  73. self._SetupMenu()
  74. self.typelb = self.GetDlgItem(self.IDC_TYPELIST)
  75. self.memberlb = self.GetDlgItem(self.IDC_MEMBERLIST)
  76. self.paramlb = self.GetDlgItem(self.IDC_PARAMLIST)
  77. self.listview = self.GetDlgItem(self.IDC_LISTVIEW)
  78. # Setup the listview columns
  79. itemDetails = (commctrl.LVCFMT_LEFT, 100, "Item", 0)
  80. self.listview.InsertColumn(0, itemDetails)
  81. itemDetails = (commctrl.LVCFMT_LEFT, 1024, "Details", 0)
  82. self.listview.InsertColumn(1, itemDetails)
  83. if self.tlb is None:
  84. self.OnFileOpen(None, None)
  85. else:
  86. self._SetupTLB()
  87. return TypeBrowseDialog_Parent.OnInitDialog(self)
  88. def _SetupTLB(self):
  89. self.typelb.ResetContent()
  90. self.memberlb.ResetContent()
  91. self.paramlb.ResetContent()
  92. self.typeinfo = None
  93. self.attr = None
  94. if self.tlb is None:
  95. return
  96. n = self.tlb.GetTypeInfoCount()
  97. for i in range(n):
  98. self.typelb.AddString(self.tlb.GetDocumentation(i)[0])
  99. def _SetListviewTextItems(self, items):
  100. self.listview.DeleteAllItems()
  101. index = -1
  102. for item in items:
  103. index = self.listview.InsertItem(index + 1, item[0])
  104. data = item[1]
  105. if data is None:
  106. data = ""
  107. self.listview.SetItemText(index, 1, data)
  108. def SetupAllInfoTypes(self):
  109. infos = self._GetMainInfoTypes() + self._GetMethodInfoTypes()
  110. self._SetListviewTextItems(infos)
  111. def _GetMainInfoTypes(self):
  112. pos = self.typelb.GetCurSel()
  113. if pos < 0:
  114. return []
  115. docinfo = self.tlb.GetDocumentation(pos)
  116. infos = [("GUID", str(self.attr[0]))]
  117. infos.append(("Help File", docinfo[3]))
  118. infos.append(("Help Context", str(docinfo[2])))
  119. try:
  120. infos.append(("Type Kind", typekindmap[self.tlb.GetTypeInfoType(pos)]))
  121. except:
  122. pass
  123. info = self.tlb.GetTypeInfo(pos)
  124. attr = info.GetTypeAttr()
  125. infos.append(("Attributes", str(attr)))
  126. for j in range(attr[8]):
  127. flags = info.GetImplTypeFlags(j)
  128. refInfo = info.GetRefTypeInfo(info.GetRefTypeOfImplType(j))
  129. doc = refInfo.GetDocumentation(-1)
  130. attr = refInfo.GetTypeAttr()
  131. typeKind = attr[5]
  132. typeFlags = attr[11]
  133. desc = doc[0]
  134. desc = desc + ", Flags=0x%x, typeKind=0x%x, typeFlags=0x%x" % (
  135. flags,
  136. typeKind,
  137. typeFlags,
  138. )
  139. if flags & pythoncom.IMPLTYPEFLAG_FSOURCE:
  140. desc = desc + "(Source)"
  141. infos.append(("Implements", desc))
  142. return infos
  143. def _GetMethodInfoTypes(self):
  144. pos = self.memberlb.GetCurSel()
  145. if pos < 0:
  146. return []
  147. realPos, isMethod = self._GetRealMemberPos(pos)
  148. ret = []
  149. if isMethod:
  150. funcDesc = self.typeinfo.GetFuncDesc(realPos)
  151. id = funcDesc[0]
  152. ret.append(("Func Desc", str(funcDesc)))
  153. else:
  154. id = self.typeinfo.GetVarDesc(realPos)[0]
  155. docinfo = self.typeinfo.GetDocumentation(id)
  156. ret.append(("Help String", docinfo[1]))
  157. ret.append(("Help Context", str(docinfo[2])))
  158. return ret
  159. def CmdTypeListbox(self, id, code):
  160. if code == win32con.LBN_SELCHANGE:
  161. pos = self.typelb.GetCurSel()
  162. if pos >= 0:
  163. self.memberlb.ResetContent()
  164. self.typeinfo = self.tlb.GetTypeInfo(pos)
  165. self.attr = self.typeinfo.GetTypeAttr()
  166. for i in range(self.attr[7]):
  167. id = self.typeinfo.GetVarDesc(i)[0]
  168. self.memberlb.AddString(self.typeinfo.GetNames(id)[0])
  169. for i in range(self.attr[6]):
  170. id = self.typeinfo.GetFuncDesc(i)[0]
  171. self.memberlb.AddString(self.typeinfo.GetNames(id)[0])
  172. self.SetupAllInfoTypes()
  173. return 1
  174. def _GetRealMemberPos(self, pos):
  175. pos = self.memberlb.GetCurSel()
  176. if pos >= self.attr[7]:
  177. return pos - self.attr[7], 1
  178. elif pos >= 0:
  179. return pos, 0
  180. else:
  181. raise error("The position is not valid")
  182. def CmdMemberListbox(self, id, code):
  183. if code == win32con.LBN_SELCHANGE:
  184. self.paramlb.ResetContent()
  185. pos = self.memberlb.GetCurSel()
  186. realPos, isMethod = self._GetRealMemberPos(pos)
  187. if isMethod:
  188. id = self.typeinfo.GetFuncDesc(realPos)[0]
  189. names = self.typeinfo.GetNames(id)
  190. for i in range(len(names)):
  191. if i > 0:
  192. self.paramlb.AddString(names[i])
  193. self.SetupAllInfoTypes()
  194. return 1
  195. def GetTemplate(self):
  196. "Return the template used to create this dialog"
  197. w = 272 # Dialog width
  198. h = 192 # Dialog height
  199. style = (
  200. FRAMEDLG_STD
  201. | win32con.WS_VISIBLE
  202. | win32con.DS_SETFONT
  203. | win32con.WS_MINIMIZEBOX
  204. )
  205. template = [
  206. ["Type Library Browser", (0, 0, w, h), style, None, (8, "Helv")],
  207. ]
  208. template.append([130, "&Type", -1, (10, 10, 62, 9), SS_STD | win32con.SS_LEFT])
  209. template.append([131, None, self.IDC_TYPELIST, (10, 20, 80, 80), LBS_STD])
  210. template.append(
  211. [130, "&Members", -1, (100, 10, 62, 9), SS_STD | win32con.SS_LEFT]
  212. )
  213. template.append([131, None, self.IDC_MEMBERLIST, (100, 20, 80, 80), LBS_STD])
  214. template.append(
  215. [130, "&Parameters", -1, (190, 10, 62, 9), SS_STD | win32con.SS_LEFT]
  216. )
  217. template.append([131, None, self.IDC_PARAMLIST, (190, 20, 75, 80), LBS_STD])
  218. lvStyle = (
  219. SS_STD
  220. | commctrl.LVS_REPORT
  221. | commctrl.LVS_AUTOARRANGE
  222. | commctrl.LVS_ALIGNLEFT
  223. | win32con.WS_BORDER
  224. | win32con.WS_TABSTOP
  225. )
  226. template.append(
  227. ["SysListView32", "", self.IDC_LISTVIEW, (10, 110, 255, 65), lvStyle]
  228. )
  229. return template
  230. if __name__ == "__main__":
  231. import sys
  232. fname = None
  233. try:
  234. fname = sys.argv[1]
  235. except:
  236. pass
  237. dlg = TypeBrowseDialog(fname)
  238. if win32api.GetConsoleTitle(): # empty string w/o console
  239. dlg.DoModal()
  240. else:
  241. dlg.CreateWindow(win32ui.GetMainFrame())