Fungsi FormatMessage (winbase.h)

Memformat string pesan. Fungsi ini memerlukan definisi pesan sebagai input. Definisi pesan dapat berasal dari buffer yang diteruskan ke fungsi . Ini dapat berasal dari sumber daya tabel pesan dalam modul yang sudah dimuat. Atau pemanggil dapat meminta fungsi untuk mencari sumber daya tabel pesan sistem untuk definisi pesan. Fungsi ini menemukan definisi pesan dalam sumber daya tabel pesan berdasarkan pengidentifikasi pesan dan pengidentifikasi bahasa. Fungsi menyalin teks pesan yang diformat ke buffer output, memproses urutan sisipan yang disematkan jika diminta.

Sintaks

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
);

Parameter

[in] dwFlags

Opsi pemformatan, dan cara menginterpretasikan parameter lpSource . Byte dwFlags urutan rendah menentukan bagaimana fungsi menangani jeda baris di buffer output. Byte urutan rendah juga dapat menentukan lebar maksimum baris output yang diformat.

Parameter ini bisa menjadi satu atau beberapa nilai berikut.

Nilai Makna
FORMAT_MESSAGE_ALLOCATE_BUFFER
0x00000100
Fungsi ini mengalokasikan buffer yang cukup besar untuk menahan pesan yang diformat, dan menempatkan penunjuk ke buffer yang dialokasikan pada alamat yang ditentukan oleh lpBuffer. Parameter lpBuffer adalah penunjuk ke LPTSTR; Anda harus melemparkan pointer ke LPTSTR (misalnya, (LPTSTR)&lpBuffer). Parameter nSize menentukan jumlah minimum TCHAR yang akan dialokasikan untuk buffer pesan output. Pemanggil harus menggunakan fungsi LocalFree untuk membebaskan buffer ketika tidak lagi diperlukan.

Jika panjang pesan yang diformat melebihi 128K byte, maka FormatMessage akan gagal dan panggilan berikutnya ke GetLastError akan mengembalikan ERROR_MORE_DATA.

Di versi Windows sebelumnya, nilai ini tidak tersedia untuk digunakan saat mengkompilasi aplikasi Bursa Windows. Pada Windows 10 nilai ini dapat digunakan.

Windows Server 2003 dan Windows XP:

Jika panjang pesan yang diformat melebihi 128K byte, maka FormatMessage tidak akan gagal secara otomatis dengan kesalahan ERROR_MORE_DATA.

FORMAT_MESSAGE_ARGUMENT_ARRAY
0x00002000
Parameter Argumen bukan struktur va_list , tetapi merupakan penunjuk ke array nilai yang mewakili argumen.

Bendera ini tidak dapat digunakan dengan nilai bilangan bulat 64-bit. Jika Anda menggunakan bilangan bulat 64-bit, Anda harus menggunakan struktur va_list .

FORMAT_MESSAGE_FROM_HMODULE
0x00000800
Parameter lpSource adalah handel modul yang berisi sumber daya tabel pesan untuk dicari. Jika handel lpSource ini NULL, file gambar aplikasi proses saat ini akan dicari. Bendera ini tidak dapat digunakan dengan FORMAT_MESSAGE_FROM_STRING.

Jika modul tidak memiliki sumber daya tabel pesan, fungsi gagal dengan ERROR_RESOURCE_TYPE_NOT_FOUND.

FORMAT_MESSAGE_FROM_STRING
0x00000400
Parameter lpSource adalah penunjuk ke string yang dihentikan null yang berisi definisi pesan. Definisi pesan mungkin berisi urutan sisipan, sama seperti teks pesan dalam sumber daya tabel pesan. Bendera ini tidak dapat digunakan dengan FORMAT_MESSAGE_FROM_HMODULE atau FORMAT_MESSAGE_FROM_SYSTEM.
FORMAT_MESSAGE_FROM_SYSTEM
0x00001000
Fungsi harus mencari sumber daya tabel pesan sistem untuk pesan yang diminta. Jika bendera ini ditentukan dengan FORMAT_MESSAGE_FROM_HMODULE, fungsi mencari tabel pesan sistem jika pesan tidak ditemukan dalam modul yang ditentukan oleh lpSource. Bendera ini tidak dapat digunakan dengan FORMAT_MESSAGE_FROM_STRING.

