Creating a text editor just to try and hone my programming skills some more. I have the winform opening new text files, saving them and the usual undo, redo, copy, paste etc etc. However. I'm now trying to change the font.
When you click the "change font" button in the menu strip, a new form appears and loads all available fonts you can use into a list box.
List<string> fonts = new List<string>();
foreach (FontFamily font in System.Drawing.FontFamily.Families)
{
fonts.Add(font.Name);
}
listboxfont.DataSource = fonts;
Now before I edit the text on the other page, I wanted to edit a sample label to test everything is okay!
After some research, I come across many bits of code like this..
lblsample.Font = new Font(listboxfont.SelectedItem, 12);
I might be wrong, but I see no reason why I can't use the selected item from the list box, which IS the fonts and use that to edit the label however it is giving me the error..
"Text_editor.font does not contain a constructor that takes 2
arguments.
Have tried and tried but no luck. Can anybody help?
It is because listboxfont.SelectedItem is an object. You need to cast it to a string so:
lblsample.Font = new Font((string)listboxfont.SelectedItem, 12);
or if you prefer:
lblsample.Font = new Font(listboxfont.SelectedItem.ToString(), 12);
That should do the trick!
UPDATE - Full example
Add listbox named listboxfont
Add label named lblsample
Add button named btnPreview
private void Form1_Load(object sender, EventArgs e)
{
List<string> fonts = new List<string>();
foreach (FontFamily font in System.Drawing.FontFamily.Families)
{
fonts.Add(font.Name);
}
listboxfont.DataSource = fonts;
}
private void btnPreview_Click(object sender, EventArgs e)
{
lblsample.Font = new Font(listboxfont.SelectedItem.ToString(), 12);
}
You have declared a variable named font in your Text_editor form. (note the casing.. all lowercase!)
OR
The message you typed in your question has a typo. Is it Text_editor.fonts does not contain a constructor that takes 2 arguments.? If yes, then you have used your fonts variable wrongly, which is not of Font type, but instead is of List<string> type.
Name your variables properly, and it should start working.
Try this:
lblsample.Font = new Font(listboxfont.SelectedItem.ToString(), 12.0f);
The Font constructor requests a String and a float
public Font(
string familyName,
float emSize
)
Related
How do I make bold a variable amount of items in a listbox? I've seen solutions like this one, but it appears to only work if I know exactly which items should be bold before runtime. Here's my specific case:
I have a listbox with a list of strings read from a file. I have a search bar that, when typed in, will automatically move items matching that string to the top of the listbox. Unfortunately, being at the top isn't enough of an indicator of "search result," so I also want to make those items bold. Before runtime, I do know all the items I want to be bold will be at the top of the list, but I have no idea how many items that will be. Additionally, when the user erases the search bar's contents, the list will be reordered to its initial order and the bold items should be made not bold.
How do I go back and forth between bold/not bold for specific listbox items at runtime?
Here is my code for the search and display functionality:
private void txtSearch_TextChanged(object sender, EventArgs e)
{
string searchTerm = txtSearch.Text.Trim();
if(searchTerm.Trim() == "") // If the search box is blank, just repopulate the list box with everything
{
listBoxAllTags.DataSource = fullTagList;
return;
}
searchedTagList = new List<UmfTag>();
foreach(UmfTag tag in fullTagList)
{
if(tag.ToString().ToLower().Contains(searchTerm.ToLower()))
{
searchedTagList.Add(tag);
}
}
// Reorder the list box to put the searched tags on top. To do this, we'll create two lists:
// one with the searched for tags and one without. Then we'll add the two lists together.
List<UmfTag> tempList = new List<UmfTag>(searchedTagList);
tempList.AddRange(fullTagList.Except(searchedTagList));
listBoxAllTags.DataSource = new List<UmfTag>(tempList);
}
I was able to solve my own problem. I indeed used the solution present in this question, but I altered it like so:
private void listBoxAllTags_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
FontStyle fontStyle = FontStyle.Regular;
if(e.Index < searchedTagList.Count)
{
fontStyle = FontStyle.Bold;
}
if(listBoxAllTags.Items.Count > 0) // Without this, I receive errors
{
e.Graphics.DrawString(listBoxAllTags.Items[e.Index].ToString(), new Font("Arial", 8, fontStyle), Brushes.Black, e.Bounds);
}
e.DrawFocusRectangle();
}
The second if statement (checking if the count is greater than 0) is required. Without it, I received "index[-1]" errors because my program first starts with empty listboxes, and the DrawString method couldn't draw the string for the empty listBox.Items[] array.
I have 2 comboboxes for the font and the fontsize. When I click them it changes the font size or the font in my richtextbox. Now I want it to work like in word. If the line you just moved to is in a different font or size. It should detect that and change the comboxes to match the font and size of the current line. Somoeone else asked this same question and got a result which didn't work for me. It was as follows
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
MessageBox.Show("we got here"); // this is my added part to let me know if the code is even getting executed. It is not.
richTextBox1.SelectionStart = 1;
richTextBox1.SelectionLength = 1;
comboBox1.Text = richTextBox1.SelectionFont.ToString();
comboBox2.Text = null;
comboBox2.Text = richTextBox1.SelectionFont.Size.ToString();
}
I held out hope that it was my answer but I could not see how SelectionFont would make any difference when nothing was selected. Also the richTextBox1_SelectionChanged event seems to not be being called when I move through the document with the up/down arrows. The problem is not with the comboboxes, the problem is that as I arrow through my document I need to be able to know what font and size it is at the caret position so it can fire an event to change the combo boxes to match.
The code that you are using will always make the selection from character at index 1 and are of the length 1. instead for that you need to use which will give you the the following code without specifying the selection(so it will take the selection from the ritchTextBox).
string fontName = richTextBox1.SelectionFont.Name;
float fontsize = richTextBox1.SelectionFont.Size;
You should save the values for the new comboBox position temporarily in variables, otherwise if you do it directly
comboBox1.SelectedIndex = comboBox1.FindStringExact(richTextBox1.SelectionFont.Name);
the comboBox1_SelectedIndexChanged event will be immediately called and could affect the results.
So just try:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
int comboBox1Index = comboBox1.FindStringExact(richTextBox1.SelectionFont.Name);
int comboBox2Index = comboBox2.FindStringExact(richTextBox1.SelectionFont.Size.ToString());
comboBox1.SelectedIndex = comboBox1Index;
comboBox2.SelectedIndex = comboBox2Index;
}
I adapted Sujith's solution and half of Markus's solution and came up with the following which works just fine for me:
Private Sub Description_SelectionChanged(sender As Object, e As EventArgs) Handles Description.SelectionChanged
Dim fontName As String = Description.SelectionFont.Name
Dim fontSize As Single = Description.SelectionFont.Size
tbSelectFont.Text = fontName
tbSelectSize.Text = fontSize
End Sub
My Question is to how to extend a TextBox such that it may start behaving like RichTextBox?
There can be various properties that RichTextBox may add: appearance mainly.
Should I use this kind of method where I extend the TextBox class and create a basic TextBox which would contain several other textboxes which would behave like a big container node containing small specialized nodes?
For starters, to have texts with alternate color after '+', I ve used this way:
class CustomTextBox : TextBox
{
List<TextBox> _textboxes = new List<TextBox>();
string _Text="";
List<Color> colorlist = new List<Color>();
public override string Text
{
get{return this._Text;}
set{this._Text = value;}
}
public CustomTextBox()
{
foreach(Color color in (Color[]) Enum.GetValues(typeOf(Color)))
{
colorlist.add(color);
}
this.KeyUp+= new KeyUpEventHandler(TextChangedCheck);
}
int i=0;
private void TextChangedCheck(object sender, KeyUpEventArgs e)
{
if(e.KeyData == Keys.Add)
{
TextBox Temp = new TextBox();
Temp.Text = this.Text;
this.Text = "";
Temp.ForeColor = colorlist[i];
i++;
this._textboxes.Add(Temp);
this.Controls.Add(_textboxes[i]);
e.Handled = true;
}
}
}
EDIT:
The MAIN purpose of this question is to extend a TextBox using its own properties to have a RTB like behavior and not using Graphics or related.
I'd have to guess what you really want to achieve here.
But if you want a Control with formatted text (FT) and really really really don't want a RichTextBox, I think you shouldn't create a new, embedded TextBox for every piece of FT.
Instead you should write the FT yourself, maybe on a panel with DrawString and use only one Textbox for text entry. Interesting project, really, once one accepts the challenge. Of course you must think your format through and also consider all sorts of interface questions..
Last week I have avoided a RTF for a tiny help system by using a ListView; it formats by line only, using the first character to indicate the format from a list of a dozen or so.. Works fine, but only one format per line.
Here's my code:
private void DialogFont_Load(object sender, EventArgs e)
{
LoadInstalledFonts();
}
private void LoadInstalledFonts()
{
var fontCollection = new System.Drawing.Text.InstalledFontCollection();
foreach (var font in fontCollection.Families)
{
lstFonts.Items.Add(font.Name);
}
}
How can I display each font using its own design, sort of like a preview of the fonts? I'm using the ListBox control to list the fonts.
You can do it easily in WPF.
The XAML would look like:
<ComboBox Width="100" Height="30" x:Name="FontSelector">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" FontFamily="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And C# codebehind:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
FontSelector.ItemsSource = Fonts.SystemFontFamilies;
}
You could also check this article over on CodeProject which walks through (in a Winforms example) how to populate a list box with fonts like you want: http://www.codeproject.com/KB/selection/FontListBoxAndCombo.aspx
Maybe go with a ListView instead of a ListBox? The ListViewItem type has a Font property you could use. I'm not aware of any special per-item formatting capabilities of ListBox.
Update: In case you're still working on this, here's a snippet of some code that worked for me (this won't compile as-is as it's just a clip from a larger user control; I'm sure you can figure out what goes where though):
private void PopulateListView(IEnumerable<FontFamily> fontFamilies)
{
try
{
m_listView.BeginUpdate();
float fontSize = m_listView.Font.Size;
Color foreColor = m_listView.ForeColor;
Color backColor = m_listView.BackColor;
string sampleText = m_sampleText;
foreach (FontFamily fontFamily in fontFamilies)
{
var listViewItem = new ListViewItem(fontFamily.Name)
{
UseItemStyleForSubItems = false
};
var sampleSubItem = new ListViewItem.ListViewSubItem(listViewItem, sampleText, foreColor, backColor, new Font(fontFamily, fontSize));
listViewItem.SubItems.Add(sampleSubItem);
m_listView.Items.Add(listViewItem);
}
}
finally
{
m_listView.EndUpdate();
}
}
Here's what the result looks like:
First thing, I want to make sure that you are aware of the FontDialog control, and you are purposely wanting to create a custom Font Dialog. If you weren't aware of it, then maybe you can take a look at it and make sure that it doesn't fit your needs before trying to create your own. And the following Stack Overflow question shows you how to make sure it is populated with all the device fonts and not just TrueType fonts.
Now, if you still want to create your own, then the following is a simplified solution:
Add a Label to your Font Dialog and set its text to whatever you want the user to see as a sample of the font. Something like AabBcC, or it could even be a random sentence.
You can set the Font of the label in the SelectedIndexChanged event of your ListBox. This in effect changes the sample text to match the font you specify. The following is a simple example:
Note that you can also use a Textbox if you want your user to specify the text that they want to see in another font. Also, some fonts like Andy and Aharomi throw an ArgumentException stating that the Font doesn't support a regular style, so it would be wise to catch this exception type.
private void lstFonts_SelectedIndexChanged(object sender, EventArgs e)
{
lblSample.Font = new Font(lstFonts.SelectedItem.ToString(), 12);
}
Using a ListBox, I would think you'd need to do owner-draw. When drawing each list item, you'd need to select the font for that item.
In the code behind of my page I want to attach a label in multiple places. To achieve this and avoid creating mutliple instances of the same label I've tried:
Label lblNone = new Label();
lblNone.Text = "<br/> None. <br/>";
Master.mainContent.Controls.Add(lblNone);
Master.mainContent.Controls.Add(lblNone);
Master.mainContent.Controls.Add(lblNone);
For some reason I only see 1 instance of the "None." on my page?
Why is this?
You have no option.. you need to create one instance of Label for each control you want to see in the screen.
This is because of the behavior of the ControlCollection class.
it will not allow multiple adds of the same "reference".
When you add a control to one ControlCollection it is automatically removed from the previous so, even if you were adding your label to different ControlCollections it wouldn't work.
PS: By ControlCollection I mean the type of the property Master.mainContent.Controls
You might find it easier to create a method for this as so: -
protected void Page_Load(object sender, EventArgs e)
{
this.Controls.Add(CreateLiteral("text"));
this.Controls.Add(CreateLiteral("text"));
this.Controls.Add(CreateLiteral("text"));
}
private Literal CreateLiteral(string Content)
{
Literal L = new Literal();
L.Text = Content;
return L;
}
Thanks,
Phil.