home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Shareware / Comunicatii / jyte / jyte.exe / win32gui_struct.py < prev    next >
Text File  |  2003-10-15  |  10KB  |  238 lines

  1. # This is a work in progress - see Demos/win32gui_menu.py
  2.  
  3. # win32gui_struct.py - helpers for working with various win32gui structures.
  4. # As win32gui is "light-weight", it does not define objects for all possible
  5. # win32 structures - in general, "buffer" objects are passed around - it is
  6. # the callers responsibility to pack the buffer in the correct format.
  7. #
  8. # This module defines some helpers for the commonly used structures.
  9. #
  10. # In general, each structure has 3 functions:
  11. #
  12. # buffer, extras = PackSTRUCTURE(items, ...)
  13. # item, ... = UnpackSTRUCTURE(buffer)
  14. # buffer, extras = EmtpySTRUCTURE(...)
  15. #
  16. # 'extras' is always items that must be held along with the buffer, as the
  17. # buffer refers to these object's memory.
  18. # For structures that support a 'mask', this mask is hidden from the user - if
  19. # 'None' is passed, the mask flag will not be set, or on return, None will
  20. # be returned for the value if the mask is not set.
  21. #
  22. # NOTE: I considered making these structures look like real classes, and
  23. # support 'attributes' etc - however, ctypes already has a good structure
  24. # mechanism - I think it makes more sense to support ctype structures
  25. # at the win32gui level, then there will be no need for this module at all.
  26.  
  27. import win32gui
  28. import win32con
  29. import struct
  30. import array
  31.  
  32. # MENUITEMINFO struct
  33. # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Resources/Menus/MenuReference/MenuStructures/MENUITEMINFO.asp
  34. # We use the struct module to pack and unpack strings as MENUITEMINFO
  35. # structures.  We also have special handling for the 'fMask' item in that
  36. # structure to avoid the caller needing to explicitly check validity
  37. # (None is used if the mask excludes/should exclude the value)
  38. menuitem_fmt = '9IP2I'
  39.  
  40. def PackMENUITEMINFO(fType=None, fState=None, wID=None, hSubMenu=None,
  41.                      hbmpChecked=None, hbmpUnchecked=None, dwTypeData=None,
  42.                      text=None, hbmpItem=None):
  43.     # 'extras' are objects the caller must keep a reference to (as their
  44.     # memory is used) for the lifetime of the INFO item.
  45.     extras = []
  46.     fMask = 0
  47.     if fType is None: fType = 0
  48.     else: fMask |= win32con.MIIM_FTYPE
  49.     if fState is None: fState = 0
  50.     else: fMask |= win32con.MIIM_STATE
  51.     if wID is None: wID = 0
  52.     else: fMask |= win32con.MIIM_ID
  53.     if hSubMenu is None: hSubMenu = 0
  54.     else: fMask |= win32con.MIIM_SUBMENU
  55.     if hbmpChecked is None:
  56.         assert hbmpUnchecked is None, \
  57.                 "neither or both checkmark bmps must be given"
  58.         hbmpChecked = hbmpUnchecked = 0
  59.     else:
  60.         assert hbmpUnchecked is not None, \
  61.                 "neither or both checkmark bmps must be given"
  62.         fMask |= win32con.MMIM_CHECKMARKS
  63.     if dwTypeData is None: dwTypeData = 0
  64.     else: fMask |= win32con.MIIM_DATA
  65.     if hbmpItem is None: hbmpItem = 0
  66.     else: fMask |= win32con.MIIM_BITMAP
  67.     if text is not None:
  68.         fMask |= win32con.MIIM_STRING
  69.         str_buf = array.array("c", text+'\0')
  70.         cch = len(str_buf)
  71.         # We are taking address of strbuf - it must not die until windows
  72.         # has finished with our structure.
  73.         lptext = str_buf.buffer_info()[0]
  74.         extras.append(str_buf)
  75.     else:
  76.         lptext = 0
  77.         cch = 0
  78.     # Create the struct.
  79.     dwItemData = 0
  80.     item = struct.pack(
  81.                 menuitem_fmt,
  82.                 struct.calcsize(menuitem_fmt), # cbSize
  83.                 fMask,
  84.                 fType,
  85.                 fState,
  86.                 wID,
  87.                 hSubMenu,
  88.                 hbmpChecked,
  89.                 hbmpUnchecked,
  90.                 dwItemData,
  91.                 lptext,
  92.                 cch,
  93.                 hbmpItem
  94.                 )
  95.     # Now copy the string to a writable buffer, so that the result
  96.     # could be passed to a 'Get' function
  97.     return array.array("c", item), extras
  98.  
  99. def UnpackMENUITEMINFO(s):
  100.     cb,
  101.     fMask,
  102.     fType,
  103.     fState,
  104.     wID,
  105.     hSubMenu,
  106.     hbmpChecked,
  107.     hbmpUnchecked,
  108.     dwItemData,
  109.     lptext,
  110.     cch,
  111.     hbmpItem = struct.unpack(menuitem_fmt, s)
  112.     assert cb==len(s)
  113.     if fMask & win32con.MIIM_FTYPE==0: fType = None
  114.     if fMask & win32con.MIIM_STATE==0: fState = None
  115.     if fMask & win32con.MIIM_ID==0: wID = None
  116.     if fMask & win32con.MIIM_SUBMENU==0: hSubMenu = None
  117.     if fMask & win32con.MIIM_CHECKMARKS==0: hbmpChecked = hbmpUnchecked = None
  118.     if fMask & win32con.MIIM_DATA==0: dwItemData = None
  119.     if fMask & win32con.MIIM_BITMAP==0: hbmpItem = None
  120.     if fMask & win32con.MIIM_STRING:
  121.         text = PyGetString(lptext, cch)
  122.     else:
  123.         text = None
  124.     return fType, fState, wID, hSubMenu, bmpChecked, bmpUnchecked, \
  125.            dwTypeData, text, hbmpItem
  126.  
  127. ##########################################################################
  128. #
  129. # Tree View structure support - TVITEM, TVINSERTSTRUCT and TVDISPINFO
  130. ##########################################################################
  131.  
  132. # XXX - Note that the following implementation of TreeView structures is ripped
  133. # XXX - from the SpamBayes project.  It may not quite work correctly yet - I
  134. # XXX - intend checking them later - but having them is better than not at all!
  135.  
  136. # Helpers for the ugly win32 structure packing/unpacking
  137. def _GetMaskAndVal(val, default, mask, flag):
  138.     if val is None:
  139.         return mask, default
  140.     else:
  141.         mask |= flag
  142.         return mask, val
  143.  
  144. def PackTVINSERTSTRUCT(parent, insertAfter, tvitem):
  145.     tvitem_buf, extra = PackTVITEM(*tvitem)
  146.     tvitem_buf = tvitem_buf.tostring()
  147.     format = "ii%ds" % len(tvitem_buf)
  148.     return struct.pack(format, parent, insertAfter, tvitem_buf), extra
  149.  
  150. def PackTVITEM(hitem, state, stateMask, text, image, selimage, citems, param):
  151.     extra = [] # objects we must keep references to
  152.     mask = 0
  153.     mask, hitem = _GetMaskAndVal(hitem, 0, mask, commctrl.TVIF_HANDLE)
  154.     mask, state = _GetMaskAndVal(state, 0, mask, commctrl.TVIF_STATE)
  155.     if not mask & commctrl.TVIF_STATE:
  156.         stateMask = 0
  157.     mask, text = _GetMaskAndVal(text, None, mask, commctrl.TVIF_TEXT)
  158.     mask, image = _GetMaskAndVal(image, 0, mask, commctrl.TVIF_IMAGE)
  159.     mask, selimage = _GetMaskAndVal(selimage, 0, mask, commctrl.TVIF_SELECTEDIMAGE)
  160.     mask, citems = _GetMaskAndVal(citems, 0, mask, commctrl.TVIF_CHILDREN)
  161.     mask, param = _GetMaskAndVal(param, 0, mask, commctrl.TVIF_PARAM)
  162.     if text is None:
  163.         text_addr = text_len = 0
  164.     else:
  165.         text_buffer = array.array("c", text+"\0")
  166.         extra.append(text_buffer)
  167.         text_addr, text_len = text_buffer.buffer_info()
  168.     format = "iiiiiiiiii"
  169.     buf = struct.pack(format,
  170.                       mask, hitem,
  171.                       state, stateMask,
  172.                       text_addr, text_len, # text
  173.                       image, selimage,
  174.                       citems, param)
  175.     return array.array("c", buf), extra
  176.  
  177. # Make a new buffer suitable for querying hitem's attributes.
  178. def EmptyTVITEM(hitem, mask = None, text_buf_size=512):
  179.     extra = [] # objects we must keep references to
  180.     if mask is None:
  181.         mask = commctrl.TVIF_HANDLE | commctrl.TVIF_STATE | commctrl.TVIF_TEXT | \
  182.                commctrl.TVIF_IMAGE | commctrl.TVIF_SELECTEDIMAGE | \
  183.                commctrl.TVIF_CHILDREN | commctrl.TVIF_PARAM
  184.     if mask & commctrl.TVIF_TEXT:
  185.         text_buffer = array.array("c", "\0" * text_buf_size)
  186.         extra.append(text_buffer)
  187.         text_addr, text_len = text_buffer.buffer_info()
  188.     else:
  189.         text_addr = text_len = 0
  190.     format = "iiiiiiiiii"
  191.     buf = struct.pack(format,
  192.                       mask, hitem,
  193.                       0, 0,
  194.                       text_addr, text_len, # text
  195.                       0, 0,
  196.                       0, 0)
  197.     return array.array("c", buf), extra
  198.     
  199. def UnpackTVItem(buffer):
  200.     item_mask, item_hItem, item_state, item_stateMask, \
  201.         item_textptr, item_cchText, item_image, item_selimage, \
  202.         item_cChildren, item_param = struct.unpack("10i", buffer)
  203.     # ensure only items listed by the mask are valid (except we assume the
  204.     # handle is always valid - some notifications (eg, TVN_ENDLABELEDIT) set a
  205.     # mask that doesn't include the handle, but the docs explicity say it is.)
  206.     if not (item_mask & commctrl.TVIF_TEXT): item_textptr = item_cchText = None
  207.     if not (item_mask & commctrl.TVIF_CHILDREN): item_cChildren = None
  208.     if not (item_mask & commctrl.TVIF_IMAGE): item_image = None
  209.     if not (item_mask & commctrl.TVIF_PARAM): item_param = None
  210.     if not (item_mask & commctrl.TVIF_SELECTEDIMAGE): item_selimage = None
  211.     if not (item_mask & commctrl.TVIF_STATE): item_state = item_stateMask = None
  212.     
  213.     if item_textptr:
  214.         text = win32gui.PyGetString(item_textptr)
  215.     else:
  216.         text = None
  217.     return item_hItem, item_state, item_stateMask, \
  218.         text, item_image, item_selimage, \
  219.         item_cChildren, item_param
  220.  
  221. # Unpack the lparm from a "TVNOTIFY" message
  222. def UnpackTVNOTIFY(lparam):
  223.     format = "iiii40s40s"
  224.     buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam)
  225.     hwndFrom, id, code, action, buf_old, buf_new \
  226.           = struct.unpack(format, buf)
  227.     item_old = UnpackTVItem(buf_old)
  228.     item_new = UnpackTVItem(buf_new)
  229.     return hwndFrom, id, code, action, item_old, item_new
  230.  
  231. def UnpackTVDISPINFO(lparam):
  232.     format = "iii40s"
  233.     buf = win32gui.PyMakeBuffer(struct.calcsize(format), lparam)
  234.     hwndFrom, id, code, buf_item = struct.unpack(format, buf)
  235.     item = UnpackTVItem(buf_item)
  236.     return hwndFrom, id, code, item
  237.