Winapi 如何仅使用标准库写入Windows上的备用屏幕缓冲区?
我正在为我的跨平台终端操作板条箱开发一个备用屏幕功能 形势 当我想写一些东西到控制台时,我可以使用下面的代码来写到当前控制台。这适用于UNIX和Windows系统:Winapi 如何仅使用标准库写入Windows上的备用屏幕缓冲区?,winapi,rust,output,buffer,handle,Winapi,Rust,Output,Buffer,Handle,我正在为我的跨平台终端操作板条箱开发一个备用屏幕功能 形势 当我想写一些东西到控制台时,我可以使用下面的代码来写到当前控制台。这适用于UNIX和Windows系统: write!(::std::fmt::io::stdout(), "Some text"). 当我切换到备用屏幕时,我不想写入当前屏幕,而是写入备用屏幕。这取决于您所处的平台不同。基本原理是一样的:我需要将句柄全局存储在某个位置,以便将存储的输出句柄置于交替屏幕模式,并将所有输出、命令和操作写入存储的输出句柄 当我处于备用模式时,
write!(::std::fmt::io::stdout(), "Some text").
当我切换到备用屏幕时,我不想写入当前屏幕,而是写入备用屏幕。这取决于您所处的平台不同。基本原理是一样的:我需要将句柄全局存储在某个位置,以便将存储的输出句柄
置于交替屏幕模式,并将所有输出、命令和操作写入存储的输出句柄
当我处于备用模式时,我的代码会写入备用屏幕,当我处于主屏幕模式时,我的代码会写入主屏幕
- Unix
对于UNIX系统,我可以使用切换到。我将
存储在某个地方,所有UNIX代码都使用该句柄访问终端::std::io::stdout()
输出。在交替屏幕模式下,我所做的所有
写入操作都在交替屏幕上完成,而在主屏幕上,所有
写入操作都在主屏幕上完成
- 窗户
对于Windows系统,我可以使用。我将使用创建一个新的屏幕缓冲区,然后使用它来更改活动缓冲区。最后,我需要存储从
获取的句柄。通过这个输出句柄,我可以将输出写入备用屏幕缓冲区CreateConsoleScreenBuffer
write!(::std::fmt::io::stdout(),“一些文本”)
,在Windows和Unix系统上,我会写入主屏幕而不是备用屏幕,因为stdout()
是
问题
上述方法在一定程度上起作用;当我想写入存储的句柄时
对于Unix,我可以执行以下操作:
// (...) some logic to get the handle to the current screen.
let stored_handle: Write = ...;
write!(stored_handle, "Some text);
#[cfg(target_os = "windows")]
let storage = WindowsScreenManager::new();
#[cfg(not(target_os = "windows"))]
let storage = UnixScreenManager::new();
write!(storage, "Some text");
但对于Windows,我可以不这样做:
// (...) some logic to get the handle to the current screen for windows.
let stored_handle: HANDLE = ...;
write!(stored_handle, "Some text);
我可以为存储stdout
的结构实现std::io::Write
,以便为Windows创建自己的逻辑,用WinAPI向控制台写入。如果我这样做,我将能够像下面那样写入该结构:
// (...) some logic to get the handle to the current screen.
let stored_handle: Write = ...;
write!(stored_handle, "Some text);
#[cfg(target_os = "windows")]
let storage = WindowsScreenManager::new();
#[cfg(not(target_os = "windows"))]
let storage = UnixScreenManager::new();
write!(storage, "Some text");
这对我的情况并不理想,因为我不能使用像\n\t
这样的生锈字符串转义字符。这样做时,我的字符串将不包含任何换行符或制表符。考虑一下,因为WinAPI不知道这些格式化选项。此外,我不想在我这方面手动管理所有写入Windows控制台的操作
我真的想把WinAPI句柄
用作std::io::Write
,这样它就可以在写操作中使用了代码>宏,就像我在UNIX中所做的那样。只需存储stdout()
并使用write
宏,但存储句柄
并写入该句柄
我想这应该可以在调用println!()
或写!(stdout())
在Windows上,它将向当前进程的标准输出句柄写入。但是现在我想写入备用句柄,而不仅仅是默认句柄。还是我错了
如果无法完成上述操作,我将如何写入备用屏幕句柄
,而不使用自己的实现来使用WinAPI写入控制台?在编译时替换字符串中的转义,如\n
和\t
。你到底有什么问题?如果我使用它们,我会在控制台中看到一些奇怪的符号。可能是因为在使用WriteConsoleOutputCharacterA
将其写入控制台之前,我将其编码为utf16(这需要完成)。另外,它增加了我使用WinAPI处理所有控制台写入操作的复杂性。IIRCWriteConsoleOutputCharacterA
用于ANSI字符串。如果用UTF-16(UniCode)编码字符串,则正确的函数是。结果仍然相同,反斜杠仍然显示为符号。如果用value.encode\u utf16().collect()替换win32\u字符串的主体,是否也一样?我不认为encode\u-wide
实际上是从UTF-8到UTF-16的转码OsStr
可以是任意字节。