Atlanta Custom Software Development 

 
   Search        Code/Page
 

User Login
Email

Password

 

Forgot the Password?
Services
» Web Development
» Maintenance
» Data Integration/BI
» Information Management
Programming
  Database
Automation
OS/Networking
Graphics
Links
Tools
» Regular Expr Tester
» Free Tools


Sometimes you might need to find out the closest character index in textbox/richtextbox from your mouse position. If you are doing drag n drop text and you want to drop it at a specified location in the textbox based on your current mouse position then you will surely need this code. This simple code will show you the following techniques.

- How to get the closest character in the textbox from mouse coordinates.
- How to create a custom carate and show at a specified character location in textbox
- How to get/set caret default blink time.

Step-By-Step Example

- Create a windows application project
- Add one textbox on the form1, set multiline=true and scrollbar=both
- Add the following code in form code section (after form class declaration)

Click here to copy the following block
Imports System.Runtime.InteropServices


Public Class Form1
  Inherits System.Windows.Forms.Form


  'Public Declare Function SendMessagePT Lib "user32.dll" Alias "SendMessageA" ( _
  '  ByVal hwnd As Integer, _
  '  ByVal wMsg As Integer, _
  '  ByVal wParam As Integer, _
  '  ByVal lParam As Point) As Integer

  Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
    ByVal hwnd As IntPtr, _
    ByVal wMsg As Integer, _
    ByVal wParam As Integer, _
    ByVal lParam As Integer) As Integer

  Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
  ByVal hwnd As IntPtr, _
  ByVal wMsg As Integer, _
  ByVal wParam As Integer, _
  ByVal lParam As IntPtr) As Integer

  Public Const EM_LINEINDEX = &HBB
  Public Const EM_POSFROMCHAR = &HD6
  Friend WithEvents GroupBox1 As System.Windows.Forms.GroupBox
  Friend WithEvents TextBox1 As System.Windows.Forms.RichTextBox
  Public Const EM_CHARFROMPOS = &HD7

  '///

  Public Declare Function CreateCaret Lib "user32" ( _
    ByVal hWnd As Integer, _
    ByVal hBitmap As Integer, _
    ByVal nWidth As Integer, _
    ByVal nHeight As Integer) As Integer

  Public Declare Function ShowCaret Lib "user32" ( _
    ByVal hWnd As Integer) As Integer

  Public Declare Function SetCaretBlinkTime Lib "user32" ( _
    ByVal wMSeconds As Integer) As Integer
  Public Declare Function GetCaretBlinkTime Lib "user32" () As Integer


  Public Structure POINTAPI
    Public X As Integer
    Public Y As Integer
  End Structure

  Function GetCharFromPos(ByVal txt As TextBoxBase, ByVal pt As Point) As Integer

    '// Convert the point into a DWord with horizontal position
    '// in the loword and vertical position in the hiword:
    Dim xy As Integer = (pt.X And &HFFFF) + ((pt.Y And &HFFFF) << 16)
    '// Get the position from the text box.
    Dim res As Integer
    If TypeOf (txt) Is RichTextBox Then
      Dim p As POINTAPI
      p.X = pt.X
      p.Y = pt.Y
      Dim lp As IntPtr = IntPtr.Zero
      lp = Marshal.AllocCoTaskMem(Marshal.SizeOf(p))
      Marshal.StructureToPtr(p, lp, False)
      res = SendMessage(txt.Handle, EM_CHARFROMPOS, 0, lp)
      'Free the block of memory allocated
      Marshal.FreeCoTaskMem(lp)
    Else
      res = SendMessage(txt.Handle, EM_CHARFROMPOS, 0, xy)
    End If

    '// the Platform SDK appears to be incorrect on this matter.
    '// the hiword is the line number and the loword is the index
    '// of the character on this line
    Dim lineNumber As Integer = ((res And &HFFFF) >> 16)
    Dim charIndex As Integer = (res And &HFFFF)

    '// Find the index of the first character on the line within
    '// the control:
    Dim lineStartIndex As Integer = SendMessage(txt.Handle, EM_LINEINDEX, lineNumber, 0)
    '// Return the combined index:

    Return lineStartIndex + charIndex
  End Function


  Sub ShowCustomCaret(ByVal ctl As Windows.Forms.Control, _
            Optional ByVal width As Integer = 3, _
            Optional ByVal height As Integer = 16, _
            Optional ByVal CaretBlinkTimeinMs As Integer = 400)

    On Error Resume Next
    With ctl
      CreateCaret(.Handle.ToInt32, 0, width, height)
      ShowCaret(.Handle.ToInt32)

      Debug.Write("Current blinktime : " & GetCaretBlinkTime)
      SetCaretBlinkTime(CaretBlinkTimeinMs)
    End With
  End Sub

  Private Sub TextBox1_GotFocus(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles TextBox1.GotFocus

    ' show a block cursor of 2x16
    ShowCustomCaret(sender, 3, 16)
  End Sub
  Private Sub TextBox2_GotFocus(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles TextBox2.GotFocus

    ' show a block cursor of 2x16
    ShowCustomCaret(sender, 3, 16)
  End Sub
  Private Sub TextBox1_MouseMove(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseMove

    Try
      Dim pt As Point
      Dim ret As Integer
      pt = New Point(e.X, e.Y)

      ret = GetCharFromPos(TextBox1, pt)
      TextBox1.Select(ret, 0)
      Me.Text = "Character Pos at (Y=" & pt.X & ",Y=" & pt.Y & ") is [" & ret & "]"
    Catch ex As Exception

    End Try

  End Sub

  Private Sub TextBox2_MouseMove(ByVal sender As Object, _
  ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox2.MouseMove

    Try
      Dim pt As Point
      Dim ret As Integer
      pt = New Point(e.X, e.Y)

      ret = GetCharFromPos(TextBox2, pt)
      TextBox2.Select(ret, 0)
      Me.Text = "Character Pos at (Y=" & pt.X & ",Y=" & pt.Y & ") is [" & ret & "]"
    Catch ex As Exception
    End Try

  End Sub

#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 TextBox2 As System.Windows.Forms.TextBox
  Friend WithEvents Label1 As System.Windows.Forms.Label
  <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
    Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(Form1))
    Me.TextBox2 = New System.Windows.Forms.TextBox
    Me.Label1 = New System.Windows.Forms.Label
    Me.GroupBox1 = New System.Windows.Forms.GroupBox
    Me.TextBox1 = New System.Windows.Forms.RichTextBox
    Me.GroupBox1.SuspendLayout()
    Me.SuspendLayout()
    '
    'TextBox2
    '
    Me.TextBox2.Font = New System.Drawing.Font("Courier New", 9.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
    Me.TextBox2.Location = New System.Drawing.Point(6, 19)
    Me.TextBox2.Multiline = True
    Me.TextBox2.Name = "TextBox2"
    Me.TextBox2.ScrollBars = System.Windows.Forms.ScrollBars.Both
    Me.TextBox2.Size = New System.Drawing.Size(309, 159)
    Me.TextBox2.TabIndex = 1
    Me.TextBox2.Text = resources.GetString("TextBox2.Text")
    Me.TextBox2.WordWrap = False
    '
    'Label1
    '
    Me.Label1.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
    Me.Label1.ForeColor = System.Drawing.Color.Blue
    Me.Label1.Location = New System.Drawing.Point(8, 200)
    Me.Label1.Name = "Label1"
    Me.Label1.Size = New System.Drawing.Size(336, 40)
    Me.Label1.TabIndex = 4
    Me.Label1.Text = "Click on the textbox and then try to move mouse over the textbox to find the clos" & _
      "est character position "
    '
    'GroupBox1
    '
    Me.GroupBox1.Controls.Add(Me.TextBox2)
    Me.GroupBox1.Location = New System.Drawing.Point(11, 13)
    Me.GroupBox1.Name = "GroupBox1"
    Me.GroupBox1.Size = New System.Drawing.Size(321, 184)
    Me.GroupBox1.TabIndex = 5
    Me.GroupBox1.TabStop = False
    Me.GroupBox1.Text = "GroupBox1"
    '
    'TextBox1
    '
    Me.TextBox1.Location = New System.Drawing.Point(360, 32)
    Me.TextBox1.Name = "TextBox1"
    Me.TextBox1.Size = New System.Drawing.Size(327, 165)
    Me.TextBox1.TabIndex = 6
    Me.TextBox1.Text = resources.GetString("TextBox1.Text")
    '
    'Form1
    '
    Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
    Me.ClientSize = New System.Drawing.Size(713, 237)
    Me.Controls.Add(Me.TextBox1)
    Me.Controls.Add(Me.GroupBox1)
    Me.Controls.Add(Me.Label1)
    Me.Name = "Form1"
    Me.Text = "Form1"
    Me.GroupBox1.ResumeLayout(False)
    Me.GroupBox1.PerformLayout()
    Me.ResumeLayout(False)

  End Sub

#End Region
End Class


Submitted By : Nayan Patel  (Member Since : 5/26/2004 12:23:06 PM)

Job Description : He is the moderator of this site and currently working as an independent consultant. He works with VB.net/ASP.net, SQL Server and other MS technologies. He is MCSD.net, MCDBA and MCSE. In his free time he likes to watch funny movies and doing oil painting.
View all (893) submissions by this author  (Birth Date : 7/14/1981 )


Home   |  Comment   |  Contact Us   |  Privacy Policy   |  Terms & Conditions   |  BlogsZappySys

© 2008 BinaryWorld LLC. All rights reserved.