Jakub Florczyk - Blog o programowaniu .NET i Android

Programista praktyczny

Lepszy MeasureString w .NET Compact Framework

Jeżeli starałeś się zbudować dynamiczne GUI w .NET Compact Framework, prawdopodobnie zauważyłeś niedostatek metody MeasureString z parametrem SizeF.

W .NET CF, Graphics ma tylko jedną metodę mierzenia napisów:

        ///

        /// Measures the specified string when drawn with the specified Font.
        /// 

        public SizeF MeasureString(string text, Font font);

Dla długiego napisu w którym nie ma znaków łamania powyższa metoda zwraca kosmicznie długi rozmiar.

Jeżeli pisałeś wcześniej w wersji desktopowej to pewnie zauważyłeś, że jest wersja tej metody z parametrem SizeF, który określa docelowy rozmiar w który napis będzie wpasowywany i łamany. Obejściem tego problemu jest poniższy class extension na Graphicsa, który przyjmuje parametr Rectangle jako prostokąt do wpasowania napisu.

internal static class GraphicExtensions
    {
        private struct Rect
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;

            public Rect(Rectangle r)
            {
                Left = r.Left;
                Top = r.Top;
                Bottom = r.Bottom;
                Right = r.Right;
            }
        }

        public static SizeF MeasureString(this Graphics graphic, string text, Font font, Rectangle rectangle)
        {
            Rect bounds = new Rect(rectangle);
            IntPtr hFont = font.ToHfont();
            IntPtr hDc = graphic.GetHdc();            

            IntPtr originalObject = SelectObject(hDc, hFont);
            DrawText(hDc, text, text.Length, ref bounds, DT_CALCRECT | DT_WORDBREAK);
            SelectObject(hDc, originalObject);
            graphic.ReleaseHdc(hDc);

            return new SizeF(bounds.Right - bounds.Left, bounds.Bottom - bounds.Top);
        }

        private static int DT_CALCRECT = 0x00000400;
        private static int DT_WORDBREAK = 0x00000010; 

        [DllImport("coredll.dll")]
        private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

        [DllImport("coredll.dll")]
        private static extern int DrawText(IntPtr hdc, string lpStr, int nCount, ref Rect lpRect, int wFormat);
    }
Next post »

One ResponseLeave one →

Leave a Reply