如何在WPF密码框中显示几秒钟的字符?

发布于 2024-11-18 21:37:24 字数 93 浏览 3 评论 0原文

如果用户在密码框中输入1985,则会显示四个项目符号(●●●●)。如何显示输入的每个字母或数字几秒钟,然后将其更改为项目符号?我想这不能在密码框中完成,但是还有其他方法吗?

If the user enters 1985 in the password box, four bullets (●●●●) will be shown. How can I show each letter or number entered for a few seconds and after that change it to a bullet? I suppose that this can't be done in the password box, but is there any other way to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

扶醉桌前 2024-11-25 21:37:24

将文本框放在密码框的顶部,然后使用一些数据绑定和动画。只要正在进行输入,该 XAML 块就允许文本框可见,但一旦停止输入,文本框就会消失,只留下显示密码字符的密码框。

    <Window.Resources>
        <Storyboard x:Key="Storyboard1">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="textBox">
                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="TextBoxBase.TextChanged" SourceName="textBox">
            <StopStoryboard BeginStoryboardName="Storyboard1_BeginStoryboard"/>
            <BeginStoryboard x:Name="Storyboard1_BeginStoryboard" Storyboard="{StaticResource Storyboard1}"/>
        </EventTrigger>
    </Window.Triggers>




<PasswordBox x:Name="passwordBox"/>
<TextBox x:Name="textBox"
        Text="{Binding ElementName=passwordBox, Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         Opacity="100"/>

您可以调整动画中的关键时间以获得您喜欢的延迟。您还可以更改文本框中的字体设置,以使键入的文本和密码字符更好地对齐。

编辑

如果您只想显示以明文形式输入的最后一个字符:

这种情况有点不同,并且需要更多的复杂性。此场景仅使用窗口上的文本框,而不使用密码框。

<TextBox Name="tbxPwd" Margin="20,0" 
         Text="{Binding Path=DisplayedPwd}" />

在窗口的代码隐藏中(或在 ViewModel 类中),您将需要两个属性:ActualPwdDisplayedPwd。该文本框绑定到 DisplayedPwd 属性。

在代码隐藏中,您将需要以下代码:

Private Sub tbxPwd_PreviewKeyDown(sender As Object, e As System.Windows.Input.KeyEventArgs) _
  Handles tbxPwd.PreviewKeyDown

  If e.Key = Key.Back Then
     If ActualPwd.Length > 0 Then
        //Remove the last character.
        ActualPwd = ActualPwd.Substring(0, ActualPwd.Length - 1)
        ShowLastCharacter()
        tbxPwd.CaretIndex = DisplayedPwd.Length
     End If
  End If

End Sub

Private Sub tbxPwd_PreviewTextInput(sender As Object, e As System.Windows.Input.TextCompositionEventArgs) _
  Handles tbxPwd.PreviewTextInput

  ActualPwd &= e.Text
  e.Handled = True

  ShowLastCharacter()

  tbxPwd.CaretIndex = DisplayedPwd.Length

End Sub

Private Sub ShowLastCharacter()
  Dim lastChar As Char = ActualPwd.Substring(ActualPwd.Length - 1)

  //Reset the displayed pwd.
  DisplayedPwd = ""
  For i As Int32 = 0 To ActualPwd.Length - 2
     DisplayedPwd &= "•"
  Next
  DisplayedPwd &= lastChar

End Sub

tbxPwd_PreviewTextInput 方法用于检索用户键入的字符。 tbxPwd_PreviewKeyDown 方法用于检索 BackSpace 键或您想要检测的任何其他控制字符键。

此代码没有延迟,因此它始终以明文形式显示密码字符串的最后一个字符。添加一些代码和计时器以在一段延迟后将最后一个字符更改为 pwd 字符应该很容易。

上面的代码尚未经过彻底调试,因此如果用户将整个密码退格以重新开始,可能会出现问题。

提示:Alt+0149 显示“bullet”密码字符。

