gpt4 book ai didi

delphi - 如何重写调用以在 TEdit 中显示 CapsLock 提示窗口?

转载 作者:行者123 更新时间:2023-12-03 14:59:52 24 4
gpt4 key购买 nike

基本上我有这个问题:CapsLock password message in TEdit visually fails with VCL Styles .

我想做的不是解决答案或评论中所示的问题。

我想完全禁用那个丑陋的提示窗口。而是显示一个图像,让用户知道大写字母已锁定。

像这样

enter image description here

最佳答案

我找到了问题的解决方案,它涉及到我不想使用的 hack。

事情是这样的。

  1. 重写 WndProc。

代码

type
TEdit = class (Vcl.StdCtrls.TEdit)
protected
procedure WndProc(var Message: TMessage); override;
end;
  • 拦截 EM_SHOWBALLOONTIP消息,您就完成了
  • 代码

    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 的后代,如果满足某个 FOnPasswordCaps ,则可以抑制密码编辑控件上的 CapsLock 警告。事件分配为 PasswordChar <> #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 不应该被信任托管,因此我决定将其添加到此处。

    据我了解,它可以让你处理 TPasswordCapsLockStateTPasswordEdit 时触发的一个事件处理程序中接收焦点、失去焦点、在焦点上按下 CapsLock 键以及在 PasswordChar 时可选触发已更改。

    使用这种方法,我可以使用 OnPasswordCapsLock事件来显示/隐藏我的问题中的图像,而不是强制组件的使用者为每个状态使用两个事件处理程序(顺便说一句,非常聪明并且不易出错)。

    也只要 LNeedHandle := FBlockCapsBalloonTip and IsPassword;True我在 TPasswordEdit 中添加了另一个功能这是 OnEnter 的处理和OnExitOnPasswordCapsLock还有,

    那么我能说什么,科比克先生我的起首是我的轮胎。

    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;

    关于delphi - 如何重写调用以在 TEdit 中显示 CapsLock 提示窗口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47754938/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com