如何创建自己的非系统剪贴板?

时间:2012-02-11 20:39:14

标签: delphi clipboard

是否可能,如果是这样,您将如何实施自己的剪贴板?

我的意思是能够像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剪贴板一样工作,但不会干扰它(丢失它上面的任何内容)。

如何实现这一目标?

感谢。

4 个答案:

答案 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;

要以自定义格式将信息放入剪贴板,您必须使用GlobalAllocGlobalLock来分配和锁定全局内存块,将数据复制到该块中,使用{解锁块{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)

你做不到。你可以有一个内部存储器缓冲区,你可以将数据移入和移出,如果你愿意,你可以称之为“复制”和“粘贴”,但不要把它放在用户界面那样,否则你只会混淆你的用户。只有一个系统剪贴板,您不能在不影响其他程序的情况下将数据放入其中。如果你的下一个想法是保存剪贴板,用你的东西覆盖,然后恢复原始内容,不要打扰。

相关问题