Q: How to monitor clipboard change?

Hi,
Is there a way in wxpython so that my program could do something
whenever clipboard changes? I did search around, but could not find
anything...

H.J

What I've done in the past is to periodically poll the clipboard and
compare what's there to whatever was there before. If it changed, call
your function. Checking every second or two is usually more than
sufficient. So, write a function to get the clipboard and compare,
then have it call itself one or two seconds later with wx.CallLater.

···

On Thu, Aug 4, 2011 at 12:49 PM, Hu Jun <hujun.work@gmail.com> wrote:

Hi,
Is there a way in wxpython so that my program could do something
whenever clipboard changes? I did search around, but could not find
anything...

Thanks for your suggestion.
But I already tried this, the problem is if there are large amount of
data in the clipboard (50M bitmap for example), then if I poll
clipboard every 1 or 2 seconds, I always get MemoryError after some
time. following is my code:

cdata = GetClip() #GetClip is a function to get current copied bitmap
from clipboard, return a Bitmap object.
rd = cdata.ConvertToImage().GetData() #it seems Bitmap doesn't support
"=" operator, so I convert it to Image
if rd == last_rd:
    return
else:
    <do something>
    last_rd = rd

so I want to know if there is way to detect the clipboard changing iso
poll it periodically.

···

On Aug 4, 12:20 pm, Bryan Oakley <bryan.oak...@gmail.com> wrote:

On Thu, Aug 4, 2011 at 12:49 PM, Hu Jun <hujun.w...@gmail.com> wrote:
> Hi,
> Is there a way in wxpython so that my program could do something
> whenever clipboard changes? I did search around, but could not find
> anything...

What I've done in the past is to periodically poll the clipboard and
compare what's there to whatever was there before. If it changed, call
your function. Checking every second or two is usually more than
sufficient. So, write a function to get the clipboard and compare,
then have it call itself one or two seconds later with wx.CallLater.

Thanks for your suggestion.
But I already tried this, the problem is if there are large amount of
data in the clipboard (50M bitmap for example),

You'd think there would be a way to query some information about what is in the clipboard without actually getting it, but I agree I don't' see one.

So, though it seems kludgy, you can solve the memory problem by not comparing the entire Bitmap, but rather a much smaller sub-bitmap, something like:

cdata = GetClip() #GetClip is a function to get current copied bitmap

from clipboard, return a Bitmap object.

rd = cdata.GetSubBitmap(100,100).ConvertToImage().GetData()

You may also be able to do the compare faster and more memory efficiently by grabbing the bitmap data without making an image, with wx.Bitmap.CopyToBuffer()

I'll leave the details of that as an exercise for the reader. :wink:

-Chris

···

On 8/4/11 12:41 PM, Hu Jun wrote:

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

I would suggest simply calculating a hash of the underlying data, then
compare to the previous hash. Then you are only storing the previous
hash and not a copy of the old buffer.

···

On Thu, Aug 4, 2011 at 4:13 PM, Christopher Barker <Chris.Barker@noaa.gov> wrote:

You may also be able to do the compare faster and more memory efficiently by
grabbing the bitmap data without making an image, with
wx.Bitmap.CopyToBuffer()

I'll leave the details of that as an exercise for the reader. :wink:

Thanks for your suggestion, my comments in line.

So, though it seems kludgy, you can solve the memory problem by not
comparing the entire Bitmap, but rather a much smaller sub-bitmap,
something like:

cdata = GetClip() #GetClip is a function to get current copied bitmap

> from clipboard, return a Bitmap object.

rd = cdata.GetSubBitmap(100,100).ConvertToImage().GetData()

sub-bitmap compare won't guarantee the result.

You may also be able to do the compare faster and more memory
efficiently by grabbing the bitmap data without making an image, with
wx.Bitmap.CopyToBuffer()

I tried this method, but it always give me the same error:
RuntimeError: Failed to gain raw access to bitmap data.

···

On Aug 4, 1:13 pm, Christopher Barker <Chris.Bar...@noaa.gov> wrote:

I'll leave the details of that as an exercise for the reader. :wink:

-Chris

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Bar...@noaa.gov

the problem is: how to access bitmap's underlying data without making
another copy, otherwise same MemoryError happens.

···

On Aug 4, 1:26 pm, Ben Timby <bti...@gmail.com> wrote:

