Click here to Skip to main content
15,881,757 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
i want to find the keyboard cursor's location (x,y) on form in c# win. form. How to achieve this?
[see the link to see the difference between mouse cursor and keyboard cursor]

https://www.dropbox.com/s/bcocp5stn0pzvwe/Untitled.png[^]



Thanks in advance
Posted
Updated 3-Feb-14 0:26am
v3
Comments
Mitchell J. 2-Feb-14 5:45am    
What do you mean by "keyboard cursor"? How is this different to a normal cursor?
agent_kruger 2-Feb-14 5:54am    
difference is that mouse cursor is that when you move mouse that changes the x and y (co-ordinates of it) and keyboard cursor location means that whenever you write a character it moves from the starting position to after the inserted charachter.
BillWoodruff 2-Feb-14 8:08am    
Are you asking about determining the current position of the Text Insertion Cursor in a TextBox ? Or ... ?

'There isn#t a "keyboard position" on a form: there are many potential positions, depending on which control has the input focus.

You can find which control in a container has the focus, using the ContainerControl.ActiveControl property[^] and then get the keboard input point for that particular control:
C#
void myTimer_Tick(object sender, EventArgs e)
    {
    string s = "--none--";
    Control c = ActiveControl;
    if (c != null)
        {
        s = c.Name;
        TextBox tb = c as TextBox;
        if (tb != null)
            {
            s += string.Format(" : {0}", tb.SelectionStart);
            }

        }
    theKeyboardIsHere.Text = s;
    }

Fortunately, ActiveControl searches sub-containers for you!
 
Share this answer
 
