On Win7 x64 and a defined AnyCPU build configuration, I get a NullRefernce Exception on calling the Win32 method "GetTextMetrics"
The problem is inside the interop definition in: _../Source/HtmlRenderer.WinForms/Utilities/Win32Utils.cs_
The definition have to be changed from CharSet.Auto to CharSet.Ansi.
Here the correct definition:
[DllImport("gdi32.dll", CharSet = CharSet.__Ansi__)]
public static extern bool GetTextMetrics(IntPtr hdc, out TextMetric lptm);
Comments: Yes, you are right, my previous definition wasn't correct in all cases. I found a good resource for pInvoke, also listed on CodePlex: https://clrinterop.codeplex.com/releases/view/14120 Is is called "P/Invoke Interop Assistant" and there you can search for the right definition of many existing Win32 functions. Here is my new definition which works correctly for me: ``` [DllImport("gdi32.dll", EntryPoint = "GetTextMetricsW")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetTextMetricsW([In] IntPtr hdc, [Out] out TEXTMETRICW lptm); [DllImport("gdi32.dll", EntryPoint = "GetTextMetricsA")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetTextMetricsA([In] IntPtr hdc, [Out] out TEXTMETRICA lptm); [StructLayout(LayoutKind.Sequential)] public struct TEXTMETRICW { 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 ushort tmFirstChar; public ushort tmLastChar; public ushort tmDefaultChar; public ushort tmBreakChar; public byte tmItalic; public byte tmUnderlined; public byte tmStruckOut; public byte tmPitchAndFamily; public byte tmCharSet; } [StructLayout(LayoutKind.Sequential)] public struct TEXTMETRICA { 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 byte tmFirstChar; public byte tmLastChar; public byte tmDefaultChar; public byte tmBreakChar; public byte tmItalic; public byte tmUnderlined; public byte tmStruckOut; public byte tmPitchAndFamily; public byte tmCharSet; } ``` And the using of the functions can be done in this way: (But i have only tested on Win7 x64) ``` if (Environment.Is64BitOperatingSystem) { TEXTMETRICW lptm; Win32Utils.GetTextMetricsW(_hdc, out lptm); ((FontAdapter)font).SetMetrics(size.Height, lptm.tmHeight - lptm.tmDescent + lptm.tmUnderlined + 1); } else { TEXTMETRICA lptm; Win32Utils.GetTextMetricsA(_hdc, out lptm); ((FontAdapter)font).SetMetrics(size.Height, lptm.tmHeight - lptm.tmDescent + lptm.tmUnderlined + 1); } ``` Now it works on x86 and x64 build configuration, inside MSVS 2010 debugger and standalone.
The problem is inside the interop definition in: _../Source/HtmlRenderer.WinForms/Utilities/Win32Utils.cs_
The definition have to be changed from CharSet.Auto to CharSet.Ansi.
Here the correct definition:
[DllImport("gdi32.dll", CharSet = CharSet.__Ansi__)]
public static extern bool GetTextMetrics(IntPtr hdc, out TextMetric lptm);
Comments: Yes, you are right, my previous definition wasn't correct in all cases. I found a good resource for pInvoke, also listed on CodePlex: https://clrinterop.codeplex.com/releases/view/14120 Is is called "P/Invoke Interop Assistant" and there you can search for the right definition of many existing Win32 functions. Here is my new definition which works correctly for me: ``` [DllImport("gdi32.dll", EntryPoint = "GetTextMetricsW")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetTextMetricsW([In] IntPtr hdc, [Out] out TEXTMETRICW lptm); [DllImport("gdi32.dll", EntryPoint = "GetTextMetricsA")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetTextMetricsA([In] IntPtr hdc, [Out] out TEXTMETRICA lptm); [StructLayout(LayoutKind.Sequential)] public struct TEXTMETRICW { 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 ushort tmFirstChar; public ushort tmLastChar; public ushort tmDefaultChar; public ushort tmBreakChar; public byte tmItalic; public byte tmUnderlined; public byte tmStruckOut; public byte tmPitchAndFamily; public byte tmCharSet; } [StructLayout(LayoutKind.Sequential)] public struct TEXTMETRICA { 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 byte tmFirstChar; public byte tmLastChar; public byte tmDefaultChar; public byte tmBreakChar; public byte tmItalic; public byte tmUnderlined; public byte tmStruckOut; public byte tmPitchAndFamily; public byte tmCharSet; } ``` And the using of the functions can be done in this way: (But i have only tested on Win7 x64) ``` if (Environment.Is64BitOperatingSystem) { TEXTMETRICW lptm; Win32Utils.GetTextMetricsW(_hdc, out lptm); ((FontAdapter)font).SetMetrics(size.Height, lptm.tmHeight - lptm.tmDescent + lptm.tmUnderlined + 1); } else { TEXTMETRICA lptm; Win32Utils.GetTextMetricsA(_hdc, out lptm); ((FontAdapter)font).SetMetrics(size.Height, lptm.tmHeight - lptm.tmDescent + lptm.tmUnderlined + 1); } ``` Now it works on x86 and x64 build configuration, inside MSVS 2010 debugger and standalone.