none
How do you determine if a given font family is a fixed-pitch?

    Question

  • How do you determine if a given font family is a fixed-pitch?

     

    I am trying to fill a listbox with the available fonts families on a system and marked the ones that are fixed-pitch as such.

     

    I'm programming in C#/.NET 2.0, using VS2005, under XP Pro/SP3, writing a Windows Forms app.

     

    Browsing the online help, blog and the Internet, I see that through the years this question has been asked multiple times over,
    but I can't find a definitive answer.

     

    Someone's suggestion was to compare the SizeF.Width of the letters I and W using Graphics.MeasureString().

    This seems a bit of a kluge. I haven't gone this route yet as I am trying to get at the value of the PitchAndFamily in the FONT structure.
    Why the Font class doesn't expose this value (or at least a boolean property FixedPitch) when this info is right in the FONT member
    that is more than likely internal to the class, I dont know. Enough people seem to want at it though!

     

    My first attempt was to follow the suggestion to make use of a class/struct called LOGFONT and make calls to Font.ToLogFont(LOGFONT logfont)
    but LOGFONT isnt defined in the .NET BCL (this alone is confusing - why in the world does a BCL method make use of a class/struct that it itself
    does not define! Does this happen often?)

     

    I found several definitions for LOGFONT, (including one in the CE framework but not in the 2.0) and tried several of them but no matter how
    I define it, the value for the field lfPitchandFamily ALWAYS comes back as zero. At first I thought that the structure mapping was off,
    but apparently that's not the case because the next field, lfFaceName, is a string, and that value is correct!
    An "un-documented feature" in Font.ToLogFont()?

    (See APPROACH 1 below)

     

    I tried doing basically the same thing, only using a TEXTMETRIC struct and making GDI32 calls to GetTextMetric.

    This code threw an ExecutionEngineException on the call to GetTextMetrics and that is most definitely NOT GOOD!

    I stopped right there with that approach.

    (SEE APPROACH 2 BELOW)

     

    So, my last attempt at getting at lfPitchandFamily is through the classes TextMetrics and VisualStyleRenderer.
    Doing it this way throws an InvalidOperationException - "Object is currently in use elsewhere.

    (SEE APPROACH 3 BELOW)

     

    Ive also found unmanaged C++ code that makes Win32 API calls (EnumFontFamiliesEx?) and then does some bit testing.

    After my current success rate, I think that its time to ask an MVP!

     

    BOTTOMLNE:

    Can anyone tell me if there is an easier (i.e. a managed, .NET) way? Or tell me what wrong with any or all of my three approaches so far?

     

    Or am I going about this totally wrong from the start? (using FontFamily?)

     

    A very, very big THANKS IN ADVANCE for this one,

    Paul

     

     

    APPROACH 1: Using Font.ToLogFont()

    Problem: For any and every Font in FontFamily.Families, the field LOGFONT.PitchAndFamily is ALWAYS EQUALS ZERO!!

     


    using System;
    using System.Runtime.InteropServices;
    using System.Text;
    
    // usage:
    //
    // LOGFONT LF = new LOGFONT("");
    // Font.ToLogFont(LF);
    // if (LF.IsFixedPitch) . . . 
    namespace MyLogFont {
      public enum LogFontWeight : int {
        DontCare = 0,
        Thin = 100,
        ExtraLight = 200,
        UltraLight = 200,
        Light = 300,
        Normal = 400,
        Regular = 400,
        Medium = 500,
        DemiBold = 600,
        SemiBold = 600,
        Bold = 700,
        ExtraBold = 800,
        UltraBold = 800,
        Black = 900,
        Heavy = 900,
        ExtraBlack = 950,
        UltraBlack = 950,
      }
    
      public enum LogFontCharSet : byte {
        ANSI = 0,
        Default = 1,
        Symbol = 2,
        Mac = 77,
        ShiftJIS = 128,
        Hangeul = 129,
        Johab = 130,
        GB2312 = 134,
        ChineseBig5 = 136,
        Greek = 161,
        Turkish = 162,
        Hebrew = 177,
        Arabic = 178,
        Baltic = 186,
        Russian = 204,
        Thai = 222,
        EastEurope = 238,
        OEM = 255,
      }
    
      public enum LogFontPrecision : byte {
        Default = 0,
        String = 1,
        Raster = 6,
      }
    
      public enum LogFontClipPrecision : byte {
        Default = 0,
        Character = 1,
        Stroke = 2,
      }
    
      public enum LogFontQuality : byte {
        Default = 0,
        Draft = 1,
        NonAntiAliased = 3,
        AntiAliased = 4,
        ClearType = 5,
        ClearTypeCompat = 6,
      }
    
      [Flags]
      public enum LogFontPitchAndFamily : byte {
        Default = 0,
        DontCare = 0,
        Fixed = 1,
        Variable = 2,
        Roman = 16,
        Swiss = 32,
        Modern = 48,
        Script = 64,
        Decorative = 80,
      }
    
      [StructLayout(LayoutKind.Sequential, CharSet = ((CharSet)4))]
      public class LOGFONT {
        public int Height;
        public int Width;
        public int Escapement;
        public int Orientation;
        public LogFontWeight Weight;
        [MarshalAs(UnmanagedType.U1)]
        public bool Italic;
        [MarshalAs(UnmanagedType.U1)]
        public bool Underline;
        [MarshalAs(UnmanagedType.U1)]
        public bool StrikeOut;
        public LogFontCharSet CharSet;
        public LogFontPrecision OutPrecision;
        public LogFontClipPrecision ClipPrecision;
        public LogFontQuality Quality;
        public LogFontPitchAndFamily PitchAndFamily;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
        public string FaceName;
        public LOGFONT(string faceName) {
          this.Height = 0;
          this.Width = 0;
          this.Escapement = 0;
          this.Orientation = 0;
          this.Weight = LogFontWeight.DontCare; ;
          this.Italic = false;
          this.Underline = false;
          this.StrikeOut = false;
          this.CharSet = LogFontCharSet.Default;
          this.OutPrecision = LogFontPrecision.Default;
          this.ClipPrecision = LogFontClipPrecision.Default;
          this.Quality = LogFontQuality.Default; ;
          this.PitchAndFamily = LogFontPitchAndFamily.Default;
          this.FaceName = faceName;
        }
        public bool IsFixedPitch {
          get { 
            return (this.PitchAndFamily & LogFontPitchAndFamily.Fixed) == LogFontPitchAndFamily.Fixed;
          }
        }
      }
    }
    



     

     //**************************************************

     

    APPROACH 2: using GDI32 GetTextMetrics

    Problem : Throws an ExecutionEngineException on call to GetTextMetrics

     



    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Drawing;
    using System.Runtime.InteropServices;
    
    namespace TextMetricsLib {
    
      public static class TextMetrics {
    
        // tmPitchAndFamily flags 
        public const byte 
          TMPF_FIXED_PITCH = 1,
          TMPF_VECTOR = 2,
          TMPF_DEVICE = 8,
          TMPF_TRUETYPE = 4;
    
        [DllImport("Gdi32.dll", CharSet = CharSet.Unicode)]
        static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
    
        [DllImport("Gdi32.dll", CharSet = CharSet.Unicode)]
        static extern bool GetTextMetrics(IntPtr hdc, out TEXTMETRIC lptm);
    
        [DllImport("Gdi32.dll", CharSet = CharSet.Unicode)]
        static extern bool DeleteObject(IntPtr hdc);
    
        [StructLayout(LayoutKind.Sequential)]
        public struct TEXTMETRIC {
          public int tmHeight;
          public int tmAscent;
          public int tmDescent;
          public int tmInternalLeading;
          public int tmExternalLeading;
          public int tmAveCharWidth;
          public int tmMaxCharWidth;
          public int tmWeight;
          public int tmOverhang;
          public int tmDigitizedAspectX;
          public int tmDigitizedAspectY;
          public char tmFirstChar;
          public char tmLastChar;
          public char tmDefaultChar;
          public char tmBreakChar;
          public byte tmItalic;
          public byte tmUnderlined;
          public byte tmStruckOut;
          public byte tmPitchAndFamily;
          public byte tmCharSet;
        }
    
        public static TEXTMETRIC Get_TEXTMETRICS(Graphics graphics, Font font) {
          IntPtr hDC = graphics.GetHdc();
          TEXTMETRIC textMetric;
          IntPtr hFont = font.ToHfont();
          try {
            IntPtr hFontPrevious = SelectObject(hDC, hFont);
            bool result = GetTextMetrics(hDC, out textMetric);
            SelectObject(hDC, hFontPrevious);
          }
          catch (Exception ex) {
            System.Diagnostics.Debug.WriteLine(ex);
            textMetric = null;
          }
          finally {
            DeleteObject(hFont);
            graphics.ReleaseHdc(hDC);
          }
          return textMetric;
        }
      }
    }
    




    //**************************************************

     

    //APPROACH 3: using class TextMetrics and VisualSytleRender

    //  Problem : Throws an InvalidOperationException - "Object is currently in use elsewhere on

    //  Call to: IntPtr oldhDC = SelectObject(hDC, fhDC);

     

     

     private bool IsAFixedPitchFontFamily(FontFamily aFontFamily) {
        bool isFixed = false;
    
        // find the first fontStyle defined by this family
        FontStyle[] fStyles = { FontStyle.Regular, FontStyle.Bold, FontStyle.Italic, 
          FontStyle.Underline, FontStyle.Strikeout };
        FontStyle aFontStyle = fStyles[0];
        int numStyles = fStyles.GetLength(0);
        for (int i = 0; i < numStyles; i++) {
          aFontStyle = fStyles[i];
          if (aFontFamily.IsStyleAvailable(aFontStyle)) {
            break;
          }
        }
    
        using (Font f = new Font(aFontFamily.Name, 10, aFontStyle)) {
          using ( Bitmap bm = new Bitmap(100, 100)) {
            Graphics g = Graphics.FromImage(bm);
            VisualStyleElement vsElem = VisualStyleElement.Button.PushButton.Normal;
            if (VisualStyleRenderer.IsElementDefined(vsElem)) {
              VisualStyleRenderer renderer = new VisualStyleRenderer(vsElem);
              try {
                IntPtr fhDC = f.ToHfont();
                IntPtr hDC = g.GetHdc();
                IntPtr oldhDC = SelectObject(hDC, fhDC);
                TextMetrics tm = renderer.GetTextMetrics(g);
                SelectObject(hDC, oldhDC);
                DeleteObject(fhDC);
                if ((tm.PitchAndFamily & TextMetricsPitchAndFamilyValues.FixedPitch) == TextMetricsPitchAndFamilyValues.FixedPitch)
                  isFixed = true;
                else
                  isFixed = false;
              }
              catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine(ex);
                sFixed = false;
              }
            } // if
          } // using bm
        } // using f
        return isFixed;
      } //IsAFixedPitchFontFamily()
    
    
    Tuesday, June 09, 2009 7:55 AM

