windows - 如何在控制台中检测当前是否启用 Windows 10 缓冲区包装模式

标签 windows winapi console-application

有什么方法可以检测控制台应用程序是否在启用 Windows 10 新功能的情况下运行?

This MSDN page显示 HKEY_CURRENT_USER\Console\ForceV2HKEY_CURRENT_USER\Console\LineWrapHKEY_CURRENT_USER\Console\{name}\LineWrap 控制它,但除此之外解析起来不太健壮,它可能不正确。如果用户切换到旧模式或从旧模式切换出来,则更改只有在控制台重新启动后才会生效。

如果我开发应用程序,我可以在启动时进行检查。不过,可能存在竞争条件,这使得注册表检查对于任何实际用途都毫无用处。我很好奇第三方控制台窗口的解决方案是什么。

最佳答案

似乎没有这样的 API,尽管我希望在以后的 SDK 中出现(也许 GetConsoleMode 中还有额外的超扩展标志)。

同时,以下是一个快速破解,它尝试基于检查 GetMinMaxInfo 返回的 ptMaxTrackSize.X 值来检测新控制台的调整更宽的功能。

旧版控制台不允许将窗口大小调整为比屏幕缓冲区宽度更宽,而新控制台则允许。假设(a)控制台以全缓冲区宽度运行,即没有水平滚动条,并且(b)它尚未拉伸(stretch)到全/最大屏幕宽度,则检查窗口是否允许调整自身大小是相当简单的更宽(新控制台)或不更宽(旧控制台)。应该注意的是,假设(a)在技术上可以通过手动将缓冲区宽度从字符转换为像素来避免,而不是依赖 GetWindowRect,但假设(b)几乎是不可避免的。

这是代码(免责声明:快速而肮脏的概念证明,没有错误检查等)。

int main()
{
    // largest possible console size for given font and desktop
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD cd = GetLargestConsoleWindowSize(hOut);
    SHORT nScrMaxXch = cd.X, 
        nScrMaxYch = cd.Y;

    // current and max console sizes for given screen buffer
    CONSOLE_SCREEN_BUFFER_INFOEX csbix = { sizeof(csbix) };
    GetConsoleScreenBufferInfoEx(hOut, &csbix);
    SHORT nWndXch = csbix.srWindow.Right - csbix.srWindow.Left + 1,
        nWndYch = csbix.srWindow.Bottom - csbix.srWindow.Top + 1;
    SHORT nWndMaxXch = csbix.dwMaximumWindowSize.X,
        nWndMaxYch = csbix.dwMaximumWindowSize.Y;

    wprintf(L"chars:   wnd-size %d %d, max-wnd-size %d %d, largest-size %d %d\n",
        nWndXch, nWndYch, nWndMaxXch, nWndMaxYch, nScrMaxXch, nScrMaxYch);

    // current window size
    HWND hWnd = GetConsoleWindow();
    RECT rc; GetWindowRect(hWnd, &rc);
    LONG nWndXpx = rc.right - rc.left,
        nWndYpx = rc.bottom - rc.top;

    // max window tracking size
    MINMAXINFO mmi = { 0 };
    SendMessage(hWnd, WM_GETMINMAXINFO, 0, (LPARAM)&mmi);
    LONG nWndMaxXpx = mmi.ptMaxTrackSize.x,
        nWndMaxYpx = mmi.ptMaxTrackSize.y;

    wprintf(L"pixels:  wnd-size %lu %lu, max-tracking-size %lu %lu\n",
        nWndXpx, nWndYpx, nWndMaxXpx, nWndMaxYpx);

    if (nWndXch == nWndMaxXch   // full buffer width, no h-scrollbar 
    && nWndXch < nScrMaxXch     // not already stretched to full screen width
    && nWndMaxXpx > nWndXpx)    // allowed to resized wider
        wprintf(L"\n...most likely a Win10 console with ForceV2 enabled\n");

    return 0;
}

这是在旧版控制台中运行时的输出。

chars:   wnd-size 80 25, max-wnd-size 80 71, largest-size 240 71
pixels:  wnd-size 677 443, max-tracking-size 677 1179

这是在新控制台中运行时的输出。

chars:   wnd-size 80 25, max-wnd-size 80 71, largest-size 239 71
pixels:  wnd-size 677 443, max-tracking-size 1936 1186

...most likely a Win10 console with ForceV2 enabled

关于windows - 如何在控制台中检测当前是否启用 Windows 10 缓冲区包装模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34210216/

相关文章:

windows - 是否可以将 Git bash 设置为不要求我为每个命令键入 "git"?

c# - 帮助超出范围的函数 (C#)

c++ - 如何强制父窗口绘制 "under"子窗口?

php - 如何使用 symfony2 组件 OutputInterface 和 Table helper 缩进写操作?

windows - 使用 DirectX 的 g++ 窗口?

sql-server - Db Connection 简单文件,不记得扩展名

php - Apache2 access.log 对于相同的数据包不同

c - 如何在 C 中使用 printf 为文本添加下划线

c# - 控制台应用程序 - 重新创建 Azure CLI `az --login` 的 Web 浏览器本地主机回调身份验证技术

c# - 让 WebBrowser 控件在控制台应用程序中工作?