Put a textbox on top of the password box, and then use a little databinding and animation. This chunk of XAML will allow the textbox to be visible as long as there is typing going on, but as soon as the typing stops, the textbox will fade away, leaving only the password box with the password characters showing.

    <Window.Resources>
        <Storyboard x:Key="Storyboard1">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="textBox">
                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="TextBoxBase.TextChanged" SourceName="textBox">
            <StopStoryboard BeginStoryboardName="Storyboard1_BeginStoryboard"/>
            <BeginStoryboard x:Name="Storyboard1_BeginStoryboard" Storyboard="{StaticResource Storyboard1}"/>
        </EventTrigger>
    </Window.Triggers>




<PasswordBox x:Name="passwordBox"/>
<TextBox x:Name="textBox"
        Text="{Binding ElementName=passwordBox, Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         Opacity="100"/>

You can play around with the KeyTimes in the animation to get the delay that you prefer. You can also change the font settings in the textbox to get the typed text and the password characters to line up better.

EDIT

If you want to only display the last character typed as clear text:

This situation is a little different and requires some more complexity. this scenario uses only a textbox on the window, not the passwordbox.

<TextBox Name="tbxPwd" Margin="20,0" 
         Text="{Binding Path=DisplayedPwd}" />

In your code-behind for the window (or in your ViewModel class) you will need two properties, ActualPwd and DisplayedPwd. The textbox is bound to the DisplayedPwd property.

In the code-behind, you will need the following code:

Private Sub tbxPwd_PreviewKeyDown(sender As Object, e As System.Windows.Input.KeyEventArgs) _
  Handles tbxPwd.PreviewKeyDown

  If e.Key = Key.Back Then
     If ActualPwd.Length > 0 Then
        //Remove the last character.
        ActualPwd = ActualPwd.Substring(0, ActualPwd.Length - 1)
        ShowLastCharacter()
        tbxPwd.CaretIndex = DisplayedPwd.Length
     End If
  End If

End Sub

Private Sub tbxPwd_PreviewTextInput(sender As Object, e As System.Windows.Input.TextCompositionEventArgs) _
  Handles tbxPwd.PreviewTextInput

  ActualPwd &= e.Text
  e.Handled = True

  ShowLastCharacter()

  tbxPwd.CaretIndex = DisplayedPwd.Length

End Sub

Private Sub ShowLastCharacter()
  Dim lastChar As Char = ActualPwd.Substring(ActualPwd.Length - 1)

  //Reset the displayed pwd.
  DisplayedPwd = ""
  For i As Int32 = 0 To ActualPwd.Length - 2
     DisplayedPwd &= "•"
  Next
  DisplayedPwd &= lastChar

End Sub

The tbxPwd_PreviewTextInput method is used to retrieve the character that is typed by the user. The tbxPwd_PreviewKeyDown method is used to retrieve the BackSpace key, or any other control character key you want to detect.

There is no delay in this code, so it always displays the last character of the password string in clear text. It should be easy enough to add some code along with a Timer to change the last character to the pwd character after some delay.

The above code hasn't been thoroughly debugged, so there may be issues if the user backspaces out their entire password to start over.

Tip: Alt+0149 displays the 'bullet' password character.

爱,才寂寞 2024-11-25 21:37:24

只需使用一个 TextBox 即可实现这一目标。请参阅下面的代码:

窗口的 XAML 代码:

    <Label x:Name="Pwd" Height="30" Width="70" HorizontalAlignment="Left" FontSize="14"
           Margin="10,10,0,0" VerticalAlignment="Top" Content="Password:"/>
    <TextBox x:Name="textBox" Width="130" Height="30" Margin="30,10,0,0" 
             VerticalAlignment="Top" MaxLength="12" FontSize="14"
             PreviewKeyDown="TextBox_PreviewKeyDown" 
             KeyDown="TextBox_KeyDown" />
    <CheckBox x:Name="ckhShowPassword" Height="30" 
              Content="Show password characters" 
              Margin="69,0,59,42" VerticalAlignment="Bottom" 
              Checked="ckhShowPassword_Checked" Unchecked="ckhShowPassword_UnChecked"/>
    <Label x:Name="lblActualPwd" Height="30" Width="200" 
           Margin="10,100,0,0" VerticalAlignment="Top" FontSize="14"
           HorizontalAlignment="Center" HorizontalContentAlignment="Center"/>

