我目前正在尝试用 C# 编写一个带有两个屏幕缓冲区的控制台应用程序,这两个屏幕缓冲区应该来回交换(很像现代 GPU 上的 VSync)。自从System.Console
类没有提供切换缓冲区的方法,我不得不从 kernel32.dll 中 P/Invoke 几个方法。
这是我当前的代码,经过大大简化:
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);
}
会发生以下情况:
- 屏幕仍然是空的,即使它应该显示
newBuffer
- 当写到
oldBuffer
代替newBuffer
,数据立即出现。因此,我写入缓冲区的方式应该是正确的。
- 致电后
SetConsoleActiveScreenBuffer(newBuffer)
,错误代码现在是6,这意味着句柄无效。这很奇怪,因为句柄不是 -1,文档将其描述为无效。
我应该指出,我很少直接使用 Win32 API,并且对常见的 Win32 相关问题知之甚少。我将不胜感激任何形式的帮助。
正如 IInspectable 在评论中指出的那样,您正在设置dwDesiredAccess
为零。这为您提供了一个没有访问权限的句柄。在某些边缘情况下,这样的句柄很有用,但这不是其中之一。
唯一有点奇怪的是你得到的是“无效句柄”而不是“访问被拒绝”。我猜您运行的是 Windows 7,因此句柄是用户模式对象(“伪句柄”)而不是内核句柄。
无论如何,你需要设置dwDesiredAccess
to GENERIC_READ | GENERIC_WRITE
如图所示在示例代码中 https://msdn.microsoft.com/en-us/library/windows/desktop/ms685032.aspx.
此外,正如 Hans 在评论中指出的那样,pinvoke.net 上的声明不正确,将最后一个参数指定为四字节整数而不是指针大小的整数。我相信正确的声明是
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateConsoleScreenBuffer(
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwFlags,
IntPtr lpScreenBufferData
);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)