更改任何一个元素时,如何维护RichText格式(粗体/斜体/等)?

时间:2011-03-16 13:22:34

标签: c# .net winforms richtextbox

我有一个富文本框,其中可能包含一个字符串,其中包含粗体,斜体或甚至不同的字体和大小的元素。如果我选择整个字符串,包括所有差异,我如何“加粗”该字符串而不将整个字符串转换为只有“粗体”属性的通用字体?

例如:我想将“此 text”变为“ text

请注意,“有些”仍然是斜体,“text”仍然是不同的字体。

我目前所拥有的是相当简单的:

private void tsBold_Click(object sender, EventArgs e)
{
    if (rtb.SelectionFont == null) return;

    Font f;

    if (tsBold.Checked)
        f = new Font(rtb.SelectionFont, FontStyle.Bold);
    else
        f = new Font(rtb.SelectionFont, FontStyle.Regular);

    rtb.SelectionFont = f;

    rtb.Focus();
}

当然,这将使用与整个选择完全相同的字体。有没有办法只将“粗体”附加到现有字体?

ANSWER 虽然下面的“官方”答案只是冰山一角,但正是我需要朝着正确的方向努力。谢谢你的提示。

这是我的官方修正案:

我将它添加到我的RichTextBox对象:

    /// <summary>
    ///     Change the richtextbox style for the current selection
    /// </summary>
    public void ChangeFontStyle(FontStyle style, bool add)
    {
        //This method should handle cases that occur when multiple fonts/styles are selected
        // Parameters:-
        //  style - eg FontStyle.Bold
        //  add - IF true then add else remove

        // throw error if style isn't: bold, italic, strikeout or underline
        if (style != FontStyle.Bold
            && style != FontStyle.Italic
            && style != FontStyle.Strikeout
            && style != FontStyle.Underline)
            throw new System.InvalidProgramException("Invalid style parameter to ChangeFontStyle");

        int rtb1start = this.SelectionStart;
        int len = this.SelectionLength;
        int rtbTempStart = 0;

        //if len <= 1 and there is a selection font then just handle and return
        if (len <= 1 && this.SelectionFont != null)
        {
            //add or remove style 
            if (add)
                this.SelectionFont = new Font(this.SelectionFont, this.SelectionFont.Style | style);
            else
                this.SelectionFont = new Font(this.SelectionFont, this.SelectionFont.Style & ~style);

            return;
        }

        using (EnhancedRichTextBox rtbTemp = new EnhancedRichTextBox())
        {
            // Step through the selected text one char at a time    
            rtbTemp.Rtf = this.SelectedRtf;
            for (int i = 0; i < len; ++i)
            {
                rtbTemp.Select(rtbTempStart + i, 1);

                //add or remove style 
                if (add)
                    rtbTemp.SelectionFont = new Font(rtbTemp.SelectionFont, rtbTemp.SelectionFont.Style | style);
                else
                    rtbTemp.SelectionFont = new Font(rtbTemp.SelectionFont, rtbTemp.SelectionFont.Style & ~style);
            }

            // Replace & reselect
            rtbTemp.Select(rtbTempStart, len);
            this.SelectedRtf = rtbTemp.SelectedRtf;
            this.Select(rtb1start, len);
        }
        return;
    }

然后我更改了click方法以使用以下模式:

    private void tsBold_Click(object sender, EventArgs e)
    {
        enhancedRichTextBox1.ChangeFontStyle(FontStyle.Bold, tsBold.Checked);

        enhancedRichTextBox1.Focus();
    }

5 个答案:

答案 0 :(得分:6)

RTB 支持这一点。您甚至无法发现选择中具有相同字体样式的字符范围。首先检查SelectionFont属性,如果选择包含混合样式,则它将为null。如果是这种情况,则必须通过设置SelectionStart和SelectionLength属性一次迭代选择一个字符,读取SelectionFont直到它发生更改。将更改的字体应用于您发现的范围。

检查this answer以确保快速无闪烁的方法。

请注意,使用RTB实现编辑器是codeproject.com上最喜欢的主题。借用代码,如果不是整个项目,是减轻痛苦的好方法。

答案 1 :(得分:2)

要在保持格式完整的同时使文本选择为粗体,请使用:

if (rtb.SelectionFont !=null)
    rtb.SelectionFont = new Font(rtb.SelectionFont, rtb.SelectionFont.Style | FontStyle.Bold);

要在保持格式完整的同时取消选中文本,请使用:

if (rtb.SelectionFont !=null)
    rtb.SelectionFont = new Font(rtb.SelectionFont, rtb.SelectionFont.Style & ~FontStyle.Bold);

请注意,只有所有选定的文本具有相同的格式(字体大小,样式等),上述代码才有效。这是通过首先检查SelectionFont属性来检测的,如果选择包含样式的混合,它将为null。

现在使用richtextbox中的所有文本执行此操作,

现在要对richtextbox的整个文本进行粗体/非拼接,同时保持其他格式不变,您需要遍历richtextbox的所有字符并逐个应用Bold / unBold。这是完整的代码:

