Click here to Skip to main content
15,887,936 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
Hello,

there is a known bug with the WPF PasswordBox and touch devices (does not pop up virtual keyboard).

So I made an own usercontrol.
It has a PasswordBox and a TextBox, both on same position, TextBox has Opacity 0.
When the textbox gets the focus, it pops up the virtual keyboard, then gives to focus to the PasswordBox:

C#
private void Text_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
    CustomPasswordBox.Focus();
    SetSelection(CustomPasswordBox, currentCaretIndex, 0);
}


That is working perfect.

The textbox gets all input events from the mouse.
So I need to set the cursor position, selection etc. manually.

I found one problem with this, I have no idea why.

C#
//Cursor-Position
private int currentCaretIndex = 0;


This currentCaretIndex should save my cursor position.

The following code should set the selection to my CustomPasswordBox,
when using mouse on the CustomTextBox.

But it is not working, when I try to click behind the last character,
it is one position before the last character. When adding +1 to it,
I cannot click left of the first character anymore.

It seems CustomTextBox.GetCharacterIndexFromPoint is returning wrong values somehow in that cases. Any idea to fix that? Thanks a lot!


C#
//
        private void SetSelection(PasswordBox passwordBox, int start, int length)
        {
            if (start >= 0 && length <= passwordBox.Password.Length)
            {
                passwordBox.GetType().GetMethod("Select", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(passwordBox, new object[] { start, length });
            }
        }

        private int CalculatePosition(Point mousePoint)
        {
            //CaretIndex -> Cursor Position calculate
            CustomTextBox.Text = "";
            for (int i = 0; i < CustomPasswordBox.Password.Length; i++)
            {
                CustomTextBox.Text += CustomPasswordBox.PasswordChar;
            }
            return CustomTextBox.GetCharacterIndexFromPoint(mousePoint, true);
        }

        private void CustomTextBox_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            //CaretIndex -> Cursor Position calculate 
            Point mousePos = new Point(e.GetPosition(CustomTextBox).X, e.GetPosition(CustomTextBox).Y);
            currentCaretIndex = CalculatePosition(mousePos);
            //            //if (currentCaretIndex > 0)
            //    currentCaretIndex++;

            selectionStart = currentCaretIndex;
            isMouseDown = true; 
        }

        private void CustomTextBox_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (!isMouseDown)
            {
                return;
            }

            Point mousePos = new Point(e.GetPosition(CustomTextBox).X, e.GetPosition(CustomTextBox).Y);
            selectionEnd = CalculatePosition(mousePos);
            SetSelection(CustomPasswordBox, System.Math.Min(selectionStart, selectionEnd), System.Math.Max(selectionStart, selectionEnd));
        }

        private void CustomTextBox_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            isMouseDown = false;
        }
Posted
Updated 2-Jul-12 5:24am
v2

Since TextBox.GetCharacterIndexFromPoint always seems to return a position before a character, and not a psoition behind a cahracter, even if you click right of the latest character, it could be a solution to calculate myself if the position is right of the last char:

C#
if (mousePoint.X > CustomPasswordBox.Password.Length * CustomPasswordBox.FontSize)
{
    return CustomPasswordBox.Password.Length;
}
else
{
    return CustomTextBox.GetCharacterIndexFromPoint(mousePoint, true);
}


This seems to be the solution! But it is not working well, you must click a long distance right of the last char, then it is working. If you only click a bit right of it, the cursor jumps before the last char...
 
Share this answer
 
Found the solution.
Thanks for your interest.

C#
SizeF size;
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(new Bitmap(1, 1)))
{
    size = graphics.MeasureString(CustomTextBox.Text, new Font(CustomTextBox.FontFamily.ToString(), Convert.ToSingle(CustomTextBox.FontSize), System.Drawing.FontStyle.Regular, GraphicsUnit.Pixel));
}

if (mousePoint.X >= size.Width)
{
    return CustomPasswordBox.Password.Length;
}
else
{
    return CustomTextBox.GetCharacterIndexFromPoint(mousePoint, true);
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900