views:

154

answers:

4

Copying and pasting text is easy enough, since it's built into TMemo, but it seems that it can only handle text. Seems to me that any kind of data can be represented as a string, though. If I copy some arbitrary data from another program and want to paste it into a TMemo, how do I get Delphi to accept it as a raw string?

+1  A: 

have you tried to use clipbaord.astext between your tmemo and "another program"

avar
This doesn't work. If the contents of the clipboard aren't in text format, AsText returns an empty string.
Mason Wheeler
+2  A: 

Mason I'm not sure I understand your answer, but yes you can use Clipboard.AsText like avar said just add clipbrd to uses clause. Please note that if you have a null char somewhere in your string then KAZAM your string will be pasted from beginning till the null char #0. Another approach can be using memory mapped files or messages to send data between applications.

delphigeist
This should work, he just has to escape nulls
Aldo
As Mason says, this won't work if the clipboard doesn't have CF_TEXT format data. I think he wants to get any arbitrary data (in any format) and treat it as a string.
David M
+5  A: 

"If I copy some arbitrary data from another program and want to paste it into a TMemo, how do I get Delphi to accept it as a raw string?" So to clarify your question, you:

  • Want to use any other application (one you don't have code for, a normal app) and copy something in it
  • Want to paste this copied data, which can be any format including non-text, as text in your memo.

Is that correct? If so, you can't use Clipboard.AsText - that only returns text if there is data with the CF_TEXT format on the clipboard. You'll need to use the clipboard APIs directly. The clipboard holds data with a format code, and you can get a pointer to that data, and a size, and treat it as a string or however you want.

So:

  • Figure out what format you want to paste. You can iterate through all formats currently on the clipboard via EnumClipboardFormats, or use one of the predefined constants (for text, images, audio, etc.) The clipboard can hold data in many formats at once, so you may want to choose which of many you use.
  • If data in this format is on the clipboard, open it. Ensure you wrap this code in a try/finally and close the clipboard in the finally clause. If you don't close the clipboard, no other application will be able to use it, so you want it to be closed even if your application crashes.
  • Call GetClipboardData to get a handle to the data in that format. Data on (or given to, if you later implement Copy) is allocated via GlobalAlloc, so you need to lock the handle to get a pointer to it via GlobalLock (and once done, unlock with GlobalUnlock.) The data's owned by the clipboard so don't free it after you've used it. To find the size of this data in bytes, use GlobalSize.
  • This gives you a pointer to data of a known size. At this point you can do anything you want with it. Treating it as a string is one option. Since your app does not own the data you should copy it, not directly manipulate it.

Your code should be aware the data is of a certain size and probably wont be null-terminated (or may have nulls in it) so when converting to a string, make sure you don't overrun the buffer. You could encode it to avoid NULLs etc. If you want more details on something like this it's probably worth asking another question (or search for encoding arbitrary data as string.) The simplest thing to do would be to copy the data into a size+1 buffer, set the last byte to null, iterate through every byte except the very last and for non-printable characters (byte value < 32) change it to "." or some other character. Then pass a pointer to this buffer to AnsiString's constructor, cast as a PAnsiChar. (This ensures your data is treated as a string of byte-size chars - worth keeping in mind if you're using D2009+ since the native string type is Unicode.) An alternative string type to use is RawByteString. Once you have a string, add it to your memo.

There is a good example (in C, sorry) of pasting data of a specific format on MSDN. You could use that as a starting point, adding in your own custom treatment of the data. Pasting as a string is probably not the best way to view arbitrary binary data - you could use a hex editor component or some other visualiser to give you a better view of the data.

David M
Thanks, that worked!
Mason Wheeler
A: 

I'm not sure that your statement "any kind of data can be represented as a string" is meaningful. Binary data may have embedded nulls, which would interfere with treating the data as a string. And of what value is a string representation of, for instance, a bitmap image?

It's up to the application that sets the clipboard to determine the format for the clipboard information. If the application is thoughtful enough to provide a text representation of non-text information (for instance, the filename for an image, if any) then you can use that string information. Otherwise, it's not clear what pasting that information into a TMemo would even mean.

Larry Lustig
What I meant is, any kind of data can be represented as a RawByteString. I should have phrased it better.
Mason Wheeler