如何将任意数据粘贴到 TMemo 中?
复制和粘贴文本很容易,因为它内置于 TMemo 中,但它似乎只能处理文本。不过,在我看来,任何类型的数据都可以表示为字符串。如果我从另一个程序复制一些任意数据并希望将其粘贴到 TMemo 中,如何让 Delphi 将其接受为原始字符串?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
“如果我从另一个程序复制一些任意数据并希望将其粘贴到 TMemo 中,我如何让 Delphi 将其接受为原始字符串?”因此,为了澄清您的问题,您:
这是正确的吗?如果是这样,您不能使用
Clipboard.AsText
- 仅当剪贴板上存在CF_TEXT
格式的数据时才返回文本。您需要直接使用剪贴板 API。剪贴板保存带有格式代码的数据,您可以获得指向该数据的指针和大小,并将其视为字符串或您想要的任何方式。所以:
EnumClipboardFormats
,或使用预定义常量之一(用于文本、图像、音频等)。剪贴板可以同时保存多种格式的数据,因此您可能需要选择您想要的格式中的一种。使用。try/finally
中,并在finally
子句中关闭剪贴板。如果您不关闭剪贴板,则其他应用程序将无法使用它,因此即使您的应用程序崩溃,您也希望将其关闭。GetClipboardData
获取该格式数据的句柄。数据(或提供给,如果您稍后实现复制)通过GlobalAlloc
,因此您需要锁定句柄才能通过GlobalLock
(完成后,使用GlobalUnlock
。)数据归剪贴板所有,因此之后不要释放它你用过它。要查找此数据的大小(以字节为单位),请使用全局大小
。您的代码应该知道数据具有一定的大小,并且可能不会以 null 终止(或者其中可能有 null),因此在转换为字符串时,请确保不会溢出缓冲区。您可以对其进行编码以避免 NULL 等。如果您想了解有关此类内容的更多详细信息,可能值得提出另一个问题(或搜索将任意数据编码为字符串)。最简单的做法是要将数据复制到 size+1 缓冲区中,请将最后一个字节设置为 null,迭代除最后一个字节之外的每个字节,对于不可打印字符(字节值 < 32)将其更改为“。”或其他一些字符。然后将指向此缓冲区的指针传递给
AnsiString
的构造函数,转换为PAnsiChar
。 (这可确保您的数据被视为字节大小的字符串 - 如果您使用的是 D2009+,则值得记住,因为本机字符串类型是 Unicode。)要使用的替代字符串类型是RawByteString
。获得字符串后,将其添加到备忘录中。有一个很好的例子(用C语言,抱歉) 粘贴MSDN上特定格式的数据。您可以使用它作为起点,添加您自己的数据自定义处理。作为字符串粘贴可能不是查看任意二进制数据的最佳方式 - 您可以使用十六进制编辑器组件或其他一些可视化工具来更好地查看数据。
"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:
Is that correct? If so, you can't use
Clipboard.AsText
- that only returns text if there is data with theCF_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:
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.try/finally
and close the clipboard in thefinally
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.GetClipboardData
to get a handle to the data in that format. Data on (or given to, if you later implement Copy) is allocated viaGlobalAlloc
, so you need to lock the handle to get a pointer to it viaGlobalLock
(and once done, unlock withGlobalUnlock
.) 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, useGlobalSize
.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
NULL
s 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 toAnsiString
's constructor, cast as aPAnsiChar
. (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 isRawByteString
. 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.
梅森我不确定我是否理解你的答案,但是是的,你可以使用 Clipboard.AsText 就像 avar 所说的那样,只需将 Clipbrd 添加到使用子句中即可。
请注意,如果字符串中某处有空字符,那么 KAZAM 将从开头粘贴字符串到空字符 #0。另一种方法是使用内存映射文件或消息在应用程序之间发送数据。
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.
您是否尝试过在 tmemo 和“另一个程序”之间使用 Clipbaord.astext
have you tried to use clipbaord.astext between your tmemo and "another program"
我不确定你的说法“任何类型的数据都可以表示为字符串”是否有意义。二进制数据可能嵌入了空值,这会干扰将数据视为字符串。例如,位图图像的字符串表示有什么价值?
由设置剪贴板的应用程序来确定剪贴板信息的格式。如果应用程序足够周到,可以提供非文本信息的文本表示(例如图像的文件名,如果有),那么您可以使用该字符串信息。否则,不清楚将该信息粘贴到 TMemo 中意味着什么。
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.