codekingpro/portable-devtools
114k
1import commctrl2import pythoncom3import win32api4import win32con5import win32ui6from pywin.mfc import dialog7 8 9class TLBrowserException(Exception):10 "TypeLib browser internal error"11 12 13error = TLBrowserException14 15FRAMEDLG_STD = win32con.WS_CAPTION | win32con.WS_SYSMENU16SS_STD = win32con.WS_CHILD | win32con.WS_VISIBLE17BS_STD = SS_STD | win32con.WS_TABSTOP18ES_STD = BS_STD | win32con.WS_BORDER19LBS_STD = (20 ES_STD | win32con.LBS_NOTIFY | win32con.LBS_NOINTEGRALHEIGHT | win32con.WS_VSCROLL21)22CBS_STD = ES_STD | win32con.CBS_NOINTEGRALHEIGHT | win32con.WS_VSCROLL23 24typekindmap = {25 pythoncom.TKIND_ENUM: "Enumeration",26 pythoncom.TKIND_RECORD: "Record",27 pythoncom.TKIND_MODULE: "Module",28 pythoncom.TKIND_INTERFACE: "Interface",29 pythoncom.TKIND_DISPATCH: "Dispatch",30 pythoncom.TKIND_COCLASS: "CoClass",31 pythoncom.TKIND_ALIAS: "Alias",32 pythoncom.TKIND_UNION: "Union",33}34 35TypeBrowseDialog_Parent = dialog.Dialog36 37 38class TypeBrowseDialog(TypeBrowseDialog_Parent):39 "Browse a type library"40 41 IDC_TYPELIST = 100042 IDC_MEMBERLIST = 100143 IDC_PARAMLIST = 100244 IDC_LISTVIEW = 100345 46 def __init__(self, typefile=None):47 TypeBrowseDialog_Parent.__init__(self, self.GetTemplate())48 try:49 if typefile:50 self.tlb = pythoncom.LoadTypeLib(typefile)51 else:52 self.tlb = None53 except pythoncom.ole_error:54 self.MessageBox("The file does not contain type information")55 self.tlb = None56 self.HookCommand(self.CmdTypeListbox, self.IDC_TYPELIST)57 self.HookCommand(self.CmdMemberListbox, self.IDC_MEMBERLIST)58 59 def OnAttachedObjectDeath(self):60 self.tlb = None61 self.typeinfo = None62 self.attr = None63 return TypeBrowseDialog_Parent.OnAttachedObjectDeath(self)64 65 def _SetupMenu(self):66 menu = win32ui.CreateMenu()67 flags = win32con.MF_STRING | win32con.MF_ENABLED68 menu.AppendMenu(flags, win32ui.ID_FILE_OPEN, "&Open...")69 menu.AppendMenu(flags, win32con.IDCANCEL, "&Close")70 mainMenu = win32ui.CreateMenu()71 mainMenu.AppendMenu(flags | win32con.MF_POPUP, menu.GetHandle(), "&File")72 self.SetMenu(mainMenu)73 self.HookCommand(self.OnFileOpen, win32ui.ID_FILE_OPEN)74 75 def OnFileOpen(self, id, code):76 openFlags = win32con.OFN_OVERWRITEPROMPT | win32con.OFN_FILEMUSTEXIST77 fspec = "Type Libraries (*.tlb, *.olb)|*.tlb;*.olb|OCX Files (*.ocx)|*.ocx|DLL's (*.dll)|*.dll|All Files (*.*)|*.*||"78 dlg = win32ui.CreateFileDialog(1, None, None, openFlags, fspec)79 if dlg.DoModal() == win32con.IDOK:80 try:81 self.tlb = pythoncom.LoadTypeLib(dlg.GetPathName())82 except pythoncom.ole_error:83 self.MessageBox("The file does not contain type information")84 self.tlb = None85 self._SetupTLB()86 87 def OnInitDialog(self):88 self._SetupMenu()89 self.typelb = self.GetDlgItem(self.IDC_TYPELIST)90 self.memberlb = self.GetDlgItem(self.IDC_MEMBERLIST)91 self.paramlb = self.GetDlgItem(self.IDC_PARAMLIST)92 self.listview = self.GetDlgItem(self.IDC_LISTVIEW)93 94 # Setup the listview columns95 itemDetails = (commctrl.LVCFMT_LEFT, 100, "Item", 0)96 self.listview.InsertColumn(0, itemDetails)97 itemDetails = (commctrl.LVCFMT_LEFT, 1024, "Details", 0)98 self.listview.InsertColumn(1, itemDetails)99 100 if self.tlb is None:101 self.OnFileOpen(None, None)102 else:103 self._SetupTLB()104 return TypeBrowseDialog_Parent.OnInitDialog(self)105 106 def _SetupTLB(self):107 self.typelb.ResetContent()108 self.memberlb.ResetContent()109 self.paramlb.ResetContent()110 self.typeinfo = None111 self.attr = None112 if self.tlb is None:113 return114 n = self.tlb.GetTypeInfoCount()115 for i in range(n):116 self.typelb.AddString(self.tlb.GetDocumentation(i)[0])117 118 def _SetListviewTextItems(self, items):119 self.listview.DeleteAllItems()120 index = -1121 for item in items:122 index = self.listview.InsertItem(index + 1, item[0])123 data = item[1]124 if data is None:125 data = ""126 self.listview.SetItemText(index, 1, data)127 128 def SetupAllInfoTypes(self):129 infos = self._GetMainInfoTypes() + self._GetMethodInfoTypes()130 self._SetListviewTextItems(infos)131 132 def _GetMainInfoTypes(self):133 pos = self.typelb.GetCurSel()134 if pos < 0:135 return []136 docinfo = self.tlb.GetDocumentation(pos)137 infos = [("GUID", str(self.attr[0]))]138 infos.append(("Help File", docinfo[3]))139 infos.append(("Help Context", str(docinfo[2])))140 try:141 infos.append(("Type Kind", typekindmap[self.tlb.GetTypeInfoType(pos)]))142 except:143 pass144 145 info = self.tlb.GetTypeInfo(pos)146 attr = info.GetTypeAttr()147 infos.append(("Attributes", str(attr)))148 149 for j in range(attr[8]):150 flags = info.GetImplTypeFlags(j)151 refInfo = info.GetRefTypeInfo(info.GetRefTypeOfImplType(j))152 doc = refInfo.GetDocumentation(-1)153 attr = refInfo.GetTypeAttr()154 typeKind = attr[5]155 typeFlags = attr[11]156 157 desc = doc[0]158 desc = desc + ", Flags=0x%x, typeKind=0x%x, typeFlags=0x%x" % (159 flags,160 typeKind,161 typeFlags,162 )163 if flags & pythoncom.IMPLTYPEFLAG_FSOURCE:164 desc = desc + "(Source)"165 infos.append(("Implements", desc))166 167 return infos168 169 def _GetMethodInfoTypes(self):170 pos = self.memberlb.GetCurSel()171 if pos < 0:172 return []173 174 realPos, isMethod = self._GetRealMemberPos(pos)175 ret = []176 if isMethod:177 funcDesc = self.typeinfo.GetFuncDesc(realPos)178 id = funcDesc[0]179 ret.append(("Func Desc", str(funcDesc)))180 else:181 id = self.typeinfo.GetVarDesc(realPos)[0]182 183 docinfo = self.typeinfo.GetDocumentation(id)184 ret.append(("Help String", docinfo[1]))185 ret.append(("Help Context", str(docinfo[2])))186 return ret187 188 def CmdTypeListbox(self, id, code):189 if code == win32con.LBN_SELCHANGE:190 pos = self.typelb.GetCurSel()191 if pos >= 0:192 self.memberlb.ResetContent()193 self.typeinfo = self.tlb.GetTypeInfo(pos)194 self.attr = self.typeinfo.GetTypeAttr()195 for i in range(self.attr[7]):196 id = self.typeinfo.GetVarDesc(i)[0]197 self.memberlb.AddString(self.typeinfo.GetNames(id)[0])198 for i in range(self.attr[6]):199 id = self.typeinfo.GetFuncDesc(i)[0]200 self.memberlb.AddString(self.typeinfo.GetNames(id)[0])201 self.SetupAllInfoTypes()202 return 1203 204 def _GetRealMemberPos(self, pos):205 pos = self.memberlb.GetCurSel()206 if pos >= self.attr[7]:207 return pos - self.attr[7], 1208 elif pos >= 0:209 return pos, 0210 else:211 raise error("The position is not valid")212 213 def CmdMemberListbox(self, id, code):214 if code == win32con.LBN_SELCHANGE:215 self.paramlb.ResetContent()216 pos = self.memberlb.GetCurSel()217 realPos, isMethod = self._GetRealMemberPos(pos)218 if isMethod:219 id = self.typeinfo.GetFuncDesc(realPos)[0]220 names = self.typeinfo.GetNames(id)221 for i in range(len(names)):222 if i > 0:223 self.paramlb.AddString(names[i])224 self.SetupAllInfoTypes()225 return 1226 227 def GetTemplate(self):228 "Return the template used to create this dialog"229 230 w = 272 # Dialog width231 h = 192 # Dialog height232 style = (233 FRAMEDLG_STD234 | win32con.WS_VISIBLE235 | win32con.DS_SETFONT236 | win32con.WS_MINIMIZEBOX237 )238 template = [239 ["Type Library Browser", (0, 0, w, h), style, None, (8, "Helv")],240 ]241 template.append([130, "&Type", -1, (10, 10, 62, 9), SS_STD | win32con.SS_LEFT])242 template.append([131, None, self.IDC_TYPELIST, (10, 20, 80, 80), LBS_STD])243 template.append(244 [130, "&Members", -1, (100, 10, 62, 9), SS_STD | win32con.SS_LEFT]245 )246 template.append([131, None, self.IDC_MEMBERLIST, (100, 20, 80, 80), LBS_STD])247 template.append(248 [130, "&Parameters", -1, (190, 10, 62, 9), SS_STD | win32con.SS_LEFT]249 )250 template.append([131, None, self.IDC_PARAMLIST, (190, 20, 75, 80), LBS_STD])251 252 lvStyle = (253 SS_STD254 | commctrl.LVS_REPORT255 | commctrl.LVS_AUTOARRANGE256 | commctrl.LVS_ALIGNLEFT257 | win32con.WS_BORDER258 | win32con.WS_TABSTOP259 )260 template.append(261 ["SysListView32", "", self.IDC_LISTVIEW, (10, 110, 255, 65), lvStyle]262 )263 264 return template265 266 267if __name__ == "__main__":268 import sys269 270 fname = None271 try:272 fname = sys.argv[1]273 except:274 pass275 dlg = TypeBrowseDialog(fname)276 if win32api.GetConsoleTitle(): # empty string w/o console277 dlg.DoModal()278 else:279 dlg.CreateWindow(win32ui.GetMainFrame())280 