简体   繁体   中英

How to obtain the character bounds of a right-jagged inline element of a TextBlock (WPF C#)?

I have not been able to find an answer to this. I am using a TextBlock that is being displayed within a scrollviewer. TextWrapping is set to wrap:

 <ScrollViewer VerticalScrollBarVisibility="Auto" 
  Width="{Binding Parent.ActualWidth, Mode=OneWay, RelativeSource={RelativeSource Self}}"
  Height="{Binding Parent.ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Self}}" 
  Name="theScrollViewer">

      <Grid Background="White" >
      <wc:CustomTextBlock  
             InLineText="{Binding Text, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" 
             TextWrapping="Wrap"
             WordPad="{Binding WordPad, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}"
                    />

The TextBlock is populated by inline elements, each element holding one logical word as defined by:

  Regex.Split(text, @"(\s+)")

Now, in the MouseEnter event for the Inline elements, I am tyring to create a bounding rectangle with:

    static void inline_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
    {
        Run Sender = sender as Run;
        TextPointer tp0 = Sender.ContentStart;
        TextPointer tp1 = Sender.ContentEnd;

        Rect StartRect = tp0.GetCharacterRect(LogicalDirection.Forward);
        Rect EndRect = tp1.GetCharacterRect(LogicalDirection.Backward);
        StartRect.Union(EndRect);

  .........................
    }

THIS CLEARLY FAILS when the inline element is wrapped to the next row of the TextBlock.

How can the displayed position of an inline element be found when it is "wrapped" to the next row. I am looking for a way to produce two rectangles:

  1. rectangle around the first part of the inline at the end of the row,

  2. rectangle around the ending part of the inline at the start of the next row.

Any help with this is most appreciated as I am new to flowdocuments. Thanks.

Being a newbie to this, it would sure be nice to have a guru comment. In the meantime, I found this to work correctly in my situation:

 static void inline_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
    {
        Run Sender = sender as Run;
        TextPointer tp0 = Sender.ElementStart;
        TextPointer tp1 = Sender.ElementEnd;

        Rect r0 = tp0.GetCharacterRect(LogicalDirection.Forward);
        Rect r1 = tp1.GetCharacterRect(LogicalDirection.Backward);


        if (r1.Top != r0.Top)
        {
            /* this inline element spans two physical rows */
            Rect StartRect0 = r0;
            Rect EndRect0 = tp1.GetLineStartPosition(0).GetCharacterRect(LogicalDirection.Backward);
            StartRect0.Union(EndRect0);


            Rect StartRect1 = new Rect(0, r1.Top, 0, r1.Height);
            Rect EndRect1 = r1;
            StartRect1.Union(EndRect1);

        }
        else
        {
            Rect StartRect0 = tp0.GetCharacterRect(LogicalDirection.Forward);
            Rect EndRect0 = tp1.GetCharacterRect(LogicalDirection.Backward);
            StartRect0.Union(EndRect0);

        }

    }

Hope this helps somebody.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM