【C++】Windows控制台API基本使用(上)

前言

  本文章所使用的一些API为旧版API,建议使用其它方案代替它们。
  本文章多有些纰漏,若发现错误请在评论区指正。
  注: 文章内所有代码均在VS2019下编译通过。

一、控制台缓冲区大小

一、获取缓冲区大小

  GetConsoleScreenBufferInfo 可以获取到控制台窗口的一些信息。

BOOL WINAPI GetConsoleScreenBufferInfo(
  _In_  HANDLE                      hConsoleOutput,           // 输出句柄
  _Out_ PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo // 缓冲区信息结构体
);

  PCONSOLE_SCREEN_BUFFER_INFO 实际上是一个指针,可以使用_CONSOLE_SCREEN_BUFFER_INFO 或 CONSOLE_SCREEN_BUFFER_INFO 替代它。此结构体的原型为:

typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
   
  COORD      dwSize;              // 缓冲区大小
  COORD      dwCursorPosition;    // 控制台屏幕缓冲区中光标的列和行坐标
  WORD       wAttributes;
  SMALL_RECT srWindow;            // 显示窗口左上角和右下角的控制台屏幕缓冲区的坐标(即窗口大小)
  COORD      dwMaximumWindowSize; // 在给定当前屏幕缓冲区大小和字体和屏幕大小的情况下,它包含控制台窗口的最大大小(字符列和行)
} CONSOLE_SCREEN_BUFFER_INFO;

  此结构体同样包含缓冲区光标位置的信息,在获取光标位置时可以使用此结构体。
  下方代码将会输出缓冲区大小。

#include <stdio.h>
#include <Windows.h>

int main(int argc, char* argv[]) {
   
	// 获取输出句柄
	HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO info;

	GetConsoleScreenBufferInfo(outputHandle, &info);

	printf("缓冲区大小: x=%hd, y=%hd\n", info.dwSize.X, info.dwSize.Y);

	return 0;
}

Windows10中
Win7下

二、设置缓冲区大小

  (旧版API)SetConsoleScreenBufferSize 可以修改控制台的缓冲区大小。

WINBASEAPI
BOOL
WINAPI
SetConsoleScreenBufferSize(
    _In_ HANDLE hConsoleOutput, // 输出句柄
    _In_ COORD dwSize           // 新缓冲区大小
    );

  此函数接受一个 COORD 结构体 作为参数,其原型为:

typedef struct _COORD {
   
    SHORT X;
    SHORT Y;
} COORD, *PCOORD;

  下方代码将会设置缓冲区大小为115×40个字符。

#include <stdio.h>
#include <Windows.h>

int main(int argc, char* argv[]) {
   
	// 获取输出句柄
	HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);

	// 定义大小
	COORD size = {
    115, 40 };

	// 应用
	SetConsoleScreenBufferSize(outputHandle, size);
	SetConsoleScreenBufferSize(outputHandle, size);

	return 0;
}

效果
  不建议使用此API。

三、更详细的结构体

  CONSOLE_SCREEN_BUFFER_INFOEX 结构体能够记录更多的控制台信息,并且也有与之匹配的获取(GetConsoleScreenBufferInfoEx)和设置(SetConsoleScreenBufferInfoEx)函数。多数情况下,笔者更推荐使用 CONSOLE_SCREEN_BUFFER_INFOEX,因为 CONSOLE_SCREEN_BUFFER_INFOEX 拥有与之匹配的函数,而 _CONSOLE_SCREEN_BUFFER_INFO 和 CONSOLE_SCREEN_BUFFER_INFO 仅有一个获取函数(GetConsoleScreenBufferInfo),所以,能用就用吧。
  下面的代码演示了如何使用 CONSOLE_SCREEN_BUFFER_INFOEX

#include <stdio.h>
#include <Windows.h>

int main(int argc, char* argv[]) {
   
	// 获取输出句柄
	HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFOEX info;
	info.cbSize = sizeof(info);        // 不要忘记指定结构体大小

	GetConsoleScreenBufferInfoEx(outputHandle, &info);
	printf(
		"缓冲区大小: x=%hd, y=%hd\n"
		"窗口大小: x=%hd, y=%hd\n"
		"光标坐标: x=%hd, y=%hd\n"
		, info.dwSize.X, info.dwSize.Y, info.srWindow.Right + 1, info.srWindow.Bottom + 1, info.dwCursorPosition.X, info.dwCursorPosition.Y);

	return 0;
}

四、特性

  新版控制台又出特性了。在使用 GetConsoleScreenBufferInfoEx 获取控制台缓冲区信息后,如果再次设置,控制台的大小竟会缩减1行!?笔者在 stackoverflow 查找到了解决方法——只需在获取信息后将 srWindow 的 Right 和 Bottom 加 1。请参阅下方代码。

