Share via


Desenho de texto de fontes diferentes na mesma linha

Estilos de tipo diferentes dentro de uma família de fontes podem ter larguras diferentes. Por exemplo, estilos em negrito e itálico de uma família são sempre mais largos do que o estilo romano para um tamanho de ponto especificado. Ao exibir ou imprimir vários estilos de tipo em uma única linha, você deve acompanhar a largura da linha para evitar ter caracteres exibidos ou impressos em cima uns dos outros.

Você pode usar duas funções para recuperar a largura (ou extensão) do texto na fonte atual. A função GetTabbedTextExtent calcula a largura e a altura de uma cadeia de caracteres. Se a cadeia de caracteres contiver um ou mais caracteres de guia, a largura da cadeia de caracteres será baseada em uma matriz especificada de posições de parada de tabulação. A função GetTextExtentPoint32 calcula a largura e a altura de uma linha de texto.

Quando necessário, o sistema sintetiza uma fonte alterando os bitmaps de caractere. Para sintetizar um caractere em uma fonte em negrito, o sistema desenha o caractere duas vezes: no ponto de partida e, novamente, um pixel à direita do ponto de partida. Para sintetizar um caractere em uma fonte itálica, o sistema desenha duas linhas de pixels na parte inferior da célula de caracteres, move o ponto inicial um pixel para a direita, desenha as duas linhas seguintes e continua até que o caractere seja desenhado. Ao deslocar pixels, cada caractere parece estar sendo esculachado para a direita. A quantidade de tesoura é uma função da altura do caractere.

Uma maneira de escrever uma linha de texto que contém várias fontes é usar a função GetTextExtentPoint32 após cada chamada para TextOut e adicionar o comprimento a uma posição atual. O exemplo a seguir grava a linha "Esta é uma cadeia de caracteres de exemplo". Usando caracteres em negrito para "This is a", alterna para caracteres itálicos para "sample" e retorna para caracteres em negrito para "string". Depois de imprimir todas as cadeias de caracteres, ele restaura os caracteres padrão do sistema.

int XIncrement; 
int YStart; 
TEXTMETRIC tm; 
HFONT hfntDefault, hfntItalic, hfntBold; 
SIZE sz; 
LPSTR lpszString1 = "This is a "; 
LPSTR lpszString2 = "sample "; 
LPSTR lpszString3 = "string."; 
HRESULT hr;
size_t * pcch;
 
// Create a bold and an italic logical font.  
 
hfntItalic = MyCreateFont(); 
hfntBold = MyCreateFont(); 
 
 
// Select the bold font and draw the first string  
// beginning at the specified point (XIncrement, YStart).  
 
XIncrement = 10; 
YStart = 50; 
hfntDefault = SelectObject(hdc, hfntBold); 
hr = StringCchLength(lpszString1, 11, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        }
TextOut(hdc, XIncrement, YStart, lpszString1, *pcch); 
 
// Compute the length of the first string and add  
// this value to the x-increment that is used for the  
// text-output operation.  

hr = StringCchLength(lpszString1, 11, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        } 
GetTextExtentPoint32(hdc, lpszString1, *pcch, &sz); 
XIncrement += sz.cx; 
 
// Retrieve the overhang value from the TEXTMETRIC  
// structure and subtract it from the x-increment.  
// (This is only necessary for non-TrueType raster  
// fonts.)  
 
GetTextMetrics(hdc, &tm); 
XIncrement -= tm.tmOverhang; 
 
// Select an italic font and draw the second string  
// beginning at the point (XIncrement, YStart).  
 
hfntBold = SelectObject(hdc, hfntItalic); 
GetTextMetrics(hdc, &tm); 
XIncrement -= tm.tmOverhang;
hr = StringCchLength(lpszString2, 8, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        } 
TextOut(hdc, XIncrement, YStart, lpszString2, *pcch); 
 
// Compute the length of the second string and add  
// this value to the x-increment that is used for the  
// text-output operation.  

hr = StringCchLength(lpszString2, 8, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        }  
GetTextExtentPoint32(hdc, lpszString2, *pcch, &sz); 
XIncrement += sz.cx; 
 
// Reselect the bold font and draw the third string  
// beginning at the point (XIncrement, YStart).  
 
SelectObject(hdc, hfntBold);
hr = StringCchLength(lpszString3, 8, pcch);
        if (FAILED(hr))
        {
        // TODO: write error handler 
        }  
TextOut(hdc, XIncrement - tm.tmOverhang, YStart, lpszString3, 
            *pcch); 
 
// Reselect the original font.  
 
SelectObject(hdc, hfntDefault); 
 
// Delete the bold and italic fonts.  
 
DeleteObject(hfntItalic); 
DeleteObject(hfntBold); 

Neste exemplo, a função GetTextExtentPoint32 inicializa os membros de uma estrutura SIZE com o comprimento e a altura da cadeia de caracteres especificada. A função GetTextMetrics recupera a saliência da fonte atual. Como a saliência será zero se a fonte for uma fonte TrueType, o valor de saliência não alterará o posicionamento da cadeia de caracteres. No entanto, para fontes raster, é importante usar o valor de saliência.

A saliência é subtraída da cadeia de caracteres em negrito uma vez, para aproximar os caracteres subsequentes do final da cadeia de caracteres se a fonte for uma fonte de raster. Como a saliência afeta o início e o fim da cadeia de caracteres itálica em uma fonte raster, os glifos começam à direita do local especificado e terminam à esquerda do ponto de extremidade da última célula de caracteres. (A função GetTextExtentPoint32 recupera a extensão das células de caractere, não a extensão dos glifos.) Para considerar a saliência na cadeia de caracteres itálica raster, o exemplo subtrai a saliência antes de colocar a cadeia de caracteres e subtrai-a novamente antes de colocar caracteres subsequentes.

A função SetTextJustification adiciona espaço extra aos caracteres de quebra em uma linha de texto. Você pode usar a função GetTextExtentPoint para determinar a extensão de uma cadeia de caracteres e subtrair essa extensão da quantidade total de espaço que a linha deve ocupar e usar a função SetTextJustification para distribuir o espaço extra entre os caracteres de quebra na cadeia de caracteres. A função SetTextCharacterExtra adiciona espaço extra a cada célula de caractere na fonte selecionada, incluindo o caractere de interrupção. (Você pode usar a função GetTextCharacterExtra para determinar a quantidade atual de espaço extra que está sendo adicionada às células de caracteres; a configuração padrão é zero.)

Você pode colocar caracteres com maior precisão usando a função GetCharWidth32 ou GetCharABCWidths para recuperar as larguras de caracteres individuais em uma fonte. A função GetCharABCWidths é mais precisa do que a função GetCharWidth32 , mas só pode ser usada com fontes TrueType.

O espaçamento ABC também permite que um aplicativo execute um alinhamento de texto muito preciso. Por exemplo, quando o aplicativo à direita alinha uma fonte romana de raster sem usar o espaçamento ABC, a largura avançada é calculada como a largura do caractere. Isso significa que o espaço em branco à direita do glifo no bitmap está alinhado, não o glifo em si. Usando larguras ABC, os aplicativos têm mais flexibilidade no posicionamento e remoção do espaço em branco ao alinhar o texto, pois têm informações que permitem controlar o espaçamento entre caracteres.