C# 隐藏代码:

    #region "CLASS LEVEL VARIABLES"
    System.Windows.Threading.DispatcherTimer dispatcherTimer = 
        new System.Windows.Threading.DispatcherTimer();
    string actualPwd = "";
    #endregion

    #region "WINDOW EVENTS"
    public Window2()
    {
        InitializeComponent();
    }

    private void Window2_Loaded(object sender, RoutedEventArgs e)
    {
        lblActualPwd.Visibility = Visibility.Hidden;
        textBox.Focus();
    }
    #endregion

    #region "TEXTBOX EVENTS"
    private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Back)
        {
            actualPwd += GetCharFromKey(e.Key); //Store actual characters for later retrieval        
        }
        else if (e.Key == Key.Back)
        {
            if (actualPwd.Length > 0)
                actualPwd = actualPwd.Remove(actualPwd.Length - 1);
            else
                actualPwd = "";
        }
        else
        {
            actualPwd += GetCharFromKey(e.Key);
        }

        string str = "";
        for (int i = 0; i < textBox.Text.Length; i++)
            str += char.ConvertFromUtf32(8226);

        textBox.Text = str;
        textBox.Select(textBox.Text.Length, 0);
    }

    private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
        dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
        dispatcherTimer.Start();
    }
    #endregion

    #region "DISPATCHER EVENT"
    private void dispatcherTimer_Tick(object sender, EventArgs e)
    {   
        string str = "";
        for(int i = 0; i < textBox.Text.Length; i++)
            str += char.ConvertFromUtf32(8226);

        textBox.Text = str;
        textBox.Select(textBox.Text.Length, 0);
    }
    #endregion

    #region "CHECKBOX EVENTS"
    private void ckhShowPassword_Checked(object sender, RoutedEventArgs e)
    {
        if (actualPwd.Length > 0)
        {
            lblActualPwd.Foreground = Brushes.Blue;
            lblActualPwd.Content = actualPwd;
            lblActualPwd.Visibility = Visibility.Visible;
        }
        else
        {
            lblActualPwd.Foreground = Brushes.Red;
            lblActualPwd.Content = "Please input password.";
            lblActualPwd.Visibility = Visibility.Visible;
        }
    }

    private void ckhShowPassword_UnChecked(object sender, RoutedEventArgs e)
    {
        lblActualPwd.Content = string.Empty;
        lblActualPwd.Visibility = Visibility.Hidden;
    }
    #endregion

    #region "ENUM TYPE - MAP KEY TO CHARACTER"
    public enum MapType : uint
    {
        MAPVK_VK_TO_VSC = 0x0,
        MAPVK_VSC_TO_VK = 0x1,
        MAPVK_VK_TO_CHAR = 0x2,
        MAPVK_VSC_TO_VK_EX = 0x3,
    }
    #endregion

    #region "INTEROP DLL IMPORT"
    [DllImport("user32.dll")]
    public static extern bool GetKeyboardState(byte[] lpKeyState);
    [DllImport("user32.dll")]
    public static extern uint MapVirtualKey(uint uCode, MapType uMapType);
    [DllImport("user32.dll")]
    #endregion

    #region "VIRTUAL KEY UNICODE CONVERSION"
    public static extern int ToUnicode(
     uint wVirtKey,
     uint wScanCode,
     byte[] lpKeyState,
     [Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 4)] 
    StringBuilder pwszBuff,
     int cchBuff,
     uint wFlags);
    #endregion

    #region "FUNCTION - CHAR FROM KEY"
    public static char GetCharFromKey(Key key)
    {
        char ch = ' ';

        int virtualKey = KeyInterop.VirtualKeyFromKey(key);
        byte[] keyboardState = new byte[256];
        GetKeyboardState(keyboardState);

        uint scanCode = MapVirtualKey((uint)virtualKey, MapType.MAPVK_VK_TO_VSC);
        StringBuilder stringBuilder = new StringBuilder(2);

        int result = ToUnicode((uint)virtualKey, scanCode, keyboardState, stringBuilder, stringBuilder.Capacity, 0);
        switch (result)
        {
            case -1:
                break;
            case 0:
                break;
            case 1:
                {
                    ch = stringBuilder[0];
                    break;
                }
            default:
                {
                    ch = stringBuilder[0];
                    break;
                }
        }
        return ch;
    }
    #endregion

