c# - 我应该如何在 Windows 上创建自定义图形控制台/终端?

标签 c# .net windows graphics console

Windows 控制台界面(想想 cmd 窗口)对用户来说是一个非常简单的 GUI。然而,它处理渲染、用户输入和滚动的效率水平非常高。用于创建此界面的方法无疑与传统桌面 GUI 的方法有很大不同。

我有兴趣为 Windows 创建自己的自定义控制台/终端,最好使用 C# 和基于 .NET 的技术(例如托管 GDI+ 或 WPF)。作为起点,我非常热衷于重新创建标准的简单 Windows shell。然后我可以从那里扩展内容并添加功能。

我正在寻找有关如何创建此类控制台 UI 的一般指导,但一些具体要点包括:

  • 我应该使用哪种渲染模型?渲染循环?部分更新(如 WPF)? WinForms 模型(不确定它是如何工作的)?

  • 在渲染模型中使用了什么样的缓存?

  • 如何加载字体以及如何呈现它们?它们是标准的 TrueType 字体、位图字体还是其他字体?

  • 滚动如何如此高效地执行?

  • 您认为可能相关的任何其他内容!

事实上,任何关于内置 Windows 控制台 UI(甚至高级 Linux 终端 UI)如何执行这些操作以及我如何模拟它们的解释都是理想的。

编辑:明确地说,我真的很想完全从头开始。基于 GDI+ 或 WPF 等图形框架,但仅此而已。

最佳答案

我曾经从头开始实现一个文本输出窗口 - 我想要一个像 Visual Studio 中的输出窗口一样工作的窗口。结果比我想象的要复杂,而且没有任何输入功能。

不幸的是代码是 C++ 的并且属于前雇主,所以我不能与你分享。但我可以告诉您会发生什么。

您需要一种方法来存储可以快速索引的输出行。如果您要限制显示的行数,还需要很容易从顶部删除行。在 C++ 中一个 deque<string>非常完美,我不知道 C# 中的等价物是什么(如果有的话)。

您将需要以下 Windows 消息的处理程序,顺序不分先后。

  • WM_LBUTTONDOWN - 开始选择。在按下按钮时使用 SetCapture 跟踪鼠标。
  • WM_LBUTTONUP - 结束选择。
  • WM_RBUTTONUP - 转换为 WM_CONTEXTMENU。
  • WM_CONTEXTMENU - 显示包含复制/剪切/粘贴以及您想要的任何其他内容的菜单。
  • WM_KEYDOWN - 响应 4 个光标键,Home/End,PageUp/PageDown。 Ctrl-A/Ctrl-C/Ctrl-X/Ctrl-V/Ctrl-D。
  • WM_PAINT - 绘制窗口的内容。
  • WM_SIZE - 在窗口大小改变时更新滚动条。
  • WM_VSCROLL - 在垂直滚动期间更新窗口的可见部分。
  • WM_HSCROLL - 在水平滚动期间更新窗口的可见部分。
  • WM_CREATE - 用于在创建窗口时进行初始化。
  • WM_SETFOCUS - 创建系统插入符号以显示窗口中的当前位置。
  • WM_KILLFOCUS - 杀死插入符号,因为只有当前获得焦点的窗 Eloquent 会显示插入符号。
  • WM_MOUSEMOVE - 在按下鼠标左键时跟踪对选择的更改。
  • WM_CAPTURECHANGED - 结束选择。
  • WM_TIMER - 在选择过程中光标离开窗口时自动滚动。
  • WM_GETDLGCODE - 添加 DLGC_WANTARROWS 以便方向键可以通过。
  • WM_MOUSEWHEEL - 响应鼠标滚轮滚动。

随着行被添加到文本缓冲区,调整滚动条的范围。垂直滚动条范围将是总行数,水平滚动条范围将是最宽行的宽度。

最好有一个等宽的单一字体——它使计算更容易。具体的字体技术并不重要。您只需要能够跟踪角色的位置。

滚动是如何高效执行的?当窗口滚动时,您跟踪窗口的顶部和底部线条,当出现绘制消息时,您只绘制当前可见的线条。其他人仍在缓冲区中,但没有被触及。可以在窗口滚动时 blit 窗口的内容,并且只绘制从顶部或底部进入的部分,但对于今天的处理器来说,这是一种浪费——窗口将完全重绘得如此之快,以至于你不会注意到.

编辑:巧合的是,我偶然发现了这篇关于滚动条的 Microsoft 指南,这对于完成这项任务来说应该是必不可少的读物。 http://msdn.microsoft.com/en-us/library/windows/desktop/bb787527.aspx

关于c# - 我应该如何在 Windows 上创建自定义图形控制台/终端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9398278/

相关文章:

node.js - 适用于 Windows 和 Ubuntu 的 NodeJS exec() 命令

c# - 无法从 ASP.NET MVC 中的 IEnumerable 获取 JSON

c# - 如何从 p12 文件中读取 SecretKey?

mysql - Windows .bat 文件 0< 不确定 0 来自何处

java - WPF是不是一个了不起的东西?

c# - 我应该开始使用 Windows Azure

c# - 如何在 C# 中为 Windows Metro 风格应用程序在屏幕上绘图?

c# - Graphics.DrawString 斩波中间词

c# - 何时以及为何使用委托(delegate)?

c# - 使用 .NET 将文件发布到服务器 HttpWebRequest 或 WebClient