在模仿Windows內建的記事本做練習時,發現TextBox控制項沒有直接的辦法取得當前的行和列的位置,也沒有定位的功能。查了資料發現可以能過Windows API來實現,具體要用到SendMessage函數和EM_LINEFROMCHAR(0xC9)與EM_LINEINDEX(0xBB)兩個訊息常量,這需要自己引入或定義。下面是測試代碼。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication7
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//引入LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
[System.Runtime.InteropServices.DllImport("User32.DLL")]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int iParam);
private const int EM_LINEFROMCHAR = 0xC9;
private const int EM_LINEINDEX = 0xBB;
//取得行列位置
private Point GetCursorPos(TextBox textBox)
{
Point cursorPos = new Point(0, 0);
int x, y;
y = SendMessage(textBox.Handle, EM_LINEFROMCHAR, textBox.SelectionStart, 0);
x = textBox.SelectionStart - SendMessage(textBox.Handle, EM_LINEINDEX, y, 0);
cursorPos.Y = ++y;
cursorPos.X= ++x;
return cursorPos;
}
//經過測試,C#中需要在TextBox的Click事件、KeyUp事件和KeyDown事件中添加代碼才可能即時取得行列位置
private void textBox1_Click(object sender, EventArgs e)
{
Point cursorPos = GetCursorPos(this.textBox1);
this.Text = cursorPos.ToString();
}
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
Point cursorPos = GetCursorPos(this.textBox1);
this.Text = cursorPos.ToString();
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
Point cursorPos = GetCursorPos(this.textBox1);
this.Text = cursorPos.ToString();
}
//定位行號,EM_LINEINDEX會根據指定的行號得到它的字元位置,把傳回值指定給SelectionStart實現定位。
private void button1_Click(object sender, EventArgs e)
{
this.textBox1.SelectionStart= SendMessage(this.textBox1.Handle, EM_LINEINDEX, 3, 0);
this.textBox1.Focus();
Point cursorPos = GetCursorPos(this.textBox1);
this.Text = cursorPos.ToString();
}
}
}
補充說明:
EM_LINEFROMCHAR用於根據“字元位置”取得和設定當前行號,字元位置是指從開始到當前位置的字元數;
EM_LINEINDEX用於定位行號,實際是上修改字元位置定位到指定行的開始位置。
Delphi中關於EM_LINEFROMCHAR的協助說明
An application sends an EM_LINEFROMCHAR message to retrieve the index of the line that contains the specified character index in a multiline edit control. A character index is the number of characters from the beginning of the edit control.
EM_LINEFROMCHAR
wParam = (WPARAM) ich; // character index
lParam = 0; // not used; must be zero
Parameters
ich
Value of wParam. Specifies the character index of the character contained in the line whose number is to be retrieved. If the
ich parameter is -1, either the line number of the current line (the line containing the caret) is retrieved or, if there is a selection, the line number of the line containing the beginning of the selection is retrieved.
Return Values
The return value is the zero-based line number of the line containing the character index specified by ich.
Remarks
In a rich edit control, if the character index is greater than 64K, use the message EM_EXLINEFROMCHAR.
Delphi中關於EM_LINEINDEX的協助說明
An application sends an EM_LINEINDEX message to retrieve the character index of a line in a multiline edit control. The character index is the number of characters from the beginning of the edit control to the specified line.
EM_LINEINDEX
wParam = (WPARAM) line; // line number
lParam = 0; // not used; must be zero
Parameters
line
Value of wParam. Specifies the zero-based line number. A value of -1 specifies the current line number (the line that contains the caret).
Return Values
The return value is the character index of the line specified in the line parameter, or it is -1 if the specified line number is greater than the number of lines in the edit control.