Функция 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 КБ, 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 в следующем порядке:
- Нейтральная языковая
- Thread 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 в строке формата указывает первое значение в массиве аргументов ; значение %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", то форматированная выходная строка — "Билл Боб Билл". Однако если используется описатель ширины и точности, числа вставки не соответствуют непосредственно входным аргументам. Например, числа вставок для предыдущего примера могут измениться на "%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 ). Форматированная строка будет "Би Боб Билл". Повторяющиеся числа вставки, если исходная строка содержит описатели ширины и точности, могут не дать ожидаемых результатов. Если вы заменили %5 %1, функция попытается напечатать строку по адресу 6 (скорее всего, это приведет к нарушению доступа). Описатели формата с плавающей запятой ( e, E, f и g) не поддерживаются. Обходной путь — использовать функцию StringCchPrintf для форматирования числа с плавающей запятой во временный буфер, а затем использовать этот буфер в качестве строки вставки. Вставки, использующие префикс I64, обрабатываются как два 32-разрядных аргумента. Они должны использоваться до использования последующих аргументов. Обратите внимание, что вместо этого префикса можно использовать StringCchPrintf . |
Любой другой недигитный символ, следующий за символом процента, отформатирован в выходном сообщении без символа процента. Ниже приводятся некоторые примеры.
Строка форматирования | Итоговые выходные данные |
---|---|
%% | Знак единого процента. |
%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 |
См. также
Таблицы сообщений