Функция FormatMessage (winbase.h)
Форматирует строку сообщения. Для функции требуется определение сообщения в качестве входных данных. Определение сообщения может исходить из буфера, переданного в функцию. Он может поступать из ресурса таблицы сообщений в уже загруженном модуле. Кроме того, вызывающий объект может попросить функцию выполнить поиск определения сообщения в системных ресурсах таблиц сообщений. Функция находит определение сообщения в ресурсе таблицы сообщений на основе идентификатора сообщения и идентификатора языка. Функция копирует отформатированный текст сообщения в выходной буфер, обрабатывая все внедренные последовательности вставки по запросу.
Синтаксис
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
);
Параметры
[in] dwFlags
Параметры форматирования и интерпретация параметра lpSource . Байт dwFlags в нижнем порядке указывает, как функция обрабатывает разрывы строк в выходном буфере. Байт нижнего порядка также может указывать максимальную ширину форматируемой выходной строки.
Этот параметр может иметь одно или несколько из следующих значений.
Значение | Значение |
---|---|
|
Функция выделяет буфер, достаточно большой для хранения отформатированного сообщения, и помещает указатель на выделенный буфер по адресу, указанному в lpBuffer. Параметр lpBuffer является указателем на LPTSTR; Необходимо привести указатель к LPTSTR (например, (LPTSTR)&lpBuffer ). Параметр nSize указывает минимальное количество TCHAR , выделяемых для буфера выходных сообщений. Вызывающий объект должен использовать функцию LocalFree, чтобы освободить буфер, когда он больше не нужен.
Если длина форматированного сообщения превышает 128 КБ байт, formatMessage завершится ошибкой и последующий вызов GetLastError вернет ERROR_MORE_DATA. В предыдущих версиях Windows это значение было недоступно для использования при компиляции приложений Магазина Windows. С Windows 10 это значение можно использовать. Windows Server 2003 и Windows XP: Если длина отформатированного сообщения превышает 128 000 байт, formatMessage не будет автоматически завершаться ошибкой ERROR_MORE_DATA. |
|
Параметр Arguments не является va_list структурой, а является указателем на массив значений, представляющих аргументы.
Этот флаг нельзя использовать с 64-разрядными целочисленными значениями. Если вы используете 64-разрядное целое число, необходимо использовать структуру va_list . |
|
Параметр lpSource — это дескриптор модуля, содержащий ресурсы таблицы сообщений для поиска. Если этот дескриптор lpSource имеет значение NULL, будет выполнен поиск в файле образа приложения текущего процесса. Этот флаг нельзя использовать с FORMAT_MESSAGE_FROM_STRING.
Если у модуля нет ресурса таблицы сообщений, функция завершается сбоем с ERROR_RESOURCE_TYPE_NOT_FOUND. |
|
Параметр lpSource является указателем на строку, завершающуюся значением NULL, которая содержит определение сообщения. Определение сообщения может содержать последовательности вставки так же, как и текст сообщения в ресурсе таблицы сообщений. Этот флаг нельзя использовать с FORMAT_MESSAGE_FROM_HMODULE или FORMAT_MESSAGE_FROM_SYSTEM. |
|
Функция должна искать запрошенное сообщение в ресурсах системных таблиц сообщений. Если этот флаг указан с помощью FORMAT_MESSAGE_FROM_HMODULE, функция выполняет поиск в системной таблице сообщений, если сообщение не найдено в модуле, указанном в lpSource. Этот флаг нельзя использовать с FORMAT_MESSAGE_FROM_STRING.
Если этот флаг указан, приложение может передать результат функции GetLastError , чтобы получить текст сообщения для системной ошибки. |
|
Последовательности вставки в определении сообщения, например %1, должны игнорироваться и передаваться в выходной буфер без изменений. Этот флаг полезен для получения сообщения для последующего форматирования. Если этот флаг установлен, параметр Arguments игнорируется. |
Байт dwFlags в нижнем порядке может указывать максимальную ширину форматируемой выходной строки. Ниже приведены возможные значения байта нижнего порядка.
Если байт нижнего порядка не является нулевым значением, отличным от FORMAT_MESSAGE_MAX_WIDTH_MASK, он указывает максимальное количество символов в выходной строке. Функция игнорирует регулярные разрывы строк в тексте определения сообщения. Функция никогда не разделяет строку, разделенную пробелами, через разрыв строки. Функция сохраняет жестко заданные разрывы строк в тексте определения сообщения в выходном буфере. Жестко заданные разрывы строк кодируются с помощью escape-последовательности %n.
[in, optional] lpSource
Расположение определения сообщения. Тип этого параметра зависит от параметров в параметре dwFlags .
Если в dwFlags не задан ни то, ни из этих флагов, то lpSource игнорируется.
[in] dwMessageId
Идентификатор запрошенного сообщения. Этот параметр игнорируется, если dwFlags включает FORMAT_MESSAGE_FROM_STRING.
[in] dwLanguageId
Идентификатор языка для запрошенного сообщения. Этот параметр игнорируется, если dwFlags включает FORMAT_MESSAGE_FROM_STRING.
Если передать определенный LANGID в этом параметре, FormatMessage вернет сообщение только для этого LANGID . Если функция не может найти сообщение для этого LANGID, она задает Last-Error значение ERROR_RESOURCE_LANG_NOT_FOUND. Если передать ноль, FormatMessage ищет сообщение для LANGID в следующем порядке:
- Нейтралитет языка
- Поток LANGID на основе значения языкового стандарта потока
- LanGID по умолчанию для пользователя на основе значения языкового стандарта пользователя по умолчанию
- LanGID по умолчанию в системе на основе значения языкового стандарта системы по умолчанию
- Английский (США)
[out] lpBuffer
Указатель на буфер, получающий строку, завершающуюся значением NULL, указывающую форматированное сообщение. Если dwFlags включает FORMAT_MESSAGE_ALLOCATE_BUFFER, функция выделяет буфер с помощью функции LocalAlloc и помещает указатель на буфер по адресу, указанному в lpBuffer.
Размер этого буфера не может превышать 64 КБ байт.
[in] nSize
Если флаг FORMAT_MESSAGE_ALLOCATE_BUFFER не задан, этот параметр указывает размер выходного буфера в TCHAR. Если задано FORMAT_MESSAGE_ALLOCATE_BUFFER , этот параметр задает минимальное количество TCHAR , выделяемых для выходного буфера.
Размер выходного буфера не может превышать 64 КБ байт.
[in, optional] Arguments
Массив значений, используемых для вставки значений в форматируемом сообщении. %1 в строке формата указывает первое значение в массиве Arguments ; %2 указывает второй аргумент; и так далее.
Интерпретация каждого значения зависит от сведений о форматировании, связанных с вставкой в определении сообщения. По умолчанию каждое значение рассматривается как указатель на строку, завершаемую null.
По умолчанию параметр Arguments имеет тип va_list*, который является типом данных для конкретного языка и реализации для описания переменного числа аргументов. Состояние аргумента va_list не определено при возврате из функции. Чтобы снова использовать va_list , удалите указатель списка переменных аргументов с помощью va_end и повторно инициализируйте его с помощью va_start.
Если у вас нет указателя типа va_list*, укажите флаг FORMAT_MESSAGE_ARGUMENT_ARRAY и передайте указатель на массив DWORD_PTR значений; эти значения являются входными данными для сообщения, отформатированного как вставка значений. Каждая вставка должна иметь соответствующий элемент в массиве.
Возвращаемое значение
Если функция выполнена успешно, возвращаемое значение — это количество TCHAR , хранящихся в буфере вывода, за исключением завершающего символа NULL.
Если функция выполняется неудачно, возвращается нулевое значение. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.
Комментарии
В тексте сообщения поддерживается несколько escape-последовательностей для динамического форматирования сообщения. Эти escape-последовательности и их значения показаны в следующих таблицах. Все escape-последовательности начинаются с символа процента (%).
Escape-последовательность | Значение |
---|---|
%0 | Завершает текстовую строку сообщения без символа новой строки в конце. Эта escape-последовательность может использоваться для создания длинных строк или завершения самого сообщения без нового символа строки. Это полезно для сообщений с запросами. |
%n! строка форматирования! |
Определяет последовательность вставки. Значение n может находиться в диапазоне от 1 до 99. Строка формата (которая должна быть заключена восклицательными знаками) является необязательной и по умолчанию имеет значение !s! , если не определено. Дополнительные сведения см. в разделе Поля спецификации форматирования.
Строка формата может включать описатель ширины и точности для строк и описатель ширины для целых чисел. Используйте звездочку (), чтобы указать ширину и точность. Например, %1!. *s! или %1!*u!. Если описатели ширины и точности не используются, числа вставки напрямую соответствуют входным аргументам. Например, если исходной строкой является "%1 %2 %1", а входными аргументами являются "Bill" и "Bob", отформатированная выходная строка будет "Bill Bob Bill". Однако при использовании описателя ширины и точности числа вставки не соответствуют напрямую входным аргументам. Например, вставка чисел для предыдущего примера может измениться на "%1!*.*s! %4 %5!*s!". Вставка чисел зависит от того, используется ли массив аргументов (FORMAT_MESSAGE_ARGUMENT_ARRAY) или va_list. Для массива аргументов следующее число вставки равно n+2 , если предыдущая строка формата содержала одну звездочку, и n+3 , если были указаны две звездочки. Для va_list следующее число вставки равно n+1 , если предыдущая строка формата содержала одну звездочку, и n+2 , если были указаны две звездочки. Если вы хотите повторить слово "Bill", как в предыдущем примере, аргументы должны включать "Bill" дважды. Например, если исходной строкой является "%1!*.*s! %4 %5!*s!", аргументы могут быть: 4, 2, Билл, Боб, 6, Билл (если используется флаг FORMAT_MESSAGE_ARGUMENT_ARRAY ). Затем форматируемой строкой будет "Bi Bob Bill". Повторяющиеся числа вставки, если исходная строка содержит описатели ширины и точности, могут не дать предполагаемых результатов. Если вы заменили %5 на %1, функция попытается напечатать строку по адресу 6 (скорее всего, это приведет к нарушению доступа). Описатели формата с плавающей запятой — e, E, f и g — не поддерживаются. Обходной путь — использовать функцию StringCchPrintf для форматирования числа с плавающей запятой во временный буфер, а затем использовать этот буфер в качестве строки вставки. Вставки, использующие префикс I64, обрабатываются как два 32-разрядных аргумента. Они должны использоваться до использования последующих аргументов. Обратите внимание, что вместо этого префикса может быть проще использовать StringCchPrintf . |
Любой другой символ nondigit, следующий за символом процента, форматируется в выходном сообщении без символа процента. Ниже приводятся некоторые примеры.
Строка форматирования | Результирующие выходные данные |
---|---|
%% | Знак одного процента. |
%B | Один пробел. Эту строку формата можно использовать для обеспечения соответствующего количества конечных пробелов в текстовой строке сообщения. |
%. | Один период. Эта строка формата может использоваться для включения одной точки в начале строки без завершения определения текста сообщения. |
%! | Один восклицательный знак. Эта строка формата может использоваться для включения восклицательного знака сразу после вставки, не принимая ее за начало строки формата. |
%n | Жесткий разрыв строки, когда строка формата находится в конце строки. Эта строка формата полезна, когда FormatMessage предоставляет регулярные разрывы строк, чтобы сообщение соответствовало определенной ширине. |
%r | Возврат жесткой каретки без символа новой строки. |
%t | Одна вкладка. |
Замечания по безопасности
Если эта функция вызывается без FORMAT_MESSAGE_IGNORE_INSERTS, параметр Arguments должен содержать достаточно параметров для удовлетворения всех последовательностей вставки в строке сообщения и иметь правильный тип. Поэтому не используйте ненадежные или неизвестные строки сообщений с включенными вставками, так как они могут содержать больше последовательностей вставки, чем предоставляет аргументы , или те, которые могут иметь неправильный тип. В частности, небезопасно принимать произвольный код системной ошибки, возвращаемый из API, и использовать FORMAT_MESSAGE_FROM_SYSTEM без FORMAT_MESSAGE_IGNORE_INSERTS.Примеры
Функция FormatMessage может использоваться для получения строк сообщения об ошибках для системных кодов ошибок, возвращаемых GetLastError. Пример см. в разделе Извлечение кода Last-Error.
В следующем примере показано, как использовать массив аргументов, а также описатели ширины и точности.#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);
}
В следующем примере показано, как реализовать предыдущий пример с помощью 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;
}
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Windows XP [классические приложения | Приложения UWP] |
Минимальная версия сервера | Windows Server 2003 [классические приложения | Приложения UWP] |
Целевая платформа | Windows |
Header | winbase.h (включая Windows.h) |
Библиотека | Kernel32.lib |
DLL | Kernel32.dll |
См. также
Таблицы сообщений