RichTextBox放置在ViewBox内并缩放到10 - 1000%的各种级别.当百分比小于100%时,插入符号在随机光标位置消失.
我知道当视觉被缩小(压缩)时,它会丢失像素.有什么方法可以让我不再失去光标吗?
<Viewbox>
<RichTextBox Name="richTextBox1" Width="400" Height="400" />
</Viewbox>
Run Code Online (Sandbox Code Playgroud)
最终编辑:
嘿那里,只是想说,你甚至可以在没有反思的情况下工作!这不是优化的代码,我会留给你自己.这仍然依赖于内部的东西.所以它来了:
代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
rtb.LayoutUpdated += (sender, args) =>
{
var child = VisualTreeHelper.GetChild(vb, 0) as ContainerVisual;
var scale = child.Transform as ScaleTransform;
rtb.ScaleX = scale.ScaleX;
};
}
}
public class RTBwithVisibleCaret:RichTextBox
{
private UIElement _flowDocumentView;
private AdornerLayer _adornerLayer;
private UIElement _caretSubElement;
private ScaleTransform _scaleTransform;
public RTBwithVisibleCaret()
{
LayoutUpdated += (sender, args) =>
{
if (!IsKeyboardFocused) return;
if(_adornerLayer == null)
_adornerLayer = AdornerLayer.GetAdornerLayer(_flowDocumentView);
if (_adornerLayer == null || _flowDocumentView == null) return;
if(_scaleTransform != null && _caretSubElement!= null)
{
_scaleTransform.ScaleX = 1/ScaleX;
_adornerLayer.Update(_flowDocumentView);
}
else
{
var adorners = _adornerLayer.GetAdorners(_flowDocumentView);
if(adorners == null || adorners.Length<1) return;
var caret = adorners[0];
_caretSubElement = (UIElement) VisualTreeHelper.GetChild(caret, 0);
if(!(_caretSubElement.RenderTransform is ScaleTransform))
{
_scaleTransform = new ScaleTransform(1 / ScaleX, 1);
_caretSubElement.RenderTransform = _scaleTransform;
}
}
};
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var cthost = GetTemplateChild("PART_ContentHost") as FrameworkElement;
_flowDocumentView = cthost is ScrollViewer ? (UIElement)((ScrollViewer)cthost).Content : ((Decorator)cthost).Child;
}
public double ScaleX
{
get { return (double)GetValue(ScaleXProperty); }
set { SetValue(ScaleXProperty, value); }
}
public static readonly DependencyProperty ScaleXProperty =
DependencyProperty.Register("ScaleX", typeof(double), typeof(RTBwithVisibleCaret), new UIPropertyMetadata(1.0));
}
Run Code Online (Sandbox Code Playgroud)
使用此XAML:
<Window x:Class="RTBinViewBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:RTBinViewBoxTest="clr-namespace:RTBinViewBoxTest" Title="MainWindow" Height="350" Width="525">
<Viewbox Height="100" x:Name="vb">
<RTBinViewBoxTest:RTBwithVisibleCaret Width="70" x:Name="rtb">
<FlowDocument>
<Paragraph>
<Run>long long long long long long long long long long long long long long long long long long long long long long long long text</Run>
</Paragraph>
</FlowDocument>
</RTBinViewBoxTest:RTBwithVisibleCaret>
</Viewbox>
</Window>
Run Code Online (Sandbox Code Playgroud)
是的,它让我思考,当我看到,所有这些都可以通过视觉树访问!您可以遍历VisualTree来访问FlowDocumentView,而不是继承RichTextBox(获取TemplateChild所需).
原帖:
好吧,让我们来看看你的选择是什么:
正如我在上面的评论中所述:实现这一目标的最简单方法是让RichTextBox的内容缩放而不是ViewBox中的RichTextBox.如果这是一个选项,你还没有回答.
现在其他一切都会变得复杂,或多或少都有问题:
您可以使用Moq或类似的东西(想想Moles左右......)来替换SystemParameters.CaretWidth的getter 以适应ViewBox所施加的ScaleTransform.这有几个问题!第一:这些库设计用于测试场景,不建议用于生产用途.第二:您必须在RichTextBox实例化Caret之前设置该值.但这很难,因为您事先并不知道ViewBox如何缩放RichTextBox.所以,这不是一个好选择!
第二个(坏)选项是使用Reflection来获得这个漂亮的小类System.Windows.Documents.CaretElement.你可以通过RichTextBox.TextEditor.Selection.CaretElement(你必须使用Reflection,因为这些属性和类大部分都是internal sealed).由于这是一个Adorner,您可以在那里附加一个可以反转Scaling的ScaleTransform.我不得不说:这既不经过测试也没有推荐!
你的选择在这里是有限的,如果我是你,我会去我的第一个猜测!
编辑:
如果您真的想要了解第二条(不良)路线,那么如果您将ScaleTransform应用于您可以通过_caretElement类型的私有字段获得的单个子项,则可能会有更多运气CaretSubElement.如果我正确阅读该代码,那么该子元素就是您的实际Caret Visual.主要元素似乎用于绘制选择几何.如果你真的想这样做,那么在那里应用ScaleTransform.
编辑:
完整示例如下:
XAML:
<Window x:Class="RTBinViewBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Viewbox Height="100" x:Name="vb">
<RichTextBox Width="70" Name="rtb">
<FlowDocument>
<Paragraph>
<Run>long long long long long long long long long long long long long long long long long long long long long long long long text</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</Viewbox>
</Window>
Run Code Online (Sandbox Code Playgroud)
代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
rtb.GotFocus +=RtbOnGotFocus;
}
private void RtbOnGotFocus(object s, RoutedEventArgs routedEventArgs)
{
rtb.LayoutUpdated += (sender, args) =>
{
var child = VisualTreeHelper.GetChild(vb, 0) as ContainerVisual;
var scale = child.Transform as ScaleTransform;
rtb.Selection.GetType().GetMethod("System.Windows.Documents.ITextSelection.UpdateCaretAndHighlight", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(
rtb.Selection, null);
var caretElement=rtb.Selection.GetType().GetProperty("CaretElement", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(rtb.Selection, null);
if (caretElement == null)
return;
var caretSubElement = caretElement.GetType().GetField("_caretElement", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(caretElement) as UIElement;
if (caretSubElement == null) return;
var scaleTransform = new ScaleTransform(1/scale.ScaleX, 1);
caretSubElement.RenderTransform = scaleTransform;
};
}
}
Run Code Online (Sandbox Code Playgroud)
这对我有用.一切都说.
| 归档时间: |
|
| 查看次数: |
1712 次 |
| 最近记录: |