Avisar sobre CapsLock
-
11-09-2019 - |
Pergunta
Eu tenho um DataGridTemplateColumn com DataTemplate como um PasswordBox.
Eu quero avisar o usuário se CapsLock é alternado.
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
if (Keyboard.GetKeyStates(Key.CapsLock) == KeyStates.Toggled)
{
...
Agora, eu preciso levantar algum PopUp aqui. Eu não sei como fazer isso. Ajuda-me por favor.
Eu tentei brincar com dica de ferramenta como esta:
((PasswordBox)sender).SetValue(ToolTipService.InitialShowDelayProperty, 1);
((PasswordBox)sender).ToolTip = "CAPS LOCK";
Mas funciona somente quando mouse passa cursor lá e eu preciso de um Popup independente.
Solução
Você poderia mostrar uma dica de ferramenta ??p>
private void PasswordBox_KeyDown(object sender, KeyEventArgs e)
{
if ((Keyboard.GetKeyStates(Key.CapsLock) & KeyStates.Toggled) == KeyStates.Toggled)
{
if (PasswordBox.ToolTip == null)
{
ToolTip tt = new ToolTip();
tt.Content = "Warning: CapsLock is on";
tt.PlacementTarget = sender as UIElement;
tt.Placement = PlacementMode.Bottom;
PasswordBox.ToolTip = tt;
tt.IsOpen = true;
}
}
else
{
var currentToolTip = PasswordBox.ToolTip as ToolTip;
if (currentToolTip != null)
{
currentToolTip.IsOpen = false;
}
PasswordBox.ToolTip = null;
}
}
Outras dicas
Eu fiz para resolver Caps Lock aviso problema no meu WPF-Project.
Se você quiser adicionar este aviso balão em seu projeto, em seguida, siga estes passos:
-. Adicionar nova janela em seu projeto e dar o nome "WarningBalloon"
-. Adicionar seguinte código XAML contra a nova janela e adicionar aviso ícone para a pasta de imagem do projeto
<Window x:Class="MyNameSpace.WarningBalloon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="160" Width="469" WindowStyle="None" ResizeMode="NoResize" ShowInTaskbar="False" Topmost="True" IsTabStop="False" OverridesDefaultStyle="False" AllowsTransparency="True" Background="Transparent" Opacity="1" >
<Grid Height="126" Width="453">
<Grid.RowDefinitions>
<RowDefinition Height="81" />
<RowDefinition Height="45*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="177*" />
<ColumnDefinition Width="72*" />
<ColumnDefinition Width="0*" />
<ColumnDefinition Width="170*" />
</Grid.ColumnDefinitions>
<Border Margin="12,32,0,0"
CornerRadius="10,10,10,10" Grid.ColumnSpan="4" HorizontalAlignment="Left" Width="429" Height="82" VerticalAlignment="Top" Grid.RowSpan="2">
<Border.Effect>
<DropShadowEffect
Color="#FF474747" />
</Border.Effect>
<Border.Background>
<LinearGradientBrush
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop
Color="#FF58C2FF"
Offset="0" />
<GradientStop
Color="#FFFFFFFF"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Grid Height="76" Name="grid1" Width="441">
<Image Height="35" HorizontalAlignment="Left" Margin="6,6,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="35" Source="/MyNameSpace;component/Images/warning-icon.png" />
<Label Content="Caps Lock is ON" Height="31" HorizontalAlignment="Left" Margin="125,-6,0,0" Name="lblWarningHeader" VerticalAlignment="Top" FontSize="16" FontWeight="Bold" />
<TextBlock HorizontalAlignment="Right" Margin="0,22,17,-1" Name="txbMessage" Width="379">Having Caps Lock on may cause you to enter your password incorrectly. <LineBreak/> <LineBreak/> You should press Caps Lock to turn it of before entering your password. VerticalAlignment="Top" Width="346" FontSize="11"</TextBlock>
</Grid>
</Border>
<Image
Source="{Binding Path=IconSource}" Width="16" HorizontalAlignment="Left" Margin="-56,0,0,-38" Height="16" VerticalAlignment="Bottom" Grid.Row="1" />
<Path Data="M10402.99154,55.5381L10.9919,0.64 0.7,54.9" Fill="LightSkyBlue" HorizontalAlignment="Left" Margin="32,3,0,0" Stretch="Fill" Stroke="Black" Width="22" Height="31" VerticalAlignment="Top" />
</Grid>
</Window>
-. Digite o seguinte código por trás do LoginForm
private Point location;
public static bool balloonVisFlag = false;
private DispatcherTimer timer;
WarningBalloon Balloon = null;
private void ShowHideBalloon()
{
if (System.Windows.Forms.Control.IsKeyLocked(System.Windows.Forms.Keys.CapsLock))
{
if (timer == null)
{
timer = new DispatcherTimer();
}
location = GetControlPosition(psbPassword);
Balloon.Left = location.X;
Balloon.Top = location.Y;
Balloon.Show();
balloonVisFlag = true;
timer.Interval = TimeSpan.FromMilliseconds(5000);
timer.IsEnabled = true;
timer.Tick += new EventHandler(Timer_Tick);
psbPassword.Focus();
}
else
{
Balloon.Hide();
balloonVisFlag = false;
psbPassword.Focus();
}
}
Point GetControlPosition(Control myControl)
{
Point locationToScreen = myControl.PointToScreen(new Point(0, 0));
PresentationSource source = PresentationSource.FromVisual(myControl);
return source.CompositionTarget.TransformFromDevice.Transform(locationToScreen);
}
private void psbPassword_KeyDown(object sender, KeyEventArgs e)
{
ShowHideBalloon();
}
private void Window_LocationChanged(object sender, EventArgs e)
{
if (balloonVisFlag == true)
{
ShowHideBalloon();
}
}
private void Timer_Tick(object sender, EventArgs e)
{
if (balloonVisFlag == true)
{
Balloon.Hide();
balloonVisFlag = false;
}
}
}
A minha solução é um pouco diferente. Fiz um ContentControl você pode colocar qualquer coisa dentro de, e ele irá notificar o caps lock status. Adicionar esta classe ao seu código.
public sealed class ShowCapLock : ContentControl
{
public bool ShowMessage
{
get { return (bool)GetValue(ShowMessageProperty); }
set { SetValue(ShowMessageProperty, value); }
}
public static readonly DependencyProperty ShowMessageProperty =
DependencyProperty.Register("ShowMessage", typeof(bool), typeof(ShowCapLock), new PropertyMetadata(false));
static ShowCapLock()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ShowCapLock), new FrameworkPropertyMetadata(typeof(ShowCapLock)));
}
public ShowCapLock()
{
IsKeyboardFocusWithinChanged += (s,e) => RecomputeShowMessage();
PreviewKeyDown += (s,e)=> RecomputeShowMessage();
PreviewKeyUp += (s,e)=> RecomputeShowMessage();
}
private void RecomputeShowMessage()
{
ShowMessage = IsKeyboardFocusWithin && System.Console.CapsLock;
}
}
E adicione um pouco de XAML para o seu generic.xaml
<Style TargetType="{x:Type controls1:ShowCapLock}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls1:ShowCapLock}">
<Grid>
<ContentPresenter Name="Presenter"/>
<Popup Placement="Bottom" PlacementTarget="{Binding ElementName=Presenter}"
IsOpen="{TemplateBinding ShowMessage}">
<Border Background="LightGoldenrodYellow" BorderThickness="1" BorderBrush="Black">
<TextBlock Foreground="Black">
<TextBlock>Caps Lock is down.</TextBlock>
</TextBlock>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
E você pode colocar um pouco de controle em torno de qualquer coisa que você quiser notificar para Caps Lock:
<controls:ShowCapLock Grid.Row="5" Grid.Column="1">
<PasswordBox . . ./>
</controls:ShowCapLock>
Depende completamente de sua arquitetura, mas por uma solução simples:
Você deve ser a criação de uma propriedade de dependência, que será observado por algum tipo de controle sobre a janela que se tornará visível e irá exibir o aviso para o usuário.