Pergunta

Eu estou usando o .O NETCF (Windows Mobile) Graphics classe e o DrawString() método para processar um único caractere na tela.

O problema é que eu não consigo fazê-lo centrado corretamente.Não importa o que eu definida para a coordenada Y do local da cadeia de renderização, ele sempre sai menor do que e maior o tamanho do texto maior a Y offset.

Por exemplo, no texto tamanho 12, o deslocamento é de cerca de 4, mas em 32 o deslocamento é de cerca de 10.

Eu quero que o personagem verticalmente ocupar a maior parte do retângulo que está sendo desenhado e orientado horizontalmente.Aqui está o meu código básico. this é de referenciar o controle de usuário que está sendo desenhada.

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);

Sim, eu sei que não há o controle de rótulo que eu poderia usar no lugar e definir a centralização, mas na verdade, eu não preciso fazer isso manualmente, com o Graphics de classe.

Foi útil?

Solução 3

Através de uma combinação das sugestões que eu tenho, me veio com essa:

    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();
        }
    }

Até agora, este funciona perfeitamente.

A única coisa que eu mudaria é mover o FindBestFitFont() chamada para o OnResize() evento de modo a que eu não estou chamando-o de cada vez que eu desenhe uma letra.Ele só precisa ser chamado quando o controle de alterações de tamanho.Eu só incluiu-a na função para a integralidade.

Outras dicas

Eu gostaria de acrescentar mais um voto para o objeto StringFormat.Você pode usar esse simplesmente para especificar o "centro do centro" e o texto será colocado centralmente no retângulo ou pontos, desde que:

StringFormat format = new StringFormat();
format.LineAlignment = StringAlignment.Center;
format.Alignment = StringAlignment.Center;

No entanto, há um problema com isso no CF.Se você usar o Centro para ambos os valores, em seguida, ele se transforma TextWrapping fora.Nenhuma idéia de por que isso acontece, parece ser um bug com a CF.

Para alinhar um texto, use o seguinte:

StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
e.Graphics.DrawString("My String", this.Font, Brushes.Black, ClientRectangle, sf);

Por favor, note que aqui o texto é alinhado em uma dada limites.Neste exemplo, este é o ClientRectangle.

Para desenhar um texto centralizado:

TextRenderer.DrawText(g, "my text", Font, Bounds, ForeColor, BackColor, 
  TextFormatFlags.HorizontalCenter | 
  TextFormatFlags.VerticalCenter |
  TextFormatFlags.GlyphOverhangPadding);

A determinação ideal do tamanho de tipo de letra para preencher uma área é um pouco mais difícil.Um trabalho soultion eu encontrei é a tentativa-e-erro:comece com um tipo de letra grande, em seguida, medir repetidamente a cadeia e diminuir o tipo de letra, até que ele se encaixa.

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();
  }
}

Você usaria isso como:

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)

Você pode usar uma instância de StringFormat objeto passado para o DrawString método para centralizar o texto.

Ver Gráficos.Método DrawString e StringFormat Classe.

Aqui está o código.Isto assume que você está fazendo isso em um formulário, ou um 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));

A partir do seu post, parece que o ClientRectangle parte (como no, você não está usando-o) é o que apresenta dificuldade.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top