📄 folderselector.py
字号:
from __future__ import generatorsimport sys, osimport win32conimport commctrlimport win32apiimport win32guiimport winerrorimport struct, arrayimport dlgutilsfrom pprint import pprint # debugging onlyverbose = 0def INDEXTOSTATEIMAGEMASK(i): # from new commctrl.h return i << 12IIL_UNCHECKED = 1IIL_CHECKED = 2try: True, Falseexcept NameError: # Maintain compatibility with Python 2.2 True, False = 1, 0# Helpers for building the folder listclass FolderSpec: def __init__(self, folder_id, name, ignore_eids = None): self.folder_id = folder_id self.name = name self.children = [] self.ignore_eids = ignore_eids def dump(self, level=0): prefix = " " * level print prefix + self.name for c in self.children: c.dump(level+1)# Oh, lord help us.# We started with a CDO version - but CDO sucks for lots of reasons I# wont even start to mention.# So we moved to an Extended MAPI version with is nice and fast - screams# along! Except it doesn't work in all cases with Exchange (which# strikes Mark as extremely strange given that the Extended MAPI Python# bindings were developed against an Exchange Server - but Mark doesn't# have an Exchange server handy these days, and really doesn't give a# rat's arse <wink>).# So finally we have an Outlook object model version!# But then Tony Meyer came to the rescue - he noticed that we were# simply using short-term EID values for Exchange Folders - so now that# is solved, we are back to the Extended MAPI version.# These variants were deleted by MarkH - cvs is your friend :)# Last appeared in Rev 1.10########################################################################### An extended MAPI version#########################################################################from win32com.mapi import mapi, mapiutilfrom win32com.mapi.mapitags import *import pythoncomdef _BuildFoldersMAPI(manager, folder_spec): # This is called dynamically as folders are expanded. dlgutils.SetWaitCursor(1) folder = manager.message_store.GetFolder(folder_spec.folder_id).OpenEntry() # Get the hierarchy table for it. table = folder.GetHierarchyTable(0) children = [] order = (((PR_DISPLAY_NAME_A, mapi.TABLE_SORT_ASCEND),),0,0) rows = mapi.HrQueryAllRows(table, (PR_ENTRYID, PR_STORE_ENTRYID, PR_DISPLAY_NAME_A), None, order, 0) if verbose: print "Rows for sub-folder of", folder_spec.name, "-", folder_spec.folder_id pprint(rows) for (eid_tag, eid),(storeeid_tag, store_eid), (name_tag, name) in rows: # Note the eid we get here is short-term - hence we must # re-fetch from the object itself (which is what our manager does, # so no need to do it explicitly - just believe folder.id over eid) ignore = False for check_eid in folder_spec.ignore_eids: if manager.message_store.session.CompareEntryIDs(check_eid, eid): ignore = True break if ignore: continue temp_id = mapi.HexFromBin(store_eid), mapi.HexFromBin(eid) try: # may get MsgStoreException for GetFolder, or # a mapi exception for the underlying MAPI stuff we then call. # Either way, just skip it. child_folder = manager.message_store.GetFolder(temp_id) spec = FolderSpec(child_folder.GetID(), name, folder_spec.ignore_eids) # If we have no children at all, indicate # the item is not expandable. table = child_folder.OpenEntry().GetHierarchyTable(0) if table.GetRowCount(0) == 0: spec.children = [] else: spec.children = None # Flag as "not yet built" children.append(spec) except (pythoncom.com_error, manager.message_store.MsgStoreException), details: # Users have reported failure here - it is not clear if the # entire tree is going to fail, or just this folder print "** Unable to open child folder - ignoring" print details dlgutils.SetWaitCursor(0) return childrendef BuildFolderTreeMAPI(session, ignore_ids): root = FolderSpec(None, "root") tab = session.GetMsgStoresTable(0) prop_tags = PR_ENTRYID, PR_DISPLAY_NAME_A rows = mapi.HrQueryAllRows(tab, prop_tags, None, None, 0) if verbose: print "message store rows:" pprint(rows) for row in rows: (eid_tag, eid), (name_tag, name) = row hex_eid = mapi.HexFromBin(eid) try: msgstore = session.OpenMsgStore(0, eid, None, mapi.MDB_NO_MAIL | mapi.MAPI_DEFERRED_ERRORS) hr, data = msgstore.GetProps((PR_IPM_SUBTREE_ENTRYID,)+ignore_ids, 0) # It appears that not all stores have a subtree. if PROP_TYPE(data[0][0]) != PT_BINARY: print "FolderSelector dialog found message store without a subtree - ignoring" continue subtree_eid = data[0][1] ignore_eids = [item[1] for item in data[1:] if PROP_TYPE(item[0])==PT_BINARY] except pythoncom.com_error, details: # Handle 'expected' errors. if details[0]== mapi.MAPI_E_FAILONEPROVIDER: print "A message store is temporarily unavailable - " \ "it will not appear in the Folder Selector dialog" else: # Some weird error opening a folder tree # Just print a warning and ignore the tree. print "Failed to open a message store for the FolderSelector dialog" print "Exception details:", details continue folder_id = hex_eid, mapi.HexFromBin(subtree_eid) if verbose: print "message store root folder id is", folder_id spec = FolderSpec(folder_id, name, ignore_eids) spec.children = None root.children.append(spec) return root# XXX - Note - the following structure code has been copied into the new# XXX - win32gui_struct module. One day we can rip this in preference# XXX - for this new standard win32all module# Helpers for the ugly win32 structure packing/unpackingdef _GetMaskAndVal(val, default, mask, flag): if val is None: return mask, default else: mask |= flag return mask, valdef PackTVINSERTSTRUCT(parent, insertAfter, tvitem): tvitem_buf, extra = PackTVITEM(*tvitem) tvitem_buf = tvitem_buf.tostring() format = "ii%ds" % len(tvitem_buf) return struct.pack(format, parent, insertAfter, tvitem_buf), extradef PackTVITEM(hitem, state, stateMask, text, image, selimage, citems, param): extra = [] # objects we must keep references to mask = 0 mask, hitem = _GetMaskAndVal(hitem, 0, mask, commctrl.TVIF_HANDLE) mask, state = _GetMaskAndVal(state, 0, mask, commctrl.TVIF_STATE) if not mask & commctrl.TVIF_STATE: stateMask = 0 mask, text = _GetMaskAndVal(text, None, mask, commctrl.TVIF_TEXT) mask, image = _GetMaskAndVal(image, 0, mask, commctrl.TVIF_IMAGE) mask, selimage = _GetMaskAndVal(selimage, 0, mask, commctrl.TVIF_SELECTEDIMAGE) mask, citems = _GetMaskAndVal(citems, 0, mask, commctrl.TVIF_CHILDREN) mask, param = _GetMaskAndVal(param, 0, mask, commctrl.TVIF_PARAM) if text is None: text_addr = text_len = 0 else: text_buffer = array.array("c", text+"\0") extra.append(text_buffer) text_addr, text_len = text_buffer.buffer_info() format = "iiiiiiiiii" buf = struct.pack(format, mask, hitem, state, stateMask, text_addr, text_len, # text image, selimage, citems, param) return array.array("c", buf), extra# Make a new buffer suitable for querying hitem's attributes.def EmptyTVITEM(hitem, mask = None, text_buf_size=512): extra = [] # objects we must keep references to if mask is None: mask = commctrl.TVIF_HANDLE | commctrl.TVIF_STATE | commctrl.TVIF_TEXT | \ commctrl.TVIF_IMAGE | commctrl.TVIF_SELECTEDIMAGE | \ commctrl.TVIF_CHILDREN | commctrl.TVIF_PARAM if mask & commctrl.TVIF_TEXT: text_buffer = array.array("c", "\0" * text_buf_size) extra.append(text_buffer) text_addr, text_len = text_buffer.buffer_info() else: text_addr = text_len = 0 format = "iiiiiiiiii" buf = struct.pack(format, mask, hitem, 0, 0, text_addr, text_len, # text 0, 0, 0, 0) return array.array("c", buf), extradef UnpackTVItem(buffer): item_mask, item_hItem, item_state, item_stateMask, \ item_textptr, item_cchText, item_image, item_selimage, \ item_cChildren, item_param = struct.unpack("10i", buffer) # ensure only items listed by the mask are valid (except we assume the # handle is always valid - some notifications (eg, TVN_ENDLABELEDIT) set a # mask that doesn't include the handle, but the docs explicity say it is.) if not (item_mask & commctrl.TVIF_TEXT): item_textptr = item_cchText = None if not (item_mask & commctrl.TVIF_CHILDREN): item_cChildren = None if not (item_mask & commctrl.TVIF_IMAGE): item_image = None if not (item_mask & commctrl.TVIF_PARAM): item_param = None if not (item_mask & commctrl.TVIF_SELECTEDIMAGE): item_selimage = None if not (item_mask & commctrl.TVIF_STATE): item_state = item_stateMask = None if item_textptr: text = win32gui.PyGetString(item_textptr) else: text = None return item_hItem, item_state, item_stateMask, \ text, item_image, item_selimage, \ item_cChildren, item_paramdef UnpackTVNOTIFY(lparam): format = "iiii40s40s" buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam) hwndFrom, id, code, action, buf_old, buf_new \ = struct.unpack(format, buf) item_old = UnpackTVItem(buf_old) item_new = UnpackTVItem(buf_new) return hwndFrom, id, code, action, item_old, item_newdef UnpackTVDISPINFO(lparam): format = "iii40s" buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam) hwndFrom, id, code, buf_item = struct.unpack(format, buf) item = UnpackTVItem(buf_item) return hwndFrom, id, code, item# XXX - end of code copied to win32gui_struct.py#########################################################################
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -