Cambiar fuente para richtextbox sin perder formato

¿Cómo cambiar la fuente de todos los contenidos de un richtextbox sin perder el formato?

Estoy tratando de usar

rtb.SelectAll(); rtb.SelectionFont = new Font(fontName,...); 

pero el constructor de la fuente debe tomar, además del tipo de fuente, el estilo de la fuente (negrita, cursiva, …) o el tamaño de la fuente. Así que usar esto cambiaría el estilo / tamaño de todo el contenido de richtextbox.

Por supuesto, lo mismo se aplica a cualquier selección en richtextbox.

Este es un RichTextBox que he usado en el pasado. Está empalmado a partir del código que se encuentra aquí en Stack Overflow y en Internet en general:

 public class RichBox : RichTextBox { private const UInt32 CFM_BOLD = 0x00000001; private const UInt32 CFM_ITALIC = 0x00000002; private const UInt32 CFM_UNDERLINE = 0x00000004; private const UInt32 CFM_STRIKE = 0x00000008; private const UInt32 CFM_FACE = 0x20000000; private const UInt32 CFM_SIZE = 0x80000000; private const int WM_PAINT = 0xF; private const int WM_SETREDRAW = 0xB; private const int WM_USER = 0x400; private const int EM_SETCHARFORMAT = (WM_USER + 68); private const int SCF_SELECTION = 0x0001; private const int EM_GETEVENTMASK = WM_USER + 59; private const int EM_SETEVENTMASK = WM_USER + 69; private const int EM_GETSCROLLPOS = WM_USER + 221; private const int EM_SETSCROLLPOS = WM_USER + 222; [StructLayout(LayoutKind.Sequential)] private struct CHARFORMAT { public int cbSize; public uint dwMask; public uint dwEffects; public int yHeight; public int yOffset; public int crTextColor; public byte bCharSet; public byte bPitchAndFamily; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public char[] szFaceName; public short wWeight; public short sSpacing; public int crBackColor; public int LCID; public uint dwReserved; public short sStyle; public short wKerning; public byte bUnderlineType; public byte bAnimation; public byte bRevAuthor; } [DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern IntPtr LoadLibrary(string lpFileName); [DllImport("user32", CharSet = CharSet.Auto)] private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref CHARFORMAT lParam); [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, ref Point lParam); [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, IntPtr lParam); private bool frozen = false; private Point lastScroll = Point.Empty; private IntPtr lastEvent = IntPtr.Zero; private int lastIndex = 0; private int lastWidth = 0; protected override CreateParams CreateParams { get { var cp = base.CreateParams; if (LoadLibrary("msftedit.dll") != IntPtr.Zero) { cp.ClassName = "RICHEDIT50W"; } return cp; } } [Browsable(false)] [DefaultValue(typeof(bool), "False")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool FreezeDrawing { get { return frozen; } set { if (value != frozen) { frozen = value; if (frozen) { this.SuspendLayout(); SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero); SendMessage(this.Handle, EM_GETSCROLLPOS, 0, ref lastScroll); lastEvent = SendMessage(this.Handle, EM_GETEVENTMASK, 0, IntPtr.Zero); lastIndex = this.SelectionStart; lastWidth = this.SelectionLength; } else { this.Select(lastIndex, lastWidth); SendMessage(this.Handle, EM_SETEVENTMASK, 0, lastEvent); SendMessage(this.Handle, EM_SETSCROLLPOS, 0, ref lastScroll); SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero); this.Invalidate(); this.ResumeLayout(); } } } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Font CurrentFont { get { Font result = this.Font; if (this.SelectionLength == 0) { result = SelectionFont; } else { using (RichBox rb = new RichBox()) { rb.FreezeDrawing = true; rb.SelectAll(); rb.SelectedRtf = this.SelectedRtf; rb.Select(0, 1); result = rb.SelectionFont; } } return result; } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string SelectionFontName { get { return CurrentFont.FontFamily.Name; } set { CHARFORMAT cf = new CHARFORMAT(); cf.cbSize = Marshal.SizeOf(cf); cf.szFaceName = new char[32]; cf.dwMask = CFM_FACE; value.CopyTo(0, cf.szFaceName, 0, Math.Min(31, value.Length)); IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf)); Marshal.StructureToPtr(cf, lParam, false); SendMessage(this.Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam); } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public float SelectionFontSize { get { return CurrentFont.Size; } set { CHARFORMAT cf = new CHARFORMAT(); cf.cbSize = Marshal.SizeOf(cf); cf.dwMask = CFM_SIZE; cf.yHeight = Convert.ToInt32(value * 20); IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf)); Marshal.StructureToPtr(cf, lParam, false); SendMessage(this.Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam); } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool SelectionBold { get { return CurrentFont.Bold; } set { CHARFORMAT cf = new CHARFORMAT(); cf.cbSize = Marshal.SizeOf(cf); cf.dwMask = CFM_BOLD; cf.dwEffects = value ? CFM_BOLD : 0; IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf)); Marshal.StructureToPtr(cf, lParam, false); SendMessage(this.Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam); } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool SelectionItalic { get { return CurrentFont.Italic; } set { CHARFORMAT cf = new CHARFORMAT(); cf.cbSize = Marshal.SizeOf(cf); cf.dwMask = CFM_ITALIC; cf.dwEffects = value ? CFM_ITALIC : 0; IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf)); Marshal.StructureToPtr(cf, lParam, false); SendMessage(this.Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam); } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool SelectionStrikeout { get { return CurrentFont.Strikeout; } set { CHARFORMAT cf = new CHARFORMAT(); cf.cbSize = Marshal.SizeOf(cf); cf.dwMask = CFM_STRIKE; cf.dwEffects = value ? CFM_STRIKE : 0; IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf)); Marshal.StructureToPtr(cf, lParam, false); SendMessage(this.Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam); } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool SelectionUnderline { get { return CurrentFont.Underline; } set { CHARFORMAT cf = new CHARFORMAT(); cf.cbSize = Marshal.SizeOf(cf); cf.dwMask = CFM_UNDERLINE; cf.dwEffects = value ? CFM_UNDERLINE : 0; IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf)); Marshal.StructureToPtr(cf, lParam, false); SendMessage(this.Handle, EM_SETCHARFORMAT, SCF_SELECTION, lParam); } } } 

