tlbrowse.py 7.6 KB

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