Getting and using TextMetrics from dgi32.dll

I am attempting to "TextMetrics" from the gdi32.dll library.

the compiler if flaggin the function GetTextMetrics with
Error      1      Inconsistent accessibility: parameter type 'WindowsControlLibrary1.SW.TEXTMETRIC' is less accessible than method 'WindowsControlLibrary1.SW.GetTextMetrics(System.IntPtr, WindowsControlLibrary1.SW.TEXTMETRIC)'      C:\Users\garaber\Documents\Dev Software\BitSWTest\WindowsControlLibrary1\UserControl1.cs      41      33      WindowsControlLibrary1
I've seen this example out on the web and it seems to be working for others.  Thanks guys
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
      public static extern bool GetTextMetrics(IntPtr hdc, TEXTMETRIC lptm);

Open in new window

LVL 2
graberAsked:
Who is Participating?
 
graberConnect With a Mentor Author Commented:
I am not sure of the differences internally.  But it did entail a switch for gdi32.dll to vjslib.dll.  This may not be the solution though.  One of the comments on the sight mentioned, "I wouldn't trust the TEXTMETRIC as an indicator of PitchAndFamily no matter how it was obtained.   It might work today and not tomorrow."  So there are still some questions.  At best, for the time being, this code will be suspect.  I want to thank you carl for responding to the post and your help.  I'm going to shut this tread down.  I was under the presumption that GetTextMetrics was the correct approach.  The correct question now is "How do you properly measure text in a C# application"
0
 
Carl TawnSystems and Integration DeveloperCommented:
It sounds like you have a struct defined called TEXTMETRIC that has an accessibility level of private, internal or protected. Its complaining because that would give it a lower accessibility level than the method.
0
 
graberAuthor Commented:
TEXTMETRIC is defined just above.  The IDE has identified the function GetTextMetrics as the problem.  Not sure what I'm doing wrong.
public partial class SW : UserControl
   {
      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 char tmItalic; 
         public char tmUnderlined; 
         public char tmStruckOut; 
         public char tmPitchAndFamily; 
         public char tmCharSet; 
      }

      [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
      public static extern bool GetTextMetrics(IntPtr hdc, TEXTMETRIC lptm);

Open in new window

C-.jpg
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
Carl TawnSystems and Integration DeveloperCommented:
You need to change the line:

    struct TEXTMETRIC

To:

    public struct TEXTMETRIC

If you don't say otherwise then a nested struct is private. In this case that is causing a problem because it gives the struct a more restrictive visibility that the method for which it is a parameter. If you change the declaration, as above, so that it is public then it should sort the problem.
0
 
graberAuthor Commented:
I've been writing software for some time now and I still get tag by this stuff.  This is embarrassing.  Thanks Carl.  As it turns out I'm a cheep date :)
0
 