private void tsBold_Click(object sender, EventArgs e)
{
    //Loop through all the characters of richtextbox
    for (int i = 0; i < rtb.TextLength; i++)
    {
        //Select current character
        rtb.Select(i, 1);

        if (tsBold.Checked)
            //Make the selected character Bold
            rtb.SelectionFont = new Font(rtb.SelectionFont, rtb.SelectionFont.Style | FontStyle.Bold);
        else
            //Make the selected character unBold
            rtb.SelectionFont = new Font(rtb.SelectionFont, rtb.SelectionFont.Style & ~FontStyle.Bold);
    }
}

如果您需要切换Bold的现有状态(即将非粗体文本粗体化并使粗体文本为unBold),请改用:

        if (rtb.SelectionFont.Style.ToString().Contains("Bold")) //If the selected character is Bold
            //Make the selected character unBold
            rtb.SelectionFont = new Font(rtb.SelectionFont, rtb.SelectionFont.Style & ~FontStyle.Bold);
        else //If the selected character is unBold
            //Make the selected character Bold
            rtb.SelectionFont = new Font(rtb.SelectionFont, rtb.SelectionFont.Style | FontStyle.Bold);

答案 2 :(得分:0)

如果您还想更改其字体系列和字体大小,可以使用此方法: 汉斯是对的,你必须迭代每个角色。

  private void ChangeFontStyleForSelectedText(string familyName, float? emSize, FontStyle? fontStyle, bool? enableFontStyle)
    {
        _maskChanges = true;
        try
        {
            int txtStartPosition = txtFunctionality.SelectionStart;
            int selectionLength = txtFunctionality.SelectionLength;
            if (selectionLength > 0)
                using (RichTextBox txtTemp = new RichTextBox())
                {
                    txtTemp.Rtf = txtFunctionality.SelectedRtf;
                    for (int i = 0; i < selectionLength; ++i)
                    {
                        txtTemp.Select(i, 1);
                        txtTemp.SelectionFont = RenderFont(txtTemp.SelectionFont, familyName, emSize, fontStyle, enableFontStyle);
                    }

                    txtTemp.Select(0, selectionLength);
                    txtFunctionality.SelectedRtf = txtTemp.SelectedRtf;
                    txtFunctionality.Select(txtStartPosition, selectionLength);
                }
        }
        finally
        {
            _maskChanges = false;
        }
    }

      /// <summary>
    /// Changes a font from originalFont appending other properties
    /// </summary>
    /// <param name="originalFont">Original font of text</param>
    /// <param name="familyName">Target family name</param>
    /// <param name="emSize">Target text Size</param>
    /// <param name="fontStyle">Target font style</param>
    /// <param name="enableFontStyle">true when enable false when disable</param>
    /// <returns>A new font with all provided properties added/removed to original font</returns>
    private Font RenderFont(Font originalFont, string familyName, float? emSize, FontStyle? fontStyle, bool? enableFontStyle)
    {
        if (fontStyle.HasValue && fontStyle != FontStyle.Regular && fontStyle != FontStyle.Bold && fontStyle != FontStyle.Italic && fontStyle != FontStyle.Underline)
            throw new System.InvalidProgramException("Invalid style parameter to ChangeFontStyleForSelectedText");

        Font newFont;
        FontStyle? newStyle = null;
        if (fontStyle.HasValue)
        {
            if (fontStyle.HasValue && fontStyle == FontStyle.Regular)
                newStyle = fontStyle.Value;
            else if (originalFont != null && enableFontStyle.HasValue && enableFontStyle.Value)
                newStyle = originalFont.Style | fontStyle.Value;
            else
                newStyle = originalFont.Style & ~fontStyle.Value;
        }

        newFont = new Font(!string.IsNullOrEmpty(familyName) ? familyName : originalFont.FontFamily.Name,
                            emSize.HasValue ? emSize.Value : originalFont.Size,
                            newStyle.HasValue ? newStyle.Value : originalFont.Style);
        return newFont;
    }

有关更多说明,请访问:http://how-to-code-net.blogspot.ro/2014/01/how-to-make-custom-richtextbox-control.html

答案 3 :(得分:0)

我还没有根据消耗更多内存的Font对象引用来测试它

这应该有效

        if(rtbCaseContent.SelectedText.Length > 0 ) 
        {
            // calculate font style 
            FontStyle style = FontStyle.Underline;
            Font selectedFont = rtbCaseContent.SelectionFont;

            if (rtbCaseContent.SelectionFont.Bold == true)
            {
                style |= FontStyle.Bold;
            }
            if (rtbCaseContent.SelectionFont.Italic == true)
            {
                style |= FontStyle.Italic;
            }

            rtbCaseContent.SelectionFont = new Font(selectedFont,style);
        }           

答案 4 :(得分:0)

如果要在同一文本上应用更多FontStyle,可以使用按位运算符|和〜 |添加新样式并删除现有样式 例如

Font aFont=new Font(aPrototypeFont, anotherFont.Style | FontStyle.Bold);