2017-12-11 4 views
6

기본적으로이 문제가 있습니다 : CapsLock password message in TEdit visually fails with VCL Styles.TEdit에서 CapsLock 힌트 창을 표시하기 위해 호출을 재정의하는 방법은 무엇입니까?

내가 원하는 것은 대답이나 의견에 표시된대로 문제를 해결하지 않는 것입니다.

그 추악한 힌트 창을 완전히 비활성화하고 싶습니다. 캡을 잠근 것을 사용자에게 알려주는 이미지를 보여줍니다. 나는 내 문제에 대한 해결책을 발견이

enter image description here

답변

7

같은

는, 내가 오히려 사용하지 것이다 해킹을 포함한다.

이렇게됩니다.

  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?

    특정 FOnPasswordCaps 이벤트가 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. 
    

    씨 할당하는 경우, 암호 편집 컨트롤에 CapsLock 키 경고를 억제 할 수있는 것은 TEdit의 후손이다 Kobik은 PasteBin이 호스팅 할 수 없다고 생각하는 매우 우아한 코드를 만들었으므로 여기에 추가하기로 결정했습니다. 나는 그것이 당신의 TPasswordEdit가 포커스를받을 때 해고 TPasswordCapsLockState 하나의 이벤트 핸들러를 처리 할 수 ​​있습니다 이해 것과

    PasswordChar가 변경 될 때 초점과 옵션 발사에있는 동안 누르면 초점, 등 CapsLock 키를 잃는다.

    이 방법을 사용하면 구성 요소의 사용자가 각 상태에 대해 두 개의 이벤트 처리기 (매우 영리하고 오류가 발생하지 않음)를 사용하도록 강제하지 않고 OnPasswordCapsLock 이벤트를 사용하여 내 질문에 이미지를 표시하거나 숨길 수 있습니다. 한 LNeedHandle := FBlockCapsBalloonTip and IsPassword;로도

    내가 OnEnter의 처리뿐만 아니라 OnPasswordCapsLock에서 OnExit입니다 TPasswordEdit 또 다른 추가 기능,

    그래서 나는 미스터 Kobik 이인제의 있니 타이어 월의 chapeau를 무슨 말을 할 수 있습니다 True입니다.당신이 나를 웃게 만든 @JerryDodge

    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; 
    
  • +0

    너무 의외 ... 결국, VCL 스타일은 –

    +0

    :-) 이미 처음부터 해킹입니다. 고맙습니다. –

    +2

    이것은 귀하의 질문에 대한 해결책의 절반에 불과합니다. 이 아이콘을 사용하여 아이콘을 표시 할 수 있습니다. 그러나 사용자가 Caps Lock을 토글 할 때 편집 컨트롤이 툴팁을 닫을 때 해당 알림이 없습니다. 따라서 아이콘을 숨기려면 Caps Lock 상태를 추적해야합니다. 따라서 아이콘을 표시하기 위해이를 사용할 수도 있습니다.이 솔루션을 사용하면 편집의 툴팁을 닫을 수 있습니다. –

    관련 문제