Jika bendera ini ditentukan, aplikasi dapat meneruskan hasil fungsi GetLastError untuk mengambil teks pesan untuk kesalahan yang ditentukan sistem.

FORMAT_MESSAGE_IGNORE_INSERTS
0x00000200
Sisipkan urutan dalam definisi pesan seperti %1 akan diabaikan dan diteruskan ke buffer output tidak berubah. Bendera ini berguna untuk mengambil pesan untuk pemformatan nanti. Jika bendera ini diatur, parameter Argumen diabaikan.
 

Byte dwFlags urutan rendah dapat menentukan lebar maksimum baris output yang diformat. Berikut ini adalah nilai yang mungkin dari byte berurutan rendah.

Nilai Makna
0
Tidak ada batasan lebar garis output. Fungsi menyimpan pemisah baris yang ada dalam teks definisi pesan ke dalam buffer output.
FORMAT_MESSAGE_MAX_WIDTH_MASK
0x000000FF
Fungsi mengabaikan hentian baris reguler dalam teks definisi pesan. Fungsi ini menyimpan pemisah baris yang dikodekan secara permanen dalam teks definisi pesan ke dalam buffer output. Fungsi ini tidak menghasilkan jeda baris baru.
 

Jika byte urutan rendah adalah nilai bukan nol selain FORMAT_MESSAGE_MAX_WIDTH_MASK, byte menentukan jumlah maksimum karakter dalam baris output. Fungsi mengabaikan hentian baris reguler dalam teks definisi pesan. Fungsi ini tidak pernah membagi string yang dibatasi oleh spasi kosong di seluruh hentian baris. Fungsi ini menyimpan pemisah baris yang dikodekan secara permanen dalam teks definisi pesan ke dalam buffer output. Pemisah baris yang dikodekan secara permanen dikodekan dengan urutan escape %n.

[in, optional] lpSource

Lokasi definisi pesan. Jenis parameter ini tergantung pada pengaturan dalam parameter dwFlags .

dwFlags Pengaturan Makna
FORMAT_MESSAGE_FROM_HMODULE
0x00000800
Handel ke modul yang berisi tabel pesan untuk dicari.
FORMAT_MESSAGE_FROM_STRING
0x00000400
Penunjuk ke string yang terdiri dari teks pesan yang tidak diformat. Ini akan dipindai untuk sisipan dan diformat sesuai.
 

Jika tidak ada bendera ini yang diatur dalam dwFlags, maka lpSource diabaikan.

[in] dwMessageId

Pengidentifikasi pesan untuk pesan yang diminta. Parameter ini diabaikan jika dwFlags menyertakan FORMAT_MESSAGE_FROM_STRING.

[in] dwLanguageId

Pengidentifikasi bahasa untuk pesan yang diminta. Parameter ini diabaikan jika dwFlags menyertakan FORMAT_MESSAGE_FROM_STRING.

Jika Anda meneruskan LANGID tertentu dalam parameter ini, FormatMessage hanya akan mengembalikan pesan untuk LANGID tersebut . Jika fungsi tidak dapat menemukan pesan untuk LANGID tersebut, fungsi akan mengatur Last-Error ke ERROR_RESOURCE_LANG_NOT_FOUND. Jika Anda meneruskan nol, FormatMessage mencari pesan untuk LANGID dalam urutan berikut:

  1. Netral bahasa
  2. Thread LANGID, berdasarkan nilai lokal utas
  3. LANGID default pengguna, berdasarkan nilai lokal default pengguna
  4. LANGID default sistem, berdasarkan nilai lokal default sistem
  5. Bahasa Inggris AS
Jika FormatMessage tidak menemukan pesan untuk LANGID sebelumnya, itu mengembalikan string pesan bahasa apa pun yang ada. Jika gagal, ia akan mengembalikan ERROR_RESOURCE_LANG_NOT_FOUND.

[out] lpBuffer

Penunjuk ke buffer yang menerima string yang dihentikan null yang menentukan pesan yang diformat. Jika dwFlags menyertakan FORMAT_MESSAGE_ALLOCATE_BUFFER, fungsi mengalokasikan buffer menggunakan fungsi LocalAlloc , dan menempatkan penunjuk ke buffer pada alamat yang ditentukan dalam lpBuffer.

