I need to show a message to the user when text pasted from the clipboard into a TEdit
control exceeds its maximum allowed length. But I would not like the program to check every time a new letter is typed, only when text is pasted.
How would I do this?
Subclass the edit class and listen for the WM_PASTE message. For example (for 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;
Another, little more efficient WinAPI variant (which doesn't copy the clipboard buffer but just queries its size), could be (also for 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;
If you wanted to prevent the text from being pasted into the control, remove the inherited calls from the above examples.
Subclass the TEdit
to handle the EN_MAXTEXT
notification:
Sent when the current text insertion has exceeded the specified number of characters for the edit control. The text insertion has been truncated.
This applies to typing as well as pasting, and takes text selection into account for you. For example:
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.
If you only want to handle pasting, then catch WM_PASTE
to set a flag before calling inherited
, then clear the flag when inherited
exits, and if EN_MAXTEXT
is issued while the flag is set then act accordingly:
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.
Here you go:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With