WPF richTextBox问题

发布于 2024-07-08 13:00:29 字数 355 浏览 6 评论 0原文

如果一行文本换行到另一行,如何以编程方式确定字符串中的断点。

示例:输入字符串 =“这是对文本换行行的测试”。

      Based on the width of the richTextBox it could display:


            This is a test of a wrapped line of
            text.

我需要确定的是被换行的单词行中的偏移量。 在上面的例子中,单词“text”。

当我从 richTextBox 中提取 Xaml 时,我得到了原始文本。

谢谢,

鲍勃·克林格

If a line of text is wrapped to an additional line, how do I determine programmatically the point in the string where it was broken.

Example: Input string = "This is a test of a wrapped line of text".

      Based on the width of the richTextBox it could display:


            This is a test of a wrapped line of
            text.

What I need to determine is offset in the line of the word(s) that got wrapped. In the above case the word "text".

When I extract the Xaml from the richTextBox, I get the original text unwrapped.

Thanks,

Bob Kerlinger

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

别把无礼当个性 2024-07-15 13:00:29

我发现的技巧使用 TextPointer 类及其 GetCharacterRec 方法。

RichTextBox 保存一个 FlowDocument。 流文档中的文本包含在 Run 对象中(有点简化,但它有效)。 该代码在第一次运行开始时找到 TextPointer。 然后它获取第一个字符的边界矩形。 接下来,代码一次向前移动一个字符,获取一个新的边界矩形,并检查新矩形的底部是否与原始矩形不同。 如果底部不同,那么我们就在一条新线上。 然后,TextPointer 可以获取中断之前或之后的文本。

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void inspect(object sender, RoutedEventArgs e)
    {
        TextPointer pointer = FindRun(inBox.Document);

        string textAfterBreak = FindBreak(pointer);

        outBox.Text = textAfterBreak;
    }

    private string FindBreak(TextPointer pointer)
    {
        Rect rectAtStart = pointer.GetCharacterRect(LogicalDirection.Forward);

        pointer = pointer.GetNextInsertionPosition(LogicalDirection.Forward);
        Rect currentRect = pointer.GetCharacterRect(LogicalDirection.Forward);

        while (currentRect.Bottom == rectAtStart.Bottom)
        {
            pointer = pointer.GetNextInsertionPosition(LogicalDirection.Forward);
            currentRect = pointer.GetCharacterRect(LogicalDirection.Forward);
        }

        string textBeforeBreak = pointer.GetTextInRun(LogicalDirection.Backward);
        string textAfterBreak = pointer.GetTextInRun(LogicalDirection.Forward);

        return textAfterBreak;
    }

    private TextPointer FindRun(FlowDocument document)
    {
        TextPointer position = document.ContentStart;

        while (position != null)
        {
            if (position.Parent is Run)
                break;

            position = position.GetNextContextPosition(LogicalDirection.Forward);
        }

        return position;
    }
}

<Window x:Class="LineBreaker.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <RichTextBox Grid.Row="0" Name="inBox">
        </RichTextBox>
        <Button Grid.Row="1" Click="inspect">Find Break</Button>
        <TextBox Name="outBox" Grid.Row="2"/>
    </Grid>
</Window>

The trick I found uses the TextPointer class and its GetCharacterRec method.

RichTextBox holds a FlowDocument. Text in flow documents is contained in a Run object (bit of a simplification, but it works). The code finds the TextPointer at the start of the first Run. It then gets the bounding rectangle of that first character. Next the code walks forward one character at a time, gets a new bounding rectangle and checks if the bottom of the new rectangle is different from the original rectangle. If the bottom is different then we are on a new line. TextPointer can then get the text either before or after the break.

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void inspect(object sender, RoutedEventArgs e)
    {
        TextPointer pointer = FindRun(inBox.Document);

        string textAfterBreak = FindBreak(pointer);

        outBox.Text = textAfterBreak;
    }

    private string FindBreak(TextPointer pointer)
    {
        Rect rectAtStart = pointer.GetCharacterRect(LogicalDirection.Forward);

        pointer = pointer.GetNextInsertionPosition(LogicalDirection.Forward);
        Rect currentRect = pointer.GetCharacterRect(LogicalDirection.Forward);

        while (currentRect.Bottom == rectAtStart.Bottom)
        {
            pointer = pointer.GetNextInsertionPosition(LogicalDirection.Forward);
            currentRect = pointer.GetCharacterRect(LogicalDirection.Forward);
        }

        string textBeforeBreak = pointer.GetTextInRun(LogicalDirection.Backward);
        string textAfterBreak = pointer.GetTextInRun(LogicalDirection.Forward);

        return textAfterBreak;
    }

    private TextPointer FindRun(FlowDocument document)
    {
        TextPointer position = document.ContentStart;

        while (position != null)
        {
            if (position.Parent is Run)
                break;

            position = position.GetNextContextPosition(LogicalDirection.Forward);
        }

        return position;
    }
}

<Window x:Class="LineBreaker.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <RichTextBox Grid.Row="0" Name="inBox">
        </RichTextBox>
        <Button Grid.Row="1" Click="inspect">Find Break</Button>
        <TextBox Name="outBox" Grid.Row="2"/>
    </Grid>
</Window>
橘亓 2024-07-15 13:00:29

http://msdn.microsoft.com/ en-us/library/system.windows.documents.textpointer.getlinestartposition.aspx

TextPointer startOfFirstLine = richTextBox.Document.ContentStart;
TextPointer startOfNextLine = startOfFirstLine.GetLineStartPosition(1);
if(startOfNextLine != null)
{
     // At this point what you do with the TextPointer depends on what you define as the position of text.
     // If you want to find out how many characters are on the first line ...
    int firstLineCharacterCount = new TextRange(startOfFirstLine, startOfNextLine).Text.Length;
}

http://msdn.microsoft.com/en-us/library/system.windows.documents.textpointer.getlinestartposition.aspx

TextPointer startOfFirstLine = richTextBox.Document.ContentStart;
TextPointer startOfNextLine = startOfFirstLine.GetLineStartPosition(1);
if(startOfNextLine != null)
{
     // At this point what you do with the TextPointer depends on what you define as the position of text.
     // If you want to find out how many characters are on the first line ...
    int firstLineCharacterCount = new TextRange(startOfFirstLine, startOfNextLine).Text.Length;
}
你げ笑在眉眼 2024-07-15 13:00:29

startOfFirstLine.GetLineStartPosition(1) 返回 null

But startOfFirstLine.GetLineStartPosition(1) returns null

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文