#include <stdio.h>
#include <Windows.h>

int main() {
   
	// 输出句柄
	HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);

	// 控制台缓冲区信息
	CONSOLE_SCREEN_BUFFER_INFOEX csbi;
	csbi.cbSize = sizeof(csbi);

	// 获取信息
	GetConsoleScreenBufferInfoEx(outputHandle, &csbi);
	printf("获取到的 srWindow 的值:{%d %d %d %d}\n", csbi.srWindow.Left, csbi.srWindow.Top, csbi.srWindow.Right, csbi.srWindow.Bottom);
	csbi.srWindow.Right++;
	csbi.srWindow.Bottom++;
	printf("更正后的 srWindow 的值:{%d %d %d %d}\n", csbi.srWindow.Left, csbi.srWindow.Top, csbi.srWindow.Right, csbi.srWindow.Bottom);

	return 0;
}

  效果:

二、窗口大小

一、获取窗口大小

  对于这种需求,CONSOLE_SCREEN_BUFFER_INFOEX 可以解决一切问题。但现在这里将依然使用 GetConsoleScreenBufferInfo 函数获取窗口大小。下面代码将会演示此功能。

#include <stdio.h>
#include <Windows.h>

int main(int argc, char* argv[]) {
   
	// 获取输出句柄
	HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO info;

	GetConsoleScreenBufferInfo(outputHandle, &info);

	printf("窗口大小: x=%hd, y=%hd\n", info.srWindow.Right + 1, info.srWindow.Bottom + 1);

	return 0;
}

Win7+Win10
  注: srWindow会把0也算进窗口大小内,所以需要将结果加1得到正确的数字。
  使用 CONSOLE_SCREEN_BUFFER_INFOEX 的样例在第一节的第三小节。

二、设置窗口大小

  (旧版API)SetConsoleWindowInfo 可以做到这一点。
  查阅 Microsoft Docs 了解此函数的参数。
  下面的代码可以实现此功能。

#include <stdio.h>
#include <Windows.h>

int main(int argc, char* argv[]) {
   
	// 获取输出句柄
	HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);

	SMALL_RECT winSize = {
   0, 0};

	winSize.Right = 20 - 1;
	winSize.Bottom = 10 - 1;

	SetConsoleWindowInfo(outputHandle, 1, &winSize);
	SetConsoleWindowInfo(outputHandle, 1, &winSize);

	printf("窗口大小被改变。\n");

	return 0;
}

三、光标位置

一、获取光标位置

  第一节的第三小节的示例代码演示了如何获取光标位置。而 _CONSOLE_SCREEN_BUFFER_INFO 和 CONSOLE_SCREEN_BUFFER_INFO 也可以获取光标位置。
  _CONSOLE_SCREEN_BUFFER_INFO 和 CONSOLE_SCREEN_BUFFER_INFO 的 dwCursorPosition 成员规定了光标的坐标。 CONSOLE_SCREEN_BUFFER_INFOEX 也有该成员。下面代码演示了如何使用 _CONSOLE_SCREEN_BUFFER_INFO 和 CONSOLE_SCREEN_BUFFER_INFO 的 dwCursorPosition 成员获取光标信息。

#include <stdio.h>
#includ
  • 22
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
控制台程序可以调用Windows API来实现各种功能。其中,GetConsoleMode和SetConsoleMode是两个常用的API,用于设置控制台的模式,启用或关闭指定功能。通过调用GetConsoleMode可以获取控制台的模式,而通过调用SetConsoleMode可以设置控制台的模式。\[1\] 另外,控制台程序还可以使用其他的控制台API来实现不同的功能。例如,可以使用Win32 API控制台上画线。通过调用GetConsoleWindow可以获取控制台的窗口句柄,然后通过调用GetDC获取设备上下文句柄,创建画笔并设置画笔属性,最后使用MoveToEx和LineTo函数来画线。\[2\] 此外,还可以使用其他控制台API来获取控制台模式。通过调用GetStdHandle函数获取输入和输出的控制台句柄,然后通过调用GetConsoleMode函数获取输入和输出的控制台模式。\[3\] 总之,控制台程序可以通过调用Windows API来实现各种功能,包括设置控制台模式、画线等。 #### 引用[.reference_title] - *1* *3* [【C++Windows控制台API基本使用(下)](https://blog.csdn.net/weixin_48178135/article/details/121715810)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [控制台调用win32 API 示例二则](https://blog.csdn.net/bcbobo21cn/article/details/90062967)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值