I would like to add or deploy the app with more than 10 external fonts from my resource folder. I have gone through various SO questions but none of them suits my requirement except this SO answer.
Now I have implemeted the same thing in my winform app and I would like to add these fonts to combo box with their styles such as shown below.
Any suggestions are most welcome.
You have to draw the items in the ComboBox yourself if you want to show them in the drop down in their appropriate font. This isn't hard, the following code does the bare minimum:
var comboBox = new ComboBox();
comboBox.DisplayMember = "Name";
comboBox.Items.AddRange(FontFamily.Families);
comboBox.DrawMode = DrawMode.OwnerDrawFixed;
comboBox.DrawItem += (s, e) => {
var fontFamily = (FontFamily) comboBox.Items[e.Index];
var itemText = comboBox.GetItemText(fontFamily);
// Some fonts don't work with a regular style, if they don't have a
// regular style, we'll default to the provided font.
if (!fontFamily.IsStyleAvailable(FontStyle.Regular))
{
TextRenderer.DrawText(
e.Graphics, itemText, e.Font, e.Bounds, e.ForeColor, e.BackColor
TextFormatFlags.VerticalCenter | TextFormatFlags.Left);
}
else
{
using (var font = new Font(fontFamily, comboBox.Font.Size, FontStyle.Regular))
{
TextRenderer.DrawText(
e.Graphics, itemText, font, e.Bounds, e.ForeColor, e.BackColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left);
}
}
};
This implementation handles a FontFamily not having a regular font style by falling back to the ComboBox's default font. You can handle this more gracefully by attempting to find a valid style for the FontFamily before creating the font.
Related
I have created a ListBox to which I add elements during code compilation. and I want to record its color when adding one element (so that each added element has a different color)
listBox1.Items.Add(string.Format("Місце {0} | В роботі з {1} | ({2} хв)", temp[7].Substring(6, 4), temp[8].Substring(11, 5), rezult)); `
I tried everywhere possible to embed this change
BackColor = Color.Yellow;ForeColor = Color.Yellow;
I am working with listbox because I have seen so many answers about ListView.
Set the listbox DrawMode to either OwnerDrawFixed or OwnerDrawVariable and set this as the DrawItem event handler:
private void listBox1_DrawItem(object sender, DrawItemEventArgs e){
if(e.Index == 1) e.DrawBackground(); //use e.Index to see if we want to highlight the item
else e.Graphics.FillRectangle(new SolidBrush(Color.Yellow), e.Bounds); //This does the same thing as e.DrawBackground but with a custom color
e.DrawFocusRectangle();
if(e.Index < 0) return;
TextRenderer.DrawText(e.Graphics, (string)listBox1.Items[e.Index], listBox1.Font, e.Bounds, listBox1.ForeColor, TextFormatFlags.Left);
}
Well, best idea I have is to not use list box, but flowLayoutPanel and add usercontrols where you will have labels.
flowLayoutPanel works as list of controls which you can scroll, so we will just create a usercontrol, where we will put label and change the usercontrol background
Don't forget to turn on the AutoScroll feature to flowLayoutPanel, otherwise the scroll bar wont work and wont even show up.
If you want to be able to be clickable just add to the label click event.
public void CreateItem(Color OurColor, string TextToShow)
{
Label OurText = new Label()
{
Text = "TextToShow",
Font = new Font("Segoe UI", 8f),
Location = new Point(0, 0),
AutoSize = true,
};
UserControl OurUserControl = new UserControl();
OurUserControl.Size = new Size((int)((double)flowLayoutPanel1.Width * 0.9) , OurText.Font.Height);
OurUserControl.BackColor = OurColor;
OurUserControl.Controls.Add(OurText);
flowLayoutPanel1.Controls.Add(OurUserControl);
}
I am setting the ForeColor of all items in my ListView to a different color, but this get's overrided when the item is selected (changes to Black again; changes back to custom color on deselection).
I want my items to retain my custom color, even in selection.
I'm basically asking the same question that was asked here 7 years ago, and doesn't seem to have any satisfactory answer.
I tried searching in SO and elsewhere, and no luck. The only solution provided so far is to draw the whole thing (the DrawItem method), which I gave a try but is ridiculously complicated for such a petty requirement...
Is this the only way? Say it ain't so.
Enable your ListView OwnerDraw mode, then subscribe its DrawItem and DrawColumnHeader events.
If your design requires it, also subcribe the DrawSubitem event.
At this point, you can draw anything in the related areas of your ListView.
In the example, I've painted a little symbol in the Header area.
The Header text needs to be painted too.
If the Background color doesn't change (same as in design mode), you just need to use the DrawListViewItemEventArgs e parameter function e.DrawBackground();
If not, use e.Graphics.FillRectangle() to color the Item area, defined by e.Bounds.
The Item Text is drawn using e.Graphics.DrawString().
The item Text is e.Item.Text, the text area is defined by e.Bounds again.
If you don't need any specific details/settings for the item's text, you can simply use e.DrawText();, which uses the default properties (defined at design-time).
Here, the item color complex logic is that the color is specified inside the item text. Could be anything else. The item tag, its Index position, a List<Parameters>, you name it.
This is how it might look like:
(I added e.Graphics.TextRenderingHint = [] to show how you can control the quality of the rendered text. e.Graphics.TextContrast can be also used to enhance the contrast).
Note: this code sample only draws a generic image, if the ListView has an ImageList. You should also verify whether the SmallIcon/LargeIcon ImageLists are defined and draw the related Image in the specified size. It's the same procedure, though.
protected void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
e.Item.UseItemStyleForSubItems = true;
int imageOffset = 0;
Rectangle rect = e.Item.Bounds;
bool drawImage = !(e.Item.ImageList is null);
Color itemColor = Color.FromName(e.Item.Text.Substring(e.Item.Text.LastIndexOf(" ") + 1));
using (var format = new StringFormat(StringFormatFlags.FitBlackBox)) {
format.LineAlignment = StringAlignment.Center;
if (drawImage) {
imageOffset = e.Item.ImageList.ImageSize.Width + 1;
rect.Location = new Point(e.Bounds.X + imageOffset, e.Item.Bounds.Y);
rect.Size = new Size(e.Bounds.Width - imageOffset, e.Item.Bounds.Height);
e.Graphics.DrawImage(e.Item.ImageList.Images[e.Item.ImageIndex], e.Bounds.Location);
}
if (e.Item.Selected) {
using (var bkgrBrush = new SolidBrush(itemColor))
using (var foreBrush = new SolidBrush(e.Item.BackColor)) {
e.Graphics.FillRectangle(bkgrBrush, rect);
e.Graphics.DrawString(e.Item.Text, e.Item.Font, foreBrush, rect, format);
}
e.DrawFocusRectangle();
}
else {
//e.DrawDefault = true;
using (var foreBrush = new SolidBrush(itemColor)) {
e.Graphics.DrawString(e.Item.Text, e.Item.Font, foreBrush, rect, format);
}
}
}
}
// Draws small symbol in the Header beside the normal Text
protected void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.DrawBackground();
string extra = (e.ColumnIndex == 1) ? (char)32 + "\u2660" + (char)32 : (char)32 + "\u2663" + (char)32;
using (var brush = new SolidBrush(e.ForeColor)) {
e.Graphics.DrawString(extra + e.Header.Text, e.Font, brush, e.Bounds, StringFormat.GenericTypographic);
}
}
Is it possible to align currency symbol to the left and the value to the right in DevExpress GridView?
This task is beyond the regular text formatting. To accomplish it, you need to manually draw the cell content.
XtraGrid provides the event for this purpose: CustomDrawCell. The event argument object provides a reference to graphics objects, cell boundaries, and other information necessary to draw the cell text manually.
private void OnGridViewCustomDrawCell(object sender, RowCellCustomDrawEventArgs e) {
switch (e.Column.FieldName) {
case "Debit":
DrawDebitCell(e);
break;
}
}
private void DrawDebitCell(RowCellCustomDrawEventArgs e) {
e.Handled = true;
string text = string.Format(CultureInfo.CurrentCulture, "{0} {1:n2}", CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol, e.CellValue);
Size textSize = e.Appearance.CalcTextSizeInt(e.Cache, text, int.MaxValue);
e.Appearance.DrawBackground(e.Cache, e.Bounds);
if (Convert.ToInt32(textSize.Width) > e.Bounds.Width)
e.Appearance.DrawString(e.Cache, text, e.Bounds);
else {
StringFormat stringFormat = e.Appearance.GetStringFormat();
string valueText = string.Format(CultureInfo.CurrentCulture, "{0:n2}", e.CellValue);
stringFormat.Alignment = StringAlignment.Near;
e.Appearance.DrawString(e.Cache, CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol, e.Bounds, e.Appearance.Font, stringFormat);
stringFormat.Alignment = StringAlignment.Far;
e.Appearance.DrawString(e.Cache, valueText, e.Bounds, e.Appearance.Font, stringFormat);
}
}
This approach has a few disadvantages:
The manually drawn cell content is not used by built in Export and Printing system
It is necessary to calculate the text width to make sure that the value and the currency symbol will not overlap each other. For this purpose, you can use the CalcTextSizeInt method of the AppearanceObject object available via event arguments. DevExpress uses its own text rendering engine, so the standard Graphics.MeasureString method is not useful in this case
How can I change the Font Style (regular, bold, etc) ?
So far what I have is this:
if (listBox1.SelectedIndex == 3)
{
if (textBox1.Text == "regular")
{
//FontStyle regular = new FontStyle !!!wrong one!!!
}
}
So what i need is that when I'd type "regular" in the textbox, the font style will change to regular. How do I do that?
You need to create a new Font and apply it to your text box:
textBox1.Font = new Font(FontFamily.GenericSansSerif, 12.0F, FontStyle.Normal);
This will create one with a new family etc. You can read the size and family from the existing Font object to preserve those.
textBox1.Font = new Font(textBox1.Font, FontStyle.Normal);
For more information on the properties of the Font class see the MSDN page
You need to set the Control.FontWeight property
if (listBox1.SelectedIndex == 3)
{
if (textBox1.Text == "regular")
{
TextBox1.FontWeight = FontWeights.Regular;
}
}
Are you looking for something like this:
textBox1.Font = new Font(textBox1.Font, FontStyle.Bold);
I'm getting the following exception when changing my application font, because I use a strike out in a part of my application, and some fonts don't support it:
I change my application font using a font dialog. I need to check if the selected font supports the strikeout style after assigning it to my application.
What is the recommended way to do this? I know I could create a font with the style and catch the exception, but is there a more elegant way to do it?
Thanks in advance.
EDIT: The user selects a font, not necesary strikeout. In that moment I need to check if the font supports the style strikeout, because I create a strikeout font in a part of my application. If the font don't support the strikeout style would not allow the user to choose that font.
Updated : (to reflect update in the initial post):
InstalledFontCollection ifc = new InstalledFontCollection();
for (int i = 0; i < ifc.Families.Length; i++)
{
if (ifc.Families[i].IsStyleAvailable(FontStyle.StrikeOut))
{
//add particular font with this family to your "font selector"
}
}
If you are using the standard Font class, then you can use the Font.Strikeout property:
//Gets a value that indicates whether this Font specifies a horizontal line through the font.
public bool Strikeout { get; }
Finally I used the following:
private bool SupportStrikeout(Font font)
{
try
{
using (Font strikeout = new Font(font, FontStyle.Strikeout))
{
return true;
}
}
catch (ArgumentException)
{
return false;
}
}