Pergunta

Eu estou tentando calcular a largura de pixel de colunas do Excel, conforme descrito em este post , usando a fórmula oficial da especificação do OpenXML. No entanto, a fim de aplicar esta fórmula, eu preciso saber o dígito máximo Largura do normal da fonte, que é a largura de pixel da maior dígito numérico. A especificação OpenXML dá este exemplo como um esclarecimento:

Usando a fonte Calibri como exemplo, a largura máxima dígitos de 11 pontos da fonte tamanho é de 7 pixels (a 96 dpi).

Tenho verificado que esta é correta examinando visualmente a 11 pontos Calibri dígitos e é de facto 7 pixels de largura. Então, eu estou tentando criar um método que irá retornar a largura máxima dígitos para qualquer fonte / tamanho.

Tenho seguido as recomendações feitas no esta pergunta , mas não produz os resultados que eu estou esperando.

Aqui está o meu código de teste:

var font = new Font("Calibri", 11.0f, FontStyle.Regular);

for (var i = 0; i < 10; i++)
{
    Debug.WriteLine(TextRenderer.MeasureText(i.ToString(), font));
}

Este artigo relata que todos os números têm uma largura de 15.

Todas as sugestões agradar?

Obrigado, Tim

Foi útil?

Solução

Primeiro deixe-me dizer que o código que eu estou prestes a mostrar parece um corte horrível e eu não estou apresentando-a como uma solução. Pelo contrário, eu estou esperando que ele revela um pouco mais sobre o comportamento de MeasureText que pode levar você a sua solução final.

Eu fiz uma ligeira alteração ao seu código. Eu estou medindo o comprimento de dois caracteres de sublinhado. Em seguida, no corpo do loop for estou medindo o carácter pretendido com sublinhados em ambos os lados e subtraindo o comprimento de um dos dois caracteres de sublinhado sozinho. Para o cenário de teste que eu estou recebendo um resultado de 7. O principal objectivo desta era determinar se MeasureText é responsável por preenchimento em uma base caractere por caractere ou estofamento no início / fim da cadeia. Parece que é o último. Talvez isto, combinado com alguns dos outra entrada que recebeu, vai levar você para uma solução mais elegante.

var font = new Font("Calibri", 11.0f, FontStyle.Regular);
int underscoreWidth = TextRenderer.MeasureText("__", font).Width; 
for (var i = 0; i < 10; i++)
   {
      int charWidth = TextRenderer.MeasureText(String.Concat("_", i.ToString(), "_"), font).Width - underscoreWidth;
      Debug.WriteLine(charWidth);
   }

Outras dicas

TextRenderer nem sempre é exata da maneira que você esperaria:

De MSDN: http://msdn.microsoft.com/en- us / library / 8wafk2kt.aspx

Por exemplo, o comportamento padrão do TextRenderer é adicionar padding para o retângulo delimitador do texto desenhado para acomodar pendendo glifos

Você tem um objeto Graphics ou um objeto de controle? Se você estiver usando esses você pode obter restults precisas da maneira que você esperaria.

Dê uma olhada http: // MSDN. microsoft.com/en-us/library/6xe5hazb(VS.80).aspx

MeasureText adiciona o preenchimento, a quantidade é bastante imprevisível, embora cerca de escala linearmente com o tamanho da fonte. O truque consiste em subtrair duas medidas para se livrar do estofamento. Este código gerado números muito felizes:

        float size = 5;
        for (int ix = 0; ix < 10; ++ix) {
            var font = new Font("Calibri", size, FontStyle.Regular);
            string txt = new string('0', 100);
            SizeF sz1 = TextRenderer.MeasureText("00", font) - TextRenderer.MeasureText("0", font);
            Console.WriteLine("{0} {1:N3}", size, sz1.Width);
            size += 2;
        }

Output:

5 4.000
7 5.000
9 6.000
11 7.000
13 9.000
15 10.000
17 12.000
19 13.000
21 14.000
23 16.000

Que você recebe as 7 pixels que você está procurando. Esteja ciente de que você vai ter que acomodar TrueType insinuando, pode ajustar a forma do dígito para que a sua principal decorre queda em limites de pixel. Adicione pelo menos um pixel.

Medição larguras de texto pode ser um pesadelo .. Eu não sei por que eles fizeram isso tão confuso ..

Heres a maneira mais precisa Eu tenho para medir o comprimento do texto:

    protected int _MeasureDisplayStringWidth ( Graphics graphics, string text, Font font )
    {
        if ( text == "" )
            return 0;

        StringFormat format = new StringFormat ( StringFormat.GenericDefault );
        RectangleF rect = new RectangleF ( 0, 0, 1000, 1000 );
        CharacterRange[] ranges = { new CharacterRange ( 0, text.Length ) };
        Region[] regions = new Region[1];

        format.SetMeasurableCharacterRanges ( ranges );
        format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;

        regions = graphics.MeasureCharacterRanges ( text, font, rect, format );
        rect = regions[0].GetBounds ( graphics );

        return (int)( rect.Right );
    }

Eu não estou 100% de certeza que é exatamente o que você precisa.

Mas você pode querer ter um olhar para esta página da Microsoft:

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