如何正确在剪贴板存入自定义格式的内容﹖

Frank6600 2010-01-13 10:55:38
var
PRec: ^TMyRec;
Data: THandle;
begin
Data := GlobalAlloc(GMEM_DDESHARE, SizeOf(TMyRec));
PRec := GlobalLock(Data);

PRec.name := '张三';
PRec.age := 99;

GlobalUnlock(Data);
Clipboard.SetAsHandle(CF_MY, Data);

网上找到上列例子,例子中 TMyRec 是一个记录结构:

TMyRec = record
name: string[8];
age : Byte;
end;

这个例子中,我不明白的是 SizeOf 的部份。
一个记录结构,要算 Size 是容易的,尤其上例中 string 后还加了一个[8]限定长度。

但,如果要存入的是长度不定的呢﹖

例如存入一个 TStringList 的内容。
难道也用 sizeof(TStringList) 吗﹖

我要实现的比 TStringList 还要难点:基本上是 Linked List 结构。
每一个Linked List的节点内容,保存的是HTML,长度不一定。
我写一个示意代码:

TNode = class
public
HTML: string;
procedure AddChild(Node: TNode);
procedure AddBefore(Node: TNode);
Procedure AddAfter(Node: TNode);
end;

TMyTree = class
public
RootNode: TNode;
procedure AddNode(ParentNode: TNode; str: string);
end;

类似这样。
最终我要把这整个 Tree 都存入剪贴板,怎么做啊﹖

(注:Tree的形状、Node数直到黏贴前才确定。Node.HTML 的长度也是直到黏贴前才确定)



...全文
229 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Frank6600 2010-01-14
  • 打赏
  • 举报
回复
好了,感谢各位,初步的思路有了,我按这个思路去解决吧!
Frank6600 2010-01-13
  • 打赏
  • 举报
回复
> sizeof只不过是取结构占的内存大小,这不是主要问题,主要的问题是你知道如何用上面那几个函数分配内> 存并加入剪贴板,这个自己变通一下就行了,比如你的Html是String,那保存个String不就行了:

听起来像是包的概念。
那复杂结构的Copy与Paste就必须用封包与解包的概念来实现了﹖
wzwcn 2010-01-13
  • 打赏
  • 举报
回复
sizeof只不过是取结构占的内存大小,这不是主要问题,主要的问题是你知道如何用上面那几个函数分配内存并加入剪贴板,这个自己变通一下就行了,比如你的Html是String,那保存个String不就行了:
var
P: Pchar;
H: THandle;
Html:string;//你的string
begin
//..你的html 长度不定
H:= GlobalAlloc(GMEM_DDESHARE, length(Html)); //分配一块内存
P:= GlobalLock(H);//取得指向内存块的指针
move(pchar(Html)^,p^,length(Html));
GlobalUnlock(H);
Clipboard.SetAsHandle(CF_MY,H);

大概就这样,上面代码随手写的没测试
dd_zhouqian 2010-01-13
  • 打赏
  • 举报
回复
没看懂,帮顶
hjkto 2010-01-13
  • 打赏
  • 举报
回复
我有一个监视剪切板的例子,不知你需要不?
需要的话 ,留下联系方式
我打包给你
iseekcode 2010-01-13
  • 打赏
  • 举报
回复
你可以找一下这本书的随书源码,除了这个类,作者还给出了应用实例。

move方法作者的解释在上面。
DELPHI7帮助文档的:

Description
Move copies Count bytes from Source to Dest. No range checking is performed. Move compensates for overlaps between the source and destination blocks.

Whenever possible, use the global SizeOf function (Delphi) or the sizeof operator (C++) to determine the count.
Frank6600 2010-01-13
  • 打赏
  • 举报
回复
iseekcode 提供的“D5开发人员指南英文版里的一个自定义剪贴板操作类”,
如果我理解得没错,其本质就是封包,是吧﹖

它的封包原理用的是最最简单的,即用CRLF把它们接起来。
不过没看懂它怎么解包的。

// Copy the data to the TDataRec field
Move(DataPtr^, Rec, Size)

这方法不太理解,怎么没看到以 CRLF 分解的过程。


金卯刀 2010-01-13
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 iseekcode 的回复:]
如果是deep copy且跨进程,可不可以先将对象序列化或者叫串行化,通过进程间通信解决?
[/Quote]
若都是delphi程序,那好說 ^_^
Frank6600 2010-01-13
  • 打赏
  • 举报
回复


uses Clipbrd;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
Clipboard.SetComponent(Tree);
Tree.Name:='MyTree';
Clipboard.GetComponent(Self,panel1);//Owner-->self; Parent--->panel
end;
...
initialization
RegisterClasse([TTree]);//若有其他類型,也要注冊...
...



这方法挺酷的,虽然不太相信这方法能成,但很好奇它的实现逻辑是怎么样的。
iseekcode 2010-01-13
  • 打赏
  • 举报
