目录
什么是 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; // 出错了
}