Buffer ini tidak boleh lebih besar dari 64K byte.

[in] nSize

Jika bendera FORMAT_MESSAGE_ALLOCATE_BUFFER tidak diatur, parameter ini menentukan ukuran buffer output, dalam TCHAR. Jika FORMAT_MESSAGE_ALLOCATE_BUFFER diatur, parameter ini menentukan jumlah minimum TCHAR yang akan dialokasikan untuk buffer output.

Buffer output tidak boleh lebih besar dari 64K byte.

[in, optional] Arguments

Array nilai yang digunakan sebagai nilai sisipkan dalam pesan yang diformat. %1 dalam string format menunjukkan nilai pertama dalam array Argumen ; a %2 menunjukkan argumen kedua; dan sebagainya.

Interpretasi setiap nilai bergantung pada informasi pemformatan yang terkait dengan sisipan dalam definisi pesan. Defaultnya adalah memperlakukan setiap nilai sebagai penunjuk ke string yang dihentikan null.

Secara default, parameter Argumen berjenisva_list*, yang merupakan jenis data khusus bahasa dan implementasi untuk menjelaskan jumlah variabel argumen. Status argumen va_list tidak terdefinisi saat dikembalikan dari fungsi. Untuk menggunakan va_list lagi, hancurkan penunjuk daftar argumen variabel menggunakan va_end dan menginisialisasinya kembali dengan va_start.

Jika Anda tidak memiliki penunjuk jenis va_list*, tentukan bendera FORMAT_MESSAGE_ARGUMENT_ARRAY dan teruskan penunjuk ke array nilai DWORD_PTR ; nilai-nilai tersebut dimasukkan ke pesan yang diformat sebagai nilai sisipkan. Setiap sisipan harus memiliki elemen yang sesuai dalam array.

Mengembalikan nilai

Jika fungsi berhasil, nilai yang dikembalikan adalah jumlah TCHAR yang disimpan dalam buffer output, tidak termasuk karakter null yang mengakhiri.

Jika fungsi gagal, nilai yang dikembalikan adalah nol. Untuk mendapatkan informasi kesalahan yang diperluas, hubungi GetLastError.

Keterangan

Dalam teks pesan, beberapa urutan escape didukung untuk memformat pesan secara dinamis. Urutan escape ini dan maknanya diperlihatkan dalam tabel berikut. Semua urutan escape dimulai dengan karakter persen (%).

Urutan escape Makna
%0 Mengakhiri baris teks pesan tanpa karakter baris baru berikutnya. Urutan escape ini dapat digunakan untuk membangun garis panjang atau untuk mengakhiri pesan itu sendiri tanpa karakter baris baru berikutnya. Ini berguna untuk pesan perintah.
%n! format string! Mengidentifikasi urutan penyisipan. Nilai n dapat berkisar antara 1 hingga 99. String format (yang harus dikelilingi oleh tanda seru) bersifat opsional dan default ke !s! jika tidak ditentukan. Untuk informasi selengkapnya, lihat Format Bidang Spesifikasi.

String format dapat menyertakan penentu lebar dan presisi untuk string dan penentu lebar untuk bilangan bulat. Gunakan tanda bintang () untuk menentukan lebar dan presisi. Misalnya, %1!. *S! atau %1!*u!.

Jika Anda tidak menggunakan penentu lebar dan presisi, sisipkan angka sesuai langsung dengan argumen input. Misalnya, jika string sumber adalah "%1 %2 %1" dan argumen input adalah "Bill" dan "Bob", string output yang diformat adalah "Bill Bob Bill".

Namun, jika Anda menggunakan penentu lebar dan presisi, angka sisipan tidak sesuai langsung dengan argumen input. Misalnya, nomor sisipan untuk contoh sebelumnya dapat berubah menjadi "%1!*.*s! %4 %5!*s!".

Angka sisipan bergantung pada apakah Anda menggunakan array argumen (FORMAT_MESSAGE_ARGUMENT_ARRAY) atau va_list. Untuk array argumen, nomor sisipan berikutnya adalah n+2 jika string format sebelumnya berisi satu tanda bintang dan n +3 jika dua tanda bintang ditentukan. Untuk va_list, nomor sisipan berikutnya adalah n+1 jika string format sebelumnya berisi satu tanda bintang dan n+2 jika dua tanda bintang ditentukan.

