微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尝试创建行为类似于VS编辑器窗口的WPF窗口

如何解决尝试创建行为类似于VS编辑器窗口的WPF窗口

我使用了CodeProject中的CodeBox项目,除了不能禁用自动换行外,它的效果非常好。在普通的TextBox中,只需将textwrapping属性设置为Nowrap即可达到目的,但对于CodeBox(它是从代码隐藏的TextBox继承的)中却没有。我尝试添加水平滚动条,但这无济于事。滚动条是可见的,并且它更改了拖动按钮的大小,以表明它看到展开的文本比查看区域宽,但是由于该文本已经被包裹了,因此拖动没有任何区别。

我已将问题跟踪到OnRender中的一行:

“ formattedText.MaxTextWidth = this.ViewportWidth; //滚动条的空间”

我对WPF还是很陌生,它对我来说仍然是很多神秘的事物,因此对于有更多经验的人来说,解决方案可能是显而易见的。

任何建议,我将不胜感激。这是C#背后的代码,很长,但已被精简为仅显示出正在发生的事情。其余的(已被删除)只是可以使文本着色更多的代码

public partial class CodeBox : TextBox
{
    bool m_bScrollingEventEnabled;

    SolidColorBrush m_brRed      = new SolidColorBrush (Colors.Red);
    SolidColorBrush m_brorange   = new SolidColorBrush (Colors.Orange);
    SolidColorBrush m_brBlack    = new SolidColorBrush (Colors.Black);

    public CodeBox ()
    {
        this.TextChanged += new TextChangedEventHandler (txtTest_TextChanged);
        this.Foreground = new SolidColorBrush (Colors.Transparent);
        this.Background = new SolidColorBrush (Colors.Transparent);
        this.textwrapping = System.Windows.textwrapping.Nowrap;
        base.textwrapping = System.Windows.textwrapping.Nowrap;
        InitializeComponent ();
    }

    public static DependencyProperty BaseForegroundProperty = DependencyProperty.Register ("BaseForeground",typeof (Brush),typeof (CodeBox),new FrameworkPropertyMetadata (new SolidColorBrush (Colors.Black),FrameworkPropertyMetadataOptions.AffectsRender));

    public Brush BaseForeground
    {
        get { return (Brush)GetValue (BaseForegroundProperty); }
        set { SetValue (BaseForegroundProperty,value); }
    }

    public static DependencyProperty BaseBackgroundProperty = DependencyProperty.Register ("BaseBackground",FrameworkPropertyMetadataOptions.AffectsRender));

    public Brush BaseBackground
    {
        get { return (Brush)GetValue (BaseBackgroundProperty); }
        set { SetValue (BaseBackgroundProperty,value); }
    }

    void txtTest_TextChanged (object sender,TextChangedEventArgs e)
    {
        this.InvalidateVisual ();
    }

    protected override void OnRender (System.Windows.Media.DrawingContext drawingContext)
    {
        //base.OnRender(drawingContext);
        if (this.Text.Length > 0)
        {
            EnsureScrolling ();
            FormattedText formattedText = new FormattedText (
                this.Text,CultureInfo.GetCultureInfo ("en-us"),FlowDirection.LeftToRight,new Typeface (this.FontFamily.source),this.FontSize,BaseForeground);  //Text that matches the textBox's
            double leftMargin = 4.0 + this.BorderThickness.Left;
            double topMargin = 2 + this.BorderThickness.Top;
            ***formattedText.MaxTextWidth = this.ViewportWidth; // space for scrollbar***
            formattedText.MaxTextHeight = Math.Max (this.ActualHeight + this.VerticalOffset,0); //Adjust for scrolling
            drawingContext.PushClip (new RectangleGeometry (new Rect (0,this.ActualWidth,this.ActualHeight)));//restrict text to textBox

            int iStartVisibleLine = GetFirstVisibleLineIndex ();
            int iEndVisibleLine = GetLastVisibleLineIndex ();
            for (int iIdx = iStartVisibleLine; iIdx <= iEndVisibleLine - 1; ++iIdx)
            {
                // Text coloring
                int iOffset = GetCharacterIndexFromLineIndex (iIdx);
                int iOffsetNext = GetCharacterIndexFromLineIndex (iIdx + 1);
                string strLine = Text.Substring (iOffset,iOffsetNext - iOffset);
            }

            drawingContext.DrawText (formattedText,new Point (leftMargin,topMargin - this.VerticalOffset));
        }
    }

    private void EnsureScrolling ()
    {
        if (!m_bScrollingEventEnabled)
        {
            DependencyObject dp = VisualTreeHelper.GetChild (this,0);
            ScrollViewer sv = VisualTreeHelper.GetChild (dp,0) as ScrollViewer;
            sv.ScrollChanged += new ScrollChangedEventHandler (ScrollChanged);
            m_bScrollingEventEnabled = true;
        }
    }

    private void ScrollChanged (object sender,ScrollChangedEventArgs e)
    {
        this.InvalidateVisual ();
    }
}

