Если пользователь вводит пароль в поле пароля в 1985 году, будут показаны четыре пули (●●●●). Как я могу показать каждую букву или номер, введенный в течение нескольких секунд, и после этого изменить его на пулю? Я полагаю, что это невозможно сделать в окне пароля, но есть ли другой способ сделать это?
Как показать символы в течение нескольких секунд в поле пароля WPF?
Ответ 1
Поместите текстовое поле поверх поля пароля, а затем используйте небольшую привязку данных и анимацию. Этот фрагмент 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"/>
Вы можете поиграть с KeyTimes в анимации, чтобы получить задержку, которую вы предпочитаете. Вы также можете изменить настройки шрифта в текстовом поле, чтобы получить типизированный текст и символы пароля, чтобы они лучше соответствовали.
ИЗМЕНИТЬ
Если вы хотите отображать только последний символ, набранный как чистый текст:
Эта ситуация немного отличается и требует некоторой сложности. этот сценарий использует только текстовое поле в окне, а не пароль.
<TextBox Name="tbxPwd" Margin="20,0"
Text="{Binding Path=DisplayedPwd}" />
В вашем коде для окна (или в вашем классе ViewModel) вам понадобятся два свойства: ActualPwd
и DisplayedPwd
. Текстовое поле привязано к свойству 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 отображает символ пароля "пуля".
Ответ 2
Это может быть достигнуто только одним 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"/>
Код С#:
#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
извлечен из MapType
Ответ 3
Я реализовал аналогичную функциональность, оставив здесь в качестве более простого примера, заменил пароль на текстовое поле, чтобы показать пароль, когда мышь наводит пароль на пароль следующим образом
код xaml для окна
<PasswordBox Name="LicencePasswordBox" MouseEnter="LicencePasswordBox_MouseEnter"></PasswordBox>
<TextBox IsReadOnly="True" Name="LicencePasswordTextBox" MouseLeave="LicencePasswordBox_MouseLeave" Visibility="Hidden"></TextBox>
С# код за
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;
}
Также, если вы разрабатываете приложение mpp или mvp-vm wpf, не забудьте привязать приходящее значение как к LicencePasswordBox, так и к LicencePasswordTextBox в коде за