正如一条评论告诉您的,您可以使用MeasureCharacterRanges 来实现此目的。我必须首先说我编辑并删除了我以前的答案,因为它太长了。其次,所有这些代码都改编自here。
这个解决方案远非完美,但它可能会引导您实现您想要的。首先,我们有一个方法可以测量最长 32 个字符的字符串的字符:
// Measure the characters in a string with
// no more than 32 characters.
private List<RectangleF> MeasureCharactersInWord(
Graphics gr, Font font, string text)
{
List<RectangleF> result = new List<RectangleF>();
using (StringFormat string_format = new StringFormat())
{
string_format.Alignment = StringAlignment.Near;
string_format.LineAlignment = StringAlignment.Near;
string_format.Trimming = StringTrimming.None;
string_format.FormatFlags =
StringFormatFlags.MeasureTrailingSpaces;
CharacterRange[] ranges = new CharacterRange[text.Length];
for (int i = 0; i < text.Length; i++)
{
ranges[i] = new CharacterRange(i, 1);
}
string_format.SetMeasurableCharacterRanges(ranges);
RectangleF rect = new RectangleF(0, 0, 10000, 100);
Region[] regions =
gr.MeasureCharacterRanges(
text, font, this.ClientRectangle,
string_format);
foreach (Region region in regions)
result.Add(region.GetBounds(gr));
}
return result;
}
在这之后,我们现在需要一个方法来测量整个字符串,不管多长:
private List<RectangleF> MeasureCharacters(Graphics gr,Font font, int
posY,string text)
{
List<RectangleF> results = new List<RectangleF>();
// The X location for the next character.
float x = 0;
// Get the character sizes 31 characters at a time.
for (int start = 0; start < text.Length; start += 32)
{
// Get the substring.
int len = 32;
if (start + len >= text.Length) len = text.Length - start;
string substring = text.Substring(start, len);
// Measure the characters.
List<RectangleF> rects =
MeasureCharactersInWord(gr, font, substring);
// Remove lead-in for the first character.
if (start == 0) x += rects[0].Left;
// Save all but the last rectangle.
for (int i = 0; i < rects.Count + 1 - 1; i++)
{
RectangleF new_rect = new RectangleF(
x, posY,
rects[i].Width, rects[i].Height);
results.Add(new_rect);
// Move to the next character's X position.
x += rects[i].Width;
}
}
// Return the results.
return results;
}
这是绘制字符串并将所有字符位置存储在 2 行中的方法:
List<List<RectangleF>> linesCharactersPositions = new List<List<RectangleF>>();
private void Form3_Paint(object sender, PaintEventArgs e)
{
linesCharactersPositions = new List<List<RectangleF>>();
string[] lines = new string[] { "12345678 0234567890123456789012asdjkhfkjasdhfklhasdlkfjhlasdkjhfasdlfhlasdc",
"vm,xv,cxznvrtrutyquiortorutoqwruyoiurweyoquitiqwrtiqwetryqweiufhsduafh" };
Font f = new Font("Arial", 18);
int lineY = 10;
foreach (string line in lines)
{
DrawLongStringWithCharacterBounds(e.Graphics, line, new Font("Arial", 18), new PointF(10, lineY));
linesCharactersPositions.Add(MeasureCharacters(e.Graphics, f,lineY, line));
lineY += 20;
}
}
最后,MouseMove 事件:
private void Form_MouseMove(object sender, MouseEventArgs e)
{
Graphics g = this.CreateGraphics();
int characterCount = 0;
foreach(var linePositions in linesCharactersPositions)
{
for (int i = 0; i < linePositions.Count; i++)
{
if (linePositions[i].Contains(e.Location))
{
label1.Text = "Index: " + (i+characterCount);
}
}
characterCount += linePositions.Count;
}
}