1つのコメントがあなたに言ったように、これは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;
}
最後に
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 023456789asdjkhfkjasdhfklhasdlkfjhlasdkjhfasdlfhlasdc",
"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
イベント:
これは、文字列や店舗2つのライン内のすべての文字位置を描画する方法であり、
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;
}
}
可能な重複が[MeasureStringは常に空白が収まると思っ](http://stackoverflow.com/questions/40910320/measurestring-always-thinks-whitespace-will-fit) – pinkfloydx33
https://msdn.microsoft。 com/ru-ru/library/windows/desktop/dd144860(v = vs.85).aspx –
https://www.codeproject.com/tips/844745/analyzing-text-with-directwrite-in-net-using -sharp –