Solved

Getting text position under mouse cursor?

Posted on 2004-11-02
542 Views
Last Modified: 2012-08-14
Hi.
I'm trying to make a TextBox handle Drag & Drop operations and everything is fine and smooth except for the visual feedback I'm trying to achieve.
I want to be able to drag a text data to insert it into the text at the location pointed by mouse cursor.
I can send a mouseclick (MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP) message to the TextBox during the DragDrop event to set the caret position, but doing it before the actual drop causes unwanted DragDrop event to raise and makes things complicated.
Any way to set the caret position right without raising the DragDrop event?

In short words: how to get the text position at a given point?
0
Question by:xyzzer
    9 Comments
     
    LVL 27

    Expert Comment

    by:planocz
    "In short words: how to get the text position at a given point?"....

    here is the x, y point of a textbox.

       Private Sub TextBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseMove
            Dim x, y As Integer
            x = sender.mousePosition.x()
            y = sender.mousePosition.y()

        End Sub


    Still working on the drag drop part.
    0
     
    LVL 85

    Accepted Solution

    by:
    To get the Insert position for the TextBox from the X, Y mouse coordinates you have to use several SendMessage API calls.

    If you change the TextBox to a RichTextBox though, you can get it for free.  The caret will move as you drag over the RTB.  Try it with the small app below.  Drag the Label over the RTB and drop it anywhere in the Text.

    ~IM

    Public Class Form1
        Inherits System.Windows.Forms.Form

    #Region " Windows Form Designer generated code "

        Public Sub New()
            MyBase.New()

            'This call is required by the Windows Form Designer.
            InitializeComponent()

            'Add any initialization after the InitializeComponent() call

        End Sub

        'Form overrides dispose to clean up the component list.
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If Not (components Is Nothing) Then
                    components.Dispose()
                End If
            End If
            MyBase.Dispose(disposing)
        End Sub

        'Required by the Windows Form Designer
        Private components As System.ComponentModel.IContainer

        'NOTE: The following procedure is required by the Windows Form Designer
        'It can be modified using the Windows Form Designer.  
        'Do not modify it using the code editor.
        Friend WithEvents Label1 As System.Windows.Forms.Label
        Friend WithEvents RichTextBox1 As System.Windows.Forms.RichTextBox
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            Me.Label1 = New System.Windows.Forms.Label
            Me.RichTextBox1 = New System.Windows.Forms.RichTextBox
            Me.SuspendLayout()
            '
            'Label1
            '
            Me.Label1.Location = New System.Drawing.Point(8, 8)
            Me.Label1.Name = "Label1"
            Me.Label1.Size = New System.Drawing.Size(272, 24)
            Me.Label1.TabIndex = 2
            Me.Label1.Text = "Label1"
            '
            'RichTextBox1
            '
            Me.RichTextBox1.AllowDrop = True
            Me.RichTextBox1.Location = New System.Drawing.Point(8, 40)
            Me.RichTextBox1.Name = "RichTextBox1"
            Me.RichTextBox1.Size = New System.Drawing.Size(272, 216)
            Me.RichTextBox1.TabIndex = 3
            Me.RichTextBox1.Text = "RichTextBox1"
            '
            'Form1
            '
            Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
            Me.ClientSize = New System.Drawing.Size(288, 266)
            Me.Controls.Add(Me.RichTextBox1)
            Me.Controls.Add(Me.Label1)
            Me.Name = "Form1"
            Me.Text = "Form1"
            Me.ResumeLayout(False)

        End Sub

    #End Region

        Private Sub Label1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseMove
            If e.Button = MouseButtons.Left Then
                Label1.DoDragDrop(Label1.Text, DragDropEffects.Copy Or DragDropEffects.Move)
            End If
        End Sub

        Private Sub RichTextBox1_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles RichTextBox1.DragEnter
            If (e.Data.GetDataPresent(DataFormats.Text)) Then
                e.Effect = DragDropEffects.Copy
            Else
                e.Effect = DragDropEffects.None
            End If
        End Sub

        Private Sub RichTextBox1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles RichTextBox1.DragDrop
            If (e.Data.GetDataPresent(DataFormats.Text)) Then
                RichTextBox1.SelectedText = e.Data.GetData(DataFormats.Text)
            End If
        End Sub

    End Class
    0
     
    LVL 2

    Author Comment

    by:xyzzer
    Thanks a lot! I started with a RichTextBox, but it seemed harder to control, so I got back to regular one. The problem was, that I was dragging a list of strings from the listbox and casted it to string on drop and the RichTextBox only gives feedback to dragged string objects.

    By the way, what about:

    "To get the Insert position for the TextBox from the X, Y mouse coordinates you have to use several SendMessage API calls."

    You do know a way for that?
    0
     
    LVL 85

    Expert Comment

    by:Mike Tomlinson
    I'll see if I can whip it up for you.  I could do it in VB6 code but have to convert the calls and what not...tis a pain.  ;)

    ~IM
    0
     
    LVL 96

    Expert Comment

    by:Bob Learned
    If you are trying to drag and drop text into a RichTextBox, then you need RichTextBox.GetCharIndexFromPosition to determine the SelectionStart position for the mouse cursor.

    Bob
    0
     
    LVL 2

    Author Comment

    by:xyzzer
    I have accepted the answer that worked for me, but if you know how to do it for TextBox - it would be nice too. If got the code for VB6 - it should be enough too.
    Thenks again.
    0
     
    LVL 85

    Expert Comment

    by:Mike Tomlinson
    I haven't had time to get back to the original TextBox problem.

    You have to use the SendMessage() API with EM_CHARFROMPOS to get the row and EM_LINEINDEX to get the column.

    ~IM
    0
     

    Expert Comment

    by:ralan2
    xyzzer,

    In .NET, it is simple to find the cursor (insertion point) location in a standard textbox.
    Simply query the .SelectionStart property. Even if no text is actually selected, this property tells you at what location in the textbox.text string the cursor currently resides.

    ralan2
    0
     
    LVL 2

    Author Comment

    by:xyzzer
    That's for keyboard cursor. I needed that for a mouse cursor.
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    IT, Stop Being Called Into Every Meeting

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    Welcome my friends to the second instalment and follow-up to our Minify and Concatenate Your Scripts and Stylesheets (http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/A_4334-Minify-and-Concatenate-Your-Scripts-and-Stylesheets.html)…
    This article describes relatively difficult and non-obvious issues that are likely to arise when creating COM class in Visual Studio and deploying it by professional MSI-authoring tools. It is assumed that the reader is already familiar with the cla…
    In this sixth video of the Xpdf series, we discuss and demonstrate the PDFtoPNG utility, which converts a multi-page PDF file to separate color, grayscale, or monochrome PNG files, creating one PNG file for each page in the PDF. It does this via a c…
    This video discusses moving either the default database or any database to a new volume.

    909 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    13 Experts available now in Live!

    Get 1:1 Help Now