Home > Software engineering >  Is is possible to change cursor blink rate and cursor movement speed in wpf?
Is is possible to change cursor blink rate and cursor movement speed in wpf?

Time:05-27

I tested both Word 2010 and Word 2019 on the same systems and same Keyboard Properties. I did not change the properties of the Windows Keyboard.

Cursor movement and cursor blinking were fast in Word 2010, but very slow in Word 2019.

I want to modify Cursor's blink rate and movement speed in wpf project.

How to do it? Thanks for any help.

<Grid>
         <TextBox x:Name="tb"  Height="230" Padding="4"  TextWrapping="Wrap" AcceptsReturn="True"  Width="320" Focusable="True" Loaded="tb_Loaded"  />
    
     </Grid>
  private void tb_Loaded(object sender, RoutedEventArgs e)
     {
       Keyboard.Focus(tb);
     }

Edit: I looked here but don't know if it is correct and how to do it.

CodePudding user response:

WPF basically respects Windows's control panel settings of the blink rate. So does Word 2019 on my system. If you want to change the rate on your textbox, your only option is to disable the built-in caret (text cursor), and draw it yourself.

The following is shamelessly stolen inspired by this article, with some kinks ironed out:

  • SelectionChanged triggers too early when TextBox height is not a full multiple of line height causing buggy cursor positioning. Changed to LayoutUpdated.
  • Caret.Height respects the text height, instead of hardcoded.

Now on to the magic. Try this on your MainWindow.xaml:

<Grid x:Name="YouNeedAGridToContainTheTextBoxAndCanvas">

  <TextBox x:Name="CustomTextBox"
    FontSize="20" 
    AcceptsReturn="True" TextWrapping="Wrap"
    CaretBrush="Transparent" />
    <!--CaretBrush must be Transparent, as we will draw manually below-->

  <Canvas ClipToBounds="True">
    <Border x:Name="Caret" 
      Width="4" 
      Visibility="Collapsed"
      Background="Transparent"> <!--Start drawing Transparent-->
      <Border.Triggers>
        <EventTrigger RoutedEvent="Border.Loaded">
          <BeginStoryboard>
            <Storyboard RepeatBehavior="Forever">
              <ColorAnimationUsingKeyFrames 
                Storyboard.TargetProperty="Background.Color"
                FillBehavior="HoldEnd">
                <ColorAnimationUsingKeyFrames.KeyFrames>
                  <!--Ease to Red in 1sec-->
                  <EasingColorKeyFrame KeyTime="0:0:1.0" Value="Red"/>
                  <!--Ease back into Transparent in another 1sec-->
                  <EasingColorKeyFrame KeyTime="0:0:2.0" Value="Transparent" />
                </ColorAnimationUsingKeyFrames.KeyFrames>
              </ColorAnimationUsingKeyFrames>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Border.Triggers>
    </Border>
  </Canvas>

</Grid>

You then need to manually update the drawing position by using code behind in your MainWindow.xaml.cs:

public MainWindow() //Constructor
{
    InitializeComponent();

    CustomTextBox.LayoutUpdated  = (_, _) => {
        var rect = CustomTextBox.GetRectFromCharacterIndex(CustomTextBox.CaretIndex);
        if (rect.IsEmpty) return;
        Canvas.SetLeft(Caret, rect.Left);
        Canvas.SetTop(Caret, rect.Top);
        Caret.Height = rect.Height;
    };
    CustomTextBox.LostFocus  = (_, _) => Caret.Visibility = Visibility.Collapsed;
    CustomTextBox.GotFocus  = (_, _) => Caret.Visibility = Visibility.Visible;
    CustomTextBox.Focus();
}

Feel free to tweak the color animation, adding frames as needed and playing with the KeyTime for faster/slower pulsing. Use <DiscreteColorKeyFrame> instead of <EasingColorKeyFrame> if you want a hard blink instead of pulsing.

  • Related