I would suggest simply calculating a hash of the underlying data, then
compare to the previous hash. Then you are only storing the previous
hash and not a copy of the old buffer.

You didn’t mention which platform you are using to develop and as a target…
Keep in mind all this has absolutely nothing to do with wxPython other than, I am assuming, you want to display and/or manipulate a bitmap from the clipboard. You must do this in “pure Python” and have the ability to do so using the MS Windows clipboard access library is available through ctypes.

In particular see Creating a Clipboard Format Listener by MSW. It seems to be exactly what you are looking for.

“A clipboard format listener is a window which has [been] registered to [the Windows(r) OS] be notified [via a callback, just like wxPython events] when the contents of the clipboard has [been] changed [by anyone].”
When MSW says “window” they mean a Microsoft OS-generated window, These include wxPython top level windows, so this would suit your purposes.

Making MSW OS calls using ctypes can be somewhat bizarre due to Microsoft’s “unique” call conventions. MSW OS “calls” are termed “messages”. If you are interested, I and probably others can give you guidelines on how to write ctypes-based calls using Python.

Ray Pasco

Hi,

You didn’t mention which platform you are using to develop and as a target…
Keep in mind all this has absolutely nothing to do with wxPython other than, I am assuming, you want to display and/or manipulate a bitmap from the clipboard. You must do this in “pure Python” and have the ability to do so using the MS Windows clipboard access library is available through ctypes.

In particular see Creating a Clipboard Format Listener by MSW. It seems to be exactly what you are looking for.

“A clipboard format listener is a window which has [been] registered to [the Windows(r) OS] be notified [via a callback, just like wxPython events] when the contents of the clipboard has [been] changed [by anyone].”
When MSW says “window” they mean a Microsoft OS-generated window, These include wxPython top level windows, so this would suit your purposes.

Making MSW OS calls using ctypes can be somewhat bizarre due to Microsoft’s “unique” call conventions. MSW OS “calls” are termed “messages”. If you are interested, I and probably others can give you guidelines on how to write ctypes-based calls using Python.

To the OP (Windows only):

http://code.activestate.com/recipes/355593-windows-clipboard-viewer/

Andrea.

“Imagination Is The Only Weapon In The War Against Reality.”
http://xoomer.alice.it/infinity77/

==> Never EVER use RemovalGroup for your house removal. You’ll regret it forever.

http://thedoomedcity.blogspot.com/2010/03/removal-group-nightmare.html <==

···

On 5 August 2011 04:39, Ray Pasco wrote:

The demo doesn’t work on Win7. I suspect it has not been updated from when it was written for XP (Created by Georg Nelles
on Sat, 4 Dec 2004).

There’s a list of minor, but “show stopper” changes that need to be made to apps running on Win7, but I don’t know where to find it.

Ray

So, though it seems kludgy, you can solve the memory problem by not
comparing the entire Bitmap, but rather a much smaller sub-bitmap,
something like:

cdata = GetClip() #GetClip is a function to get current copied bitmap

from clipboard, return a Bitmap object.

rd = cdata.GetSubBitmap(100,100).ConvertToImage().GetData()

sub-bitmap compare won't guarantee the result.

no it won't, but it is likely to be "good enough". It depends where your images are coming from, but what are the odds that the bitmap will change, but that a given corner of it will be identical? and you could get smarter by grabbing a couple sub-bitmaps.

You may also be able to do the compare faster and more memory
efficiently by grabbing the bitmap data without making an image, with
wx.Bitmap.CopyToBuffer()

I tried this method, but it always give me the same error:
RuntimeError: Failed to gain raw access to bitmap data.

darn -- not sure what to do with that one. Robin may have an idea. Ideally you could do this and hash the data to avoid the whole creation of the Image -- if you can create an Image, the data must be available.

Though the Windows solutions offered sound like a better option -- to bad wx hasn't wrapped that functionality.

-Chris

···

On 8/4/11 3:12 PM, Hu Jun wrote:

On Aug 4, 1:13 pm, Christopher Barker<Chris.Bar...@noaa.gov> wrote:

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Well since it is a Windows machine. did you think about writing for instance some .NET code that you would compile into a dll. As far as I remember .NET has complete clases that let you monitor the clipboard and trigger events and execute eventhandlers when changes happen.