Windows操作系统下的wcswidth_l版本

3
我有一些需要在Windows控制台中写入的文本,我需要知道它实际上占用的列数。在支持该函数的平台上,wcswidth_l似乎是最好的选择(虽然mbswidth_l()会更好,因为我不想使用wchar_t,但由于某种原因它并不存在)。但除了其他平台外,我需要在Windows上也能够实现该功能。虽然可能没有可移植的解决方案,但我不知道Windows上是否有任何解决方案。我认为控制台应该有一个API可以获取光标位置等信息,所以我可以输出文本并检查位置的变化。这样可能是准确的,但额外输出是完全不可接受的。

如何在Windows上获取字符串或字符的列宽?

编辑:

wcswidth_l返回显示字符串所用的控制台列数。有些字符占用一个列,而其他字符(例如日语字符)占用两个。

例如,“a あ”的“列宽”为四。'a'是一个,' '是一个,而'あ'则为两个。(假设控制台实际上设置为显示非ASCII字符)。此外,如果API支持使用代码页65001(UTF-8)的字符串,则更好。


没有额外的输出是什么原因?是性能问题还是跟踪问题? - chris
UTF-8无法设置为当前代码页。恐怕您应该习惯使用UTF-16(wchar)。是的,这很遗憾,但UTF-8直到1993年Windows NT即将推出时才被发布。但实际上,再也没有人应该编写ANSI或MBCS Windows应用程序了。 - Ben
@chris 主要是性能问题,虽然我实际上还没有测量额外输出的成本。我们还会记录输出的数量,但我认为直接使用控制台API可以解决这个问题。 - bames53
我不知道你可以将控制台设置为使用UTF-8——谢谢。 - Ben
@chris 谢谢,我可能会尝试一下看看性能如何。 - bames53
显示剩余2条评论
2个回答

0

首先,Windows Console API 位于这里

其次,您要查找的函数是GetConsoleFontSize吗?

我将尝试在一秒钟内快速输入一个示例。

编辑:给你。如果有小错误,请原谅我。事实上,我发现它甚至更容易。 GetCurrentConsoleFont 在传递索引给 GetConsoleFontSize 之前,填充了一个 COORD 结构,所以节省了步骤 :)

#define _WIN32_WINNT 0x0501 //XP, 0x0601=windows 7
#include <windows.h>

int main()
{
    HANDLE hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);

    CONSOLE_FONT_INFO cfi;
    GetCurrentConsoleFont (hStdOutput, FALSE, &cfi);

    //cfi.dwFontSize.X == x size
    //cfi.dwFontSize.Y == y size
}

编辑:

如果你不介意看不见的输出,你可以使用CreateConsoleScreenBuffer来几乎拥有一个无形的控制台窗口,而不影响你的窗口。通过GetConsoleScreenBufferInfoEx可以获取光标位置,然后你可以使用WriteConsole将内容写入你的缓冲区(看不见),再次检查光标位置与实际写入字符数进行对比。请注意,事先检查光标位置不需要清除屏幕以使用此方法。

如果你不能承受额外的可见或不可见的输出,我不确定是否真的有可能实现。


不,我不认为GetConsoleFontSize是我要找的。它似乎返回有关字体的信息。我想知道特定字符串或字符在控制台中显示时使用了多少列。 - bames53
我最终决定创建一个控制台屏幕缓冲区。这样做存在一些缺点,比如必须在允许不准确的结果和对超出控制台宽度或控制台缓冲区长度的任何内容进行特殊处理之间做出选择。 - bames53

0

可移植方法

由于字符的宽度更多地依赖于字符本身而非它们所显示的系统(好的,可能会有例外,但应该相当罕见),因此可以使用单独的函数来处理这个问题(在 Windows 上也是如此)。这需要 Unicode 字符,因为它使得分析字符串宽度更加容易,但人们肯定可以编写一个包装器来在不同编码间进行转换。

现有实现

这里提供了适用且可移植的实现,用户可以将其插入自己的应用程序中,并在 Windows 上退而使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接