How to change the font of multiple sizes in richtextbox in C#?

試著忘記壹切 提交于 2019-12-12 15:06:38

问题


I have a richtextbox and I would like to make it work like WordPad. My problem is that, for example, if I type "123" using the Calibri font, and then "456" using the Arial font and I want to change the size of 2345 it won't let me to do it because they have two different font types. This is where I have the problem:

private void combo_sizes_TextChanged(object sender, EventArgs e)
{
    if (rtb.SelectionFont == null)
    {
        rtb.SelectionFont = new Font(combo_fonts.Text, Convert.ToInt16(combo_sizes.Text));
    }
    rtb.SelectionFont = new Font(rtb.SelectionFont.FontFamily, Convert.ToInt16(combo_sizes.Text));
}

I know tha when the selected text in the rtb contains multiple fonts the SelectionFont equals to null, so in that case I have made it to get the selected text's size and font from two comboboxes, but I would like to change the size without losing its original font. Is there a solution?

Thanks


回答1:


Break your selected text into chars. Get each char's Font, and change its size.




回答2:


There are two built-in fonts in a RichTextBox (RTB):

  • Font is the one that will be used after for any input. So if you want to switch to another font, this is what you should set
  • SelectionFont however is the font of the current selection. This will change with the selection but it is also used to set font of part of the text that has already been entered.

But there can be only one of either at a time and place. If you want to switch back to a standard Front you need to keep a standard Font somewhere.

Or you can store all fonts you use in a List and you can offer them in a comboBox.

Please also note that:

  • All formatting after the text has been entered must be done be selecting a part and then changing the properties of that selection: Font, Colors, Styles..
  • After any part of the Text has been formatted in any way you must not change the text directly in your code but only use AppendText, Copy, Cut, Past or else you'll you'll mess up the formatting!

Your code may work like this:

public Form1()
{
    InitializeComponent();

    lastSelectionFont = rtb.SelectionFont;
    lastFont = rtb.Font;
    //..

}

Font lastSelectionFont;
Font lastFont;
private void richTextBox1_TextChanged(object sender, EventArgs e)
{

    if (rtb.SelectionLength > 0)
    {
        lastSelectionFont = rtb.SelectionFont;
        rtb.SelectionFont = new Font(rtb.SelectionFont.FontFamily, 
                                Convert.ToInt16(combo_sizes.Text));
    }
    else
    {
        lastFont = rtb.Font;
        rtb.Font = new Font(rtb.Font.FontFamily, 
                               Convert.ToInt16(combo_sizes.Text));
    }
}

Note that the SelectionFont won't be null ubnless you set it to null. You probably have hit problems when there was no selection..

But again, I'm not sure about your ideas of 'saving' the previous Forn. Think of wordPad: It doesn't do anythink like that either. Adding all fonts you use into a List of Fonts, maybe even with theris colors, and nice names as font&styles sound very attractive.




回答3:


I needed the same here. And I didn't find the best solution... So, here is the Ugly one.

private void UglyChangeFontSize(RichTextBox rtb, float newSize = -1f, FontFamily fontFamily = null) {
    if (rtb.SelectionFont != null) {

        if (newSize < 0) newSize = rtb.SelectionFont.Size;
        if (fontFamily == null) fontFamily = rtb.SelectionFont.FontFamily;

        rtb.SelectionFont = new Font(fontFamily, newSize, rtb.SelectionFont.Style);
    }
    else {
        // Backup Selection
        var sel = rtb.SelectionStart;
        var selLen = rtb.SelectionLength;

        // Change, char by char
        for (int k = 0; k < selLen; k++) {
            rtb.Select(sel + k, 1);

            if (newSize < 0) newSize = rtb.SelectionFont.Size;
            var ff = fontFamily ?? rtb.SelectionFont.FontFamily;

            rtb.SelectionFont = new Font(fontFamily, newSize, rtb.SelectionFont.Style);
        }

        // Restore Selection
        rtb.SelectionStart = sel;
        rtb.SelectionLength = selLen;
    }
}

IMPROVED VERSION

This is a better version, its includes:

  1. Disabling the RichTextBox drawing (when changing the font);
  2. Prevents the "char-by-char modification" to go to the Undo/Redo stack;
  3. Show the WaitCursor when performing the change.

Requirements

  1. External.cs
  2. RichOLE.cs
  3. (Optional) RicherTextBox -- I built my Code around this one, it is a nice start to build a WordPad-like project

The code

RichTextBox myRichTextBox = new RichTextBox();
RichOLE mRichOle = new RichOLE(myRichTextBox);

...

private void UglyChangeFontSize(RichTextBox rtb, float newSize = -1f, FontFamily fontFamily = null) {
    if (rtb.SelectionFont != null) {

        if (newSize < 0) newSize = rtb.SelectionFont.Size;
        if (fontFamily == null) fontFamily = rtb.SelectionFont.FontFamily;

        rtb.SelectionFont = new Font(fontFamily, newSize, rtb.SelectionFont.Style);
    }
    else {
        Cursor = Cursors.WaitCursor;

        // Hide the modifications from the user
        External.LockWindowAndKeepScrollPosition(rtb, () => 
        {
            // Backup Selection
            var sel = rtb.SelectionStart;
            var selLen = rtb.SelectionLength;

            // Disable UNDO for this "in pieces modifications" [START]
            rtb.SelectedRtf = rtb.SelectedRtf; // Required to allow Undo
            //mFontLockEvents = true; // RicherTextBox
            mRichOle.EnableUndo(false);
            // Disable UNDO for this "in pieces modifications" [END]

            // Change, char by char
            for (int k = 0; k < selLen; k++) {
                rtb.Select(sel + k, 1);

                // again, ugly... buuut we have Branch Prediction (google it)
                if (newSize < 0) newSize = rtb.SelectionFont.Size;
                var ff = fontFamily ?? rtb.SelectionFont.FontFamily;

                rtb.SelectionFont = new Font(fontFamily, newSize, rtb.SelectionFont.Style);
            }

            // Disable UNDO for this "in pieces modifications" [START]
            //mFontLockEvents = false; // RicherTextBox
            mRichOle.EnableUndo(true);
            // Disable UNDO for this "in pieces modifications" [END]

            // Restore Selection
            rtb.SelectionStart = sel;
            rtb.SelectionLength = selLen;
        });
        Cursor = Cursors.Default;
    }
}


来源:https://stackoverflow.com/questions/26700102/how-to-change-the-font-of-multiple-sizes-in-richtextbox-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!