博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Delphi-操作剪贴板
阅读量:4657 次
发布时间:2019-06-09

本文共 10930 字,大约阅读时间需要 36 分钟。

使用剪切板[1]: AsText、SetTextBuf、GetTextBuf

剪切板类 TClipboard 定义在 Clipbrd 单元, 使用前先要

uses Clipbrd;

 

代码如下:

uses Clipbrd;procedure TForm1.Button1Click(Sender: TObject);var  clip: TClipboard;begin  clip := TClipboard.Create; {
建立} clip.AsText := Self.Text; {
把窗体标题放入剪切板} ShowMessage(clip.AsText); {
从剪切板读取, 返回结果是: Form1} {
因为剪切板是全局的, 此时可以在其他地方粘贴一试} clip.Free; {
释放}end;

根据 Delphi 给我们提供的方便, 上面的例子可以简化为:

uses Clipbrd;procedure TForm1.Button1Click(Sender: TObject);begin  Clipboard.AsText := Text;  ShowMessage(Clipboard.AsText); {
Form1}end;

这个 Clipboard 是什么? 是不是和 Screen 一样的类型变量?

答案是否定的! Clipboard 只是个函数, 是一个无参函数, 是定义在 Clipbrd 单元的一个全局函数, 它返回一个 TClipboard 类型的变量, 当我看到这个函数的源码时, 真是感觉又学了一招, 非常精巧的思路.

除了用 TClipboard.AsText 属性, 我们还可以使用 SetTextBuf 把文本放入剪切板、使用 GetTextBuf 读出剪切板中的文本.

uses Clipbrd;{
使用 SetTextBuf}procedure TForm1.Button1Click(Sender: TObject);begin Clipboard.SetTextBuf(PChar(Text)); {
按参数类型要求, 需要转换一下} ShowMessage(Clipboard.AsText); {
Form1}end;{
使用 GetTextBuf 就和使用 API 差不多, 需要给个缓冲区}procedure TForm1.Button2Click(Sender: TObject);var arr: array[0..255] of Char;begin Clipboard.AsText := Text; Clipboard.GetTextBuf(arr, Length(arr)); ShowMessage(arr); {
Form1}end;{
如果不给缓冲区, 那你自己得申请并释放内存}procedure TForm1.Button3Click(Sender: TObject);var pc: PChar;begin Clipboard.AsText := Text; GetMem(pc, 256); {
申请内存} Clipboard.GetTextBuf(pc, 256); ShowMessage(pc); {
Form1} FreeMem(pc); {
释放内存}end;

 

使用剪切板[2]: Assign、HasFormat

准备工作: 在窗体上放置一个 TPanel; 在 TPanel 上放一个 TImage; 另外需要三个按钮.

第一版代码:

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls, ExtCtrls;type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Button3: TButton;    Panel1: TPanel;    Image1: TImage;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure Button3Click(Sender: TObject);  end;var  Form1: TForm1;implementation{
$R *.dfm}uses Clipbrd;procedure TForm1.Button1Click(Sender: TObject);begin Image1.Left := 0; Image1.Top := 0; Panel1.AutoSize := True; Image1.AutoSize := True; Image1.Picture.LoadFromFile('c:/temp/test.bmp'); TButton(Sender).Caption := '导入';end;procedure TForm1.Button2Click(Sender: TObject);begin Clipboard.Assign(Image1.Picture); {
把 Image1 中的图片放入剪切板} {
现在在图像软件中都可以粘贴了, 可以用 Windows 画图板试试} TButton(Sender).Caption := '复制';end;procedure TForm1.Button3Click(Sender: TObject);var bit: TBitmap; {
准备用一个 TBitmap 从剪切板中结束图片} x,y: Integer;begin bit := TBitmap.Create; bit.Assign(Clipboard); {
从剪切板获取} x := Panel1.Width + Panel1.Left * 2; {
x,y 是准备在窗体上的粘贴位置} y := Panel1.Top; Canvas.Draw(x, y, bit); {
粘贴就是画出来呗} bit.Free; TButton(Sender).Caption := '粘贴';end;end.

不过现在程序还有漏洞: 假如剪切板中没有东西, 粘贴什么? 如果剪切板中不是图片, 怎么粘贴?

其实我们只用 TClipboard.HasFormat 函数判断一下剪切板中是不是图片就行了.

