是否可能,如果是这样,您将如何实施自己的剪贴板?
我的意思是能够像Windows剪贴板那样复制和粘贴任何内容,但实际上并没有干扰系统剪贴板。
为了更好地了解这就是我的尝试:
uses
ClipBrd;
...
procedure TMainForm.actCopyExecute(Sender: TObject);
var
MyClipboard: TClipboard;
begin
MyClipboard := TClipboard.Create;
try
MyClipboard.AsText := 'Copy this text';
finally
MyClipboard.Free;
end;
end;
这样可以将字符串“Copy this text”复制到剪贴板,但它会覆盖Windows剪贴板上的内容。
上面必须创建一个Windows剪贴板实例,而不是实际创建自己的实例。
请注意,自定义剪贴板可以保存任何数据,而不仅仅是纯文本。它应该与Windows剪贴板一样工作,但不会干扰它(丢失它上面的任何内容)。
如何实现这一目标?
感谢。
答案 0 :(得分:5)
你的问题令人困惑;你说你想在不影响系统剪贴板的情况下这样做,但是(从你自己的评论到你的问题)你似乎想要实现像MS Office Paste Special
这样的东西。
如果是第一个,正如其他人所说,你不能使用TClipboard
包装器那样做;你必须实现自己的,并且在应用程序之间传递信息将非常困难。
如果是第二个,请使用Windows API RegisterClipboardFormat来定义您自己的格式。
type
TForm1=class(TForm)
YourCustomFormat: Word;
procedure FormCreate(Sender: TObject);
end;
implementation
constructor TForm1.FormCreate(Sender: TObject);
begin
YourCustomFormat := RegisterClipboardFormat('Your Custom Format Name');
end;
要以自定义格式将信息放入剪贴板,您必须使用GlobalAlloc和GlobalLock来分配和锁定全局内存块,将数据复制到该块中,使用{解锁块{3}},使用TClipboard.SetAsHandle
将内存块传输到剪贴板。然后,您需要调用GlobalUnlock来释放内存块。
要以自定义格式检索内容,基本上会执行相同的操作,只需颠倒几个步骤即可。您像以前一样使用GlobalAlloc / GlobalLock,使用TClipboard.GetAsHandle
检索剪贴板的内容,将其复制到本地变量,然后调用GlobalFree。
这是一个将自定义格式(在本例中为RTF文本)放入剪贴板的旧示例 - 它来自GlobalFree的Dr. Peter newsgroup post。 (代码和格式是来自原始帖子的;我没有对它进行过测试,甚至没有对其进行编译。)从我的指示中可以清楚地反过来将其恢复出去,我将其留给你锻炼身体。 :)
procedure TForm1.BtnSetRTFClick(Sender: TObject);
Const
testtext: PChar = '{\rtf1\ansi\pard\plain 12{\ul 44444}}';
testtext2: PChar = '{\rtf1\ansi'+
'\deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}}'
+'\pard\plain 12{\ul 44444}}';
flap: Boolean = False;
Var
MemHandle: THandle;
rtfstring: PChar;
begin
If flap Then
rtfstring := testtext2
Else
rtfstring := testtext;
flap := not flap;
MemHandle := GlobalAlloc( GHND or GMEM_SHARE, StrLen(rtfstring)+1 );
If MemHandle <> 0 Then Begin
try
StrCopy( GlobalLock( MemHandle ), rtfstring );
GlobalUnlock( MemHandle );
With Clipboard Do Begin
Open;
try
AsText := '1244444';
SetAsHandle( CF_RTF, MemHandle );
finally
Close;
end;
End;
Finally
GlobalFree( MemHandle );
End;
End
Else
MessageDlg('Global Alloc failed!',
mtError, [mbOK], 0 );
end;
答案 1 :(得分:2)
您应该定义自己的自定义剪贴板。它可能看起来像这样:
type
TMyCustomClipboard = class
private
FStream: TMemoryStream;
function GetAsText: string;
procedure SetAsText(const Value: string);
...
public
constructor Create;
destructor Destroy; override;
procedure Clear;
property AsText: string read GetAsText write SetAsText;
procedure AsAnyThing: AnyType read GetAsAnyThing write AsAnyThing;
...
end;
然后您可以使用FStream
作为自定义剪贴板容器。您可以在该流中存储(复制)任何数据,并在需要时使用(粘贴)它。您只需要为数据类型编写一些Get / Set方法。
答案 2 :(得分:1)
TClipboard是一个类封装系统剪贴板,因此您无法使用它来实例化剪贴板的另一个副本。您应该实现自己的类,表示具有setter和getter的通用缓冲区。
答案 3 :(得分:1)
你做不到。你可以有一个内部存储器缓冲区,你可以将数据移入和移出,如果你愿意,你可以称之为“复制”和“粘贴”,但不要把它放在用户界面那样,否则你只会混淆你的用户。只有一个系统剪贴板,您不能在不影响其他程序的情况下将数据放入其中。如果你的下一个想法是保存剪贴板,用你的东西覆盖,然后恢复原始内容,不要打扰。