MS Windows Clipboard
Alex Martelli
aleaxit at yahoo.com
Mon Oct 30 05:54:08 EST 2000
"Alex Martelli" <aleaxit at yahoo.com> wrote in message
news:8ti9ca0tcj at news1.newsguy.com...
[snip]
> Now, doing it in Python itself is not a bad idea, actually. I suspect
> one could do it all with calldll, and with win32all it should be far
> easier. Of course, if one's application does not otherwise need any
[snip]
Well, here's an attempt at pretty-literal translation (from C++/ATL
to Python/win32all), but, there are some peculiarities...:
import win32ui, win32clipboard as clip, win32con, win32api, win32gui
hPrev = 0
nCbcs = 0
def onDrawCb(*a):
global nCbcs
nCbcs += 1
# print "Draw %d" % nCbcs
if hPrev: return win32api.SendMessage(hPrev,*a[-1][1:4])
else: return 1
def onCcbc(*a):
global hPrev
if hPrev==a[-1][2]: hPrev=a[-1][3]
elif hPrev: return win32api.SendMessage(hPrev,*a[-1][1:4])
else: return 0
def wait(timeout_msec=5000, need_changes=1):
global hPrev, nCbcs
win=win32ui.CreateFrame()
win.CreateWindow(None,'',win32con.WS_OVERLAPPEDWINDOW)
win.HookMessage(onDrawCb,win32con.WM_DRAWCLIPBOARD)
win.HookMessage(onCcbc,win32con.WM_CHANGECBCHAIN)
try:
hPrev=clip.SetClipboardViewer(win.GetSafeHwnd())
except win32api.error, err:
if err.args[0]: raise
nCbcs=0
if timeout_msec:
timid = win.SetTimer(1,20)
curtime = win32api.GetTickCount()
endtime = timeout_msec + curtime
while nCbcs<need_changes:
win32gui.PumpWaitingMessages()
if timeout_msec and win32api.GetTickCount()>endtime: break
if timeout_msec:
win.KillTimer(timid)
clip.ChangeClipboardChain(win.GetSafeHwnd(), hPrev)
win.DestroyWindow()
return nCbcs
Decommenting the print statement within onDrawCb shows a
peculiar "stutter" -- it seems to be called _twice_ for
each clipboard change (plus, twice at the start if the
clipboard is non-empty at entry -- which is why I zero
out the nCbcs counter _after_ the SetClipboardViewer
that causes the first 2 calls). I don't know why that
is -- no equivalent in the C++ version, no mention in
the docs either (that I can see).
The try/except around SetClipboardViewer is another
peculiarity, but a documented one: win32clipboard raises
a win32api.error if there was no previously set
clipboard-viewer (...?), so I must test for a 0
error-code in order to propagate only 'true' errors.
The *a arguments to the message-hook functions are
due to a documentation error (I think!): under the
docs for HookMessage, it's said that the handling
callable will be called with TWO arguments (a "handler
object", then a tuple of message-arguments). In fact,
it seems only one object (the tuple) is being passed.
So, I'm taking whatever arguments are being passed,
and hoping the tuple-of-args is the last (or only)
one -- just in case the docs are in fact right and
it's a bug in the current win32all build (for sure,
either the docs or the win32all code will have to
be changed, but I don't know which, because I do not
understand what that 'handler object' is supposed to
be).
All in all, then, we're talking about 40+ lines of
code for Python (using win32all), versus 95 for C++
(using ATL) -- the latter includes a bit more
comments and some amount of Python-interfacing
code that the Python version doesn't need, though:-).
Looking specifically at the heart of the wait
function, it's 25 lines for C++ and 23 for Python --
basically just the difference in comments and
whitespace. Makes sense, since we're programming
at just about the same level in either language.
I think this argues in favour of doing the
non-portable-anyway system-level programming
in the system-level language (C++), as the VHLL
buys you nothing much here, but, as this surely
isn't performance-critical code, I guess somebody
else might argue "might as well do it in Python"
instead:-). However, the win32all/Pythonwin
framework appears to be somewhat less 'stable'
(considering documentation issues too, as well
as that mysterious 'stutter') than the ATL fw
I'm using in C++ -- particularly when coding at
system level, I'd rather have a clue about what
IS going on rather than take a purely empirical
"tweak until it seems to work" approach:-).
Alex
More information about the Python-list
mailing list