Soru TextRenderer.MeasureText ve Graphics.MeasureString boyutunda uyuşmuyor


Bu bir yuvarlama problemi değil. Fark ~ 5+ piksel.

Test Çantası Dizesi: "" MACD (26,12,9) -0.000016 "

e.Graphics.MeasureString("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)
TextRenderer.MeasureText("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)

Sonuç her zaman:

139.3942
134

Neden bu kadar büyüklük farkı var? Sadece boya yöntemi dışındaki dize genişliğine ihtiyacım var. Fakat MeasureString ile eşleşmeli veya tersi.


23
2017-07-15 09:13


Menşei




Cevaplar:


TextRenderer metni oluşturmak için GDI'yı kullanır. Graphics GDI + kullanır. İki boyut farklı olduğundan, metin yerleştirme için biraz farklı bir yöntem kullanın.

Hangisini kullanmanız gerektiği, metnin gerçekte çizilmesi için neyin kullanılacağına bağlıdır. GDI + ile çiziyorsanız Graphics.DrawString, kullanarak ölçmek Graphics.MeasureString. GDI kullanarak çizim yapıyorsanız TextRenderer.DrawText, kullanarak ölçmek TextRenderer.MeasureText.

Metin bir Windows Forms denetiminde görüntülenecekse, TextRenderer Eğer UseCompatibleTextRendering ayarlandı false (varsayılan olan).

Sorunun satırları arasında okumak, kullanıyor görünüyorsun TextRenderer çünkü sende hiç yok Graphics dışında örnek Paint Etkinlik. Bu durumda, ölçümü yapmak için kendiniz bir tane oluşturabilirsiniz:

using( Graphics g = someControl.CreateGraphics() )
{
    SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}

Grafik örneğini oluşturmak için bir kontrole erişiminiz yoksa, bunu ekran için bir tane oluşturmak için kullanabilirsiniz.

using( Graphics g = Graphics.FromHwnd(IntPtr.Zero) )
{
     SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}

54
2017-07-15 09:23



Test ettiğim diğer tüm dizeler için boyut her ikisi için de doğrudur. Soru şu ki bu 'özel' durumda doğru değil. Framework, someControl.CreateGraphics () işlevini kullanmaya izin vermez. Kontrol mevcut değildir. - Aseem Gautam
+1, ayrıca bkz. stackoverflow.com/questions/6107280/... - takrl
@Aseem neredeyse sahibim her zaman İki deneyimim, deneyimlerimde oldukça farklı sonuçlar verdi. O zamandan beri kodu sildim, ama bir noktada, sınırların üzerinde düşündüğü metnin üstüne renkli kutular çizen üç ölçüm yöntemi vardı. Üçü de neredeyse her durumda farklıydı. - Shibumi
@Aseem: Dürüst olmak gerekirse oldukça normal TextRenderer.MeasureText ve Graphics.MeasureString farklı sonuçlar döndürmek için. Kontrol örneğiniz yoksa, Graphics tüm ekran için örnek; Cevabımı bu etkiyle güncelledim. - Sven
Bu blog yazısı neden açıklamaktadır. Net varsayılan olarak GDI + yerine metin oluşturma için GDI kullanıyor: blogs.msdn.com/b/jfoscoding/archive/2005/10/13/480632.aspx - RenniePet


MeasureString'i boya olayının dışında kullanmak için aşağıdaki sınıfı yaptım ve oldukça iyi çalışıyor.

public interface ITextMeasurer
    {
        SizeF MeasureString(string text, Font font, StringFormat format);
    }

    public class TextMeasurer : ITextMeasurer
    {
        private readonly Image _fakeImage;
        private readonly Graphics _graphics;

        public TextMeasurer()
        {
            _fakeImage = new Bitmap(1, 1);
            _graphics = Graphics.FromImage(_fakeImage);
        }

        public SizeF MeasureString(string text, Font font, StringFormat format)
        {
            return _graphics.MeasureString(text, font, int.MaxValue, format);
        }
    }

1
2017-07-15 14:24



Kullanarak bir denetiminiz yoksa bir Grafik örneği oluşturabilirsiniz. Graphics.FromHwnd(IntPtr.Zero)bir bitmap oluşturmaya gerek yoktur. Ayrıca, sınıfınız tek kullanımlık iki kaynağı kapsar, ancak tek kullanımlık değildir, bu kötü bir uygulamadır. - Sven
Aynı zamanda, bu arayüzün ne noktada olduğunu merak ediyorum. Arabirimler, yalnızca bir şeyin birden çok uygulamasını yapmayı beklerseniz kullanışlıdır. - Nyerguds
Arabirim ve uygulama farklı kütüphanelerde olduğunda da yararlıdırlar ve kütüphaneyi arayüzle değil, uygulama ile (örn. Kod enjeksiyonu) referans olarak kullanabilirsiniz. - Mike