SetConsoleActiveScreenBuffer 不显示屏幕缓冲区

SetConsoleActiveScreenBuffer does not display screen buffer

我目前正在尝试用 C# 编写一个带有两个屏幕缓冲区的控制台应用程序,这两个缓冲区应该来回交换(很像现代 GPU 上的 VSync)。由于 System.Console class 没有提供切换缓冲区的方法,我不得不 P/Invoke kernel32.dll.

中的几种方法

这是我当前的代码,经过粗略的简化:

static void Main(string[] args)
{
    IntPtr oldBuffer = GetStdHandle(-11); //Gets the handle for the default console buffer
    IntPtr newBuffer = CreateConsoleScreenBuffer(0, 0x00000001, IntPtr.Zero, 1, 0); //Creates a new console buffer

    /* Write data to newBuffer */

    SetConsoleActiveScreenBuffer(newBuffer);
}

发生了以下事情:

我应该指出,我很少直接使用 Win32 API 并且对常见的 Win32 相关问题知之甚少。如果能提供任何帮助,我将不胜感激。

正如 IInspectable 在评论中指出的那样,您将 dwDesiredAccess 设置为零。这为您提供了一个没有访问权限的句柄。在某些极端情况下,这样的句柄很有用,但这不是其中之一。

唯一有点奇怪的是你得到的是 "invalid handle" 而不是 "access denied"。我猜你是 运行 Windows 7,所以句柄是用户模式对象("pseudohandle")而不是内核句柄。

无论如何,您需要将dwDesiredAccess设置为GENERIC_READ | GENERIC_WRITE,如图in the sample code


此外,正如 Hans 在评论中指出的那样,pinvoke.net 上的声明不正确,将最后一个参数指定为四字节整数而不是指针大小的整数。我相信正确的声明是

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateConsoleScreenBuffer(
    uint dwDesiredAccess,
    uint dwShareMode, 
    IntPtr lpSecurityAttributes, 
    uint dwFlags,
    IntPtr lpScreenBufferData
    );