2009-05-07 8 views
6

Ich habe ein Steuerelement in C# WinForms subclassed, und bin benutzerdefinierte Zeichnung Text in meinem OnPaint() Handler. Die Schriftart Courier New mit dem folgenden Code in meiner Form festgelegt ist:Warum zeigt DrawString unerwartetes Verhalten in C# Winforms?

FontFamily family = new FontFamily("Courier New"); 
this.myControl.Font = new Font(family, 10); 

Bei der Steuerung selbst wird die Zeichenfolge in realText gespeichert, und ich verwende den folgenden Code, um es auf den Bildschirm zu zeichnen:

protected override void OnPaint(PaintEventArgs e) 
{ 
    base.OnPaint(e); 

    e.Graphics.DrawString(realText, Font, new SolidBrush(ForeColor), ClientRectangle); 
} 

das Ergebnis für einige zufällige Beispiel Text sieht wie folgt aus: http://img219.imageshack.us/img219/1778/courier.png

Wenn Sie die Ansicht vergrößern, können Sie beispielsweise sehen können, dass der Raum zwischen dem ersten ‚als‘ anders ist, als t er Abstand zwischen dem zweiten 'as' (1 Pixel gegenüber 2 Pixel). Hat jemand eine Idee, was das verursachen könnte oder wie ich es verhindern kann? Es gibt viel mehr Ähnlichkeiten in der Beabstandung, da ich mit verschiedenen Schriftarten zeichne, aber ich nehme an, dass es sich um Ergebnisse desselben Problems handelt.

Vielen Dank im Voraus für Ihre Ideen.

Antwort

6

Ich rate, dass es ist, weil Sie Graphics.DrawString() anstelle von TextRenderer.DrawText() verwenden. Der ehemalige malt Text mit GDI +, die irgendwie beschissen und veraltet ist. Letzteres verwendet GDI, das moderner ist (in Bezug auf Text-Rendering). Ich glaube, das ist der Unterschied, der in der vorherigen Antwort (WinForms vs. Windows) festgestellt wurde.

Sie könnten auch versuchen, die Überladung von Graphics.DrawString(), die ein StringFormat Objekt und geben Sie StringFormat.GenericTypographic. Dies ist jedoch ein bisschen ein hack um das Problem. Wenn Sie .NET 2.0 oder höher verwenden, sollten Sie die Klasse TextRenderer anstelle der beschissenen Klasse Graphics für alle Ihre Textdarstellungsanforderungen verwenden. Graphics.MeasureString() und Graphics.DrawString() existieren ausschließlich für Abwärtskompatibilität mit .NET 1.0 und 1.1.

bearbeiten: Oh ja, und Ihr Code leckt ein GDI-Objekt bei jedem Malzyklus. Pinselobjekte sind verwaltete Wrapper um nicht verwaltete Ressourcen, daher müssen sie explizit entsorgt werden.

+0

Wunderbar, das hat es getan, ohne auf win32 Code zurückgreifen zu müssen. Danke – Ko9

+0

Wird das GDI-Objekt freigegeben, wenn der Garbage Collector ausgeführt wird? –

+0

Nein. Pinsel- und Stiftobjekte in .NET sind nur verwaltete Wrapper um nicht verwaltete Ressourcen (GDI-Pinsel oder -Stift). Wenn der Garbage Collector ausgeführt wird, wird der .NET-Wrapper, nicht jedoch das zugrunde liegende GDI-Objekt entfernt. Die allgemeine Faustregel für GDI-Objekte besteht darin, sie entweder in einen using-Block zu packen oder sie explizit in Ihrem Finalizer zu entfernen. Sie sollten dies überprüfen können, indem Sie den Task-Manager verwenden (aktivieren Sie die Spalte GDI-Objekte) und beobachten, wie sich die Anzahl erhöht, wenn Sie die Ressourcen verlieren. Die Anzahl wird nicht sinken, selbst wenn Sie den GC in Aktion treten. –

0

Ich muss ehrlich sein, aber das ist mir noch nie passiert. Allerdings versuchen die Smoothing zu Anti-Aliasing-Einstellung:

e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; 

Eine andere Sache beiseite, stellen Sie sicher, dass die von Ihrer Verwendung hat Double auf true gesetzt. Versuchen Sie auch, nicht ein neues SolidBrush in jedem OnPaint Aufruf zu erstellen ..

+0

Versuchte es, änderte nichts traurig. Versuchte alle Ihre Vorschläge tatsächlich, keiner von ihnen half: -/ – Ko9

0

Meine Erfahrung mit Malerei Texten subclassed Kontrollen WinForms ist, dass das Text-Rendering-Engine nutzt (GDI +?) Ist nicht so gut wie Windows-eigene Font-Engine und liefert sicherlich auch dann andere Ergebnisse, wenn es gut funktioniert.

Ich bin der Autor eines Visual Studio-Add-Ins (http://entrian.com/source-search), das Steuerelemente in Visual Studio erstellen muss und damit die Zeichensätze genauso aussehen wie die Standardsteuerelemente in Visual Studio (Listenansichten, Baumansichten usw.).) Ich muss WinForms umgehen und den Text mit der Win32-API malen:

... und Familie.

Wahrscheinlich nicht, was Sie hören wollten, aber da ist es.