回复
如果是deep copy且跨进程,可不可以先将对象序列化或者叫串行化,通过进程间通信解决?
金卯刀 2010-01-13
  • 打赏
  • 举报
回复
另外,只要是TCompent類型的,也可以用delphi提供的TClipBoard中的方法,如下:

uses Clipbrd;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
Clipboard.SetComponent(Tree);
Tree.Name:='MyTree';
Clipboard.GetComponent(Self,panel1);//Owner-->self; Parent--->panel
end;
...
initialization
RegisterClasse([TTreeView]);//若有其他類型,也要注冊...
...


在同一進程中,若知道拷貝的對象是什么具體類型,則可用assign;若不知道,則可用此法...
金卯刀 2010-01-13
  • 打赏
  • 举报
回复
但你要用剪切板,不知道是否有跨進程這個因素?若是這樣,問題就不那么簡單了....
金卯刀 2010-01-13
  • 打赏
  • 举报
回复
你的需求看起來是對象拷貝中的 Deep Copy。
了解一下你所使用的對象中的assign方法
iseekcode 2010-01-13
  • 打赏
  • 举报
回复
下面是D5开发人员指南英文版里的一个自定义剪贴板操作类:

A Unit That Defines Custom Clipboard

unit cbdata;
interface

uses
SysUtils, Windows, clipbrd;

const
DDGData = ‘CF_DDG’; // constant for registerin

type
// Record data to be stored to the clipboard
TDataRec = packed record
LName: string[10];
FName: string[10];
MI: string[2];
Age: Integer;
BirthDate: TDateTime;
end;

{ Define an object around the TDataRec that contains the methods
for copying and pasting the data to and from the clipboard }

TData = class
public
Rec: TDataRec;
procedure CopyToClipBoard;
procedure GetFromClipBoard;
end;

var
CF_DDGDATA: word; // Receives the return value of RegisterClipboardFormat().
implementation

procedure TData.CopyToClipBoard;
{ This function copies the contents of the TDataRec field, Rec, to the
clipboard as both binary data, as text. Both formats will be
available from the clipboard }
const
CRLF = #13#10;
var
Data: THandle;
DataPtr: Pointer;
TempStr: String[50];
begin
// Allocate SizeOf(TDataRec) bytes from the heap
Data := GlobalAlloc(GMEM_MOVEABLE, SizeOf(TDataRec));
try
// Obtain a pointer to the first byte of the allocated memory
DataPtr := GlobalLock(Data);
try
// Move the data in Rec to the memory block
Move(Rec, DataPtr^, SizeOf(TDataRec));
{ Clipboard.Open must be called if multiple clipboard formats are
being copied to the clipboard at once. Otherwise, if only one
format is being copied the call isn’t necessary }
ClipBoard.Open;
// First copy the data as its custom format
ClipBoard.SetAsHandle(CF_DDGDATA, Data);
// Now copy the data as text format
with Rec do
TempStr := FName+CRLF+LName+CRLF+MI+CRLF+IntToStr(Age)+CRLF+
DateTimeToStr(BirthDate);
ClipBoard.AsText := TempStr;
{ If a call to Clipboard.Open is made you must match it
with a call to Clipboard.Close }
Clipboard.Close
finally
// Unlock the globally allocated memory
GlobalUnlock(Data);
end;
except
{ A call to GlobalFree is required only if an exception occurs.
Otherwise, the clipboard takes over managing any allocated
memory to it.}
GlobalFree(Data);
raise;
end;
end;

procedure TData.GetFromClipBoard;
{ This method pastes memory saved in the clipboard if it is of the
format CF_DDGDATA. This data is stored in the TDataRec field of
this object. }
var
Data: THandle;
DataPtr: Pointer;
Size: Integer;
begin
// Obtain a handle to the clipboard
Data := ClipBoard.GetAsHandle(CF_DDGDATA);
if Data = 0 then Exit;
// Obtain a pointer to the memory block referred to by Data
DataPtr := GlobalLock(Data);
try
// Obtain the size of the data to retrieve
if SizeOf(TDataRec) > GlobalSize(Data) then
Size := GlobalSize(Data)
else
Size := SizeOf(TDataRec);
// Copy the data to the TDataRec field
Move(DataPtr^, Rec, Size)
finally
// Free the pointer to the memory block.
GlobalUnlock(Data);
end;
end;

initialization
// Register the custom clipboard format
CF_DDGDATA := RegisterClipBoardFormat(DDGData);
end.

This unit performs several tasks. First, it registers the new format with the Win32 Clipboard by calling the RegisterClipboardFormat() function. This function returns a value that identifies this new format. Any application that registers this same format, as specified by the string para-meter, will obtain the same value when calling this function. The new format is also available on the ClipBoard’s list of formats, which can be accessed by the Clipboard.Formats property.

The unit also defines the record containing the data to be placed onto the Clipboard and the object that encapsulates this record. The record, TDataRec, has string fields to hold a person’s name, an integer field to hold the person’s age, and a TDataTime field to hold the person’s birth date.

