2

I have a combobox and I need to populate it with all the available fonts in the system - their actual name, style, etc...

From all the information I can find online, I am able to put together the DrawItem event, but I keep running into the following error, "Cannot invoke non-delegate type 'System.Drawing.Font'" In fact, I borrowed line per line from other websites and made some changes. So, I thought it should have worked.

Here is how I populate the items list in the ComboBox:

method MainForm.MainForm_Load(sender: System.Object; e: System.EventArgs);
var thefont:Font;
begin
    if (ComboBox4.Items.Count>0) then
        ComboBox4.Items.Clear;

    for each oneFontFamily in FontFamily.Families do
    begin
        if (oneFontFamily.IsStyleAvailable(FontStyle.Regular)) then
            thefont := new Font(oneFontFamily.Name, 15)
        else if (oneFontFamily.IsStyleAvailable(FontStyle.Bold)) then
            thefont := new Font(oneFontFamily.Name, 15,FontStyle.Bold)
        else if (oneFontFamily.IsStyleAvailable(FontStyle.Italic)) then
            thefont := new Font(oneFontFamily.Name, 15,FontStyle.Italic)
        else if (oneFontFamily.IsStyleAvailable(FontStyle.Strikeout)) then
            thefont := new Font(oneFontFamily.Name, 15, FontStyle.Strikeout)
        else if (oneFontFamily.isStyleAvailable(FontStyle.Underline)) then
            thefont := new Font(oneFontFamily.Name, 15, FontStyle.Underline);

    if (thefont <> nil) then
        ComboBox4.Items.Add(theFont);
        end;
end;

Here is the combobox4 drawitem event:

method MainForm.comboBox4_DrawItem(sender: System.Object; e: System.Windows.Forms.DrawItemEventArgs);
begin
    if e.index = -1 then exit;

    // Draw the background of the item
    e.DrawBackground();

    // Should we draw the focus rectangle
    if ((e.State and DrawItemState.Focus) <> DrawItemState.Checked) then
        e.DrawFocusRectangle();

        // Create a new background brush.
        var b := new SolidBrush(e.ForeColor);

        // Draw the item.
        // This line raises the above mentioned error.
        e.Graphics.DrawString(FontFamily(comboBox4.Items[e.Index]).Name, font(comboBox4.Items[e.Index]), b, e.Bounds.x,e.Bounds.y);  <<===== Here is where the error is raised
end;

UPDATED: I modified the line that was causing the error and it compiles without error now but as I stated in my comment it is not drawing the fonts in their own style and size.

e.Graphics.DrawString(FontFamily(comboBox4.Items[e.Index]).Name, new font((comboBox4.Items[e.Index] as Font), (comboBox4.Items[e.Index] as Font).Style), b, e.Bounds.x,e.Bounds.y);

UPDATE: I forgot to set the DrawMode to OwnerDrawFixed. Now it is calling my DrawItem Event but still not drawing the Fonts in their own style and sizes.

I want the combobox to look like the following image:

someone else's combobox

Not like mine below:

actual Image of the winform with combobox

ThN
  • 3,235
  • 3
  • 57
  • 115
  • What is the e.Index value? Make sure to check that it isn't -1. How many fonts are actually in your ComboBox list? – LarsTech Nov 18 '11 at 16:30
  • @ LarsTech, as many as there are in the system I guess. :) Whatever number of fonts the FontFamily has. e.Index is location for each font object stored in items objectCollection list. – ThN Nov 18 '11 at 16:41
  • I only ask because I'm not a delphi-prism programmer, but it "looks" like you are only adding one font because it's not inside the begin-end block. – LarsTech Nov 18 '11 at 16:48
  • :) I just realized that and made the changes. – ThN Nov 18 '11 at 16:52
  • DrawString method is wants string, font, x, y as parameters and I am passing string, don't know what , x, y. That's why it is having trouble drawing the fonts. So, how do you typecast font from an object of font? – ThN Nov 18 '11 at 16:57
  • Does it matter that your have "font" in lowercase and not "Font"? – LarsTech Nov 18 '11 at 17:01
  • @LarsTech, I actually got it to compile without any error, but it still doesn't actually draw the font as they are supposed to appear in their own style. Upper case or Lower case font is still the same. – ThN Nov 18 '11 at 17:08

2 Answers2

1

Here is something that most probably helps you: http://www.vbaccelerator.com/home/net/code/controls/ListBox_and_ComboBox/Font_Picker/article.asp

Be sure to implement the required infrastructure from this article too, though: http://www.vbaccelerator.com/home/NET/Code/Controls/ListBox_and_ComboBox/Icon_ComboBox/article.asp

Sebastian P.R. Gingter
  • 5,955
  • 3
  • 31
  • 73
1

Here is my answer with working code.

  • create a new project and open your main winform. Open your ToolBox and place a combobox on your mainform.
  • Open the property window for the combobox that you just placed on the winform.
  • Set the following properties for your combobox as follows: DrawMode = OwnerDrawFixed, DropDownStyle = DropDownList, FormattingEnabled = true, GenerateMemeber = true, IntegralHeight = false and ItemHeight = 25.
    • Create Mainform_Load method by double clicking on the main winform and copy the following code accordingly to your load method.

,

Method MainForm.MainForm_Load(sender: System.Object; e:System.EvenArgs);
var 
   thefont:Font;
begin
if (ComboBox1.Items.Count>0) then
   ComboBox1.Items.Clear;

for each oneFontFamily in FontFamily.Families do
begin
    if (oneFontFamily.IsStyleAvailable(FontStyle.Regular)) then
        thefont := new Font(oneFontFamily.Name, 12)
    else if (oneFontFamily.IsStyleAvailable(FontStyle.Bold)) then
        thefont := new Font(oneFontFamily.Name, 12,FontStyle.Bold)
    else if (oneFontFamily.IsStyleAvailable(FontStyle.Italic)) then
        thefont := new Font(oneFontFamily.Name, 12,FontStyle.Italic)
    else if (oneFontFamily.IsStyleAvailable(FontStyle.Strikeout)) then
        thefont := new Font(oneFontFamily.Name, 12, FontStyle.Strikeout)
    else if (oneFontFamily.isStyleAvailable(FontStyle.Underline)) then
        thefont := new Font(oneFontFamily.Name, 12, FontStyle.Underline);

    if (thefont <> nil) then
        ComboBox1.Items.Add(theFont);
end;
end;
  • Create DrawItem event for the your comboBox and copy the following code accordingly into your drawitem event.

'

    Method MainForm.ComboBox1_DrawItem(sender:System.Object; e: System.Windows.Forms.DrawItemEventArgs);
    var theobject:Font;
    begin
       if e.Index=-1 then exit;
       // Draw the background of the item
       e.DrawBackground();

       // Should we draw the focus rectangle
       if ((e.State and DrawItemState.Focus) <> DrawItemState.Checked) then
          e.DrawFocusRectangle();

       // Create a new background brush.
       var b := new SolidBrush(e.ForeColor);
       theobject := (ComboBox1.Items[e.Index] as font);

       // Draw the item.
       e.Graphics.DrawString(theobject.Name, theObject, b,e.Bounds);
    end;

When you have it all done and running you should have a combobox1 displaying fonts as follows:

ComboBox displaying Font Text

ThN
  • 3,235
  • 3
  • 57
  • 115