Folosesc clasa .NETCF (Windows Mobile) Graphics
și metoda DrawString ()
pentru a reda un singur caracter pe ecran.
Problema este că nu par să-l centreze corect. Indiferent de ceea ce am stabilit pentru coordonata Y a locației șirului de randare, el întotdeauna ieșea mai jos decât acesta și cu cât dimensiunea textului este mai mare, cu atât este mai mare decalajul Y.
De exemplu, la dimensiunea textului 12, decalajul este de aproximativ 4, dar la 32 offsetul este de aproximativ 10.
Vreau ca personajul să preia vertical cea mai mare parte a dreptunghiului în care este tras și să fie centrat orizontal. Iată codul meu de bază. acest
face referire la controlul utilizatorului în care este redactat.
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);
Da, știu că există controlul de etichetare pe care l-aș putea folosi și am setat centrarea cu asta, dar de fapt trebuie să fac acest lucru manual cu clasa Graphics
.
Puteți utiliza o instanță a obiectului StringFormat
introdus în metoda DrawString
pentru a centra textul.
Consultați Metoda Graphics.DrawString și StringFormat Class .
Iată câteva coduri. Aceasta presupune că faceți acest lucru pe un formular sau pe un UserControl.
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));
Din postarea dvs., sună ca partea ClientRectangle (ca și în cazul în care nu o utilizați) este ceea ce vă dă dificultăți.
Pentru a desena un text centrat:
TextRenderer.DrawText(g, "my text", Font, Bounds, ForeColor, BackColor,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter |
TextFormatFlags.GlyphOverhangPadding);
Determinarea dimensiunii optime a fontului pentru a umple o zonă este ceva mai dificilă. Un suflet de lucru pe care l-am găsit este încercarea și eroarea: începeți cu un font mare, apoi măsurați în mod repetat șirul și micșorați fontul până se potrivește.
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();
}
}
Ați folosi acest lucru ca:
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)
Printr-o combinație a sugestiilor pe care le-am primit, am venit cu acest lucru:
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();
}
}
Până acum, acest lucru funcționează fără probleme.
Singurul lucru pe care l-aș schimba este să muiesc apelul FindBestFitFont () la evenimentul OnResize (), astfel încât să nu îl sun de fiecare dată când scot o scrisoare. Trebuie doar să fie apelată când se modifică mărimea controlului. Tocmai l-am inclus în funcția de completare.
Aș dori să adaug un alt vot pentru obiectul StringFormat. Puteți folosi acest mod simplu pentru a specifica "centru, centru" și textul va fi desenat central în dreptunghi sau puncte furnizate:
StringFormat format = new StringFormat();
format.LineAlignment = StringAlignment.Center;
format.Alignment = StringAlignment.Center;
Cu toate acestea, există o problemă cu aceasta în CF. Dacă utilizați Centrul pentru ambele valori, atunci se oprește TextWrapping. Nici o idee de ce se întâmplă acest lucru, pare a fi un bug cu CF.
Pentru a alinia un text folosiți următoarele:
StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
e.Graphics.DrawString("My String", this.Font, Brushes.Black, ClientRectangle, sf);
Rețineți că textul este aliniat în limitele date. În această probă, acesta este raportul ClientRectangle.