Warn about CapsLock

后端 未结 4 445
长情又很酷
长情又很酷 2020-12-10 17:57

I have a DataGridTemplateColumn with DataTemplate as a PasswordBox.

I want to warn user if CapsLock is toggled.

private void PasswordBox_PasswordChan         


        
相关标签:
4条回答
  • 2020-12-10 18:19

    I have made warning balloon to solve Caps Lock warning problem in my WPF-Project.

    enter image description here

    If you want to add this balloon warning in your project then follow these steps:

    - Add new Window in your project and give name "WarningBalloon".
    - Add following XAML code against new Window and add warning icon to image folder of project.

    <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>
    

    - Type the following code behind the 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;
            }
        }    
    }
    
    0 讨论(0)
  • 2020-12-10 18:31

    It completely depends on your architecture, but for a simple solution:

    You should be setting a Dependency Property, which will be observed by some sort of control on the Window that will become visible and will display the warning for the user.

    0 讨论(0)
  • 2020-12-10 18:35

    My solution is a little bit different. I made a ContentControl you can put anything inside of, and it will notify the caps lock status. Add this class to your code.

      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;
        }
      }
    

    And add some XAML to your 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>
    

    And you can put a little control around anything you want to notify for caps lock:

                <controls:ShowCapLock Grid.Row="5" Grid.Column="1">
                    <PasswordBox  . . ./>
                </controls:ShowCapLock>
    
    0 讨论(0)
  • 2020-12-10 18:42

    You could show a ToolTip

    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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题