第二版代码:

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls, ExtCtrls;type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Button3: TButton;    Panel1: TPanel;    Image1: TImage;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure Button3Click(Sender: TObject);  end;var  Form1: TForm1;implementation{
$R *.dfm}uses Clipbrd;procedure TForm1.Button1Click(Sender: TObject);begin Image1.Left := 0; Image1.Top := 0; Panel1.AutoSize := True; Image1.AutoSize := True; Image1.Picture.LoadFromFile('c:/temp/test.bmp'); TButton(Sender).Caption := '导入';end;procedure TForm1.Button2Click(Sender: TObject);begin {
如果 Image1 还没有图片, 就别复制了, 退出吧} if Image1.Picture = nil then Exit; Clipboard.Assign(Image1.Picture); TButton(Sender).Caption := '复制';end;procedure TForm1.Button3Click(Sender: TObject);var bit: TBitmap; x,y: Integer;begin {
如果当前剪切板中的东西不是图片, 就退出} if not Clipboard.HasFormat(CF_BITMAP) then Exit; bit := TBitmap.Create; bit.Assign(Clipboard); x := Panel1.Width + Panel1.Left * 2; y := Panel1.Top; Canvas.Draw(x, y, bit); bit.Free; TButton(Sender).Caption := '粘贴';end;end.

现在有出了新的问题: CF_BITMAP 常量表示图片, 其他格式怎么表示? 有多少格式可以用于剪切板?

使用剪切板[3]: SetComponent、GetComponent
本例演示把一个组件(TEdit)放入剪切板, 又取出(放到一个 TPanel 上)的过程.

放入剪切板的方法是个过程: SetComponent(要放入的组件);

取出的方法是个函数: GetComponent(指定属主, 指定父窗口): 函数返回取出的组件的句柄.

取出以前, 最好要判断一下当前剪切板中是不是个组件: HasFormat(CF_COMPONENT);

取出以前还必须要注册要取出的组件类, 譬如: RegisterClasses([TEdit]);

准备工作: 在窗体上添加 TEdit、TPanel 和三个按钮.

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls, ExtCtrls;type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Button3: TButton;    Edit1: TEdit;    Panel1: TPanel;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure Button3Click(Sender: TObject);  end;var  Form1: TForm1;implementation{
$R *.dfm}uses Clipbrd;var obj: TComponent; {
用于接受 GetComponent 的返回值}procedure TForm1.Button1Click(Sender: TObject);begin Clipboard.SetComponent(Edit1); TButton(Sender).Caption := '复制';end;procedure TForm1.Button2Click(Sender: TObject);begin RegisterClasses([TEdit]); if Clipboard.HasFormat(CF_COMPONENT) then obj := Clipboard.GetComponent(nil, Panel1); TButton(Sender).Caption := '粘贴';end;procedure TForm1.Button3Click(Sender: TObject);begin if Assigned(obj) then obj.Free; TButton(Sender).Caption := '删除';end;end.

一般情况下, 应该把 RegisterClasses(); 过程提前放置(起码可以避免反复执行), 譬如在 Form1.OnCreate 事件中;

大家好像都习惯再提前到: initialization. 程序修改如下:

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls, ExtCtrls;type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Button3: TButton;    Edit1: TEdit;    Panel1: TPanel;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure Button3Click(Sender: TObject);  end;var  Form1: TForm1;implementation{
$R *.dfm}uses Clipbrd;var obj: TComponent;procedure TForm1.Button1Click(Sender: TObject);begin Clipboard.SetComponent(Edit1); TButton(Sender).Caption := '复制';end;procedure TForm1.Button2Click(Sender: TObject);begin if Clipboard.HasFormat(CF_COMPONENT) then obj := Clipboard.GetComponent(nil, Panel1); TButton(Sender).Caption := '粘贴';end;procedure TForm1.Button3Click(Sender: TObject);begin if Assigned(obj) then obj.Free; TButton(Sender).Caption := '删除';end;initialization RegisterClasses([TEdit]);end.

另外, 关于剪切板中格式的问题还没有详谈, 这里有来了一个 CF_COMPONENT.

Windows 系统已经定义了十几种剪切板的格式常数, 譬如: CF_BITMAP、CF_TEXT 等等;

不过这里的 CF_COMPONENT 是 Delphi 自定义的, 可以猜测: 在需要的时候, 我们也可以自定义剪切板中的格式.

使用剪切板[4]: 如果把子控件一起复制?
如果连同子控件一起复制到剪切板, 需要定义一个新类型.

譬如在一个 TPanel 中包含一个 TEdit; 在复制 TPanel 时, 若要连同 TEdit 一起复制, 需要重新从 TPanel 中继承出一个类来(譬如是 TMyPanel), 把 TEdit 包含在新的类中.

TMyPanel 类的单元:

unit MyPanel;interfaceuses Classes, StdCtrls, ExtCtrls;type  TMyPanel = class(TPanel)    Edit1: TEdit;     constructor Create(AOwner: TComponent); override;  end;implementation{
TMyPanel }constructor TMyPanel.Create(AOwner: TComponent);begin inherited; Edit1 := TEdit.Create(Self); Edit1.Parent := Self; Edit1.Left := 10; Edit1.Top := 10; RegisterClasses([TMyPanel]); {
在这里就给注册了}end;end.

