C语言 调整 Windows 控制台 API 报告窗口的大小



在 Windows 控制台 API 中,您可以收集 BUFFER 大小调整时的输入(通过窗口大小调整(,但无法收集 WINDOW 大小调整时的输入。为了说明这个问题,这里有一个小程序:

#include <Windows.h>
#include <stdio.h>
#define STR_BUF_SIZE 128
#define ENABLE_WINDOW_INPUT
int main() {
    HANDLE screenBufferHandle = CreateConsoleScreenBuffer(
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        CONSOLE_TEXTMODE_BUFFER,
        NULL
    );
    SetConsoleActiveScreenBuffer(screenBufferHandle);
    HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO info;
    INPUT_RECORD recordBuffer[32];
    char strBuf[STR_BUF_SIZE];
    while (1) {
        // Collect the input
        int inputLeft, inputToProcess;
        do {
            GetNumberOfConsoleInputEvents(in, &inputLeft);
            if (!inputLeft) {
                break;
            }
            inputLeft -= 32;
            ReadConsoleInput(
                in,
                recordBuffer,
                32,
                &inputToProcess
            );
            int i = 0;
            while (i < inputToProcess) {
                if (recordBuffer[i].EventType == WINDOW_BUFFER_SIZE_EVENT) {
                    COORD size = recordBuffer[i].Event.WindowBufferSizeEvent.dwSize;
                    sprintf_s(strBuf, STR_BUF_SIZE, "Event recorded, %dx%dn", size.X, size.Y);
                    OutputDebugString(strBuf);
                }
                i++;
            }
        } while (inputLeft > 0);
        GetConsoleScreenBufferInfo(screenBufferHandle, &info);
    }
}

这将在调整缓冲区大小时报告 (调试(。这是当这成为一个问题的时候:如果出现以下情况,则不会调整缓冲区的大小:

  • 缓冲区已经比窗口高(出现垂直滚动条(

  • 调整大小事件仅影响 Y 轴

在这种情况下,不会调整缓冲区的大小,窗口会缩小,滚动条上的控点也会缩小。但是,我希望窗口报告此事件,因为

我想保持缓冲区与窗口完全相同的大小,以隐藏滚动条。

我遇到了同样的挑战,所以我写了这个函数来处理它。从程序中的正确位置调用,窗口调整大小事件可以在事件本身的几毫秒内捕获。 向所有人致以最良好的祝愿。

#include <视窗>

/*------------------------------------------------------------------------------------

check_console_window_resize_event()
2022.10.05 - Created by Greg Spears and placed in the public domain.
           - Tested -- use at your own risk.
Params: none
Returns: TRUE if the console window has changed size.  FALSE if not.
USAGE: Best practice is to call the function repeatedly from your main application 
loop.   Preferably a place where the function can be called several times per second 
throughout the program's run time.

*--------------------------------------------------------------------------------**/

国际check_console_window_resize_event(无效({

/* variables declared static hold their value between function calls.*/
static int old_screen_w=0, old_screen_h=0;
static HANDLE hConOut=NULL;
int current_screen_w, current_screen_h;
int window_resized = FALSE;
CONSOLE_SCREEN_BUFFER_INFO csbi;
SECURITY_ATTRIBUTES sa;
if(!hConOut)
{
    /* First call -- get the window handle one time and save it*/
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    /* Using CreateFile we get the true console handle, avoiding any redirection.*/
    hConOut = CreateFile( TEXT("CONOUT$"),
         GENERIC_READ | GENERIC_WRITE,
         FILE_SHARE_READ | FILE_SHARE_WRITE,
         &sa, OPEN_EXISTING, (DWORD)0, (HANDLE)0 );
}
if(!hConOut) /* actually, this is a bad error, let your app handle the error as needed*/
    return FALSE;
GetConsoleScreenBufferInfo( hConOut, &csbi );
current_screen_w  = csbi.srWindow.Right - csbi.srWindow.Left + 1;
current_screen_h  = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
if(!old_screen_w && !old_screen_h)
{
    /* Execution comes here if this is first time this function is called.  
    ** Initialize the static variables and bail...*/
    old_screen_w = current_screen_w;
    old_screen_h = current_screen_h;
    return FALSE;
}
/* At last the real work of this function can be realized...*/
if(current_screen_w != old_screen_w || current_screen_h != old_screen_h)
{
    old_screen_w = current_screen_w;
    old_screen_h = current_screen_h;
    window_resized = TRUE;
}
return window_resized;

}

最新更新