Frage

Ich bin Erzeugung eine Quittung und bin mit der Graphics-Objekt der DrawString Methode aufzurufen den gewünschten Text zu drucken.

graphics.DrawString(string, font, brush, widthOfPage / 2F, yPoint, stringformat);

Dies funktioniert gut für das, was ich tun musste. Ich wusste immer, was ich den Ausdruck, so konnte ich keine Saiten manuell trimmen, damit es ordnungsgemäß auf 80mm Bonpapier passen würde. Dann hatte ich ein Extra an Funktionalität hinzuzufügen, die diese flexibler machen würde. Der Benutzer könnte in Strings übergeben, die an der Unterseite hinzugefügt werden würde.

Da ich nicht wusste, was sie setzen werde wurde, habe ich nur meine eigene Zeilenumbruch-Funktion, die auf und die Zeichenfolge selbst wickeln in einer Reihe von Zeichen erfolgt. Um die Anzahl der Zeichen, um herauszufinden, tat ich so etwas wie folgt aus:

float width = document.DefaultPageSettings.PrintableArea.Width;
int max = (int)(width / graphics.MeasureString("a", font).Width);

Nun ist die Breite zurückkehrt mir 283, die in mm ist etwa 72, was Sinn macht, wenn Sie sich für die Margen auf 80 mm Papier berücksichtigen.

Aber die MeasureString Methode 10.5 auf einem Courier New 8pt Schriftart zurück. Anstatt also um das, was von immer ich erwartet hatte 36 zu sein - 40, ich bin 26 bekommen, in zwei Zeilen Text resultierenden in 3-4 gedreht wird

.

Die Einheiten für PrintableArea.Width sind 1 / 100stel eines Zolls und der Pageunit für das Grafik-Objekt ist Display (die besagt, ist in der Regel 1 / 100stel eines Zolls für Drucker). Also warum bin ich nur 26 zurück zu bekommen?

War es hilfreich?

Lösung

Von WindowsClient.net:

  

GDI + fügt eine kleine Menge (1/6 em) an jedes Ende jeden angezeigten Zeichenfolge. Diese 1/6 em ermöglicht Glyphen mit überhängenden Enden (wie kursiv ‚ f ‘), und gibt auch GDI + eine kleine Menge Spielraum mit Rasteranpassung Expansion zu helfen.

     

Die Standardaktion von DrawString wird gegen Sie arbeitet benachbarte Läufe bei der Anzeige:

     
      
  • Zum einen die Standard-String fügt eine zusätzliche 1/6 em an jedem Ende eines jeden Ausgang;
  •   
  • Zweitens, wenn Einhängeraster Breiten geringer sind als entworfen, wird die Zeichenfolge darf ein em schrumpfen um bis.
  •   
     

Um diese Probleme zu vermeiden:

     
      
  • Geben Sie stets MeasureString und DrawString einen String basierend auf dem typographischen String (GenericTypographic).
      Stellen Sie die Grafik TextRenderingHint auf TextRenderingHintAntiAlias. Diese Rendering-Methode verwendet Anti-Aliasing und Subpixel-Glyphe Positionierung die Notwendigkeit für netz Einbau zu vermeiden, und ist somit von Natur aus unabhängig von der Auflösung.
  •   

Es gibt zwei Möglichkeiten von Text in .NET Zeichnung:

  • GDI + (graphics.MeasureString und graphics.DrawString)
  • GDI (TextRenderer.MeasureText und TextRenderer.DrawText)

Von Michael Kaplan (rip) ausgezeichnetem Blog Sortierung It All Out In .NET 1.1 alles verwendet GDI + für Text-Rendering. Aber es gab einige Probleme:

  
      
  • Es gibt einige Performance-Probleme durch die etwas staatenlos Art von GDI + verursacht, in dem Gerätekontexte eingestellt werden würde und dann das Original nach jedem Gespräch wieder hergestellt.
  •   
  • Die Formmaschinen für den internationalen Text haben viele Male für Windows / Uniscribe und für Avalon (Windows Presentation Foundation) aktualisiert worden, aber noch nicht für GDI + aktualisiert worden ist, die für neue Sprachen internationale Rendering Unterstützung bewirkt, nicht das gleiche Niveau haben, Qualität.
  •   

So sie wussten, sie wollten das .NET Framework ändern mit GDI zu stoppen + 's Text-Rendering-System, und verwenden Sie GDI . Zunächst hoffte, dass sie sie könnten einfach ändern:

graphics.DrawString

die alte DrawText API anstelle von GDI + nennen. Aber sie konnten nicht den Text-Wrapping und Abstand Spiel machen genau wie das, was GDI + tat. So waren sie gezwungen, graphics.DrawString zu halten GDI + zu nennen (Kompatiblität Gründe, die Leute, die graphics.DrawString riefen würde plötzlich feststellen, dass ihr Text nicht wickeln, wie es verwendet wird).

Eine neue statische TextRenderer Klasse wurde erstellt GDI Text-Rendering zu wickeln. Es verfügt über zwei Methoden:

TextRenderer.MeasureText
TextRenderer.DrawText
  

. Hinweis: TextRenderer ist ein Wrapper um GDI, während graphics.DrawString noch ein Wrapper um GDI + ist


Dann war da noch die Frage, was mit allen vorhandenen .NET-Steuerelemente zu tun, z.

  • Label
  • Button
  • TextBox

Sie wollten sie wechseln TextRenderer (das heißt GDI) zu verwenden, aber sie musste vorsichtig sein. Es könnte Leute geben, die Zeichnung auf ihren Kontrollen angewiesen, wie sie in tat .NET 1.1. Und so wurde geboren " kompatibel Text-Rendering ".