Answers

  • Hmm, this is indeed a lot harder than it ought to be.  GDI+ doesn't set the LOGFONT.lfPitchAndFamily field at all.  Looks like some legacy code that could no longer be supported, EnumFontFamiliesEx() has a similar restriction.  Hacking away at it, this code produced a correct list of fonts:

        public static List<FontFamily> EnumFixedPitchFonts() {
          List<FontFamily> retval = new List<FontFamily>();
          using (Graphics gr = Application.OpenForms[0].CreateGraphics()) {
            foreach (FontFamily fam in FontFamily.Families) {
              if (!fam.IsStyleAvailable(FontStyle.Regular)) continue;
              using (Font fnt = new Font(fam, 10, FontStyle.Regular)) {
                if (gr.MeasureString("iii", fnt).Width == gr.MeasureString("WWW", fnt).Width)
                  retval.Add(fam);   
              }
            }
            return retval;
          }
        }

    The Graphics object creation could use a little help.

    Hans Passant.
    • Marked as answer by PMBottas Monday, June 15, 2009 11:35 PM
    Tuesday, June 09, 2009 1:42 PM
    Moderator
  • I tried one more thing.  I moved the VB6 code from the Form to a UserControl on a Form.  On  the UserControl the code returns 33 for every screen font and 47 for every printer font.  Only on the Form does the PitchAndFamily change with the font.  The code is identical, but the results are different.  I wouldn't trust the TEXTMETRIC as an indicator of PitchAndFamily no matter how it was obtained.   It might work today and not tomorrow.  Comparing "i" and "w" seems to be the most reliable method to determine relative pitch.
    • Marked as answer by Zhi-Xin Ye Monday, June 15, 2009 12:47 PM
    • Unmarked as answer by PMBottas Monday, June 15, 2009 11:34 PM
    • Marked as answer by PMBottas Monday, June 15, 2009 11:36 PM
    Thursday, June 11, 2009 9:22 AM

