Comment définir la police de caractères RichTextBox.SelectionFont sans modifier le style?
-
06-07-2019 - |
Question
L’un des contrôles de mon application limite la capacité d’un utilisateur à modifier uniquement le style de police (B, I, U) et la couleur du texte. J'ai créé un contrôle personnalisé qui hérite de RichTextBox à cet effet. Je suis en mesure d'intercepter CTRL-V et de définir la police du texte collé sur SystemFonts.DefaultFont
. Le problème auquel je suis actuellement confronté est si le texte collé contient, par exemple, un style mi-gras mi-gras - le gras est perdu.
I.e. "Foo Bar " va simplement coller comme "Foo Bar".
Ma seule idée actuellement est de parcourir le texte caractère par caractère ( très lent) et de faire quelque chose comme:
public class MyRichTextBox : RichTextBox
{
private RichTextBox hiddenBuffer = new RichTextBox();
/// <summary>
/// This paste will strip the font size, family and alignment from the text being pasted.
/// </summary>
public void PasteUnformatted()
{
this.hiddenBuffer.Clear();
this.hiddenBuffer.Paste();
for (int x = 0; x < this.hiddenBuffer.TextLength; x++)
{
// select the next character
this.hiddenBuffer.Select(x, 1);
// Set the font family and size to default
this.hiddenBuffer.SelectionFont = new Font(SystemFonts.DefaultFont.FontFamily, SystemFonts.DefaultFont.Size, this.hiddenBuffer.SelectionFont.Style);
}
// Reset the alignment
this.hiddenBuffer.SelectionAlignment = HorizontalAlignment.Left;
base.SelectedRtf = this.hiddenBuffer.SelectedRtf;
this.hiddenBuffer.Clear();
}
}
Quelqu'un peut-il penser à une solution plus propre (et plus rapide)?
La solution
'nobugz' over sur les forums MSDN a répondu à cette question pour moi (j'avais besoin d'une réponse rapide; après presque une journée de SOV, j'ai donc dû chercher ailleurs - ne me jugez pas!):
using System.Runtime.InteropServices;
...
public static bool SetRtbFace(RichTextBox rtb, Font font, bool selectionOnly) {
CHARFORMATW fmt = new CHARFORMATW();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.szFaceName = font.FontFamily.Name;
fmt.dwMask = 0x20000000; // CFM_FACE
return IntPtr.Zero != SendMessage(rtb.Handle, 0x444, (IntPtr)(selectionOnly ? 1 : 4), fmt);
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private class CHARFORMATW {
public int cbSize;
public int dwMask;
public int dwEffects;
public int yHeight;
public int yOffset;
public int crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x40)]
public string szFaceName;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, CHARFORMATW lParam);
Autres conseils
Pour ceux qui veulent une réponse Delphi, un extrait pour vous donner l’idée de base:
using RichEdit; //reqd. for the constants and types
var
chformat : TCharFormat2;
fontname : string;
begin
FillChar(chformat,sizeof(chformat),0);
chformat.cbSize := sizeof(chformat);
//only modify the szFaceName field, height etc. left alone
chformat.dwMask := CFM_FACE;
//get the fontname set by the user
fontname := AdvFontSelector1.Text;
strpcopy(chformat.szFaceName,fontname);
RichEdit1.Perform(EM_SETCHARFORMAT, SCF_SELECTION, lparam(@chformat));
end;