2011-03-16 12 views
11

Tengo un cuadro de texto enriquecido que puede contener una cadena que tiene elementos en negrita, cursiva o incluso fuentes y tamaños diferentes. Si selecciono la cadena completa, incluidas todas las diferencias, ¿cómo puedo "Negrita" esa cadena sin convertir toda la cadena a la fuente genérica con solo un atributo "negrita"?¿Cómo mantengo el formato de RichText (negrita/cursiva/etc.) al cambiar cualquier elemento?

Por ejemplo: Quiero convertir "Este es un poco detext" en "Este es un poco detext"

Tenga en cuenta que "es un poco de" permaneció en cursiva y "texto" seguía siendo una fuente diferente .

Lo que tengo actualmente es bastante simple:

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

Por supuesto, esto va a aplicar exactamente el mismo tipo de letra a toda la selección. ¿Hay alguna forma de agregar "negrita" a la (s) fuente (s) existente (s)?

RESPUESTA Mientras que el "oficial" respuesta a continuación es sólo la punta del iceberg, que fue el empujón que necesitaba en la dirección correcta. Gracias por el consejo.

aquí está mi solución oficial:

he añadido esto a mi RichTextBox objeto:

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

entonces he cambiado los métodos Haga clic para utilizar el siguiente patrón:

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

     enhancedRichTextBox1.Focus(); 
    } 
+0

Por qué es tan duro en Windows Forms? Es un ['EM_SETCHARFORMAT'] (http://msdn.microsoft.com/en-us/library/bb774230 (v = VS.85) .aspx trivial) en el nivel de Win32. Como tiene el asa de la ventana a mano, ¿no puede hacerlo de esa manera? –

Respuesta

6

RTB hace no apoya esto bien. Ni siquiera puede descubrir el rango de caracteres dentro de la selección que tiene el mismo estilo de fuente. Comience por verificar primero la propiedad SelectionFont, será nula si la selección contiene una combinación de estilos. Si ese es el caso, tendrá que repetir la selección de un carácter a la vez estableciendo las propiedades SelectionStart y SelectionLength, lea SelectionFont hasta que cambie. Aplica la fuente cambiada al rango que descubriste.

Comprueba this answer por una forma de mantener esto razonablemente rápido y sin parpadeos.

Tenga en cuenta que la implementación de un editor con RTB es un tema favorito en codeproject.com. El código de préstamo, si no el proyecto completo, es una buena manera de disminuir el dolor.

+0

Para mantener el mío "libre de parpadeos", acabo de utilizar un objeto RTB generado por código, luego actualicé los resultados en el RTB principal cuando lo hice. Muy rápido, y sin parpadeo. – Jerry

+0

No es una mala idea, muy cara. Estás doblando la cantidad de memoria que consumes. –

0

En caso de que desee cambiar también la familia de fuentes y el tamaño de fuente, puede utilizar este método: Hans tiene razón, debe iterar cada carácter.

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

Para más explicaciones se podía ir a: http://how-to-code-net.blogspot.ro/2014/01/how-to-make-custom-richtextbox-control.html

0

Estoy todavía a probarlo en términos de referencias a objetos de fuente que consumen más memoria embargo

Esto debería funcionar

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

Para hacer una selección de texto en negrita mientras se mantiene el formateo intacto, use esto:

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

Para la selección de texto sin negrita, manteniendo intacta su formato, utilice esto:

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

Tenga en cuenta que por encima de código sólo funcionará si todo el texto seleccionado tiene mismo formato (tamaño de fuente, estilo, etc.). Esto se detecta al verificar primero la propiedad SelectionFont, será nulo si la selección contiene una combinación de estilos.

ahora para hacer esto con todo el texto en RichTextBox,

ahora a Negrita/sin negrita todo el texto de RichTextBox, manteniendo otra modificación del formato, es necesario recorrer todos los caracteres de RichTextBox y aplicar Negrita/sin negrita uno a uno. Aquí está el código completo:

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

Si necesita cambiar el estado actual de Bold (es decir, hacer que el texto no en negrita y hacer el texto en negrita sin negrita), utilice en su lugar:

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

si desea aplicar más FontStyle en el mismo texto, puede usar operadores bit a bit | y ~ | añade un nuevo estilo y ~ elimina un estilo existente por ejemplo

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