The object encapsulating TDataRec, TData, defines the methods CopyToClipboard() and
GetFromClipboard().
计算机应用基础 3 D A:2008-4-5 B:"2008-4-5" C:'2008-4-5 D:=2008-4-5 答案: C 19、Excel 2003主界面窗口中默认打开有格式工具栏和______。 A:常用工具栏 B:窗体工具栏 C:绘图工具栏 D:列表工具栏 答案: A 20、关于窗口的说法中,不正确的是______。 A:应用程序窗口的第一行为标题栏 B:在窗口的右上方有三个按钮,分别是"最小化"、"关闭"、"移动"按钮 C:在窗口中可用图标代表一个程序、数据文件、系统文件或文件夹 D:窗口是屏幕中可见的矩形区域,它的周围有一个边框 答案: B 21、Windows中有很多功能强大的应用程序,其中"磁盘碎片整理程序"的主要用途是___ ___。 A:将进行磁盘文件碎片整理,提高磁盘的读写速度 B:将磁盘的文件碎片删除,释放磁盘空间 C:将进行磁盘碎片整理,并重新格式化 D:将不小心摔坏的软盘碎片重新整理规划使其重新可用 答案: A 22、在Windows中,下列______操作不会被写入剪贴板。 A:复制 B:剪切 C:删除 D:截屏 答案: C 23、在Windows 中,可以用来做墙纸的文件格式可以是______。 A:*.doc和*.txt B:*.html和*.txt C:*.bmp和*.html D:*.txt和*.bmp 答案: C 24、在Windows 中,"回收站"中的文件或文件夹被还原后,将从回收站移出到______。 A:一个专门存放还原文件的文件夹中 B:驱动器C:目录下 C:原先的位置 D:任何一个文件夹下 答案: C 25、在Internet上使用的基本通信协议是______。 A:DECNET B:TCP/IP C:NetBIOS D:IPX/SPX 答案: B 26、Internet邮件地址中,不能少的字符是______。 A:. B:@ C:com D:cn 答案: B 27、PowerPoint中,下列裁剪图片的说法错误的是_______。 A:裁剪图片是指保存图片的大小不变,而将不希望显示的部分隐藏起来 B:当需要重新显示被隐藏的部分时,还可以通过"裁剪"工具进行恢复 C:按住鼠标右键向图片内部拖动时,可以隐藏图片的部分区域 D:如果要裁剪图片,单击选定图片,再单击"图片"工具栏中的"裁剪"按钮 答案: C 28、PowerPoint中,怎样使幻灯片中元素按照用户特定的路线来设置动画进入的效果__ _____。 A:动画效果是事先确定的,只能选择,不能改变 B:只能用FLASH 软件制作,实现这样的效果 C:插入动画对象 D:自定义动画 添加效果 绘制自定义动作路径 答案: D 29、下列操作可能使得计算机感染病毒的操作是______。 A:新建一个文件夹 B:删除文件 C:强行关闭计算机 D:使用外来的软件或光盘 答案: D 30、关于计算机中使用的软件,叙述错误的是________。 A:软件凝结着专业人员的劳动成果 B:软件像书籍一样,借来复制一下并不损害他人 C:未经软件著作权人的同意复制其软件是侵权行为 D:软件如同硬件一样,也是一种商品 答案: B 31、下面关于防火墙说法不正确的是_____。 A:防火墙可以防止所有病毒通过网络传播 B:防火墙可以由代理服务器实现 C:所有进出网络的通信流都应该通过防火墙 D:防火墙可以过滤所有的外网访问 答案: A 32、下面,关于计算机安全属性说法不正确的是______。 A:计算机的安全属性包括:保密性、完整性、不可抵赖性、可靠性 B:计算机的安全属性包括:保密性、完整性、不可抵赖性、可用性 C:计算机的安全属性包括:可靠性、完整性、保密性、完全性 D:计算机的安全属性包括:保密性、完整性、可用性、可靠性 答案: C 33、在"画图"工具中,可以打开的文件类型不包括______。 A:.bmp B:.jpg C:.gif D:.doc 答案: D 34、下面四类文件中,不属于多媒体文件类别的是______。 A:WAV文件 B:MPEG文件 C:AVI文件 D:EXE文件 答案: D 35、下面既属于多媒体输入设备,又属于多媒体输出设备的是______。 A:扫描仪 B:触摸屏 C:光学照相机 D:打印机 答案: B 36、多媒体和电视的区别在于______。 A:有无声音 B:有无图像 C:有无动画 D:有无交互性 答案: D 37、路由器工作在ISO/OSI模型的______。 A:应用层和物理层 B:网络层和物理层 C:数据链路层 D:物理层 答案: B 38、目前局域网的带宽一般为______。 A:10M~100Mbps B:128Kbps C:56Kbps D:10Kbps 答案: A 39、BBS的中文名称是

16,746

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