To Zephyr:
您的办法看上去确实可行,但有没有考虑过:
1. 数据输入时,需要保证用户输入和密码缓冲区的数据一致:
1.1 需要处理"BackSpace"、"Home"、"End"、移动Cursor的左右箭头键等编辑键,
1.2 需要处理"Shift+"、鼠标拖动的块选择功能,以及"Cut"、"Paste"编辑消息
1.3 需要处理Windows IME,关闭任何软件输入法,防止用户输入了汉字密码。
2. 如果系统中有多个密码框,则需要为每个密码框编写OnKeyPress事件,如果编写成通用的
OnKeyPress方法,则要解决保存密码的字符串变量的内存管理问题。
软件如此DIY,还叫什么RAD?
我的解决办法:
根据WINAPI,获得一个窗口的Text属性是使用GetWindowText()函数,而GetWindowText()函数又是通过
向目标窗口句柄发送WM_GETTEXT消息而获得Text属性的(原文:
If the target window is owned by the current process, GetWindowText causes a WM_GETTEXT message
to be sent to the specified window or control. )。所以我们只需要从TCustomEdit或TEdit派生,在派生
类中重载WM_GETTEXT消息:
...
TSafeEdit = class(TEdit)
protected
procedure WMGETTEXT(var message: TWMGetText)
message WM_GETTEXT;
end;
implementation
procedure TSafeEdit.WMGETTEXT(var message: TWMGetText);
begin
message.Text := '';
message.TextMax := 1;
message.Result := 0;
end;
...
这样GetWindowText只能返回空字符串了。可是这样作右碰到了新的问题:
如果这是读TSafeEdit.Text属性,返回的也是空串,因为Text属性是在TControl中实现的,而TControl:
property Text: TCaption read GetText write SetText;
function TControl.GetText: TCaption;
var
Len: Integer;
begin
Len := GetTextLen;
SetString(Result, PChar(nil), Len);
if Len <> 0 then GetTextBuf(Pointer(Result), Len + 1);
end;
function TControl.GetTextBuf(Buffer: PChar
BufSize: Integer): Integer;
begin
Result := Perform(WM_GETTEXT, BufSize, Longint(Buffer));
end;
这样可以看出:Text属性也是用WM_GETTEXT消息实现的,所以...
最终的解决办法:
重载GetText方法是不可能的,因为他是TControl的虚函数,只有重新定义Text属性
TSafeEdit = class(TEdit)
private
FRealText: string;
procedure SetText(const value: string);
published
property Text: string read FRealText write SetText;
end;
implementation
procedure TSafeEdit.WMGETTEXT(var message: TWMGetText);
begin
inherited;
FRealText := message.Text;
message.Text := '';
message.TextMax := 1;
message.Result := 0;
end;
procedure TSafeEdit.SetText(const value: string);
begin
if FRealText <> Value then SetTextBuf(PChar(Value));
end;
这样读写都没有问题了。