Comments
BillWoodruff 2-Feb-14 20:42pm    
+5 I wonder how many readers will know that knowing 'ActiveControl (for Form, UserControl, PropertyGrid, and other descendants of ContainerControls) performs a recursive search which will examine the contents of nested Controls which are not ContainerControls (i.e., Panel) is information "worth its weight in gold" ?
OriginalGriff 3-Feb-14 4:48am    
I wonder how many reader will know it even exists? :laugh:
agent_kruger 3-Feb-14 6:31am    
sorry sir, for 3 but check the updated question and active control cannot be used in my project sir
OriginalGriff 3-Feb-14 6:52am    
You can (in theory) find the Caret (that's what the input point on your image is called) in another application, but it's not a lot of fun...or even guaranteed to work.
But...there is code here:
http://bytes.com/topic/c-sharp/answers/259851-getting-position-caret
which purports to do it - it's at the bottom. However, you will need to set up the PInvoke signatures, and I really don't know if it will work on modern operating systems - there is a good chance it won't. I haven't tried it (because I don't need to do it) and I think it's probably a nasty solution to whatever problem you are going to use it for!
Good luck...
BillWoodruff 3-Feb-14 8:23am    
Why can't ActiveControl be used in your Project ?
Note: code examples here have been tested, and verified, in Visual Studio 2013, compiled against .NET FrameWork 4.5, using the 'AnyCPU build option on a Win 8/64 machine.

After some research, I've found there is a known problem with using 'GetPositionFromCharIndex to determine the caret position (insertion cursor point) in a TextBox under certain circumstances. However, 'GetPositionFromCharIndex works fine with a RichTextBox.

With a TextBox:

To reliably get the caret point in a TextBox, it is necessary to use a WinAPI call:
C#
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCaretPos(out Point lpPoint);
Here's the original code I posted modifed to use the WinAPI 'GetCaretPos function:
private Point GetCursorTextBox(TextBox theTextBox)
{
    // see note below on this
    // Control currentActiveControl = ActiveControl;

    // see note below on why this check is here ...
    if (this.ActiveControl != theTextBox)
    {
        this.ActiveControl = theTextBox;
    }`
    
    // get the caret position which is the
    // row-column address of where in the
    // TextBox's Lines collection the insertion cursor is at
    Point chrTbLocation;

    GetCaretPos(out chrTbLocation);

    // index of the character insertion cursor is at
    int selStart = theTextBox.SelectionStart + theTextBox.SelectionLength;

    // line number the insertion cursor is at
    int line = theTextBox.GetLineFromCharIndex(selStart);

    // point in the Screen insertion cursor is at
    Point chrScrnLocation = theTextBox.PointToScreen(chrTbLocation);

    // point in the Form insertion cursor is at
    Point chrFrmLocation = this.PointToClient(chrScrnLocation);

    // for testing only ...

    // this should be identical to the value in 'selStart
    int charPosition = textBox1.GetCharIndexFromPosition(chrTbLocation);

    Console.WriteLine("Caret at: Line: {0} Column: {1} in TextBox: {2}", line, selStart, theTextBox.Name);
    Console.WriteLine("Screen Location: {0} Form Location: {1}", chrScrnLocation, chrFrmLocation);
    Console.WriteLine();

    // see note below on this
    // ActiveControl = currentActiveControl;

    // return the caret point in Form co-ordinates
    return chrFrmLocation;
}
Note that at the start of the method, a check is done to determine if the TextBox argument to the method is the current ActiveControl on the Form; if it is not, then the TextBox argument is made the ActiveControl. This is done because the call to 'GetCaretPos has no way of "knowing" which Control on the Form, if any, currently is the ActiveControl.

But, also, note that if you invoke the 'GetCursorTextBox method from an EventHandler of the TextBox passed in as an argument, such as in the TextChanged EventHandler, then that check is not really necessary because the TextChanged event is only going to be raised when the TextBox is the ActiveControl.

If having the ActiveControl changed by the 'GetCursorTextBox method presents a problem for you, then preserve the current ActiveControl at the start of the method, and set it back at the end of the method. Code to do this is shown commented out.

With a RichTextBox:

This code will work fine with a RichTextBox:
private Point GetCursorRichTextBox(RichTextBox theRichTextBox)
{
    // index of the character insertion cursor is at
    int selStart = theRichTextBox.SelectionStart + theRichTextBox.SelectionLength;

    // line number the insertion cursor is at
    int line = theRichTextBox.GetLineFromCharIndex(selStart);

    // point in the TextBox insertion cursor is at
    Point chrTbLocation = theRichTextBox.GetPositionFromCharIndex(selStart);

    // point in the Screen insertion cursor is at
    Point chrScrnLocation = theRichTextBox.PointToScreen(chrTbLocation);

    // point in the Form insertion cursor is at
    Point chrFrmLocation = this.PointToClient(chrScrnLocation);

    // for testing only ...

    // this should be identical to the value in 'selStart
    int charPosition = theRichTextBox.GetCharIndexFromPosition(chrTbLocation);

    Console.WriteLine("Caret at: Line: {0} Column: {1} in RichTextBox: {2}", line, selStart, theRichTextBox.Name);
    Console.WriteLine("Screen Location: {0} Form Location: {1}", chrScrnLocation, chrFrmLocation);
    Console.WriteLine();

    // return the caret point in Form co-ordinates
    return chrFrmLocation; 
}
 
Share this answer
 
v4
Comments
agent_kruger 3-Feb-14 9:00am    
no sir, sorry to say that doesn't work at all (1 Point) but thank you for taking time and writting the code (+2 Points)
BillWoodruff 3-Feb-14 9:12am    
It certainly does work. Put a TextBox on a Windows Form, and insert that code in the Form it's on, then call the method passing a reference to a TextBox, and you get back the location in Form co-ordinates of where the insertion cursor is at in the TextBox.

Point iCursorAt = GetCursorInfo(NameOfMyTextBox);

If there is no selection, no cursor position set by user action, then when the method is called, the location returned will be the same as if the insertion cursor was at the first character in the TextBox.
agent_kruger 3-Feb-14 9:18am    
sir, i tried it and current location of my textbox is "783, 192" and size is "193, 163" and on writting "1" it shows answer "785,194" and on writting "123456789" it shows "785,194". Why this is so sir?
BillWoodruff 3-Feb-14 10:12am    
Well, testing in VS 2013, using FrameWork 4.5, I am finding some strange results; and, I have used code like this several years ago, in VS 2008, with no problem. I am observing that if I manually set the insertion cursor, and then type, I get results as expected from the call to 'GetPositionFromCharIndex, but if I delete all the text, and start typing the value doesn't change ... even though I can see by inspection that 'selStart and 'line variables are being updated as expected.

It's GMT +7 here, and I'm a bit burned-out, so I'll take another look at this tomorrow morning. I am sure this is the right technique to use.

I am sure someone with the good name of 'Spock has great patience, but, if your patience fails, well, you are half-human, after all, so: just keep down-voting me :)
agent_kruger 3-Feb-14 18:50pm    
no sir, at least you tried :)

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