212 lines
6.2 KiB
Python
212 lines
6.2 KiB
Python
import pythoncom
|
|
import win32com.server.util
|
|
import time
|
|
|
|
import win32com, sys, string, win32api, traceback
|
|
import win32com.client.dynamic
|
|
import win32com.client
|
|
import pythoncom
|
|
from win32com.axcontrol import axcontrol
|
|
from pywintypes import Unicode
|
|
from win32com import storagecon
|
|
from win32com.test.util import CheckClean
|
|
|
|
import pywintypes
|
|
import win32ui
|
|
import win32api, os
|
|
|
|
from pywin32_testutil import str2bytes
|
|
|
|
S_OK = 0
|
|
|
|
import datetime
|
|
if issubclass(pywintypes.TimeType, datetime.datetime):
|
|
import win32timezone
|
|
now = win32timezone.now()
|
|
else:
|
|
now = pywintypes.Time(time.time())
|
|
|
|
class LockBytes:
|
|
_public_methods_ = [ 'ReadAt', 'WriteAt', 'Flush', 'SetSize', 'LockRegion', 'UnlockRegion', 'Stat' ]
|
|
_com_interfaces_ = [ pythoncom.IID_ILockBytes ]
|
|
|
|
def __init__(self, data = ""):
|
|
self.data = str2bytes(data)
|
|
self.ctime = now
|
|
self.mtime = now
|
|
self.atime = now
|
|
|
|
def ReadAt(self, offset, cb):
|
|
print("ReadAt")
|
|
result = self.data[offset:offset + cb]
|
|
return result
|
|
|
|
def WriteAt(self, offset, data):
|
|
print("WriteAt " +str(offset))
|
|
print("len " + str(len(data)))
|
|
print("data:")
|
|
#print data
|
|
if len(self.data) >= offset:
|
|
newdata = self.data[0:offset] + data
|
|
print(len(newdata))
|
|
if len(self.data) >= offset + len(data):
|
|
newdata = newdata + self.data[offset + len(data):]
|
|
print(len(newdata))
|
|
self.data = newdata
|
|
return len(data)
|
|
|
|
def Flush(self, whatsthis=0):
|
|
print("Flush" + str(whatsthis))
|
|
fname = os.path.join(win32api.GetTempPath(), "persist.doc")
|
|
open(fname, "wb").write(self.data)
|
|
return S_OK
|
|
|
|
def SetSize(self, size):
|
|
print("Set Size" + str(size))
|
|
if size > len(self.data):
|
|
self.data = self.data + str2bytes("\000" * (size - len(self.data)))
|
|
else:
|
|
self.data = self.data[0:size]
|
|
return S_OK
|
|
|
|
def LockRegion(self, offset, size, locktype):
|
|
print("LockRegion")
|
|
pass
|
|
|
|
def UnlockRegion(self, offset, size, locktype):
|
|
print("UnlockRegion")
|
|
pass
|
|
|
|
def Stat(self, statflag):
|
|
print("returning Stat " + str(statflag))
|
|
return (
|
|
"PyMemBytes",
|
|
storagecon.STGTY_LOCKBYTES,
|
|
len(self.data),
|
|
self.mtime,
|
|
self.ctime,
|
|
self.atime,
|
|
storagecon.STGM_DIRECT|storagecon.STGM_READWRITE|storagecon.STGM_CREATE ,
|
|
storagecon.STGM_SHARE_EXCLUSIVE,
|
|
"{00020905-0000-0000-C000-000000000046}",
|
|
0, # statebits ?
|
|
0
|
|
)
|
|
|
|
|
|
class OleClientSite:
|
|
_public_methods_ = [ 'SaveObject', 'GetMoniker', 'GetContainer', 'ShowObject', 'OnShowWindow', 'RequestNewObjectLayout' ]
|
|
_com_interfaces_ = [ axcontrol.IID_IOleClientSite ]
|
|
|
|
def __init__(self, data = ""):
|
|
self.IPersistStorage = None
|
|
self.IStorage = None
|
|
|
|
def SetIPersistStorage(self, IPersistStorage):
|
|
self.IPersistStorage = IPersistStorage
|
|
|
|
def SetIStorage(self, IStorage):
|
|
self.IStorage = IStorage
|
|
|
|
def SaveObject(self):
|
|
print("SaveObject")
|
|
if self.IPersistStorage != None and self.IStorage != None:
|
|
self.IPersistStorage.Save(self.IStorage,1)
|
|
self.IStorage.Commit(0)
|
|
return S_OK
|
|
|
|
def GetMoniker(self, dwAssign, dwWhichMoniker):
|
|
print("GetMoniker " + str(dwAssign) + " " + str(dwWhichMoniker))
|
|
|
|
def GetContainer(self):
|
|
print("GetContainer")
|
|
|
|
def ShowObject(self):
|
|
print("ShowObject")
|
|
|
|
def OnShowWindow(self, fShow):
|
|
print("ShowObject" + str(fShow))
|
|
|
|
def RequestNewObjectLayout(self):
|
|
print("RequestNewObjectLayout")
|
|
|
|
|
|
def test():
|
|
# create a LockBytes object and
|
|
#wrap it as a COM object
|
|
# import win32com.server.dispatcher
|
|
lbcom = win32com.server.util.wrap(LockBytes(), pythoncom.IID_ILockBytes) #, useDispatcher=win32com.server.dispatcher.DispatcherWin32trace)
|
|
|
|
# create a structured storage on the ILockBytes object
|
|
stcom = pythoncom.StgCreateDocfileOnILockBytes(lbcom, storagecon.STGM_DIRECT| storagecon.STGM_CREATE | storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE, 0)
|
|
|
|
# create our ClientSite
|
|
ocs = OleClientSite()
|
|
# wrap it as a COM object
|
|
ocscom = win32com.server.util.wrap(ocs, axcontrol.IID_IOleClientSite)
|
|
|
|
# create a Word OLE Document, connect it to our site and our storage
|
|
oocom=axcontrol.OleCreate("{00020906-0000-0000-C000-000000000046}",
|
|
axcontrol.IID_IOleObject,
|
|
0,
|
|
(0,),
|
|
ocscom,
|
|
stcom,
|
|
)
|
|
|
|
mf=win32ui.GetMainFrame()
|
|
hwnd=mf.GetSafeHwnd()
|
|
|
|
# Set the host and document name
|
|
# for unknown reason document name becomes hostname, and document name
|
|
# is not set, debugged it, but don't know where the problem is?
|
|
oocom.SetHostNames("OTPython", "This is Cool")
|
|
|
|
# activate the OLE document
|
|
oocom.DoVerb( -1, ocscom, 0, hwnd, mf.GetWindowRect())
|
|
|
|
# set the hostnames again
|
|
oocom.SetHostNames("OTPython2", "ThisisCool2")
|
|
|
|
# get IDispatch of Word
|
|
doc=win32com.client.Dispatch(oocom.QueryInterface(pythoncom.IID_IDispatch))
|
|
|
|
# get IPersistStorage of Word
|
|
dpcom=oocom.QueryInterface(pythoncom.IID_IPersistStorage)
|
|
|
|
# let our ClientSite know the interfaces
|
|
ocs.SetIPersistStorage(dpcom)
|
|
ocs.SetIStorage(stcom)
|
|
|
|
# use IDispatch to do the Office Word test
|
|
# pasted from TestOffice.py
|
|
|
|
wrange = doc.Range()
|
|
for i in range(10):
|
|
wrange.InsertAfter("Hello from Python %d\n" % i)
|
|
paras = doc.Paragraphs
|
|
for i in range(len(paras)):
|
|
paras[i]().Font.ColorIndex = i+1
|
|
paras[i]().Font.Size = 12 + (4 * i)
|
|
# XXX - note that
|
|
# for para in paras:
|
|
# para().Font...
|
|
# doesnt seem to work - no error, just doesnt work
|
|
# Should check if it works for VB!
|
|
|
|
|
|
dpcom.Save(stcom, 0)
|
|
dpcom.HandsOffStorage()
|
|
# oocom.Close(axcontrol.OLECLOSE_NOSAVE) # or OLECLOSE_SAVEIFDIRTY, but it fails???
|
|
|
|
#Save the ILockBytes data to "persist2.doc"
|
|
lbcom.Flush()
|
|
|
|
#exiting Winword will automatically update the ILockBytes data
|
|
#and flush it to "%TEMP%\persist.doc"
|
|
doc.Application.Quit()
|
|
|
|
if __name__=='__main__':
|
|
test()
|
|
pythoncom.CoUninitialize()
|
|
CheckClean()
|