delphi – 如何覆盖调用以在TEdit中显示CapsLock提示窗口?
基本上我有这个问题:
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; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |