Partilhar via


Função FormatMessage (winbase.h)

Formata uma cadeia de caracteres de mensagem. A função requer uma definição de mensagem como entrada. A definição de mensagem pode vir de um buffer passado para a função. Ele pode vir de um recurso de tabela de mensagens em um módulo já carregado. Ou o chamador pode pedir à função para pesquisar a definição da mensagem nos recursos da tabela de mensagens do sistema. A função localiza a definição de mensagem em um recurso de tabela de mensagens com base em um identificador de mensagem e um identificador de idioma. A função copia o texto da mensagem formatada para um buffer de saída, processando todas as sequências de inserção inseridas inseridas, se solicitado.

Sintaxe

DWORD FormatMessage(
  [in]           DWORD   dwFlags,
  [in, optional] LPCVOID lpSource,
  [in]           DWORD   dwMessageId,
  [in]           DWORD   dwLanguageId,
  [out]          LPTSTR  lpBuffer,
  [in]           DWORD   nSize,
  [in, optional] va_list *Arguments
);

Parâmetros

[in] dwFlags

As opções de formatação e como interpretar o parâmetro lpSource . O byte de baixa ordem de dwFlags especifica como a função lida com quebras de linha no buffer de saída. O byte de baixa ordem também pode especificar a largura máxima de uma linha de saída formatada.

Esse parâmetro pode usar um dos valores a seguir.

Valor Significado
FORMAT_MESSAGE_ALLOCATE_BUFFER
0x00000100
A função aloca um buffer grande o suficiente para manter a mensagem formatada e coloca um ponteiro para o buffer alocado no endereço especificado por lpBuffer. O parâmetro lpBuffer é um ponteiro para um LPTSTR; você deve converter o ponteiro em um LPTSTR (por exemplo, (LPTSTR)&lpBuffer). O parâmetro nSize especifica o número mínimo de TCHARs a serem alocados para um buffer de mensagem de saída. O chamador deve usar a função LocalFree para liberar o buffer quando ele não for mais necessário.

Se o comprimento da mensagem formatada exceder 128 K bytes, FormatMessage falhará e uma chamada subsequente para GetLastError retornará ERROR_MORE_DATA.

Nas versões anteriores do Windows, esse valor não estava disponível para uso ao compilar aplicativos da Windows Store. A partir de Windows 10 esse valor pode ser usado.

Windows Server 2003 e Windows XP:

Se o comprimento da mensagem formatada exceder 128 K bytes, FormatMessage não falhará automaticamente com um erro de ERROR_MORE_DATA.

FORMAT_MESSAGE_ARGUMENT_ARRAY
0x00002000
O parâmetro Arguments não é uma estrutura va_list , mas é um ponteiro para uma matriz de valores que representam os argumentos.

Esse sinalizador não pode ser usado com valores inteiros de 64 bits. Se você estiver usando um inteiro de 64 bits, deverá usar a estrutura va_list .

FORMAT_MESSAGE_FROM_HMODULE
0x00000800
O parâmetro lpSource é um identificador de módulo que contém os recursos de tabela de mensagens a serem pesquisados. Se esse identificador lpSource for NULL, o arquivo de imagem do aplicativo do processo atual será pesquisado. Esse sinalizador não pode ser usado com FORMAT_MESSAGE_FROM_STRING.

Se o módulo não tiver nenhum recurso de tabela de mensagens, a função falhará com ERROR_RESOURCE_TYPE_NOT_FOUND.

FORMAT_MESSAGE_FROM_STRING
0x00000400
O parâmetro lpSource é um ponteiro para uma cadeia de caracteres terminada em nulo que contém uma definição de mensagem. A definição de mensagem pode conter sequências de inserção, assim como o texto da mensagem em um recurso de tabela de mensagens pode. Esse sinalizador não pode ser usado com FORMAT_MESSAGE_FROM_HMODULE ou FORMAT_MESSAGE_FROM_SYSTEM.
FORMAT_MESSAGE_FROM_SYSTEM
0x00001000
A função deve pesquisar os recursos de tabela de mensagens do sistema para a mensagem solicitada. Se esse sinalizador for especificado com FORMAT_MESSAGE_FROM_HMODULE, a função pesquisará a tabela de mensagens do sistema se a mensagem não for encontrada no módulo especificado por lpSource. Esse sinalizador não pode ser usado com FORMAT_MESSAGE_FROM_STRING.

Se esse sinalizador for especificado, um aplicativo poderá passar o resultado da função GetLastError para recuperar o texto da mensagem para um erro definido pelo sistema.

FORMAT_MESSAGE_IGNORE_INSERTS
0x00000200
As sequências de inserção na definição de mensagem, como %1, devem ser ignoradas e passadas para o buffer de saída inalteradas. Esse sinalizador é útil para buscar uma mensagem para formatação posterior. Se esse sinalizador for definido, o parâmetro Arguments será ignorado.
 

O byte de baixa ordem de dwFlags pode especificar a largura máxima de uma linha de saída formatada. Veja a seguir os valores possíveis do byte de baixa ordem.

Valor Significado
0
Não há restrições de largura de linha de saída. A função armazena quebras de linha que estão no texto de definição de mensagem no buffer de saída.
FORMAT_MESSAGE_MAX_WIDTH_MASK
0x000000FF
A função ignora quebras de linha regulares no texto de definição de mensagem. A função armazena quebras de linha embutidas em código no texto de definição de mensagem no buffer de saída. A função não gera novas quebras de linha.
 

Se o byte de ordem baixa for um valor diferente de zero diferente de FORMAT_MESSAGE_MAX_WIDTH_MASK, ele especificará o número máximo de caracteres em uma linha de saída. A função ignora quebras de linha regulares no texto de definição de mensagem. A função nunca divide uma cadeia de caracteres delimitada por espaço em branco em uma quebra de linha. A função armazena quebras de linha embutidas em código no texto de definição de mensagem no buffer de saída. As quebras de linha embutidas em código são codificadas com a sequência de escape %n.

[in, optional] lpSource

O local da definição da mensagem. O tipo desse parâmetro depende das configurações no parâmetro dwFlags .

Dwflags Configuração Significado
FORMAT_MESSAGE_FROM_HMODULE
0x00000800
Um identificador para o módulo que contém a tabela de mensagens a ser pesquisada.
FORMAT_MESSAGE_FROM_STRING
0x00000400
Ponteiro para uma cadeia de caracteres que consiste em texto de mensagem não formatado. Ele será verificado quanto a inserções e formatado de acordo.
 

Se nenhum desses sinalizadores estiver definido em dwFlags, lpSource será ignorado.

[in] dwMessageId

O identificador de mensagem da mensagem solicitada. Esse parâmetro será ignorado se dwFlags incluir FORMAT_MESSAGE_FROM_STRING.

[in] dwLanguageId

O identificador de idioma da mensagem solicitada. Esse parâmetro será ignorado se dwFlags incluir FORMAT_MESSAGE_FROM_STRING.

Se você passar um LANGID específico nesse parâmetro, FormatMessage retornará uma mensagem somente para esse LANGID . Se a função não puder encontrar uma mensagem para esse LANGID, ela definirá Last-Error como ERROR_RESOURCE_LANG_NOT_FOUND. Se você passar zero, FormatMessage procurará uma mensagem para LANGIDs na seguinte ordem:

  1. Idioma neutro
  2. LANGID do thread, com base no valor de localidade do thread
  3. LANGID padrão do usuário, com base no valor de localidade padrão do usuário
  4. LANGID padrão do sistema, com base no valor de localidade padrão do sistema
  5. Inglês (EUA)
Se FormatMessage não localizar uma mensagem para nenhum dos LANGIDs anteriores, ela retornará qualquer cadeia de caracteres de mensagem de idioma presente. Se isso falhar, ele retornará ERROR_RESOURCE_LANG_NOT_FOUND.

[out] lpBuffer

Um ponteiro para um buffer que recebe a cadeia de caracteres terminada em nulo que especifica a mensagem formatada. Se dwFlags incluir FORMAT_MESSAGE_ALLOCATE_BUFFER, a função alocará um buffer usando a função LocalAlloc e colocará o ponteiro para o buffer no endereço especificado em lpBuffer.

Esse buffer não pode ter mais de 64 mil bytes.

[in] nSize

Se o sinalizador FORMAT_MESSAGE_ALLOCATE_BUFFER não estiver definido, esse parâmetro especificará o tamanho do buffer de saída, em TCHARs. Se FORMAT_MESSAGE_ALLOCATE_BUFFER estiver definido, esse parâmetro especificará o número mínimo de TCHARs a serem alocados para um buffer de saída.

O buffer de saída não pode ser maior que 64 K bytes.

[in, optional] Arguments

Uma matriz de valores que são usados como valores de inserção na mensagem formatada. Um %1 na cadeia de caracteres de formato indica o primeiro valor na matriz Arguments ; um %2 indica o segundo argumento; e assim por diante.

A interpretação de cada valor depende das informações de formatação associadas à inserção na definição da mensagem. O padrão é tratar cada valor como um ponteiro para uma cadeia de caracteres terminada em nulo.

Por padrão, o parâmetro Arguments é do tipo va_list*, que é um tipo de dados específico de linguagem e implementação para descrever um número variável de argumentos. O estado do argumento va_list é indefinido após o retorno da função. Para usar o va_list novamente, destrua o ponteiro da lista de argumentos variáveis usando va_end e reinicialize-o com va_start.

Se você não tiver um ponteiro do tipo va_list*, especifique o sinalizador FORMAT_MESSAGE_ARGUMENT_ARRAY e passe um ponteiro para uma matriz de valores DWORD_PTR ; esses valores são entrada para a mensagem formatada como os valores de inserção. Cada inserção deve ter um elemento correspondente na matriz.

Retornar valor

Se a função for bem-sucedida, o valor retornado será o número de TCHARs armazenados no buffer de saída, excluindo o caractere nulo de terminação.

Se a função falhar, o valor retornado será zero. Para obter informações de erro estendidas, chame GetLastError.

Comentários

No texto da mensagem, há suporte para várias sequências de escape para formatar dinamicamente a mensagem. Essas sequências de escape e seus significados são mostrados nas tabelas a seguir. Todas as sequências de escape começam com o caractere percentual (%).

Sequência de escape Significado
%0 Encerra uma linha de texto de mensagem sem um novo caractere de linha à direita. Essa sequência de escape pode ser usada para compilar longas linhas ou para encerrar a própria mensagem sem um novo caractere de linha à direita. É útil para mensagens de prompt.
%n! cadeia de caracteres de formato! Identifica uma sequência de inserção. O valor de n pode estar no intervalo de 1 a 99. A cadeia de caracteres de formato (que deve estar cercada por pontos de exclamação) é opcional e usa como padrão !s! , se não for especificado. Para obter mais informações, consulte Campos de especificação de formato.

A cadeia de caracteres de formato pode incluir um especificador de largura e precisão para cadeias de caracteres e um especificador de largura para inteiros. Use um asterisco () para especificar a largura e a precisão. Por exemplo, %1!. *s! ou %1!*u!.

Se você não usar os especificadores de largura e precisão, os números de inserção corresponderão diretamente aos argumentos de entrada. Por exemplo, se a cadeia de caracteres de origem for "%1 %2 %1" e os argumentos de entrada forem "Bill" e "Bob", a cadeia de caracteres de saída formatada será "Bill Bob Bill".

No entanto, se você usar um especificador de largura e precisão, os números de inserção não corresponderão diretamente aos argumentos de entrada. Por exemplo, os números de inserção para o exemplo anterior podem ser alterados para "%1!*.*s! %4 %5!*s!".

Os números de inserção dependem se você usa uma matriz de argumentos (FORMAT_MESSAGE_ARGUMENT_ARRAY) ou um va_list. Para uma matriz de argumentos, o próximo número de inserção será n+2 se a cadeia de caracteres de formato anterior contiver um asterisco e for n+3 se dois asteriscos forem especificados. Para um va_list, o próximo número de inserção será n+1 se a cadeia de caracteres de formato anterior contiver um asterisco e for n+2 se dois asteriscos forem especificados.

Se você quiser repetir "Bill", como no exemplo anterior, os argumentos deverão incluir "Bill" duas vezes. Por exemplo, se a cadeia de caracteres de origem for "%1!*.*s! %4 %5!*s!", os argumentos podem ser, 4, 2, Bill, Bob, 6, Bill (se estiver usando o sinalizador FORMAT_MESSAGE_ARGUMENT_ARRAY ). A cadeia de caracteres formatada seria então " Bi Bob Bill".

Números de inserção repetidos quando a cadeia de caracteres de origem contém especificadores de largura e precisão podem não produzir os resultados pretendidos. Se você substituiu %5 por %1, a função tentará imprimir uma cadeia de caracteres no endereço 6 (provavelmente resultando em uma violação de acesso).

Não há suporte para especificadores de formato de ponto flutuante, e, E, f e g. A solução alternativa é usar a função StringCchPrintf para formatar o número de ponto flutuante em um buffer temporário e, em seguida, usar esse buffer como a cadeia de caracteres de inserção.

As inserções que usam o prefixo I64 são tratadas como dois argumentos de 32 bits. Eles devem ser usados antes que os argumentos subsequentes sejam usados. Observe que pode ser mais fácil para você usar StringCchPrintf em vez desse prefixo.

 

Qualquer outro caractere nondigit após um caractere percentual é formatado na mensagem de saída sem o caractere de porcentagem. Estes são alguns exemplos:

Cadeia de formato Saída resultante
%% Um único sinal de porcentagem.
%b Um único espaço. Essa cadeia de caracteres de formato pode ser usada para garantir o número apropriado de espaços à direita em uma linha de texto de mensagem.
%. Um único período. Essa cadeia de caracteres de formato pode ser usada para incluir um único período no início de uma linha sem encerrar a definição de texto da mensagem.
%! Um único ponto de exclamação. Essa cadeia de caracteres de formato pode ser usada para incluir um ponto de exclamação imediatamente após uma inserção sem que ela seja confundida com o início de uma cadeia de caracteres de formato.
%n Uma quebra de linha dura quando a cadeia de caracteres de formato ocorre no final de uma linha. Essa cadeia de caracteres de formato é útil quando FormatMessage está fornecendo quebras de linha regulares para que a mensagem se encaixe em uma determinada largura.
%r Um retorno de carro duro sem um caractere de nova linha à direita.
%t Uma única guia.
 

Comentários de segurança

Se essa função for chamada sem FORMAT_MESSAGE_IGNORE_INSERTS, o parâmetro Arguments deverá conter parâmetros suficientes para atender a todas as sequências de inserção na cadeia de caracteres de mensagem e elas deverão ser do tipo correto. Portanto, não use cadeias de caracteres de mensagem não confiáveis ou desconhecidas com inserções habilitadas porque elas podem conter mais sequências de inserção do que Os Argumentos fornecem ou aquelas que podem ser do tipo errado. Em particular, não é seguro usar um código de erro arbitrário do sistema retornado de uma API e usar FORMAT_MESSAGE_FROM_SYSTEM sem FORMAT_MESSAGE_IGNORE_INSERTS.

Exemplos

A função FormatMessage pode ser usada para obter cadeias de caracteres de mensagem de erro para os códigos de erro do sistema retornados por GetLastError. Para obter um exemplo, consulte Recuperando o código de Last-Error.

O exemplo a seguir mostra como usar uma matriz de argumentos e os especificadores de largura e precisão.
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>

void main(void)
{
    LPWSTR pMessage = L"%1!*.*s! %4 %5!*s!";
    DWORD_PTR pArgs[] = { (DWORD_PTR)4, (DWORD_PTR)2, (DWORD_PTR)L"Bill",  // %1!*.*s! refers back to the first insertion string in pMessage
         (DWORD_PTR)L"Bob",                                                // %4 refers back to the second insertion string in pMessage
         (DWORD_PTR)6, (DWORD_PTR)L"Bill" };                               // %5!*s! refers back to the third insertion string in pMessage
    const DWORD size = 100+1;
    WCHAR buffer[size];


    if (!FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                       pMessage, 
                       0,
                       0,
                       buffer, 
                       size, 
                       (va_list*)pArgs))
    {
        wprintf(L"Format message failed with 0x%x\n", GetLastError());
        return;
    }

    // Buffer contains "  Bi Bob   Bill".
    wprintf(L"Formatted message: %s\n", buffer);
}


O exemplo a seguir mostra como implementar o exemplo anterior usando va_list.

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>

LPWSTR GetFormattedMessage(LPWSTR pMessage, ...);

void main(void)
{
    LPWSTR pBuffer = NULL;
    LPWSTR pMessage = L"%1!*.*s! %3 %4!*s!";

    // The variable length arguments correspond directly to the format
    // strings in pMessage.
    pBuffer = GetFormattedMessage(pMessage, 4, 2, L"Bill", L"Bob", 6, L"Bill");
    if (pBuffer)
    {
        // Buffer contains "  Bi Bob   Bill".
        wprintf(L"Formatted message: %s\n", pBuffer);
        LocalFree(pBuffer);
    }
    else
    {
        wprintf(L"Format message failed with 0x%x\n", GetLastError());
    }
}

// Formats a message string using the specified message and variable
// list of arguments.
LPWSTR GetFormattedMessage(LPWSTR pMessage, ...)
{
    LPWSTR pBuffer = NULL;

    va_list args = NULL;
    va_start(args, pMessage);

    FormatMessage(FORMAT_MESSAGE_FROM_STRING |
                  FORMAT_MESSAGE_ALLOCATE_BUFFER,
                  pMessage, 
                  0,
                  0,
                  (LPWSTR)&pBuffer, 
                  0, 
                  &args);

    va_end(args);

    return pBuffer;
}

Requisitos

Requisito Valor
Cliente mínimo com suporte Windows XP [aplicativos da área de trabalho | aplicativos UWP]
Servidor mínimo com suporte Windows Server 2003 [aplicativos da área de trabalho | Aplicativos UWP]
Plataforma de Destino Windows
Cabeçalho winbase.h (inclua Windows.h)
Biblioteca Kernel32.lib
DLL Kernel32.dll

Confira também

Funções do tratamento de erros

Compilador de mensagens

Tabelas de mensagens