当从剪贴板粘贴到TEdit
控件中的文本超过其允许的最大长度时,我需要向用户显示一条消息。但是,我不希望每次输入新的字母时都要检查程序,只有在粘贴文本时才会检查。
我该怎么做?
答案 0 :(得分:9)
对编辑类进行子类化并侦听WM_PASTE消息。例如(对于Unicode Delphi):
uses
Vcl.Clipbrd;
type
TEdit = class(Vcl.StdCtrls.TEdit)
private
procedure WMPaste(var Msg: TWMPaste); message WM_PASTE;
end;
implementation
procedure TEdit.WMPaste(var Msg: TWMPaste);
begin
if (MaxLength > 0) and (Length(Clipboard.AsText) > MaxLength - GetTextLen + SelLength) then
ShowMessage('Text is too long!');
inherited;
end;
另一个更高效的WinAPI变体(它不会复制剪贴板缓冲区,只是查询它的大小),也可能是(也适用于Unicode Delphi):
type
TEdit = class(Vcl.StdCtrls.TEdit)
private
procedure WMPaste(var Msg: TWMPaste); message WM_PASTE;
end;
implementation
procedure TEdit.WMPaste(var Msg: TWMPaste);
var
Data: THandle;
begin
if (MaxLength > 0) and OpenClipboard(0) then
try
Data := GetClipboardData(CF_UNICODETEXT);
if (Data <> 0) and ((GlobalSize(Data) div SizeOf(Char)) - 1 > MaxLength - GetTextLen + SelLength) then
ShowMessage('Text is too long!');
finally
CloseClipboard;
end;
inherited;
end;
如果您想阻止将文字粘贴到控件中,请从上面的示例中移除inherited来电。
答案 1 :(得分:7)
对TEdit
进行子类化以处理EN_MAXTEXT
通知:
当前文本插入超过编辑控件的指定字符数时发送。文本插入已被截断。
这适用于键入和粘贴,并为您考虑文本选择。例如:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TEdit = class(Vcl.StdCtrls.TEdit)
private
procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
end;
TForm1 = class(TForm)
Edit1: TEdit;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TEdit.CNCommand(var Message: TWMCommand);
begin
inherited;
if Message.NotifyCode = EN_MAXTEXT then
ShowMessage('Too much text!');
end;
end.
如果您只想处理粘贴,请在调用WM_PASTE
之前抓住inherited
设置标记,然后在inherited
退出时清除标记,如果EN_MAXTEXT
是在设置标志时发出,然后采取相应行动:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TEdit = class(Vcl.StdCtrls.TEdit)
private
FIsPasting: Boolean;
procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
procedure WMPaste(var Message: TMessage); message WM_PASTE;
end;
TForm1 = class(TForm)
Edit1: TEdit;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TEdit.CNCommand(var Message: TWMCommand);
begin
inherited;
if (Message.NotifyCode = EN_MAXTEXT) and FIsPasting then
ShowMessage('Too much text!');
end;
procedure TEdit.WMPaste(var Message: TMessage);
begin
FIsPasting := True;
try
inherited;
finally
FIsPasting := False;
end;
end;
end.
答案 2 :(得分:6)
你走了:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Clipbrd;
type
TPasteEdit = class(TEdit)
private
FMaxPaste: Integer;
procedure WMPaste(var Message: TWMPaste); message WM_PASTE;
protected
public
constructor Create(AOwner: TComponent); override;
published
property MaxPaste: Integer read FMaxPaste write FMaxPaste default 0;
//You can define it or use MaxLength as well
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TPastEdit }
constructor TPasteEdit.Create(AOwner: TComponent);
begin
inherited;
FMaxPaste:= 0;
end;
procedure TPasteEdit.WMPaste(var Message: TWMPaste);
begin
if Length(Clipboard.AsText) > FMaxPaste then
ShowMessage('The text you paste is too long!') // Call inherited if you want to paste anyway
else
inherited;
end;
procedure TForm1.FormCreate(Sender: TObject);
Var
PasteEdit: TPasteEdit;
begin
PasteEdit:= TPasteEdit.Create(Self);
PasteEdit.Parent:= Self;
PasteEdit.MaxPaste:= 3;
end;
end.