地图类型

This can be achieved using just one TextBox. See the code below:

XAML code for window:

    <Label x:Name="Pwd" Height="30" Width="70" HorizontalAlignment="Left" FontSize="14"
           Margin="10,10,0,0" VerticalAlignment="Top" Content="Password:"/>
    <TextBox x:Name="textBox" Width="130" Height="30" Margin="30,10,0,0" 
             VerticalAlignment="Top" MaxLength="12" FontSize="14"
             PreviewKeyDown="TextBox_PreviewKeyDown" 
             KeyDown="TextBox_KeyDown" />
    <CheckBox x:Name="ckhShowPassword" Height="30" 
              Content="Show password characters" 
              Margin="69,0,59,42" VerticalAlignment="Bottom" 
              Checked="ckhShowPassword_Checked" Unchecked="ckhShowPassword_UnChecked"/>
    <Label x:Name="lblActualPwd" Height="30" Width="200" 
           Margin="10,100,0,0" VerticalAlignment="Top" FontSize="14"
           HorizontalAlignment="Center" HorizontalContentAlignment="Center"/>

C# Code behind:

    #region "CLASS LEVEL VARIABLES"
    System.Windows.Threading.DispatcherTimer dispatcherTimer = 
        new System.Windows.Threading.DispatcherTimer();
    string actualPwd = "";
    #endregion

    #region "WINDOW EVENTS"
    public Window2()
    {
        InitializeComponent();
    }

    private void Window2_Loaded(object sender, RoutedEventArgs e)
    {
        lblActualPwd.Visibility = Visibility.Hidden;
        textBox.Focus();
    }
    #endregion

    #region "TEXTBOX EVENTS"
    private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Back)
        {
            actualPwd += GetCharFromKey(e.Key); //Store actual characters for later retrieval        
        }
        else if (e.Key == Key.Back)
        {
            if (actualPwd.Length > 0)
                actualPwd = actualPwd.Remove(actualPwd.Length - 1);
            else
                actualPwd = "";
        }
        else
        {
            actualPwd += GetCharFromKey(e.Key);
        }

        string str = "";
        for (int i = 0; i < textBox.Text.Length; i++)
            str += char.ConvertFromUtf32(8226);

        textBox.Text = str;
        textBox.Select(textBox.Text.Length, 0);
    }

    private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
        dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
        dispatcherTimer.Start();
    }
    #endregion

    #region "DISPATCHER EVENT"
    private void dispatcherTimer_Tick(object sender, EventArgs e)
    {   
        string str = "";
        for(int i = 0; i < textBox.Text.Length; i++)
            str += char.ConvertFromUtf32(8226);

        textBox.Text = str;
        textBox.Select(textBox.Text.Length, 0);
    }
    #endregion

    #region "CHECKBOX EVENTS"
    private void ckhShowPassword_Checked(object sender, RoutedEventArgs e)
    {
        if (actualPwd.Length > 0)
        {
            lblActualPwd.Foreground = Brushes.Blue;
            lblActualPwd.Content = actualPwd;
            lblActualPwd.Visibility = Visibility.Visible;
        }
        else
        {
            lblActualPwd.Foreground = Brushes.Red;
            lblActualPwd.Content = "Please input password.";
            lblActualPwd.Visibility = Visibility.Visible;
        }
    }

    private void ckhShowPassword_UnChecked(object sender, RoutedEventArgs e)
    {
        lblActualPwd.Content = string.Empty;
        lblActualPwd.Visibility = Visibility.Hidden;
    }
    #endregion

    #region "ENUM TYPE - MAP KEY TO CHARACTER"
    public enum MapType : uint
    {
        MAPVK_VK_TO_VSC = 0x0,
        MAPVK_VSC_TO_VK = 0x1,
        MAPVK_VK_TO_CHAR = 0x2,
        MAPVK_VSC_TO_VK_EX = 0x3,
    }
    #endregion

    #region "INTEROP DLL IMPORT"
    [DllImport("user32.dll")]
    public static extern bool GetKeyboardState(byte[] lpKeyState);
    [DllImport("user32.dll")]
    public static extern uint MapVirtualKey(uint uCode, MapType uMapType);
    [DllImport("user32.dll")]
    #endregion

    #region "VIRTUAL KEY UNICODE CONVERSION"
    public static extern int ToUnicode(
     uint wVirtKey,
     uint wScanCode,
     byte[] lpKeyState,
     [Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 4)] 
    StringBuilder pwszBuff,
     int cchBuff,
     uint wFlags);
    #endregion

    #region "FUNCTION - CHAR FROM KEY"
    public static char GetCharFromKey(Key key)
    {
        char ch = ' ';

        int virtualKey = KeyInterop.VirtualKeyFromKey(key);
        byte[] keyboardState = new byte[256];
        GetKeyboardState(keyboardState);

        uint scanCode = MapVirtualKey((uint)virtualKey, MapType.MAPVK_VK_TO_VSC);
        StringBuilder stringBuilder = new StringBuilder(2);

        int result = ToUnicode((uint)virtualKey, scanCode, keyboardState, stringBuilder, stringBuilder.Capacity, 0);
        switch (result)
        {
            case -1:
                break;
            case 0:
                break;
            case 1:
                {
                    ch = stringBuilder[0];
                    break;
                }
            default:
                {
                    ch = stringBuilder[0];
                    break;
                }
        }
        return ch;
    }
    #endregion

