gpt4 book ai didi

c# - 使 FlowDocument 光标在 RichTextBox 中垂直居中

转载 作者:太空狗 更新时间:2023-10-29 21:51:33 24 4
gpt4 key购买 nike

我在弄清楚这个问题时遇到了一些麻烦,希望有人能提供帮助。

我有一个带有 RichTextBox 的 WPF 项目。

当我编辑文本时,我希望文档中的光标始终保持垂直居中。

例如,在编辑时向上或向下推,而不是光标向上,我希望文本向下。这应该会造成光标保持静止的印象。

非常感谢。

最佳答案

不确定这是否是您的想法,但这里有一个 RichTextBox 的概念证明,它使插入符号在用户放置它的位置居中(在框中单击)。

虽然正如 Omkar 所说,如果文档已滚动到开头或结尾,您需要添加空格,但您需要添加白色以允许文本滚动。

<RichTextBox HorizontalAlignment="Left" Height="311" VerticalAlignment="Top" Width="509" PreviewKeyDown="HandleKeyDownEvent">
<FlowDocument>
<Paragraph Margin="0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla turpis sem, tincidunt id vestibulum venenatis, fermentum eget orci. Donec mollis neque ac leo tincidunt tempus. Pellentesque mollis, nunc sit amet fermentum rutrum, lectus augue ultrices nibh, at lacinia est est ut justo. Cras non quam eu enim vulputate porttitor eu sit amet lectus. Suspendisse potenti. Maecenas metus nunc, dapibus id dapibus rhoncus, semper quis leo. Pellentesque eget risus magna, dignissim aliquam diam. Morbi.
</Paragraph>
</FlowDocument>
</RichTextBox>

在后面的代码中:

private void HandleKeyDownEvent(object sender, KeyEventArgs e)
{
RichTextBox rtb = sender as RichTextBox;
if (rtb != null)
{
//text to scroll up relative to caret
if (e.Key == Key.Down)
{
Block paragraph;

//get the whitespace paragraph at end of documnent
paragraph =
rtb.Document.Blocks
.Where(x => x.Name == "lastParagraph")
.FirstOrDefault();

// if there is no white space paragraph create it
if (paragraph == null)
{
paragraph = new Paragraph { Name = "lastParagraph", Margin = new Thickness(0) };

//add to the end of the document
rtb.Document.Blocks.InsertAfter(rtb.Document.Blocks.LastBlock, paragraph);
}

// if viewport larger than document, add whitespace content to fill view port
if (rtb.ExtentHeight < rtb.ViewportHeight)
{
Thickness margin = new Thickness() { Top = rtb.ViewportHeight - rtb.ExtentHeight };
margin.Bottom = rtb.ViewportHeight - rtb.ExtentHeight;
paragraph.Margin = margin;

}

// if the document has been scrolled to the end or doesn't fill the view port
if (rtb.VerticalOffset + rtb.ViewportHeight == rtb.ExtentHeight)
{
// and a line to the white paragraph
paragraph.ContentEnd.InsertLineBreak();
}

//move the text up relative to caret
rtb.LineDown();
}
// text is to scroll download relative to caret
if (e.Key == Key.Up)
{
// get whitespace at start of document
Block paragraph;
paragraph =
rtb.Document.Blocks
.Where(x => x.Name == "firstParagraph")
.FirstOrDefault();

//if whitespace paragraph is null append a new one
if (paragraph == null)
{
paragraph = new Paragraph { Name = "firstParagraph", Margin = new Thickness(0) };
rtb.Document.Blocks.InsertBefore(rtb.Document.Blocks.FirstBlock, paragraph);
}

// up document is at top add white space
if (rtb.VerticalOffset == 0.0)
{
paragraph.ContentStart.InsertLineBreak();
}

//move text one line down relative to caret
rtb.LineUp();
}
}
}

编辑:这种方法似乎有效。行高是根据一行行首与下一行行首的差来确定的,避免了换行影响偏移量的问题。

    <RichTextBox
PreviewKeyDown="PreviewKeyDownHandler">
<FlowDocument>
<!-- Place content here -->
</FlowDocument>
</RichTextBox>

在后面的代码中:

    private void PreviewKeyDownHandler(object sender, KeyEventArgs e)
{
RichTextBox rtb = sender as RichTextBox;
if (rtb != null)
{
if (e.Key == Key.Down)
{
// if there is another line below current
if (rtb.CaretPosition.GetLineStartPosition(0) != rtb.CaretPosition.GetLineStartPosition(1))
{
// find the FlowDocumentView through reflection
FrameworkElement flowDocumentView = GetFlowDocument(rtb);

// get the content bounds of the current line
Rect currentLineBounds = rtb.CaretPosition.GetCharacterRect(LogicalDirection.Forward);

// move the caret down to next line
EditingCommands.MoveDownByLine.Execute(null, rtb);

// get the content bounds of the new line
Rect nextLineBounds = rtb.CaretPosition.GetCharacterRect(LogicalDirection.Forward);

// get the offset the document
double currentDocumentOffset = flowDocumentView.Margin.Top;

// add the height of the previous line to the offset
// the character rect of a line doesn't include the baseline offset so the actual height of line has to be determined
// from the difference in the offset between the tops of the character rects of the consecutive lines
flowDocumentView.Margin = new Thickness { Top = currentDocumentOffset + currentLineBounds.Top - nextLineBounds.Top };
}

// prevent default behavior
e.Handled = true;
}
if (e.Key == Key.Up)
{
if (rtb.CaretPosition.GetLineStartPosition(0) != rtb.CaretPosition.GetLineStartPosition(-1))
{
FrameworkElement flowDocumentView = GetFlowDocument(rtb);

Rect currentLineBounds = rtb.CaretPosition.GetCharacterRect(LogicalDirection.Forward);

EditingCommands.MoveUpByLine.Execute(null, rtb);

Rect nextLineBounds = rtb.CaretPosition.GetCharacterRect(LogicalDirection.Forward);

double currentDocumentOffset = flowDocumentView.Margin.Top;

flowDocumentView.Margin = new Thickness { Top = currentDocumentOffset + currentLineBounds.Top - nextLineBounds.Top };
}

e.Handled = true;
}
}
}

protected FrameworkElement GetFlowDocument(RichTextBox textBox)
{
FrameworkElement flowDocumentVisual =
GetChildByTypeName(textBox, "FlowDocumentView") as FrameworkElement;

return flowDocumentVisual;
}

protected DependencyObject GetChildByTypeName(DependencyObject dependencyObject, string name)
{
if (dependencyObject.GetType().Name == name)
{
return dependencyObject;
}
else
{
if (VisualTreeHelper.GetChildrenCount(dependencyObject) > 0)
{
int childCount = VisualTreeHelper.GetChildrenCount(dependencyObject);

for (int idx = 0; idx < childCount; idx++)
{
var dp = GetChildByTypeName(VisualTreeHelper.GetChild(dependencyObject, idx), name);
if (dp != null)
return dp;
}

return null;
}
else
{
return null;
}
}
}

关于c# - 使 FlowDocument 光标在 RichTextBox 中垂直居中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9492528/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com