Executarea textului de centru de la Graphics.DrawString ()

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 .

0
fr hi bn

6 răspunsuri

Puteți utiliza o instanță a obiectului StringFormat introdus în metoda DrawString pentru a centra textul.

Consultați Metoda Graphics.DrawString și StringFormat Class .

0
adăugat

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.

0
adăugat

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.

0
adăugat

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.

0
adăugat

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.

0
adăugat
Soluția lui Chris este minunată. BTW dacă doriți să setați în centru orizontal, dar vertical în orice poziție: e.Graphics.DrawString ("My String", this.Font, Brushes.Black, e.CellBounds.Width/2, y, sf);//y este poziția verticală
adăugat autor camino, sursa

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)
0
adăugat