Mit dem Standard-Steuerelemente in der Anwendung verhalten sich wie sie in tat .NET 1.1 (sie sind " kompatibel ").

Sie deaktivieren Kompatibilitätsmodus durch den Aufruf:

Application.SetCompatibleTextRenderingDefault(false);

Das macht Ihre Anwendung besser, schneller und mit besserer internationalen Unterstützung. Fazit:

SetCompatibleTextRenderingDefault(true)  SetCompatibleTextRenderingDefault(false)
=======================================  ========================================
 default                                  opt-in
 bad                                      good
 the one we don't want to use             the one we want to use
 uses GDI+ for text rendering             uses GDI for text rendering
 graphics.MeasureString                   TextRenderer.MeasureText
 graphics.DrawString                      TextRenderer.DrawText
 Behaves same as 1.1                      Behaves *similar* to 1.1
                                          Looks better
                                          Localizes better
                                          Faster

Es ist auch nützlich, um die Zuordnung zwischen GDI + TextRenderingHint und dem entsprechenden LOGFONT Qualität für GDI Schriftzeichen verwendet:

TextRenderingHint           mapped by TextRenderer to LOGFONT quality
========================    =========================================================
ClearTypeGridFit            CLEARTYPE_QUALITY (5) (Windows XP: CLEARTYPE_NATURAL (6))
AntiAliasGridFit            ANTIALIASED_QUALITY (4)
AntiAlias                   ANTIALIASED_QUALITY (4)
SingleBitPerPixelGridFit    PROOF_QUALITY (2)
SingleBitPerPixel           DRAFT_QUALITY (1)
else (e.g.SystemDefault)    DEFAULT_QUALITY (0)

Samples

Hier einige Vergleiche von GDI + (Graphics.DrawString) Verse GDI (TextRenderer.DrawText) Text-Rendering:

GDI + : TextRenderingHintClearTypeGridFit, GDI : CLEARTYPE_QUALITY:

eingeben Bild Beschreibung hier

GDI + : TextRenderingHintAntiAlias, GDI : ANTIALIASED_QUALITY:

eingeben Bild Beschreibung hier

GDI + : TextRenderingHintAntiAliasGridFit, GDI : nicht unterstützt wird, verwendet ANTIALIASED_QUALITY :

eingeben Bild Beschreibung hier

GDI + : TextRenderingHintSingleBitPerPixelGridFit, GDI : PROOF_QUALITY:

eingeben Bild Beschreibung hier

GDI + : TextRenderingHintSingleBitPerPixel, GDI : DRAFT_QUALITY:

eingeben Bild Beschreibung hier

Ich finde es seltsam, dass DRAFT_QUALITY identisch mit PROOF_QUALITY, die CLEARTYPE_QUALITY identisch ist.

Siehe auch

Andere Tipps

Courier New Größe 11

Wenn Sie eine Schriftart ‚Courier New‘ mit Größe erstellen = 11 Sie werden über eine Ausgabe wie in dem Bild bekommen. Sie sehen, dass die Höhe 14 Pixel ist die unterstrichenen nicht enthält. Die Breite beträgt genau 14 Pixel (Bildpunkt 7 für jedes Zeichen).

Also diese Schrift macht 14x14 Pixel.

Aber TextRenderer.MeasureText() gibt eine Breite von 21 Pixeln statt. Wenn Sie genaue Werte brauchen dies ist nutzlos.

Die Lösung ist der folgende Code:

Font i_Courier = new Font("Courier New", 11, GraphicsUnit.Pixel);

Win32.SIZE k_Size;
using (Bitmap i_Bmp = new Bitmap(200, 200, PixelFormat.Format24bppRgb))
{
    using (Graphics i_Graph = Graphics.FromImage(i_Bmp))
    {
        IntPtr h_DC = i_Graph.GetHdc();
        IntPtr h_OldFont = Win32.SelectObject(h_DC, i_Courier.ToHfont());

        Win32.GetTextExtentPoint32(h_DC, "Áp", 2, out k_Size);

        Win32.SelectObject(h_DC, h_OldFont);
        i_Graph.ReleaseHdc();
    }
}

k_Size wird die richtige Größe enthalten: 14x14

Wichtig: Dieser Code Maßnahmen richtig ein normaler Schrift. Wenn Sie die genauen Werte auch für kursiv müssen (das hat immer einen Überhang auf dem rechten Seite) können Sie über die Links lesen sollen, die in diesem Artikel erwähnt werden: http://www.codeproject.com/Articles/14915/Width-of-text-in-italic-font

ANHANG: Für diejenigen, die nie API-Aufrufe in C # hier einen Hinweis, wie Sie erstellen die Klasse Win32 verwendet haben. Dies ist nicht vollständig. Weitere Einzelheiten finden Sie unter http://www.pinvoke.net

using System.Runtime.InteropServices;

public class Win32
{       
    [StructLayout(LayoutKind.Sequential)]
    public struct SIZE
    {
        public int cx;
        public int cy;
    }

    [DllImport("Gdi32.dll")]
    public static extern bool GetTextExtentPoint32(IntPtr hdc, string lpString, int cbString, out SIZE lpSize);

    [DllImport("Gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
}

Hier ist eine Erklärung, die Sie verstehen helfen, wie es funktioniert. und was bewirkt, dass die Räume von mehr oder weniger vor und nach jedem Zeichen.

GDI DrawString Konfigurator App

Screen Capture

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top