2015-12-10 1 views
2

Есть ли способ определить, работает ли консольное приложение с включенными функциями Windows 10?Как определить, включен ли режим обертки буфера Windows 10 в консоли

This MSDN page показывает, что HKEY_CURRENT_USER\Console\ForceV2, HKEY_CURRENT_USER\Console\LineWrap и HKEY_CURRENT_USER\Console\{name}\LineWrap контроль это, но, кроме того, что является менее надежным для анализа, оно не может быть правильным. Если пользователь переключается в прежний режим или из него, изменение не вступает в силу до тех пор, пока консоль не возобновит работу.

Если я разработал приложение, я могу выполнить проверку при запуске. Однако может быть состояние гонки, которое делает проверку реестра бесполезной для любого практического использования. Мне интересно, какое решение будет для сторонних консольных окон.

+0

Зачем вам нужно знать ??? Это удобства для пользователя, они не должны изменять код, который вы пишете. Апи совсем не изменилась. –

+0

@ Это будет теория, но это неправда. 'Console.BufferHeight' в C# вызывает проблемы, пока пользователь изменяет размер окна, потому что, когда функции W10 включены, пользователь может асинхронно изменять ширину окна, которая переплачивает текст и изменяет ширину буфера и вызывает состояние гонки между rect получить, изменить и установить в 'Console.BufferHeight'. Не говоря уже о нескольких других проблемах. Я получаю как управляемые, так и неуправляемые исключения, которые не должны происходить, потому что операции с буфером, окном и курсором не являются атомарными, а интерактивное изменение размера действительно забивает его. – jnm2

+0

Основное, что происходит в моем приложении, это то, что последняя строка вывода действует как своего рода строка состояния. Он перезаписывается новыми сообщениями. Это не необычная вещь. В W10 количество строк, которые оно принимает, изменяется при изменении размера окна и [нет безопасного способа использования API] (http://stackoverflow.com/a/34208406/521757) больше для обработки окна или буфера или курсор. Pre-W10, изменяя размеры окна, блокировал операции консоли API, поэтому проблема с состоянием гонки не существовала. – jnm2

ответ

2

Для этого, похоже, нет API, хотя я бы ожидал, что он появится в некоторых более поздних версиях SDK (возможно, дополнительные гипер расширенные флаги в GetConsoleMode).

В то же время, это быстрый хак, который пытается обнаружить возможность изменения размера более новой консоли на основе проверки значения ptMaxTrackSize.X, возвращаемого GetMinMaxInfo.

Унаследованная консоль не позволяет изменять размер окна более широко, чем ширина буфера экрана, в то время как новая делает. В предположениях, что (a) консоль работает с полной шириной буфера, т.е. не имеет горизонтальной полосы прокрутки, и (b) она еще не растянута до полной/максимальной ширины экрана, довольно просто проверить, позволяет ли это окно изменять размер окна более широкая (новая консоль) или нет (устаревшая консоль). Следует отметить, что предположение (а) можно было бы технически избежать путем ручного преобразования ширины буфера из символов в пиксели, вместо того чтобы полагаться на GetWindowRect, но предположение (б) в значительной степени неизбежно.

Это код (отказ от ответственности: быстрое и грязное доказательство концепции, проверка ошибок и т. Д.).

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 
Смежные вопросы