Zentrieren Sie die Textausgabe von Graphics.DrawString()
-
08-06-2019 - |
Frage
Ich verwende .NETCF (Windows Mobile) Graphics
Klasse und die DrawString()
Methode zum Rendern eines einzelnen Zeichens auf dem Bildschirm.
Das Problem ist, dass ich es scheinbar nicht richtig zentrieren kann.Unabhängig davon, was ich für die Y-Koordinate der Position des String-Renderings einstelle, liegt sie immer unter diesem Wert, und je größer die Textgröße, desto größer der Y-Versatz.
Bei der Textgröße 12 beträgt der Versatz beispielsweise etwa 4, bei 32 beträgt der Versatz jedoch etwa 10.
Ich möchte, dass das Zeichen vertikal den größten Teil des Rechtecks einnimmt, in das es gezeichnet wird, und horizontal zentriert ist.Hier ist mein Basiscode. this
verweist auf das Benutzersteuerelement, in das es gezeichnet wird.
Graphics g = this.CreateGraphics();
float padx = ((float)this.Size.Width) * (0.05F);
float pady = ((float)this.Size.Height) * (0.05F);
float width = ((float)this.Size.Width) - 2 * padx;
float height = ((float)this.Size.Height) - 2 * pady;
float emSize = height;
g.DrawString(letter, new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular),
new SolidBrush(Color.Black), padx, pady);
Ja, ich weiß, dass es stattdessen die Beschriftungssteuerung gibt, die ich verwenden und damit die Zentrierung festlegen könnte, aber ich muss dies tatsächlich manuell mit der tun Graphics
Klasse.
Lösung 3
Durch die Kombination der Vorschläge, die ich bekommen habe, bin ich auf Folgendes gekommen:
private void DrawLetter()
{
Graphics g = this.CreateGraphics();
float width = ((float)this.ClientRectangle.Width);
float height = ((float)this.ClientRectangle.Width);
float emSize = height;
Font font = new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular);
font = FindBestFitFont(g, letter.ToString(), font, this.ClientRectangle.Size);
SizeF size = g.MeasureString(letter.ToString(), font);
g.DrawString(letter, font, new SolidBrush(Color.Black), (width-size.Width)/2, 0);
}
private Font FindBestFitFont(Graphics g, String text, Font font, Size proposedSize)
{
// Compute actual size, shrink if needed
while (true)
{
SizeF size = g.MeasureString(text, font);
// It fits, back out
if (size.Height <= proposedSize.Height &&
size.Width <= proposedSize.Width) { return font; }
// Try a smaller font (90% of old size)
Font oldFont = font;
font = new Font(font.Name, (float)(font.Size * .9), font.Style);
oldFont.Dispose();
}
}
Bisher funktioniert das einwandfrei.
Das Einzige, was ich ändern würde, wäre, den FindBestFitFont()-Aufruf auf das OnResize()-Ereignis zu verschieben, damit ich es nicht jedes Mal aufrufe, wenn ich einen Buchstaben zeichne.Es muss nur aufgerufen werden, wenn sich die Steuerelementgröße ändert.Der Vollständigkeit halber habe ich es nur in die Funktion aufgenommen.
Andere Tipps
Ich möchte eine weitere Stimme für das StringFormat-Objekt hinzufügen.Hiermit können Sie einfach „Mitte, Mitte“ angeben und der Text wird mittig im Rechteck oder an den dafür vorgesehenen Punkten gezeichnet:
StringFormat format = new StringFormat();
format.LineAlignment = StringAlignment.Center;
format.Alignment = StringAlignment.Center;
Bei CF gibt es dabei jedoch ein Problem.Wenn Sie Center für beide Werte verwenden, wird TextWrapping deaktiviert.Keine Ahnung, warum das passiert, es scheint ein Fehler in der CF zu sein.
Um einen Text auszurichten, verwenden Sie Folgendes:
StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
e.Graphics.DrawString("My String", this.Font, Brushes.Black, ClientRectangle, sf);
Bitte beachten Sie, dass der Text hier in den vorgegebenen Grenzen ausgerichtet ist.In diesem Beispiel ist dies das ClientRectangle.
So zeichnen Sie einen zentrierten Text:
TextRenderer.DrawText(g, "my text", Font, Bounds, ForeColor, BackColor,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter |
TextFormatFlags.GlyphOverhangPadding);
Etwas schwieriger ist es, die optimale Schriftgröße zum Ausfüllen eines Bereichs zu bestimmen.Eine funktionierende Lösung, die ich gefunden habe, ist Versuch und Irrtum:Beginnen Sie mit einer großen Schriftart, messen Sie dann wiederholt die Zeichenfolge und verkleinern Sie die Schriftart, bis sie passt.
Font FindBestFitFont(Graphics g, String text, Font font,
Size proposedSize, TextFormatFlags flags)
{
// Compute actual size, shrink if needed
while (true)
{
Size size = TextRenderer.MeasureText(g, text, font, proposedSize, flags);
// It fits, back out
if ( size.Height <= proposedSize.Height &&
size.Width <= proposedSize.Width) { return font; }
// Try a smaller font (90% of old size)
Font oldFont = font;
font = new Font(font.FontFamily, (float)(font.Size * .9));
oldFont.Dispose();
}
}
Sie würden dies verwenden als:
Font bestFitFont = FindBestFitFont(g, text, someBigFont, sizeToFitIn, flags);
// Then do your drawing using the bestFitFont
// Don't forget to dispose the font (if/when needed)
Sie können eine Instanz von verwenden StringFormat
Objekt in die übergeben DrawString
Methode zum Zentrieren des Textes.
Sehen Graphics.DrawString-Methode Und StringFormat-Klasse.
Hier ist ein Code.Dies setzt voraus, dass Sie dies in einem Formular oder einem UserControl tun.
Graphics g = this.CreateGraphics();
SizeF size = g.MeasureString("string to measure");
int nLeft = Convert.ToInt32((this.ClientRectangle.Width / 2) - (size.Width / 2));
int nTop = Convert.ToInt32((this.ClientRectangle.Height / 2) - (size.Height / 2));
Aus Ihrem Beitrag geht hervor, dass der ClientRectangle-Teil (d. h. Sie verwenden ihn nicht) Ihnen Schwierigkeiten bereitet.