目錄
什么是 WriteConsoleA?
函數簽名
參數詳解
返回值
一個最簡單的例子
跟 ReadConsoleA 對比
再試一個有趣的例子
為什么傳地址給 lpNumberOfCharsWritten?
注意事項
什么是 WriteConsoleA?
WriteConsoleA 是一個 Windows API 函數,用來把文字寫到控制臺屏幕上。就像你在 C++ 用 std::cout 輸出東西,但它是直接跟 Windows 的控制臺打交道。
把它想象成一個“送信員”:
-
你給它一堆信(文字)和一個地址(屏幕的鑰匙),它就幫你把信送到屏幕上。
-
它是 ReadConsoleA 的反向操作:ReadConsoleA 是收信,WriteConsoleA 是送信。
函數簽名
它的完整定義是:
BOOL WriteConsoleA(HANDLE hConsoleOutput, // 屏幕的“鑰匙”const VOID* lpBuffer, // 要送的“信”DWORD nNumberOfCharsToWrite, // 信有多少字符LPDWORD lpNumberOfCharsWritten,// 記錄實際送了多少LPVOID lpReserved // 不用,寫 NULL
);
看起來有點像 ReadConsoleA,對吧?我一個個拆開講。?
參數詳解
1. HANDLE hConsoleOutput - 屏幕的“鑰匙”
-
這是什么:你用 GetStdHandle(STD_OUTPUT_HANDLE) 拿到的屏幕句柄。
-
作用:告訴 WriteConsoleA:“我要往屏幕上送東西。”
-
怎么用:
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
-
就像你告訴送信員:“用這個鑰匙打開屏幕的信箱。”
2. const VOID* lpBuffer - 要送的“信”
-
這是什么:你要輸出的文字,通常是一個 const char* 字符串。
-
作用:這是送信員要送出去的內容。
-
怎么用:
const char* message = "Hello";
-
想象這是你要寄出去的信,內容是“Hello”。VOID* 表示它可以是任何類型,但我們用 char 就夠了。
3. DWORD nNumberOfCharsToWrite - 信有多少字符
-
這是什么:一個數字,告訴函數“信里有多少字符要送”。
-
作用:讓送信員知道要送多長一段文字。
-
怎么用:
-
如果 message 是“Hello”,就寫 5(或者用 strlen(message))。
-
比如:
-
DWORD length = strlen(message); // 5
-
這就像告訴送信員:“這封信有 5 個字,別漏了。”
4. LPDWORD lpNumberOfCharsWritten - 記錄實際送了多少
-
這是什么:一個變量的地址,函數會把“實際送出去多少字符”寫在這里。
-
作用:告訴你送信員成功送了多少。
-
怎么用:
DWORD how_many_written; // 定義一個變量
然后傳地址:?
&how_many_written
-
跟 ReadConsoleA 的 lpNumberOfCharsRead 一樣,送信員會記下:“我送了 5 個字符。”
?
為什么傳地址給 lpNumberOfCharsWritten?
跟 ReadConsoleA 的 lpNumberOfCharsRead 一樣:
-
函數需要修改 how_many_written,告訴你實際寫了多少字符。
-
傳地址(&how_many_written)讓函數直接改這個變量。
-
如果不傳地址,函數改不了外面的值。
?
5. LPVOID lpReserved - 不用,寫 NULL
-
這是什么:一個預留參數,微軟留著以后可能用。
-
作用:現在沒用。
-
怎么用:
NULL
-
就像告訴送信員:“沒啥特別要求,正常送就行。”
返回值
-
返回 BOOL(TRUE 或 FALSE):
-
TRUE:送信成功。
-
FALSE:出錯了(比如屏幕鑰匙壞了)。
-
一個最簡單的例子
我們寫個程序,在屏幕上顯示“Hello”:
#include <windows.h>
#include <cstring>int main() {// 1. 拿到屏幕鑰匙HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);if (screen == INVALID_HANDLE_VALUE) {return 1; // 鑰匙壞了,退出}// 2. 準備信和計數器const char* message = "Hello"; // 要送的信DWORD how_many_written; // 記錄送了多少// 3. 發送信(寫到屏幕)WriteConsoleA(screen, message, strlen(message), &how_many_written, NULL);return 0;
}
運行過程:
-
拿到鑰匙:GetStdHandle(STD_OUTPUT_HANDLE) 給你屏幕的鑰匙。
-
準備信:
-
message 是“Hello”,長度是 5。
-
how_many_written 是計數器。
-
-
送信:
-
WriteConsoleA 把“Hello”送到屏幕上。
-
how_many_written 變成 5,表示送了 5 個字符。
-
運行結果:屏幕上顯示“Hello”。
跟 ReadConsoleA 對比
參數 | ReadConsoleA | WriteConsoleA |
---|---|---|
第一個 | 鍵盤鑰匙(輸入) | 屏幕鑰匙(輸出) |
第二個 | 箱子(收信) | 信(送信) |
第三個 | 最多收多少字符 | 要送多少字符 |
第四個 | 記錄實際收了多少(地址) | 記錄實際送了多少(地址) |
第五個 | 控制選項(NULL) | 預留(NULL) |
-
ReadConsoleA 是從鍵盤“收”東西到程序里。
-
WriteConsoleA 是從程序“送”東西到屏幕上。
再試一個有趣的例子
我們結合 SetConsoleCursorPosition,在不同位置寫文字:
#include <windows.h>
#include <cstring>int main() {HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);if (screen == INVALID_HANDLE_VALUE) {return 1;}DWORD how_many_written;COORD pos;// 在 (5, 2) 寫 "Hi"pos.X = 5; pos.Y = 2;SetConsoleCursorPosition(screen, pos);const char* msg1 = "Hi";WriteConsoleA(screen, msg1, strlen(msg1), &how_many_written, NULL);// 在 (10, 5) 寫 "There"pos.X = 10; pos.Y = 5;SetConsoleCursorPosition(screen, pos);const char* msg2 = "There";WriteConsoleA(screen, msg2, strlen(msg2), &how_many_written, NULL);return 0;
}
注意事項
-
字符數:
-
nNumberOfCharsToWrite 必須匹配 lpBuffer 的長度,不然可能出錯。
-
用 strlen 確保準確。
-
-
換行:
-
如果想換行,得在字符串里加 \n,比如 "Hello\n"。
-
-
檢查返回值:
if (!WriteConsoleA(screen, message, strlen(message), &how_many_written, NULL)) {return 1; // 出錯了
}