GetFontUnicodeRanges (gdi32)
Last changed: tatiana.racheva@gmail.com-131.107.0.72

.
Summary

C# Signature:

[DllImport("gdi32.dll")]
static extern uint GetFontUnicodeRanges(IntPtr hdc, IntPtr lpgs);

User-Defined Types:

None.

Notes:

None.

Tips & Tricks:

Please add some!

Sample Code:

    //This code is nicly formated with a monospace font and a tab size of two white spaces.
    public static Void GetFontUnicodeRanges(Graphics g,Font f)
    {
        IntPtr hdc = g.GetHdc();
        IntPtr hFont = f.ToHfont();
        IntPtr old = SelectObject(hdc,hFont);
        int size = GetFontUnicodeRanges(hdc,IntPtr.Zero); //returns the size of the GLYPHSET structure in bytes required to store the information.
        IntPtr mem = Marshal.AllocHGlobal(size); //Allocates the unmanaged memory needed for the GLYPHSET structure.
        GetFontUnicodeRanges(hdc,mem); //Fills the GLYPHSET structure.
        //Now we have to extract the data from the GLYPHSET structure:
        //The unsafe way
        //int* p = (int*)mem.ToPointer(); //In order to access the GLYPHSET structure in the memory
        //The content of p is now the GLYPHSET structure
        //The GLYPHSET structure
        //{
        //    DWORD    cbThis;                        = p[0]
        //    DWORD    flAccel;                        = p[1]
        //    DWORD    cGlyphsSupported;    = p[2]
        //    DWORD    cRanges;                        = p[3]
        //    WCRANGE  ranges;                        = p[4] to p[cRanges + 3]
        //}
        //
        //The WCRANGE structure
        //{
        //  WCHAR  wcLow;                                = p[x] >> 16
        //  USHORT cGlyphs;                            = p[x] & 0xffff
        //}
        //The safe way, remember that the offset is in bytes
        int p0 = Marshal.ReadInt32(mem,0);
        int p1 = Marshal.ReadInt32(mem,4);
        int p2 = Marshal.ReadInt32(mem,8);
        int p3 = Marshal.ReadInt32(mem,12);
        //Uncomment this if us want proof of the flipping performed by Marshal.ReadInt32
        //        for(int i=0;i<size;i+=4)
        //        {
        //            int p = Marshal.ReadByte(mem,i);
        //            System.Diagnostics.Debug.Write(String.Format("{0,2:X}",p));
        //            p = Marshal.ReadByte(mem,i+1);
        //            System.Diagnostics.Debug.Write(String.Format("{0,2:X}",p));
        //            p = Marshal.ReadByte(mem,i+2);
        //            System.Diagnostics.Debug.Write(String.Format("{0,2:X}",p));
        //            p = Marshal.ReadByte(mem,i+3);
        //            System.Diagnostics.Debug.WriteLine(String.Format("{0,2:X}",p));
        //            p = Marshal.ReadInt32(mem,i);
        //            System.Diagnostics.Debug.WriteLine(String.Format("{0,8:X}",p));
        //        }
        int total = 0; //Must contain the same value as p2 after completing the for loop
        for(int i=0;i<p3;i++)
        {
            int p = Marshal.ReadInt32(mem,16+i*4);
            //Note that the order of the two elements in the WCRANGW structure is flipped.
            //The flip is performed by the ReadInt32, because of the way the x386 stores values in memory.
            //I.e. an int 0xabcd is stored 0xdcba. This means that the elements in the WCRANGW structure is
            //wcLow(0xab) cGlyphs(0xcd) is stored as 0xbadc the flipped value is 0xcdab
            int cGlyphs = p >> 16;
            int wcLow= p & 0xffff;
            total += cGlyphs;
        }
        System.Diagnostics.Debug.WriteLine(p2.ToString() + " == " + total.ToString());
        SelectObject(hdc,old);
        Marshal.FreeHGlobal(mem);
        g.ReleaseHdc(hdc);
    }

Alternative Managed API:

Do you know one? Please contribute it!

Documentation