MapType enum retrieved from MapType

面如桃花 2024-11-25 21:37:24

我已经实现了类似的功能,在这里作为一个更简单的示例,密码框替换为文本框,以在鼠标悬停时显示密码密码框,如下所示

的 xaml 代码

 <PasswordBox Name="LicencePasswordBox" MouseEnter="LicencePasswordBox_MouseEnter"></PasswordBox>
 <TextBox IsReadOnly="True" Name="LicencePasswordTextBox" MouseLeave="LicencePasswordBox_MouseLeave" Visibility="Hidden"></TextBox>

用于窗口C# 代码

 private void LicencePasswordBox_MouseEnter(object sender, MouseEventArgs e)
    {
        LicencePasswordBox.Visibility = Visibility.Hidden;
        LicencePasswordTextBox.Visibility = Visibility.Visible;
    }

    private void LicencePasswordBox_MouseLeave(object sender, MouseEventArgs e)
    {
        LicencePasswordBox.Visibility = Visibility.Visible;
        LicencePasswordTextBox.Visibility = Visibility.Hidden;
    }

另外,如果您正在开发 mvp 或 mvp-vm wpf 应用程序,请不要忘记将传入的值绑定到后面代码中的 LicensePasswordBox 和 LicensePasswordTextBox

I have implemented similar functionality leaving here as a simpler example, passwordbox replaced by textbox to show password when mouse hovers password box as follows

xaml code for window

 <PasswordBox Name="LicencePasswordBox" MouseEnter="LicencePasswordBox_MouseEnter"></PasswordBox>
 <TextBox IsReadOnly="True" Name="LicencePasswordTextBox" MouseLeave="LicencePasswordBox_MouseLeave" Visibility="Hidden"></TextBox>

c# code behind

 private void LicencePasswordBox_MouseEnter(object sender, MouseEventArgs e)
    {
        LicencePasswordBox.Visibility = Visibility.Hidden;
        LicencePasswordTextBox.Visibility = Visibility.Visible;
    }

    private void LicencePasswordBox_MouseLeave(object sender, MouseEventArgs e)
    {
        LicencePasswordBox.Visibility = Visibility.Visible;
        LicencePasswordTextBox.Visibility = Visibility.Hidden;
    }

Also if you are developing an mvp or mvp-vm wpf application, do not forget to bind coming value to both LicencePasswordBox and LicencePasswordTextBox in code behind

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文