基本上我有这个问题:
CapsLock password message in TEdit visually fails with VCL Styles.
我想完全禁用那个丑陋的提示窗口.而是显示一个图像,让用户知道帽子被锁定.
像这样
解决方法
我找到了我的问题的解决方案,它涉及到我宁愿不使用的黑客攻击.
它是这样的.
>覆盖WndProc.
码
- type
- TEdit = class (Vcl.StdCtrls.TEdit)
- protected
- procedure WndProc(var Message: TMessage); override;
- end;
>拦截EM_SHOWBALLOONTIPmessage,你就完成了
码
- procedure TEdit.WndProc(var Message: TMessage);
- begin
- if Message.Msg = EM_SHOWBALLOONTIP then
- showmessage('Do your thing.')
- else
- inherited;
- end;
有关更多信息,请查看MSDN文档:
How do I suppress the CapsLock warning on password edit controls?
这是TEdit的后代,如果使用PasswordChar<>分配某个FOnPasswordCaps事件,则允许在密码编辑控件上抑制CapsLock警告. #0
- unit NCREditUnit;
- interface
- uses
- Vcl.StdCtrls,vcl.Controls,Winapi.Messages,System.Classes;
- type
- TNCREdit = class(TEdit)
- private
- FOnPasswordCapsLocked: TNotifyEvent;
- FIsCapsLocked: boolean;
- FOnPasswordCapsFreed: TNotifyEvent;
- FBlockCapsBalloonTip: boolean;
- FValuePasswordChrOnCaps: boolean;
- procedure SetOnPasswordCapsEvents;
- procedure SetOnPasswordCapsFreed(const aValue: TNotifyEvent);
- procedure SetOnPasswordCapsLocked(const aValue: TNotifyEvent);
- protected
- procedure WndProc(var Message: TMessage); override;
- procedure KeyUp(var Key: Word; Shift: TShiftState); override;
- procedure DoEnter; override;
- procedure DoExit; override;
- published
- property BlockCapsBalloonTip: boolean read FBlockCapsBalloonTip write FBlockCapsBalloonTip default False;
- property ValuePasswordChrOnCaps: boolean read FValuePasswordChrOnCaps write FValuePasswordChrOnCaps default True;
- //... The usual property declaration of TEdit
- property OnPasswordCapsLocked: TNotifyEvent read FOnPasswordCapsLocked write SetOnPasswordCapsLocked;
- property OnPasswordCapsFreed: TNotifyEvent read FOnPasswordCapsFreed write SetOnPasswordCapsFreed;
- end;
- implementation
- uses
- Winapi.CommCtrl,Winapi.Windows;
- { TNCREdit }
- procedure TNCREdit.DoEnter;
- begin
- inherited;
- if FBlockCapsBalloonTip then
- begin
- FIsCapsLocked := Odd(GetKeyState(VK_CAPITAL));
- SetOnPasswordCapsEvents;
- end;
- end;
- procedure TNCREdit.DoExit;
- begin
- if FBlockCapsBalloonTip and (FIsCapsLocked) then
- begin
- FIsCapsLocked := False;
- SetOnPasswordCapsEvents;
- end;
- inherited;
- end;
- procedure TNCREdit.KeyUp(var Key: Word; Shift: TShiftState);
- begin
- if Key = VK_CAPITAL then
- FIsCapsLocked := not FIsCapsLocked;
- SetOnPasswordCapsEvents;
- inherited;
- end;
- procedure TNCREdit.SetOnPasswordCapsEvents;
- begin
- if FIsCapsLocked then
- begin
- if Assigned(FOnPasswordCapsLocked) and
- ((self.PasswordChar <> #0) or ( not FValuePasswordChrOnCaps)) then
- begin
- FOnPasswordCapsLocked(Self);
- end;
- end
- else
- begin
- if Assigned(FOnPasswordCapsLocked) and
- ((self.PasswordChar <> #0) or ( not FValuePasswordChrOnCaps)) then
- begin
- FOnPasswordCapsFreed(Self);
- end;
- end;
- end;
- procedure TNCREdit.SetOnPasswordCapsFreed(const aValue: TNotifyEvent);
- begin
- FOnPasswordCapsFreed := aValue;
- FBlockCapsBalloonTip := True;
- end;
- procedure TNCREdit.SetOnPasswordCapsLocked(const aValue: TNotifyEvent);
- begin
- FOnPasswordCapsLocked := aValue;
- FBlockCapsBalloonTip := True;
- end;
- procedure TNCREdit.WndProc(var Message: TMessage);
- begin
- if (Message.Msg = EM_SHOWBALLOONTIP) and FBlockCapsBalloonTip then Exit;
- inherited;
- end;
- end.
Kobik先生制作了一段非常优雅的代码,我认为不应该信任PasteBin,所以我决定在这里添加它.
根据我的理解,它允许您在TPasswordEdit接收焦点时触发的一个事件处理程序中处理TPasswordCapsLockState,失去焦点,在焦点处按下CapsLock键,并在PasswordChar更改时触发可选触发.
使用这种方法,我可以使用OnPasswordCapsLock事件在我的问题中显示/隐藏图像,而不是强迫组件的使用者为每个状态使用两个事件处理程序(顺便说一句非常聪明且不易出错).
也只要LNeedHandle:= FBlockCapsBalloonTip和IsPassword;是真的我有另一个TPasswordEdit的附加功能,它也是在OnPasswordCapsLock中处理OnEnter和OnExit,
那么我能说什么Kobik Je vous轮胎mon chapeau.
- type
- TPasswordCapsLockState = (pcsEnter,pcsExit,pcsKey,pcsSetPasswordChar);
- TPasswordCapsLockEvent = procedure(Sender: TObject;
- Locked: Boolean; State: TPasswordCapsLockState) of object;
- TPasswordEdit = class(TCustomEdit)
- private
- FIsCapsLocked: boolean;
- FBlockCapsBalloonTip: boolean;
- FOnPasswordCapsLock: TPasswordCapsLockEvent;
- protected
- procedure WndProc(var Message: TMessage); override;
- procedure KeyUp(var Key: Word; Shift: TShiftState); override;
- procedure DoEnter; override;
- procedure DoExit; override;
- procedure HandlePasswordCapsLock(State: TPasswordCapsLockState); virtual;
- function GetIsPassword: Boolean; virtual;
- public
- property IsPassword: Boolean read GetIsPassword;
- published
- property BlockCapsBalloonTip: boolean read FBlockCapsBalloonTip write FBlockCapsBalloonTip default False;
- //... The usual property declaration of TEdit
- property OnPasswordCapsLock: TPasswordCapsLockEvent read FOnPasswordCapsLock write FOnPasswordCapsLock;
- end;
- implementation
- function TPasswordEdit.GetIsPassword: Boolean;
- begin
- Result := ((PasswordChar <> #0) or
- // Edit control can have ES_PASSWORD style with PasswordChar == #0
- // if it was creaed with ES_PASSWORD style
- (HandleAllocated and (GetWindowLong(Handle,GWL_STYLE) and ES_PASSWORD <> 0)));
- end;
- procedure TPasswordEdit.HandlePasswordCapsLock;
- var
- LNeedHandle: Boolean;
- begin
- LNeedHandle := FBlockCapsBalloonTip and IsPassword;
- if LNeedHandle then
- begin
- FIsCapsLocked := Odd(GetKeyState(VK_CAPITAL));
- if Assigned(FOnPasswordCapsLock) then
- FOnPasswordCapsLock(Self,FIsCapsLocked,State);
- end;
- end;
- procedure TPasswordEdit.DoEnter;
- begin
- inherited;
- HandlePasswordCapsLock(pcsEnter);
- end;
- procedure TPasswordEdit.DoExit;
- begin
- inherited;
- HandlePasswordCapsLock(pcsExit);
- end;
- procedure TPasswordEdit.KeyUp(var Key: Word; Shift: TShiftState);
- begin
- inherited;
- if Key = VK_CAPITAL then
- HandlePasswordCapsLock(pcsKey);
- end;
- procedure TPasswordEdit.WndProc(var Message: TMessage);
- begin
- if (Message.Msg = EM_SHOWBALLOONTIP) and FBlockCapsBalloonTip and IsPassword then
- Exit;
- // Optional - if password char was changed
- if (Message.Msg = EM_SETPASSWORDCHAR) and Self.Focused then
- HandlePasswordCapsLock(pcsSetPasswordChar);
- inherited;
- end;