该项目的xaml:

<TextBox x:Class="CodeBoxControl.CodeBox"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:c="clr-namespace:CodeBoxControl">
<TextBox.Template>
    <ControlTemplate targettype="c:CodeBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Border BorderThickness="{TemplateBinding Border.BorderThickness}" BorderBrush="{TemplateBinding Border.BorderBrush}"
            Background="{TemplateBinding Panel.Background}" Name="Bd" SnapsToDevicePixels="True">
            <ScrollViewer Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="UIElement.IsEnabled">
                <Setter Property="Panel.Background" TargetName="Bd">
                    <Setter.Value>
                        <DynamicResource ResourceKey="{x:Static SystemColors.ControlBrushKey}" />
                    </Setter.Value>
                </Setter>
                <Setter Property="TextElement.Foreground">
                    <Setter.Value>
                        <DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
                    </Setter.Value>
                </Setter>
                <Trigger.Value>
                    <s:Boolean>False</s:Boolean>
                </Trigger.Value>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
</TextBox.Template>

使用CodeBox代码的父窗口中的Xaml:

<c:CodeBox Name="disassemblyOutput"
                 FontFamily="Courier New"
                 FontSize="20"
                 VerticalScrollBarVisibility="Auto"
                 HorizontalScrollBarVisibility="Auto"
                 BaseForeground="Black"
                 Margin="4,4,4"
                 Background="#CEE9C9"
                 Foreground="magenta"
                 textwrapping="Nowrap"
                 AutoWordSelection="False"/>

这是将文本加载到CodeBox窗口中的代码示例:

private void OnLoadDASM (object sender,RoutedEventArgs e)
{
    disassemblyOutput.FontSize = 12;
    disassemblyOutput.Clear ();
    disassemblyOutput.m_eWindowData = CodeBox.EWindowData.EDasm;

    disassemblyOutput.Background = new SolidColorBrush (Colors.Transparent);//Color.Fromrgb (0xCE,0xE9,0xC9));
    disassemblyOutput.Foreground = new SolidColorBrush (Colors.Transparent);
    disassemblyOutput.BaseBackground = new SolidColorBrush (Color.Fromrgb (0xCE,0xC9));
    disassemblyOutput.BaseForeground = new SolidColorBrush (Colors.Transparent);

    disassemblyOutput.textwrapping = textwrapping.Nowrap;

    disassemblyOutput.Text += "Loop_02_0A0F  0A0F: SIO   F3 10 28                 5475 Keyboard  Set Error Indicator  Restore Data Key              " + Environment.NewLine;
    disassemblyOutput.Text += "                                                   disable Interrupt                                                 " + Environment.NewLine;
    disassemblyOutput.Text += "              0A12: SNS   70 12 FF,1       0x0B0C  5475 Keyboard  2 sense bytes                                      " + Environment.NewLine;
}

这就是我想要的: https://i.stack.imgur.com/M4ts0.png 以及显示内容https://i.stack.imgur.com/gdBco.png

我还注意到,当文本换行并且使用垂直滚动条时,窗格顶部的文本消失了,向下滚动的次数越多,消失的越多: 1

解决方法

解决方法是将MaxTextWidth设置为行的宽度,而不是ViewportWidth属性:

iStartVisibleLine = GetFirstVisibleLineIndex ();
iEndVisibleLine   = GetLastVisibleLineIndex ();
iOffset           = GetCharacterIndexFromLineIndex (0);
iOffsetNext       = GetCharacterIndexFromLineIndex (1);
strLine           = Text.Substring (iOffset,iOffsetNext - iOffset);
geomFirstLine     = formattedText.BuildHighlightGeometry (new Point (leftMargin,topMargin - this.VerticalOffset),iOffset,strLine.Length);
rcBounds          = geomFirstLine.GetRenderBounds (null);
formattedText.MaxTextWidth = rcBounds.Width; // Space for scrollbar

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?