Jika Anda ingin mengulangi "Tagihan", seperti dalam contoh sebelumnya, argumen harus menyertakan "Tagihan" dua kali. Misalnya, jika string sumber adalah "%1!*.*s! %4 %5!*s!", argumennya bisa, 4, 2, Bill, Bob, 6, Bill (jika menggunakan bendera FORMAT_MESSAGE_ARGUMENT_ARRAY ). String yang diformat kemudian akan menjadi " Bi Bob Bill".

Mengulangi menyisipkan angka ketika string sumber berisi lebar dan penentu presisi mungkin tidak menghasilkan hasil yang dimaksudkan. Jika Anda mengganti %5 dengan %1, fungsi akan mencoba mencetak string pada alamat 6 (kemungkinan mengakibatkan pelanggaran akses).

Penentu format floating-point—e, E, f, dan g—tidak didukung. Solusinya adalah menggunakan fungsi StringCchPrintf untuk memformat angka floating-point ke dalam buffer sementara, lalu menggunakan buffer tersebut sebagai string sisipan.

Sisipan yang menggunakan awalan I64 diperlakukan sebagai dua argumen 32-bit. Mereka harus digunakan sebelum argumen berikutnya digunakan. Perhatikan bahwa mungkin lebih mudah bagi Anda untuk menggunakan StringCchPrintf alih-alih awalan ini.

 

Karakter nondigit lain yang mengikuti karakter persen diformat dalam pesan output tanpa karakter persen. Berikut ini adalah beberapa contohnya.

Memformat untai (karakter) Output yang dihasilkan
%% Tanda persen tunggal.
%B Satu spasi. String format ini dapat digunakan untuk memastikan jumlah spasi berikutnya yang sesuai dalam baris teks pesan.
%. Satu periode. String format ini dapat digunakan untuk menyertakan satu periode di awal baris tanpa mengakhiri definisi teks pesan.
%! Satu tanda seru. String format ini dapat digunakan untuk menyertakan tanda seru segera setelah penyisipan tanpa kesalahan untuk awal string format.
%n Garis keras putus saat string format terjadi di akhir baris. String format ini berguna ketika FormatMessage menyediakan hentian baris reguler sehingga pesan pas dalam lebar tertentu.
%r Pengangkutan keras kembali tanpa karakter garis baru berikutnya.
%t Satu tab.
 

Keterangan Keamanan

Jika fungsi ini dipanggil tanpa FORMAT_MESSAGE_IGNORE_INSERTS, parameter Argumen harus berisi parameter yang cukup untuk memenuhi semua urutan penyisipan dalam string pesan, dan harus berjenis yang benar. Oleh karena itu, jangan gunakan string pesan yang tidak tepercaya atau tidak dikenal dengan sisipan diaktifkan karena dapat berisi lebih banyak urutan penyisipan daripada yang disediakan Argumen , atau yang mungkin merupakan jenis yang salah. Secara khusus, tidak aman untuk mengambil kode kesalahan sistem arbitrer yang dikembalikan dari API dan menggunakan FORMAT_MESSAGE_FROM_SYSTEM tanpa FORMAT_MESSAGE_IGNORE_INSERTS.

Contoh

Fungsi FormatMessage dapat digunakan untuk mendapatkan string pesan kesalahan untuk kode kesalahan sistem yang dikembalikan oleh GetLastError. Misalnya, lihat Mengambil Kode Last-Error.

Contoh berikut menunjukkan cara menggunakan array argumen dan penentu lebar dan presisi.
#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);
}


Contoh berikut menunjukkan cara mengimplementasikan contoh sebelumnya menggunakan 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;
}

Persyaratan

Persyaratan Nilai
Klien minimum yang didukung Windows XP [aplikasi desktop | Aplikasi UWP]
Server minimum yang didukung Windows Server 2003 [aplikasi desktop | Aplikasi UWP]
Target Platform Windows
Header winbase.h (termasuk Windows.h)
Pustaka Kernel32.lib
DLL Kernel32.dll

Lihat juga

Fungsi Penanganan Kesalahan

Pengkompilasi Pesan

Tabel Pesan