I would like to have a TMemo which will always begin with the string 'SELECT c_name FROM ' and I want to lock it so users cannot remove or replace this string in the TMemo, they will have to write their text AFTER this string. Can someone help me with that ? I tried something with the onChange event but the problem is that users can click at the begining of the TMemo and edit it by the begining.
I'm using Delphi 6.
What you are asking for is not possible with TMemo
. It is just a thin wrapper around a standard Win32 EDIT
control, which does not support this kind of functionality.
You need to use TRichEdit
instead. It supports protecting text like you have described. After adding the desired text, select it using the TRichEdit.SelStart
and TRichEdit.SelLength
properties and then set the TRichEdit.SelAttributes.Protected
property to true. If the user tries to modify the protected text in any way, TRichEdit
will reject the modification by default (you can override that decision by using the TRichEdit.OnProtectChange
event to set the AllowChange
parameter to true). For example:
RichEdit1.Text := 'SELECT c_name FROM ';
RichEdit1.SelStart := 0;
RichEdit1.SelLength := 19;
RichEdit1.SelAttributes.Protected := True;
Update: by default, protecting the text also prevents the user from copying it. If you want the user to be able to copy the protected text, you have to explicitly enable that. Although TRichEdit
has a OnProtectChange
event to allow access to protected text, it does not tell you WHY the text is requesting access. However, the underlying EN_PROTECTED
notification does. So, you can subclass the TRichEdit
to intercept EN_PROTECTED
directly, and then return 0 (allow access) only when the user is copying the protected text.
interface
uses
...;
type
TMyForm = class(TForm)
RichEdit1: TRichEdit;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
DefRichEditWndProc: TWndMethod;
procedure RichEditWndProc(var Message: TMessage);
public
{ Public declarations }
end;
...
implementation
uses
Richedit;
procedure TMyForm.FormCreate(Sender: TObject);
begin
DefRichEditWndProc := RichEdit1.WindowProc;
RichEdit1.WindowProc := RichEditWndProc;
RichEdit1.Text := 'SELECT c_name FROM ';
RichEdit1.SelStart := 0;
RichEdit1.SelLength := 19;
RichEdit1.SelAttributes.Protected := True;
end;
procedure TMyForm.RichEditWndProc(var Message: TMessage);
begin
DefRichEditWndProc(Message);
if Message.Msg = CN_NOTIFY then
begin
if TWMNotify(Message).NMHdr.code = EN_PROTECTED then
begin
if PENProtected(Message.lParam).Msg = WM_COPY then
Message.Result := 0;
end;
end;
end;
Alternatively:
interface
uses
...;
type
TRichEdit = class(ComCtrls.TRichEdit)
private
procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
end;
TMyForm = class(TForm)
RichEdit1: TRichEdit;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
...
implementation
uses
Richedit;
procedure TMyForm.FormCreate(Sender: TObject);
begin
RichEdit1.Text := 'SELECT c_name FROM ';
RichEdit1.SelStart := 0;
RichEdit1.SelLength := 19;
RichEdit1.SelAttributes.Protected := True;
end;
procedure TRichEdit.CNNotify(var Message: TWMNotify);
begin
inherited;
if Message.NMHdr.code = EN_PROTECTED then
begin
if PENProtected(Message.NMHdr).Msg = WM_COPY then
Message.Result := 0;
end;
end;