【问题标题】:How do I maintain RichText formatting (bold/italic/etc) when changing any one element?更改任何一个元素时如何保持 RichText 格式(粗体/斜体/等)?
【发布时间】:2011-07-16 14:29:50
【问题描述】:

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

例如:我想把“This is some text”变成“This is some text

请注意,“is some”仍然是斜体,“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();
}

当然,这会将完全相同的字体应用于整个选择。有什么方法可以将“粗体”附加到现有字体?

回答 虽然下面的“官方”答案只是冰山一角,但这是我在正确方向上需要的推动力。谢谢你的提示。

这是我的官方修复:

我将此添加到我的 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;
    }

然后我将点击方法更改为使用以下模式:

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

        enhancedRichTextBox1.Focus();
    }

【问题讨论】:

  • 为什么这在 WinForms 中这么难?在 Win32 级别,这是一个微不足道的 EM_SETCHARFORMAT。既然你手头有窗把手,你就不能那样做吗?
  • 请不要将答案发布为对您问题的更新。您可以自行回答自己的问题。此外,这样人们就可以为您的答案投票。

标签: c# .net winforms richtextbox


【解决方案1】:

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

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

【讨论】:

    【解决方案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 的所有字符并逐个应用加粗/取消加粗。完整代码如下:

    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);
        }
    }
    

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

            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);
    

    【讨论】:

      【解决方案3】:

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

      这应该可以工作

              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】:

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

          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

        【讨论】:

          【解决方案5】:

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

          查看this answer 以了解保持此过程相当快速且无闪烁的方法。

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

          【讨论】:

          • 为了保持我的“无闪烁”,我只使用了代码生成的 RTB 对象,然后在完成后更新主 RTB 中的结果。非常快,而且没有闪烁。
          • 不错的主意,但非常昂贵。您消耗的内存量增加了一倍。
          猜你喜欢
          • 1970-01-01
          • 2016-01-02
          • 1970-01-01
          • 1970-01-01
          • 2015-01-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多