测试单元:

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    procedure FormCreate(Sender: TObject);    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);  end;var  Form1: TForm1;implementation{
$R *.dfm}uses Clipbrd, MyPanel;var obj: TComponent; pnl: TMyPanel;procedure TForm1.FormCreate(Sender: TObject);begin pnl := TMyPanel.Create(Self); pnl.Parent := Self; pnl.Edit1.Text := '一起被复制'; Button1.Caption := '复制'; Button2.Caption := '粘贴';end;procedure TForm1.Button1Click(Sender: TObject);begin Clipboard.SetComponent(pnl);end;procedure TForm1.Button2Click(Sender: TObject);begin if Clipboard.HasFormat(CF_COMPONENT) then begin obj := Clipboard.GetComponent(Self, Self); TMypanel(obj).Left := 20; TMypanel(obj).Top := 60; end;end;end.

 

使用剪切板[5]: SetAsHandle、GetAsHandle - 自定义格式

如果要在剪切板中存放自己的格式, 需要用到 SetAsHandle、GetAsHandle 两个方法. SetAsHandle(用于剪切板的格式ID, 数据的内存句柄); 看这个方法的两个参数都有点麻烦. 自定义剪切板格式要用 RegisterClipboardFormat 函数; 第二个参数是内存句柄而不是内存地址, 能分配内存并返回句柄的函数暂时我只知道 GlobalAlloc、GlobalReAlloc 两个函数, 使用它们分配用于剪切板的内存时还须使用 GMEM_DDESHARE 标志. GetAsHandle(用于剪切板的格式ID) 方法返回的是数据所在内存的句柄. 通过内存句柄获取获取内存地址, 还要用到 GlobalLock 函数. 本例自定义了结构 TMyRec, 并指定了对应的剪切板格式 CF_MY.

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    procedure FormCreate(Sender: TObject);    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);  end;var  Form1: TForm1;implementation{
$R *.dfm}uses Clipbrd;Type TMyRec = record name: string[8]; age : Byte; end;var CF_MY: Word;procedure TForm1.FormCreate(Sender: TObject);begin CF_MY := RegisterClipboardFormat('My Format');end;procedure TForm1.Button1Click(Sender: TObject);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);end;procedure TForm1.Button2Click(Sender: TObject);var PRec: ^TMyRec; Data: THandle;begin if not Clipboard.HasFormat(CF_MY) then Exit; Data := Clipboard.GetAsHandle(CF_MY); PRec := GlobalLock(Data); ShowMessageFmt('%s %d 岁', [PRec.name, PRec.age]); {
张三 99 岁} GlobalUnlock(Data);end;end.

 

使用剪切板[6]: 把窗体客户区图像保存到文件或剪切板

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Button3: TButton;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure Button3Click(Sender: TObject);  end;var  Form1: TForm1;implementation{
$R *.dfm}uses Clipbrd; {
剪切板单元}//把窗体客户区保存为图片procedure TForm1.Button1Click(Sender: TObject);var bit: TBitmap;begin bit := TBitmap.Create; bit := Self.GetFormImage; bit.SaveToFile('c:/temp/img1.bmp'); bit.Free;end;//用一句话完成上一个过程procedure TForm1.Button2Click(Sender: TObject);begin Self.GetFormImage.SaveToFile('c:/temp/img2.bmp');end;//把窗体客户区图像复制到剪切板procedure TForm1.Button3Click(Sender: TObject);var Format: Word; Data: Cardinal; APalette: HPALETTE;begin {
TBitmap.SaveToClipboardFormat 函数的三个参数都是接受数据用的, 按要求类型定义即可} GetFormImage.SaveToClipboardFormat(Format, Data, APalette); {
放入剪切板} Clipboard.SetAsHandle(Format, Data);end;end.

 

转载于:https://www.cnblogs.com/YiShen/p/9720575.html

你可能感兴趣的文章
前端之练习1
查看>>
Using 1.7 requires compiling with Android 4.4 (KitKat); currently using API 8
查看>>
信息学院第九届ACM程序设计竞赛题解
查看>>
新手开发IOS的疑惑,待补充
查看>>
Java语法总结 - 内部类
查看>>
css样式优先级
查看>>
爬虫的自我修养
查看>>
我们到底需要一款什么样的管理软件
查看>>
微信mac版的bug 直接显示了消息原始数据
查看>>
【皇甫】☀Hibernate入门
查看>>
2018软件秋季学期学习总结
查看>>
php与mysql实现用户数据的增删改查
查看>>
nginx优化配置
查看>>
MySQL 2019.5.13
查看>>
Java 设计模式专栏
查看>>
docker :no such file or directory
查看>>
Level Set Hair Shell
查看>>
NOIP练习赛题目2
查看>>
51nod算法马拉松15
查看>>
[数据结构]二叉树之二叉链表的类模板实现
查看>>