PyXR

c:\python24\lib\site-packages\win32\lib \ win32gui_struct.py



0001 # This is a work in progress - see Demos/win32gui_menu.py
0002 
0003 # win32gui_struct.py - helpers for working with various win32gui structures.
0004 # As win32gui is "light-weight", it does not define objects for all possible
0005 # win32 structures - in general, "buffer" objects are passed around - it is
0006 # the callers responsibility to pack the buffer in the correct format.
0007 #
0008 # This module defines some helpers for the commonly used structures.
0009 #
0010 # In general, each structure has 3 functions:
0011 #
0012 # buffer, extras = PackSTRUCTURE(items, ...)
0013 # item, ... = UnpackSTRUCTURE(buffer)
0014 # buffer, extras = EmtpySTRUCTURE(...)
0015 #
0016 # 'extras' is always items that must be held along with the buffer, as the
0017 # buffer refers to these object's memory.
0018 # For structures that support a 'mask', this mask is hidden from the user - if
0019 # 'None' is passed, the mask flag will not be set, or on return, None will
0020 # be returned for the value if the mask is not set.
0021 #
0022 # NOTE: I considered making these structures look like real classes, and
0023 # support 'attributes' etc - however, ctypes already has a good structure
0024 # mechanism - I think it makes more sense to support ctype structures
0025 # at the win32gui level, then there will be no need for this module at all.
0026 
0027 import win32gui
0028 import win32con
0029 import struct
0030 import array
0031 import commctrl
0032 
0033 # Generic WM_NOTIFY unpacking
0034 def UnpackWMNOTIFY(lparam):
0035     format = "iii"
0036     buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam)
0037     hwndFrom, idFrom, code = struct.unpack(format, buf)
0038     code += 0x4f0000 # hrm - wtf - commctrl uses this, and it works with mfc.  *sigh*
0039     return hwndFrom, idFrom, code
0040     
0041 # MENUITEMINFO struct
0042 # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Resources/Menus/MenuReference/MenuStructures/MENUITEMINFO.asp
0043 # We use the struct module to pack and unpack strings as MENUITEMINFO
0044 # structures.  We also have special handling for the 'fMask' item in that
0045 # structure to avoid the caller needing to explicitly check validity
0046 # (None is used if the mask excludes/should exclude the value)
0047 menuitem_fmt = '9iP2i'
0048 
0049 def PackMENUITEMINFO(fType=None, fState=None, wID=None, hSubMenu=None,
0050                      hbmpChecked=None, hbmpUnchecked=None, dwTypeData=None,
0051                      text=None, hbmpItem=None):
0052     # 'extras' are objects the caller must keep a reference to (as their
0053     # memory is used) for the lifetime of the INFO item.
0054     extras = []
0055     fMask = 0
0056     if fType is None: fType = 0
0057     else: fMask |= win32con.MIIM_FTYPE
0058     if fState is None: fState = 0
0059     else: fMask |= win32con.MIIM_STATE
0060     if wID is None: wID = 0
0061     else: fMask |= win32con.MIIM_ID
0062     if hSubMenu is None: hSubMenu = 0
0063     else: fMask |= win32con.MIIM_SUBMENU
0064     if hbmpChecked is None:
0065         assert hbmpUnchecked is None, \
0066                 "neither or both checkmark bmps must be given"
0067         hbmpChecked = hbmpUnchecked = 0
0068     else:
0069         assert hbmpUnchecked is not None, \
0070                 "neither or both checkmark bmps must be given"
0071         fMask |= win32con.MIIM_CHECKMARKS
0072     if dwTypeData is None: dwTypeData = 0
0073     else: fMask |= win32con.MIIM_DATA
0074     if hbmpItem is None: hbmpItem = 0
0075     else: fMask |= win32con.MIIM_BITMAP
0076     if text is not None:
0077         fMask |= win32con.MIIM_STRING
0078         if isinstance(text, unicode):
0079             text = text.encode("mbcs")
0080         str_buf = array.array("c", text+'\0')
0081         cch = len(str_buf)
0082         # We are taking address of strbuf - it must not die until windows
0083         # has finished with our structure.
0084         lptext = str_buf.buffer_info()[0]
0085         extras.append(str_buf)
0086     else:
0087         lptext = 0
0088         cch = 0
0089     # Create the struct.
0090     dwItemData = 0
0091     item = struct.pack(
0092                 menuitem_fmt,
0093                 struct.calcsize(menuitem_fmt), # cbSize
0094                 fMask,
0095                 fType,
0096                 fState,
0097                 wID,
0098                 hSubMenu,
0099                 hbmpChecked,
0100                 hbmpUnchecked,
0101                 dwItemData,
0102                 lptext,
0103                 cch,
0104                 hbmpItem
0105                 )
0106     # Now copy the string to a writable buffer, so that the result
0107     # could be passed to a 'Get' function
0108     return array.array("c", item), extras
0109 
0110 def UnpackMENUITEMINFO(s):
0111     (cb,
0112     fMask,
0113     fType,
0114     fState,
0115     wID,
0116     hSubMenu,
0117     hbmpChecked,
0118     hbmpUnchecked,
0119     dwItemData,
0120     lptext,
0121     cch,
0122     hbmpItem) = struct.unpack(menuitem_fmt, s)
0123     assert cb==len(s)
0124     if fMask & win32con.MIIM_FTYPE==0: fType = None
0125     if fMask & win32con.MIIM_STATE==0: fState = None
0126     if fMask & win32con.MIIM_ID==0: wID = None
0127     if fMask & win32con.MIIM_SUBMENU==0: hSubMenu = None
0128     if fMask & win32con.MIIM_CHECKMARKS==0: hbmpChecked = hbmpUnchecked = None
0129     if fMask & win32con.MIIM_DATA==0: dwItemData = None
0130     if fMask & win32con.MIIM_BITMAP==0: hbmpItem = None
0131     if fMask & win32con.MIIM_STRING:
0132         text = win32gui.PyGetString(lptext, cch)
0133     else:
0134         text = None
0135     return fType, fState, wID, hSubMenu, hbmpChecked, hbmpUnchecked, \
0136            dwItemData, text, hbmpItem
0137 
0138 def EmptyMENUITEMINFO(mask = None, text_buf_size=512):
0139     extra = []
0140     if mask is None:
0141         mask = win32con.MIIM_BITMAP | win32con.MIIM_CHECKMARKS | \
0142                win32con.MIIM_DATA | win32con.MIIM_FTYPE | \
0143                win32con.MIIM_ID | win32con.MIIM_STATE | \
0144                win32con.MIIM_STRING | win32con.MIIM_SUBMENU | \
0145                win32con.MIIM_TYPE
0146  
0147     if mask & win32con.MIIM_STRING:
0148         text_buffer = array.array("c", "\0" * text_buf_size)
0149         extra.append(text_buffer)
0150         text_addr, text_len = text_buffer.buffer_info()
0151     else:
0152         text_addr = text_len = 0
0153 
0154     buf = struct.pack(
0155                 menuitem_fmt,
0156                 struct.calcsize(menuitem_fmt), # cbSize
0157                 mask,
0158                 0, #fType,
0159                 0, #fState,
0160                 0, #wID,
0161                 0, #hSubMenu,
0162                 0, #hbmpChecked,
0163                 0, #hbmpUnchecked,
0164                 0, #dwItemData,
0165                 text_addr,
0166                 text_len,
0167                 0, #hbmpItem
0168                 )
0169     return array.array("c", buf), extra
0170 
0171 ##########################################################################
0172 #
0173 # Tree View structure support - TVITEM, TVINSERTSTRUCT and TVDISPINFO
0174 # 
0175 ##########################################################################
0176 
0177 # XXX - Note that the following implementation of TreeView structures is ripped
0178 # XXX - from the SpamBayes project.  It may not quite work correctly yet - I
0179 # XXX - intend checking them later - but having them is better than not at all!
0180 
0181 # Helpers for the ugly win32 structure packing/unpacking
0182 def _GetMaskAndVal(val, default, mask, flag):
0183     if val is None:
0184         return mask, default
0185     else:
0186         if flag is not None:
0187             mask |= flag
0188         return mask, val
0189 
0190 def PackTVINSERTSTRUCT(parent, insertAfter, tvitem):
0191     tvitem_buf, extra = PackTVITEM(*tvitem)
0192     tvitem_buf = tvitem_buf.tostring()
0193     format = "ii%ds" % len(tvitem_buf)
0194     return struct.pack(format, parent, insertAfter, tvitem_buf), extra
0195 
0196 def PackTVITEM(hitem, state, stateMask, text, image, selimage, citems, param):
0197     extra = [] # objects we must keep references to
0198     mask = 0
0199     mask, hitem = _GetMaskAndVal(hitem, 0, mask, commctrl.TVIF_HANDLE)
0200     mask, state = _GetMaskAndVal(state, 0, mask, commctrl.TVIF_STATE)
0201     if not mask & commctrl.TVIF_STATE:
0202         stateMask = 0
0203     mask, text = _GetMaskAndVal(text, None, mask, commctrl.TVIF_TEXT)
0204     mask, image = _GetMaskAndVal(image, 0, mask, commctrl.TVIF_IMAGE)
0205     mask, selimage = _GetMaskAndVal(selimage, 0, mask, commctrl.TVIF_SELECTEDIMAGE)
0206     mask, citems = _GetMaskAndVal(citems, 0, mask, commctrl.TVIF_CHILDREN)
0207     mask, param = _GetMaskAndVal(param, 0, mask, commctrl.TVIF_PARAM)
0208     if text is None:
0209         text_addr = text_len = 0
0210     else:
0211         if isinstance(text, unicode):
0212             text = text.encode("mbcs")
0213         text_buffer = array.array("c", text+"\0")
0214         extra.append(text_buffer)
0215         text_addr, text_len = text_buffer.buffer_info()
0216     format = "iiiiiiiiii"
0217     buf = struct.pack(format,
0218                       mask, hitem,
0219                       state, stateMask,
0220                       text_addr, text_len, # text
0221                       image, selimage,
0222                       citems, param)
0223     return array.array("c", buf), extra
0224 
0225 # Make a new buffer suitable for querying hitem's attributes.
0226 def EmptyTVITEM(hitem, mask = None, text_buf_size=512):
0227     extra = [] # objects we must keep references to
0228     if mask is None:
0229         mask = commctrl.TVIF_HANDLE | commctrl.TVIF_STATE | commctrl.TVIF_TEXT | \
0230                commctrl.TVIF_IMAGE | commctrl.TVIF_SELECTEDIMAGE | \
0231                commctrl.TVIF_CHILDREN | commctrl.TVIF_PARAM
0232     if mask & commctrl.TVIF_TEXT:
0233         text_buffer = array.array("c", "\0" * text_buf_size)
0234         extra.append(text_buffer)
0235         text_addr, text_len = text_buffer.buffer_info()
0236     else:
0237         text_addr = text_len = 0
0238     format = "iiiiiiiiii"
0239     buf = struct.pack(format,
0240                       mask, hitem,
0241                       0, 0,
0242                       text_addr, text_len, # text
0243                       0, 0,
0244                       0, 0)
0245     return array.array("c", buf), extra
0246     
0247 def UnpackTVITEM(buffer):
0248     item_mask, item_hItem, item_state, item_stateMask, \
0249         item_textptr, item_cchText, item_image, item_selimage, \
0250         item_cChildren, item_param = struct.unpack("10i", buffer)
0251     # ensure only items listed by the mask are valid (except we assume the
0252     # handle is always valid - some notifications (eg, TVN_ENDLABELEDIT) set a
0253     # mask that doesn't include the handle, but the docs explicity say it is.)
0254     if not (item_mask & commctrl.TVIF_TEXT): item_textptr = item_cchText = None
0255     if not (item_mask & commctrl.TVIF_CHILDREN): item_cChildren = None
0256     if not (item_mask & commctrl.TVIF_IMAGE): item_image = None
0257     if not (item_mask & commctrl.TVIF_PARAM): item_param = None
0258     if not (item_mask & commctrl.TVIF_SELECTEDIMAGE): item_selimage = None
0259     if not (item_mask & commctrl.TVIF_STATE): item_state = item_stateMask = None
0260     
0261     if item_textptr:
0262         text = win32gui.PyGetString(item_textptr)
0263     else:
0264         text = None
0265     return item_hItem, item_state, item_stateMask, \
0266         text, item_image, item_selimage, \
0267         item_cChildren, item_param
0268 
0269 # Unpack the lparm from a "TVNOTIFY" message
0270 def UnpackTVNOTIFY(lparam):
0271     format = "iiii40s40s"
0272     buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam)
0273     hwndFrom, id, code, action, buf_old, buf_new \
0274           = struct.unpack(format, buf)
0275     item_old = UnpackTVITEM(buf_old)
0276     item_new = UnpackTVITEM(buf_new)
0277     return hwndFrom, id, code, action, item_old, item_new
0278 
0279 def UnpackTVDISPINFO(lparam):
0280     format = "iii40s"
0281     buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam)
0282     hwndFrom, id, code, buf_item = struct.unpack(format, buf)
0283     item = UnpackTVITEM(buf_item)
0284     return hwndFrom, id, code, item
0285 
0286 #
0287 # List view items
0288 def PackLVITEM(item=None, subItem=None, state=None, stateMask=None, text=None, image=None, param=None, indent=None):
0289     extra = [] # objects we must keep references to
0290     mask = 0
0291     mask, item = _GetMaskAndVal(item, 0, mask, None)
0292     mask, subItem = _GetMaskAndVal(subItem, 0, mask, None)
0293     mask, state = _GetMaskAndVal(state, 0, mask, commctrl.LVIF_STATE)
0294     if not mask & commctrl.LVIF_STATE:
0295         stateMask = 0
0296     else:
0297         if stateMask is None:
0298             stateMask = state
0299     mask, text = _GetMaskAndVal(text, None, mask, commctrl.LVIF_TEXT)
0300     mask, image = _GetMaskAndVal(image, 0, mask, commctrl.LVIF_IMAGE)
0301     mask, param = _GetMaskAndVal(param, 0, mask, commctrl.LVIF_PARAM)
0302     mask, indent = _GetMaskAndVal(indent, 0, mask, commctrl.LVIF_INDENT)
0303     if text is None:
0304         text_addr = text_len = 0
0305     else:
0306         if isinstance(text, unicode):
0307             text = text.encode("mbcs")
0308         text_buffer = array.array("c", text+"\0")
0309         extra.append(text_buffer)
0310         text_addr, text_len = text_buffer.buffer_info()
0311     format = "iiiiiiiiii"
0312     buf = struct.pack(format,
0313                       mask, item, subItem,
0314                       state, stateMask,
0315                       text_addr, text_len, # text
0316                       image, param, indent)
0317     return array.array("c", buf), extra
0318 
0319 def UnpackLVITEM(buffer):
0320     item_mask, item_item, item_subItem, \
0321         item_state, item_stateMask, \
0322         item_textptr, item_cchText, item_image, \
0323         item_param, item_indent = struct.unpack("10i", buffer)
0324     # ensure only items listed by the mask are valid
0325     if not (item_mask & commctrl.LVIF_TEXT): item_textptr = item_cchText = None
0326     if not (item_mask & commctrl.LVIF_IMAGE): item_image = None
0327     if not (item_mask & commctrl.LVIF_PARAM): item_param = None
0328     if not (item_mask & commctrl.LVIF_INDENT): item_indent = None
0329     if not (item_mask & commctrl.LVIF_STATE): item_state = item_stateMask = None
0330     
0331     if item_textptr:
0332         text = win32gui.PyGetString(item_textptr)
0333     else:
0334         text = None
0335     return item_item, item_subItem, item_state, item_stateMask, \
0336         text, item_image, item_param, item_indent
0337 
0338 # Unpack an "LVNOTIFY" message
0339 def UnpackLVDISPINFO(lparam):
0340     format = "iii40s"
0341     buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam)
0342     hwndFrom, id, code, buf_item = struct.unpack(format, buf)
0343     item = UnpackLVITEM(buf_item)
0344     return hwndFrom, id, code, item
0345 
0346 def UnpackLVNOTIFY(lparam):
0347     format = "3i8i"
0348     buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam)
0349     hwndFrom, id, code, item, subitem, newstate, oldstate, \
0350         changed, pt_x, pt_y, lparam = struct.unpack(format, buf)
0351     return hwndFrom, id, code, item, subitem, newstate, oldstate, \
0352         changed, (pt_x, pt_y), lparam
0353 
0354 
0355 # Make a new buffer suitable for querying an items attributes.
0356 def EmptyLVITEM(item, subitem, mask = None, text_buf_size=512):
0357     extra = [] # objects we must keep references to
0358     if mask is None:
0359         mask = commctrl.LVIF_IMAGE | commctrl.LVIF_INDENT | commctrl.LVIF_TEXT | \
0360                commctrl.LVIF_PARAM | commctrl.LVIF_STATE
0361     if mask & commctrl.LVIF_TEXT:
0362         text_buffer = array.array("c", "\0" * text_buf_size)
0363         extra.append(text_buffer)
0364         text_addr, text_len = text_buffer.buffer_info()
0365     else:
0366         text_addr = text_len = 0
0367     format = "iiiiiiiiii"
0368     buf = struct.pack(format,
0369                       mask, item, subitem, 
0370                       0, 0,
0371                       text_addr, text_len, # text
0372                       0, 0, 0)
0373     return array.array("c", buf), extra
0374 
0375 
0376 # List view column structure
0377 def PackLVCOLUMN(fmt=None, cx=None, text=None, subItem=None, image=None, order=None):
0378     extra = [] # objects we must keep references to
0379     mask = 0
0380     mask, fmt = _GetMaskAndVal(fmt, 0, mask, commctrl.LVCF_FMT)
0381     mask, cx = _GetMaskAndVal(cx, 0, mask, commctrl.LVCF_WIDTH)
0382     mask, text = _GetMaskAndVal(text, None, mask, commctrl.LVCF_TEXT)
0383     mask, subItem = _GetMaskAndVal(subItem, 0, mask, commctrl.LVCF_SUBITEM)
0384     mask, image = _GetMaskAndVal(image, 0, mask, commctrl.LVCF_IMAGE)
0385     mask, order= _GetMaskAndVal(order, 0, mask, commctrl.LVCF_ORDER)
0386     if text is None:
0387         text_addr = text_len = 0
0388     else:
0389         if isinstance(text, unicode):
0390             text = text.encode("mbcs")
0391         text_buffer = array.array("c", text+"\0")
0392         extra.append(text_buffer)
0393         text_addr, text_len = text_buffer.buffer_info()
0394     format = "iiiiiiii"
0395     buf = struct.pack(format,
0396                       mask, fmt, cx,
0397                       text_addr, text_len, # text
0398                       subItem, image, order)
0399     return array.array("c", buf), extra
0400 
0401 def UnpackLVCOLUMN(lparam):
0402     format = "iiiiiiii"
0403     mask, fmt, cx, text_addr, text_size, subItem, image, order = \
0404             struct.unpack(format, lparam)
0405     # ensure only items listed by the mask are valid
0406     if not (mask & commctrl.LVCF_FMT): fmt = None
0407     if not (mask & commctrl.LVCF_WIDTH): cx = None
0408     if not (mask & commctrl.LVCF_TEXT): text_addr = test_size = None
0409     if not (mask & commctrl.LVCF_SUBITEM): subItem = None
0410     if not (mask & commctrl.LVCF_IMAGE): image = None
0411     if not (mask & commctrl.LVCF_ORDER): order = None
0412     if text_addr:
0413         text = win32gui.PyGetString(text_addr)
0414     else:
0415         text = None
0416     return fmt, cx, text, subItem, image, order
0417 
0418 
0419 # Make a new buffer suitable for querying an items attributes.
0420 def EmptyLVCOLUMN(mask = None, text_buf_size=512):
0421     extra = [] # objects we must keep references to
0422     if mask is None:
0423         mask = commctrl.LVCF_FMT | commctrl.LVCF_WIDTH | commctrl.LVCF_TEXT | \
0424                commctrl.LVCF_SUBITEM | commctrl.LVCF_IMAGE | commctrl.LVCF_ORDER
0425     if mask & commctrl.LVCF_TEXT:
0426         text_buffer = array.array("c", "\0" * text_buf_size)
0427         extra.append(text_buffer)
0428         text_addr, text_len = text_buffer.buffer_info()
0429     else:
0430         text_addr = text_len = 0
0431     format = "iiiiiiii"
0432     buf = struct.pack(format,
0433                       mask, 0, 0,
0434                       text_addr, text_len, # text
0435                       0, 0, 0)
0436     return array.array("c", buf), extra
0437 
0438 # List view hit-test.
0439 def PackLVHITTEST(pt):
0440     format = "iiiii"
0441     buf = struct.pack(format,
0442                       pt[0], pt[1],
0443                       0, 0, 0)
0444     return array.array("c", buf), None
0445 
0446 def UnpackLVHITTEST(buf):
0447     format = "iiiii"
0448     x, y, flags, item, subitem = struct.unpack(format, buf)
0449     return (x,y), flags, item, subitem
0450 
0451 def PackHDITEM(cxy = None, text = None, hbm = None, fmt = None,
0452                param = None, image = None, order = None):
0453     extra = [] # objects we must keep references to
0454     mask = 0
0455     mask, cxy = _GetMaskAndVal(cxy, 0, mask, commctrl.HDI_HEIGHT)
0456     mask, text = _GetMaskAndVal(text, None, mask, commctrl.LVCF_TEXT)
0457     mask, hbm = _GetMaskAndVal(hbm, 0, mask, commctrl.HDI_BITMAP)
0458     mask, fmt = _GetMaskAndVal(fmt, 0, mask, commctrl.HDI_FORMAT)
0459     mask, param = _GetMaskAndVal(param, 0, mask, commctrl.HDI_LPARAM)
0460     mask, image = _GetMaskAndVal(image, 0, mask, commctrl.HDI_IMAGE)
0461     mask, order = _GetMaskAndVal(order, 0, mask, commctrl.HDI_ORDER)
0462 
0463     if text is None:
0464         text_addr = text_len = 0
0465     else:
0466         if isinstance(text, unicode):
0467             text = text.encode("mbcs")
0468         text_buffer = array.array("c", text+"\0")
0469         extra.append(text_buffer)
0470         text_addr, text_len = text_buffer.buffer_info()
0471 
0472     format = "iiiiiiiiiii"
0473     buf = struct.pack(format,
0474                       mask, cxy, text_addr, hbm, text_len,
0475                       fmt, param, image, order, 0, 0)
0476     return array.array("c", buf), extra
0477 

Generated by PyXR 0.9.4
SourceForge.net Logo