What is my Clipboardowner for a script?
-
Hello;
I was just looking into the clipboard functions and found that the specialized function
CopyBitmapToClipboard
requires aCLIPBOARDOWNER
.I assume this has to do with delay-rendering of clipboard content and the
WM_RENDERFORMAT
message under Windows - no idea how the clipboard works under Mac... Wasn't actually aware that C4D uses that mechanism at all, but that's how it looks.So, if I use
CopyBitmapToClipboard
in a script or plugin of my own, I wouldn't delay-render the bitmap, so I'd use neither theCLIPBOARDOWNER_BODYPAINT
nor theCLIPBOARDOWNER_PICTUREVIEWER
constants, which (I assume) would cause the clipboard to sendWM_RENDERFORMAT
to either window instead of my script. Of course, these are the only constants available, and the function description does not offer anything else.When getting a bitmap from the system,
GetC4DClipboardOwner
returns 0, so I assume I can pass 0 safely too in calls toCopyBitmapToClipboard
? Or am I overlooking some larger context here? As I am neither BodyPaint nor the PictureViewer, I would never want to use these constants anyway. But there is no speaking constant for 0, andCopyBitmapToClipboard
makes it even a mandatory parameter?Can I crash C4D by using one of the two
CLIPBOARDOWNER
constants in a script (while not implementing a delay-render to clipboard at all which C4D doesn't even offer)?GetC4DClipboardOwner
allows me to retrieve the clipboard owner, but under what circumstances would I want to know that? If this is only for the delayed retrieval of clipboard content, then this should work fully transparently (?)(Edit: Does look better with less formatting now?)
-
Hello @cairyn,
Thank you for reaching out to us. I see you saw my post yesterday before I hid it. I was not implying that you should change the existing one, and more meant that you should try to reduce the complexity of presentation and content of future requests, as at least I often struggle with both of in your topics.
The reason I hid my posting was that I was a bit lazy yesterday and accidentally looked at the Linux implementation of the clipboard. So, for Windows, the backend implementation of
GetC4DClipboardOwner()
looks like this:Int32 ClipBoard::GetC4DOwner() { if (!_GeClippboardWindow || _GeClippboardWindow != GetClipboardOwner()) return 0; return m_ownerid; }
And this seems to be never to be able to get past the conditional expression in the first line, at least I never managed to do so.
GetClipboardOwner()
is a Windows function, and_GeClippboardWindow
is a window handle (HWND
) our clipboard is storing, the two simply never match up.When writing a bitmap to the clipboard, and setting the owner identifier manually, the outcome is never what one would expect.
>>> bmp = c4d.bitmaps.BaseBitmap() >>> c4d.CopyBitmapToClipboard(bmp, c4d.CLIPBOARDOWNER_PICTUREVIEWER) >>> c4d.GetC4DClipboardOwner() 0 >>> c4d.CopyBitmapToClipboard(bmp, 12345678) >>> c4d.GetC4DClipboardOwner() 0
The reason is that the field
m_ownerid
is never actually written when the backend function which is invoked byCopyBitmapToClipboard()
is being called. The reason is again here that something with window handles is going wrong, causingm_ownerid
always being0
.So, to summarize:
- The
ownerid
argument ofCopyBitmapToClipboard
is effectively meaningless, as it is never being written to the backend field storing that information. - There are in principle no restrictions to
ownerid
, you can write anything that fits into anInt32
there. The only functions that inside the clipboard rely on this field are the one's mentioned in this thread. It could of course be that the Picture Viewer or Bodypaint do some clever poking around in the backend, but this seems unlikely. To be absolutely sure, I would avoid writing the owner identifiersCLIPBOARDOWNER_BODYPAINT
andCLIPBOARDOWNER_PICTUREVIEWER
manually. But this is all very theoretical since writingm_ownerid
does not work in the first place.
I am not sure yet how we will deal with this. It could for example be that the Windows API we are relying on has changed. It seems likely that we will simply make the argument
ownerid
and the concept of owners private, i.e., hide them in the C++ and Python docs, as this all is quite minor.Thank you for pointing this out.
Cheers,
Ferdinand - The
-
Hmm, there seem to be recent changes in that functionality. When I try to copy a newly rendered image from the PictureViewer, the owner actually seems to be set fine in the R23.110:
>>> c4d.GetC4DClipboardOwner() 200000244
(I assume that Python cannot do anything that C++ would not support...)
On the other hand, your other code indeed returns 0 so maybe the functionality wasn't consistent in R23 anyway.
Thanks, I will go with an ownerid of 0 for now... as there are no callbacks targeting my script, it can't hurt anyway.
-
Hey @cairyn,
yeah, you are right. @m_adam already pointed this out too. I screwed up and overwrote my clipboard when I tried this out. I have edited my initial posting, to not confuse future readers.
GetC4DClipboardOwner
works fine in regards to the Picture Viewer and Bodypaint, but the argumentownerid
ofCopyBitmapToClipboard
is effectively meaningless in the public API, as it lacks the window handle context to actually cause theownerid
to be stored. The owner id will always be set to0
.And to underline the answer to your major question: It seems very unlikely that you could crash Cinema 4D with writing a made-up owner id into the clipboard (in the case the function would work properly and actually store the id). It is hard to give here absolute answers, as there is a lot of code in our code base. In the context of the clipboard alone, crashing can be excluded, but there could be other parts of Cinema 4D which make assumptions based on the owner id. Which is why I would recommend not using the predefined ones (which is rather theoretical due to said limitations of
CopyBitmapToClipboard
).Cheers,
Ferdinand