All replies

  • Hmm, this is indeed a lot harder than it ought to be.  GDI+ doesn't set the LOGFONT.lfPitchAndFamily field at all.  Looks like some legacy code that could no longer be supported, EnumFontFamiliesEx() has a similar restriction.  Hacking away at it, this code produced a correct list of fonts:

        public static List<FontFamily> EnumFixedPitchFonts() {
          List<FontFamily> retval = new List<FontFamily>();
          using (Graphics gr = Application.OpenForms[0].CreateGraphics()) {
            foreach (FontFamily fam in FontFamily.Families) {
              if (!fam.IsStyleAvailable(FontStyle.Regular)) continue;
              using (Font fnt = new Font(fam, 10, FontStyle.Regular)) {
                if (gr.MeasureString("iii", fnt).Width == gr.MeasureString("WWW", fnt).Width)
                  retval.Add(fam);   
              }
            }
            return retval;
          }
        }

    The Graphics object creation could use a little help.

    Hans Passant.
    • Marked as answer by PMBottas Monday, June 15, 2009 11:35 PM
    Tuesday, June 09, 2009 1:42 PM
    Moderator
  • Mr Passant,
    Well, kluge-y as is it, it does what I want - thanks.

    But, any idea how it is done in the "Font Picker" common dialog (when you set the FixedPitchOnly prop to true)?

    Thanks again
    Paul
    Tuesday, June 09, 2009 2:22 PM
  • For what it's worth,  the VB6 code How To List Fixed Pitch Fonts with GetTextMetrics works with the Screen or Printer object.  Similar .NET code with the hdc's obtained from the Graphics class returns 33 for tmPitchAndFamily for every FontFamily.
    • Edited by JohnWein Wednesday, June 10, 2009 9:31 AM
    Tuesday, June 09, 2009 7:26 PM
  • John,
    Yes, I saw this example also in my browsing but I didn't pay much attention to it. That is until today.

    Keep in mind that I have never written any VB.NET only Visual Basic. To tell you the truth, it's been about 10+ years since I've written ANY form of BASIC, (I've been into  C/C++/C# ) and that was just messin' around with VB6 because my roommate was learning it. I haven't written any production quality BASIC since I was on DEC VAX's & PDP-11's using BASIC Plus 2 & RMS DBMS back in the 1980's!!!

    Anyway, I followed the "Step-by-Step" instructions at the top of the page, and it gives me 20 or so errors even before I compile.
    I managed to straighten most of it out, other than getting the error "Printer is not declared".
    Probably because my printer died last month so I uninstalled the drivers!!

    But... You said that it works with Screen as well so I changed it to My.Computer.Screen but there's no FontCount or Fonts under that.

    Any help??


    Here's where I'm at  (look for the ?????'s)

    Oh, and shouldn't this :

       If (tm.tmPitchAndFamily And FIXED_PITCH_BIT) = 0 Then

    be this:

        If (tm.tmPitchAndFamily And FIXED_PITCH_BIT) = FIXED_PITCH_BIT Then

    if it IS a fixed pitch font?

    Equal to 0 would mean that the bit is NOT set, correct?

    (then again, It is 3:45 AM EDT as I write this and I've been coding since 8:00 AM yesterday - straight thru)

    Thanks,
    Paul

    Option Explicit On
    
    Public Class Form1
    
    
        Private Declare Function GetTextMetrics Lib "gdi32" _
           Alias "GetTextMetricsA" _
           (ByVal hdc As Long, _
        ByVal lpMetrics As TEXTMETRIC) _
           As Long
    
        Private Structure TEXTMETRIC
            Dim tmHeight As Long
            Dim tmAscent As Long
            Dim tmDescent As Long
            Dim tmInternalLeading As Long
            Dim tmExternalLeading As Long
            Dim tmAveCharWidth As Long
            Dim tmMaxCharWidth As Long
            Dim tmWeight As Long
            Dim tmOverhang As Long
            Dim tmDigitizedAspectX As Long
            Dim tmDigitizedAspectY As Long '
            Dim tmFirstChar As Byte
            Dim tmLastChar As Byte
            Dim tmDefaultChar As Byte
            Dim tmBreakChar As Byte
            Dim tmItalic As Byte
            Dim tmUnderlined As Byte
            Dim tmStruckOut As Byte
            Dim tmPitchAndFamily As Byte
            Dim tmCharSet As Byte
        End Structure
    
        Const FIXED_PITCH_BIT As Byte = 1
    
        Private Sub Command1_Click()
            Dim index As Long
            Dim tm As TEXTMETRIC
            Dim ret As Long
            Dim FontFound As Boolean
    
            FontFound = False   ' Just in case none are found!
            List1.Items.Clear()
            For index = 0 To My.Computer.Screen ????? FontCount - 1      ' Determine number of fonts.
                ?????.FontName = ?????.Fonts(index)  ' Select the font.
                ret = GetTextMetrics(?????.hdc, tm)    ' Retrieve information.
                ' Test the fixed pitch bit.
                ' Fonts with this bit off are fixed pitch.
                If (tm.tmPitchAndFamily And FIXED_PITCH_BIT) = 0 Then
                    List1.Items.Add(?????.Fonts(index))
                    FontFound = True   ' Found at least one!
                End If
            Next index
            If Not FontFound Then List1.Items.Add("No fixed pitched fonts found!")
        End Sub
    
    End Class
    






    Wednesday, June 10, 2009 7:48 AM
  • It's VB6 code,  not VB.NET code.  I can't get very similar code to return  anything other than 33 for tmPitchAndFamily in .NET.
    Wednesday, June 10, 2009 9:27 AM
  • What do you mean by: "anything other than 33 for tmPitchAndFamily in .NET."
    can I see your code, please?
    I can't ANY return values for tmPitchAndFamily
    Paul
    Wednesday, June 10, 2009 9:30 AM
  • Theer has got to be a way to get at this info.
    I mean, how in the world are they getting it at in the Font picker common dialog
    (set the FixedPitchOnly property to true and the dialog will only show the fixed pitch fonts!!)

     I've never stepped into the BCL source (can I even do that under VS2005 - ie is the .NET 2.0 source available)

    Wednesday, June 10, 2009 9:36 AM
  • I mean the value returned in tmPicthAndFamily from GetTextMetrics is always 33.  I didn't save my .NET code because it wasn't of any value.
    Wednesday, June 10, 2009 9:40 AM
  • This is wsa under VB?

    my first attempt (see OP - code for  APPROACH 1) under C# always returns zero for tmPicthAndFamily!

    Wednesday, June 10, 2009 9:44 AM
  • This is the code I used.  I referenced vjslib and targeted x86.

    using com.ms.win32;
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
          int HDc = User32.GetDC((int)this.Handle);
          TEXTMETRIC tm = new TEXTMETRIC();
          foreach (FontFamily FF in FontFamily.Families)
          {
            try
            {
              this.Font = new Font(FF, 10);
            }
            catch (Exception ex)
            {
              Console.WriteLine(ex.ToString());
            }
            Gdi32.GetTextMetrics(HDc, tm);
            Console.WriteLine(FF.Name + " " + tm.tmPitchAndFamily.ToString());
          }
        }
      }
    }
    
    Wednesday, June 10, 2009 10:19 AM
  • Stepping into the BCL souce isn't going to help.  The FontDialog is a native Windows dialog.  Certainly, it can (or could) be done as testified by the VB6 code, which I verified works fine.  There's a lot of legacy code that still works that is difficult to duplicate today.
    Wednesday, June 10, 2009 10:27 AM
  • John,

    Well thank you for trying, I really appreciate it.

     

    Your code got me thinking of something else I came across while browsing for a solution (here)

    The function GDI32.GetOutlineMetrics; it apparently is specifically designed for TTFs.

     

     I tried modifying your code to use that method instead but on the first call to the function, I can’t get even get it to return me the byte count it needs for a buffer size for the second call to get the metrics. (it returns zero bytes) I’m fairly new to .NET and even though I have years of experience writing low level stuff, like device drivers, runtime systems, library tools, etc in various assembly languages, I guess I'm a little bit in over my head here.

    (need to dive in deep to PInvolk, Marshalling and Reflection techniques. Add those to my list of .NET "must learn"s)
     

    For now I guess I’m going to have to take the kludged way out and compare the length the length of two characters using MeasureString and just assume that there is a fairly low percentage (like zero) of variable pitch fonts out there where the width of a lowercase “i” is the same as a capital “W”.

     

    However, if some time in the future, the answer to this comes to you in flash of brilliance, please don’t hesitate to drop me an email, because this one is going to be crawling around in the back of my mind for some time to come.

     

    There has got just to be a way to get at this info!

     

    (You don’t suppose that the VisualStyleRenderer.GetTextMetrics method gives valid values for PitchandFamily? – nah, it probably calls the same under lying base methods. Why reinvent the wheel)

     

    Thanks again

    Paul Bottas

     

    Thursday, June 11, 2009 2:24 AM
  • VisualStyleRenderer.GetTextMetrics returns 0 for all fonts.  Also, it requires that the user has visual styles turned on.  I couldn't get anything out of GetOutlineTextMetrics either.
    Thursday, June 11, 2009 6:11 AM
  • John,
    Well that good to know.
    Maybe my skill set hasn't tarnished as much as thought it has, being away from any serious coding for 7+ years.
    (I got laid off back in September as manufacturing QC manager and decided to brush up on coding by learning C# & .NET while I'm not looking for work)

    Again my thanks!

    You wouldn't happen to have any inside contacts at MSFT that you could put this one to.
    Like I said in my OP, over the years, its seems that a lot of people have asked this very question.
    With nary a satisfactory solution.
    Paul

    Thursday, June 11, 2009 6:25 AM
  • I tried one more thing.  I moved the VB6 code from the Form to a UserControl on a Form.  On  the UserControl the code returns 33 for every screen font and 47 for every printer font.  Only on the Form does the PitchAndFamily change with the font.  The code is identical, but the results are different.  I wouldn't trust the TEXTMETRIC as an indicator of PitchAndFamily no matter how it was obtained.   It might work today and not tomorrow.  Comparing "i" and "w" seems to be the most reliable method to determine relative pitch.
    • Marked as answer by Zhi-Xin Ye Monday, June 15, 2009 12:47 PM
    • Unmarked as answer by PMBottas Monday, June 15, 2009 11:34 PM
    • Marked as answer by PMBottas Monday, June 15, 2009 11:36 PM
    Thursday, June 11, 2009 9:22 AM
  • John,
    Now I'm reallllly confused (I think.)

    Are you saying that you added a control to the form (let's say a TextBox)
    and in the statements:

    int HDc = User32.GetDC((int)this.Handle);

      and  

    this.Font = new Font(FF, 10);

    the "this"  is the UserControl?? (ie the TextBox) and it works???

    Paul

    • Edited by PMBottas Monday, June 15, 2009 8:27 PM
    Monday, June 15, 2009 8:21 PM
  • No.  The VB6 code only works with a Form.

    "I moved the VB6 code from the Form to a UserControl on a Form.  On  the UserControl the code returns 33 for every screen font and 47 for every printer font.  Only on the Form does the PitchAndFamily change with the font."

    What isn't clear?  Does this make it clearer:  Only when the VB6 code is on a Form does the PitchAndFamily change with the font. That is, a stand alone VB6 exe.  It won't work in a dll or ocx.

    Monday, June 15, 2009 8:40 PM
  • John,
    First, I really appreciate the time you've taken with this.

    Secondly, sorry about that.

    I thought that you were getting the handle to the form itself.

    I got so pumped when you replied last week, that I missed the fact that it was a Click handler for a button.

    I took your (and Mr. Passant's) advice and went with just comparing the length of 'i' to 'W'. (and I don't have VB6 and
    I couldn't check your code as is, and besides I had already implemented the compare method and was off on something else. I just saw today that a Moderator had marked your reply as the answer and was just re-visting the issue)

    In my app, in the dialog where the user changes fonts, I show a sample of what the report will look like if they choose a given font (fixed or otherwise, with the fixed-pitch ones marked in bold). I'm not going to get so elaborate and compute columns width for the longest string for each column and position the output a given point in the form. It's really just a simple listing so if the want to go mess up the columns, so be it!!

    Thanks again,
    Paul

     

    Monday, June 15, 2009 9:11 PM
  • You should mark Nobugz's post as the answer.
    Monday, June 15, 2009 10:11 PM