在 c 中为 Windows 获取终端大小?

Posted

技术标签:

【中文标题】在 c 中为 Windows 获取终端大小?【英文标题】:Getting terminal size in c for windows? 【发布时间】:2011-10-12 08:05:50 【问题描述】:

如何在 Windows 下的控制台窗口中使用纯 c 检查 ymax 和 xmax?

linux有这段代码:

#include <stdio.h>
#include <sys/ioctl.h>
int main (void)

    struct winsize max;
    ioctl(0, TIOCGWINSZ , &max);
    printf ("lines %d\n", max.ws_row);
    printf ("columns %d\n", max.ws_col);

现在我想知道如何对 windows 做同样的事情。我试过winioctl.h,但它没有定义struct winsize,也没有定义任何其他类似名称。

有什么建议吗?谢谢。

PS。在 linux 中,您还可以使用 getenv("LINES"); 找到控制台大小。 windows下有类似的变量吗?

PPS。另外,总是有ncurses.h,我想这两个系统都可以使用,但我避免使用它,因为与我拥有的其他库发生冲突。

购买力平价。这个问题Getting terminal width in C?这里有很多tips,不用重复了。

【问题讨论】:

【参考方案1】:

以下两个函数将更直接地获取窗口大小。

请注意,我使用 gcc 发现,如果程序是管道式的,这种方法和 GetConsoleScreenBufferInfo 都不起作用。这有点痛苦,因为 for/f 然后也不起作用。显然屏幕数据在管道中不可用。

嗯,上面这句话当然是非常愚蠢的。 ;) STDOUT 不是管道中的屏幕!这确实意味着我更喜欢在 STD_OUTPUT_HANDLE 之上使用 STD_ERROR_HANDLE。与标准输出相比,我不太可能将标准错误引导到屏幕之外。

typedef struct _CONSOLE_FONT_INFO 
  DWORD nFont;
  COORD dwFontSize;
 CONSOLE_FONT_INFO, *PCONSOLE_FONT_INFO;

BOOL WINAPI GetCurrentConsoleFont(
   HANDLE             hConsoleOutput,
   BOOL               bMaximumWindow,
   PCONSOLE_FONT_INFO lpConsoleCurrentFont
);

/* Get the window width */
int getww_(void)

    CONSOLE_FONT_INFO info;
    GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &info);
    return info.dwFontSize.X;


/* Get the window height */
int getwh_(void)

    CONSOLE_FONT_INFO info;
    GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &info);
    return info.dwFontSize.Y;

【讨论】:

因为这是一个 sn-p,我添加了#include 和一个 main() 来打印 getww() 和 getwh()。当我运行它时,我得到了正在使用的字体大小 - 12x7 - 而不是控制台大小。我做错了吗? +1 用于建议 STD_ERROR_HANDLE 让 @quantum 的代码在您在脚本中使用它或需要管道输出时正常工作。【参考方案2】:

这会打印控制台的大小,而不是缓冲区:

#include <windows.h>

int main(int argc, char *argv[]) 
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    int columns, rows;

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
    rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;

    printf("columns: %d\n", columns);
    printf("rows: %d\n", rows);
    return 0;

此代码有效是因为srWindow“包含显示窗口左上角和右下角的控制台屏幕缓冲区坐标”,而SMALL_RECT结构“指定屏幕缓冲区字符的行和列细胞”根据 MSDN。我减去平行边以获得控制台窗口的大小。因为我得到的1 比实际值少,所以我加了一个。

【讨论】:

我没时间测试它,但看起来这是问题的正确答案。您介意指出此答案与当前接受的显示缓冲区大小的答案之间的区别吗?谢谢! @DrBeco 在大多数情况下,您答案中的缓冲区大小和此答案中提到的显示窗口具有相同的宽度,但这不是必需的。但是,正如您所注意到的,缓冲区和窗口可以并且通常确实具有不同的高度 - 这就是提供向后滚动 Windows 控制台会话的能力的原因。我发现从大缓冲区的角度考虑最容易,它具有较小的视口(显示)窗口,可以查看主缓冲区的任何部分。 正是我想要的。 +1 或者你可以使用 CONSOLE_SCREEN_BUFFER_INFO.dwSize.X 和 .Y 简称。 如果STDOUT被重定向到一个文件,那么GetConsoleScreenBufferInfo()调用返回FALSE,所以应该测试一下。【参考方案3】:

(部分回答)

这段代码:

CONSOLE_SCREEN_BUFFER_INFO csbi;
int ret;
ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ),&csbi);
if(ret)

    printf("Console Buffer Width: %d\n", csbi.dwSize.X);
    printf("Console Buffer Height: %d\n", csbi.dwSize.Y);

给出缓冲区的大小。唯一的问题是dwSize.Y 并不是真正的屏幕大小(这里是 300 而不是 25 行)。但是dwSize.X 匹配列的编号。只需windows.h 即可工作。

【讨论】:

以上是关于在 c 中为 Windows 获取终端大小?的主要内容,如果未能解决你的问题,请参考以下文章

获取终端窗口的大小(行/列)

win7超级终端怎么没有呢?怎么解决??

在Windows窗体c ++ / cli程序中为已定义的标识符获取未定义的标识符错误

如何激活windows 2000

获取win7当前使用的堆栈大小

webstorm在windows11中打不开