Agrega nuevas propiedades como SelectionBold, SelectionItalic, etc. donde puede aplicar el atributo y no perder el otro formato del texto.

Puede pasar el nuevo nombre de fuente mientras mantiene intactos otros valores utilizando las propiedades de fuente richtextbox existentes. Para cambiar solo el nombre de la fuente de un texto seleccionado, debe hacer:

 if (rtb.SelectionFont !=null) rtb.SelectionFont = new Font(fontName, rtb.SelectionFont.Size, rtb.SelectionFont.Style); 

Tenga en cuenta que el código anterior solo funcionará si todo el texto seleccionado tiene el 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 cambiar el nombre de la fuente de todos los contenidos de richtextbox y mantener intactos otros formatos, debe recorrer todos los caracteres de richtextbox y aplicar el nombre de la fuente uno por uno.

 for (int i = 0; i < rtb.TextLength; i++) { rtb.Select(i, 1); rtb.SelectionFont = new Font(fontName, rtb.SelectionFont.Size, rtb.SelectionFont.Style); } 

Puede pasar nuevos valores para cualquier parámetro que desee y usar las propiedades rtb para conservar otros valores. Por ejemplo, si desea cambiar la font family pero desea conservar el font size la font size , esto es lo que haría:

 rtb.SelectionFont = new Font(fontName, rtb.Font.Size); 

Esto cambiará la familia SelectionFont a fontName pero conservará el tamaño de la fuente. Puede seguir el mismo patrón para otras sobrecargas.

 Private Sub changeFont(ByVal fontz As FontStyle, getStr As RichTextBox) Dim currentFont As System.Drawing.Font = txt.SelectionFont Dim newFontStyle As System.Drawing.FontStyle newFontStyle = fontz getStr.SelectionFont = New Font(currentFont.FontFamily, currentFont.Size, newFontStyle) End Sub 

Esto cambiará la propiedad de la fuente del texto seleccionado.
Muestra:

 changeFont(FontStyle.Italic, [textbox_name])