Reputation: 31
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
Upvotes: 3
Views: 2737
Reputation: 3015
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:
Requirements
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;
}
}
Upvotes: 0
Reputation: 54433
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:
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.
Upvotes: 0
Reputation: 12439
Break your selected text
into char
s. Get each char
's Font, and change its size.
Upvotes: 1