testClipboard.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. # testClipboard.py
  2. import unittest
  3. import pythoncom
  4. import win32con
  5. import winerror
  6. import win32clipboard
  7. from pywin32_testutil import str2bytes
  8. from win32com.server.util import NewEnum, wrap
  9. from win32com.server.exception import COMException
  10. IDataObject_Methods = """GetData GetDataHere QueryGetData
  11. GetCanonicalFormatEtc SetData EnumFormatEtc
  12. DAdvise DUnadvise EnumDAdvise""".split()
  13. # A COM object implementing IDataObject used for basic testing.
  14. num_do_objects = 0
  15. def WrapCOMObject(ob, iid=None):
  16. return wrap(ob, iid=iid, useDispatcher = 0)
  17. class TestDataObject:
  18. _com_interfaces_ = [pythoncom.IID_IDataObject]
  19. _public_methods_ = IDataObject_Methods
  20. def __init__(self, strval):
  21. global num_do_objects
  22. num_do_objects += 1
  23. self.strval = strval
  24. self.supported_fe = []
  25. for cf in (win32con.CF_TEXT, win32con.CF_UNICODETEXT):
  26. fe = cf, None, pythoncom.DVASPECT_CONTENT, -1, pythoncom.TYMED_HGLOBAL
  27. self.supported_fe.append(fe)
  28. def __del__(self):
  29. global num_do_objects
  30. num_do_objects -= 1
  31. def _query_interface_(self, iid):
  32. if iid==pythoncom.IID_IEnumFORMATETC:
  33. return NewEnum(self.supported_fe, iid=iid)
  34. def GetData(self, fe):
  35. ret_stg = None
  36. cf, target, aspect, index, tymed = fe
  37. if aspect & pythoncom.DVASPECT_CONTENT and \
  38. tymed==pythoncom.TYMED_HGLOBAL:
  39. if cf == win32con.CF_TEXT:
  40. ret_stg = pythoncom.STGMEDIUM()
  41. # ensure always 'bytes' by encoding string.
  42. ret_stg.set(pythoncom.TYMED_HGLOBAL, str2bytes(self.strval))
  43. elif cf == win32con.CF_UNICODETEXT:
  44. ret_stg = pythoncom.STGMEDIUM()
  45. ret_stg.set(pythoncom.TYMED_HGLOBAL, str(self.strval))
  46. if ret_stg is None:
  47. raise COMException(hresult=winerror.E_NOTIMPL)
  48. return ret_stg
  49. def GetDataHere(self, fe):
  50. raise COMException(hresult=winerror.E_NOTIMPL)
  51. def QueryGetData(self, fe):
  52. cf, target, aspect, index, tymed = fe
  53. if aspect & pythoncom.DVASPECT_CONTENT == 0:
  54. raise COMException(hresult=winerror.DV_E_DVASPECT)
  55. if tymed!=pythoncom.TYMED_HGLOBAL:
  56. raise COMException(hresult=winerror.DV_E_TYMED)
  57. return None # should check better
  58. def GetCanonicalFormatEtc(self, fe):
  59. RaiseCOMException(winerror.DATA_S_SAMEFORMATETC)
  60. # return fe
  61. def SetData(self, fe, medium):
  62. raise COMException(hresult=winerror.E_NOTIMPL)
  63. def EnumFormatEtc(self, direction):
  64. if direction != pythoncom.DATADIR_GET:
  65. raise COMException(hresult=winerror.E_NOTIMPL)
  66. return NewEnum(self.supported_fe, iid=pythoncom.IID_IEnumFORMATETC)
  67. def DAdvise(self, fe, flags, sink):
  68. raise COMException(hresult=winerror.E_NOTIMPL)
  69. def DUnadvise(self, connection):
  70. raise COMException(hresult=winerror.E_NOTIMPL)
  71. def EnumDAdvise(self):
  72. raise COMException(hresult=winerror.E_NOTIMPL)
  73. class ClipboardTester(unittest.TestCase):
  74. def setUp(self):
  75. pythoncom.OleInitialize()
  76. def tearDown(self):
  77. try:
  78. pythoncom.OleFlushClipboard()
  79. except pythoncom.com_error:
  80. # We never set anything!
  81. pass
  82. def testIsCurrentClipboard(self):
  83. do = TestDataObject("Hello from Python")
  84. do = WrapCOMObject(do, iid=pythoncom.IID_IDataObject)
  85. pythoncom.OleSetClipboard(do)
  86. self.failUnless(pythoncom.OleIsCurrentClipboard(do))
  87. def testComToWin32(self):
  88. # Set the data via our DataObject
  89. do = TestDataObject("Hello from Python")
  90. do = WrapCOMObject(do, iid=pythoncom.IID_IDataObject)
  91. pythoncom.OleSetClipboard(do)
  92. # Then get it back via the standard win32 clipboard functions.
  93. win32clipboard.OpenClipboard()
  94. got = win32clipboard.GetClipboardData(win32con.CF_TEXT)
  95. # CF_TEXT gives bytes on py3k - use str2bytes() to ensure that's true.
  96. expected = str2bytes("Hello from Python")
  97. self.assertEqual(got, expected)
  98. # Now check unicode
  99. got = win32clipboard.GetClipboardData(win32con.CF_UNICODETEXT)
  100. self.assertEqual(got, "Hello from Python")
  101. win32clipboard.CloseClipboard()
  102. def testWin32ToCom(self):
  103. # Set the data via the std win32 clipboard functions.
  104. val = str2bytes("Hello again!") # ensure always bytes, even in py3k
  105. win32clipboard.OpenClipboard()
  106. win32clipboard.SetClipboardData(win32con.CF_TEXT, val)
  107. win32clipboard.CloseClipboard()
  108. # and get it via an IDataObject provided by COM
  109. do = pythoncom.OleGetClipboard()
  110. cf = win32con.CF_TEXT, None, pythoncom.DVASPECT_CONTENT, -1, pythoncom.TYMED_HGLOBAL
  111. stg = do.GetData(cf)
  112. got = stg.data
  113. # The data we get back has the \0, as our STGMEDIUM has no way of
  114. # knowing if it meant to be a string, or a binary buffer, so
  115. # it must return it too.
  116. self.failUnlessEqual(got, str2bytes("Hello again!\0"))
  117. def testDataObjectFlush(self):
  118. do = TestDataObject("Hello from Python")
  119. do = WrapCOMObject(do, iid=pythoncom.IID_IDataObject)
  120. pythoncom.OleSetClipboard(do)
  121. self.assertEqual(num_do_objects, 1)
  122. do = None # clear my ref!
  123. pythoncom.OleFlushClipboard()
  124. self.assertEqual(num_do_objects, 0)
  125. def testDataObjectReset(self):
  126. do = TestDataObject("Hello from Python")
  127. do = WrapCOMObject(do)
  128. pythoncom.OleSetClipboard(do)
  129. do = None # clear my ref!
  130. self.assertEqual(num_do_objects, 1)
  131. pythoncom.OleSetClipboard(None)
  132. self.assertEqual(num_do_objects, 0)
  133. if __name__=='__main__':
  134. from win32com.test import util
  135. util.testmain()