graberAuthor Commented:
GetText Metrics is returning false.... Did I miss something?
   public partial class Form1 : Form
   {
      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 char tmItalic; 
         public char tmUnderlined; 
         public char tmStruckOut; 
         public char tmPitchAndFamily; 
         public char tmCharSet; 
      }

      [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
      public static extern bool GetTextMetrics(IntPtr hDC, TEXTMETRIC lptm);

      [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
      public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

      [DllImport("Gdi32.dll", CharSet = CharSet.Auto)]
      public static extern bool DeleteObject(IntPtr hdc);

      [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
      public static extern UInt32 GetLastError();


      public Form1()
      {
         InitializeComponent();
      }

      private void Form1_Paint(object sender, PaintEventArgs e)
      {
         Font font = new Font(Font.FontFamily, 10, FontStyle.Regular, GraphicsUnit.Pixel);
         TEXTMETRIC tm = new TEXTMETRIC();
         IntPtr hDC = e.Graphics.GetHdc();
         IntPtr hFont = font.ToHfont();
         IntPtr hFontPrev = SelectObject(hDC, hFont);
         bool bResults = GetTextMetrics(hDC, tm);
         SelectObject(hDC, hFontPrev);
         DeleteObject(hFont);
         e.Graphics.ReleaseHdc(hDC);
      }

Open in new window

0
 
graberAuthor Commented:
Am I too assume that this matter is closed.  The question as asking for "Getting and using TextMetrics".  We're not using it yet.
Gregg
0
 
Carl TawnSystems and Integration DeveloperCommented:
Sorry, didn't see that last post. Try the following, as a test, and see if it returns true:
            System.Windows.Forms.Label label = new System.Windows.Forms.Label();
            Graphics g = Graphics.FromHwnd(label.Handle);

            API.TEXTMETRIC metric = new API.TEXTMETRIC();
            bool result = API.GetTextMetrics(g.GetHdc(), metric);

Open in new window

0
 
graberAuthor Commented:
Thanks carl for responding.  I had to alter it a bit to work with the stub.  See if this is ok.  As it runs right now it is still returning false. Bummer.  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace GetTextMetricsTest
{
   public partial class Form1 : Form
   {
      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 char tmItalic; 
         public char tmUnderlined; 
         public char tmStruckOut; 
         public char tmPitchAndFamily; 
         public char tmCharSet; 
      }

      [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
      public static extern bool GetTextMetrics(IntPtr hDC, TEXTMETRIC lptm);

      [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
      public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

      [DllImport("Gdi32.dll", CharSet = CharSet.Auto)]
      public static extern bool DeleteObject(IntPtr hdc);

      [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
      public static extern UInt32 GetLastError();


      public Form1()
      {
         InitializeComponent();
      }

      private void Form1_Paint(object sender, PaintEventArgs e)
      {
         System.Windows.Forms.Label label = new System.Windows.Forms.Label();
         Graphics g = Graphics.FromHwnd(label.Handle);
         TEXTMETRIC tm = new TEXTMETRIC();
         bool result = GetTextMetrics(g.GetHdc(), tm); 
         //Font font = new Font(Font.FontFamily, 10, FontStyle.Regular, GraphicsUnit.Pixel);
         //TEXTMETRIC tm = new TEXTMETRIC();
         //IntPtr hDC = e.Graphics.GetHdc();
         //IntPtr hFont = font.ToHfont();
         //IntPtr hFontPrev = SelectObject(hDC, hFont);
         //bool bResults = GetTextMetrics(hDC, tm);
         //SelectObject(hDC, hFontPrev);
         //DeleteObject(hFont);
         //e.Graphics.ReleaseHdc(hDC);
      }
   }
}

Open in new window

0
 
graberAuthor Commented:
Carl ... Do you own and operate your own business?...
0
 
Carl TawnSystems and Integration DeveloperCommented:
Ok, that should be working. There must be something in your form, or elsewhere that is causing GetTextMetrics to return false. I would try that block of code by itself in a simple winforms app, but don't put the code in the Paint event.

On a side note, I don't run my own business, but I do do the occasional freelance project.
0
 
graberAuthor Commented:
How about a C# console application?
0
 
Carl TawnSystems and Integration DeveloperCommented:
You can do it as a console app, but you will need to add references to the System.Windows.Forms and System.Drawing assemblies, as they won't be included by default.
0
 
graberAuthor Commented:
Will do.  Thanks again carl.
0
 
graberAuthor Commented:
The code as it stands is still returning false.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;

namespace ConsoleGetTextMetrics
{
   class Program
   {
      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 char tmItalic; 
         public char tmUnderlined; 
         public char tmStruckOut; 
         public char tmPitchAndFamily; 
         public char tmCharSet; 
      }

      [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
      public static extern bool GetTextMetrics(IntPtr hDC, TEXTMETRIC lptm);
      [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
      public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
      [DllImport("Gdi32.dll", CharSet = CharSet.Auto)]
      public static extern bool DeleteObject(IntPtr hdc);
      [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
      public static extern UInt32 GetLastError();

      static void Main(string[] args)
      {

         System.Windows.Forms.Label label = new System.Windows.Forms.Label();
         Graphics g = Graphics.FromHwnd(label.Handle);
         TEXTMETRIC tm = new TEXTMETRIC();
         bool result = GetTextMetrics(g.GetHdc(), tm); 
      }
   }
}

Open in new window

0
 
graberAuthor Commented:
Sorry about the extra DllImports they weren't necessary and should have been removed.
0
 
graberAuthor Commented:
I found this out on .Net Framework Developement Center
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/1bc0166b-8a68-4067-a44b-e11ff7d55720
And it appears to work.  I'm using visual studio 2005 on vista OS with a reference for vjslib (com.ms.win32)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using com.ms.win32;

namespace GetTextMetricsAttempt3
{
   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());
         }
      }
   }
}

Open in new window

0
 
Carl TawnSystems and Integration DeveloperCommented:
Oh well, as long as its working for you now. Although I can't see any reason why your other version shouldn't have worked.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.