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

问题描述 投票:30回答:7

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

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

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

  • 我应该使用什么样的渲染模型?渲染循环?部分更新(如WPF)? WinForms模型(不确定这是如何工作的)?
  • 渲染模型中使用了哪种缓存?
  • 如何加载字体以及如何呈现它们?它们是标准的TrueType字体,位图字体还是其他什么?
  • 滚动如何有效地执行?
  • 您认为可能与之相关的任何其他内容!

事实上,对内置Windows控制台UI(甚至是高级Linux终端UI)如何做这些事情以及如何模仿它们的任何解释都是理想的。

编辑:要清楚,我真的想从头开始完成这项工作。基于像GDI +或WPF这样的图形框架,但不多了。

c# .net windows graphics console
7个回答
19
投票

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

不幸的是,代码是用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 - 杀死插入符号,因为只有当前聚焦的窗口才会显示插入符号。
  • WM_MOUSEMOVE - 在鼠标左键按下时跟踪选择的更改。
  • WM_CAPTURECHANGED - 结束选择。
  • WM_TIMER - 在选择期间光标离开窗口时自动滚动。
  • WM_GETDLGCODE - 添加DLGC_WANTARROWS以便箭头键通过。
  • WM_MOUSEWHEEL - 响应鼠标滚轮进行滚动。

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

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

滚动如何有效地执行?在滚动时跟踪窗口的顶部和底部线条,当出现绘制消息时,您只绘制当前可见的线条。其他人仍然在缓冲区,但他们没有被触及。可以在滚动窗口时将窗口内容加入blit,只绘制从顶部或底部进入的部分,但是使用今天的处理器会浪费精力 - 窗口会快速重新绘制,以至于您不会注意到。

编辑:巧合的是,我遇到了这个微软滚动条指南,这对于这个任务应该是必不可少的阅读。 http://msdn.microsoft.com/en-us/library/windows/desktop/bb787527.aspx


8
投票

如果你想创建一个漂亮的基于.NET的命令提示符替换,那么我建议查看http://poshconsole.codeplex.com/它使用WPF作为图形元素,它实现了PowerShell脚本宿主。 PowerShell是微软取代古老的命令提示符。 PowerShell默认安装在Windows 7中,但您可以下载它用于XP和Vista。尽管直接使用.NET对象编写脚本,但PowerShell具有高度可扩展性。它也可以嵌入其他程序中。

WPF + PowerShell将是您想要做的一个很好的起点。如果您愿意,可以将PowerShell替换为您自己的命令/脚本引擎。如果你真的很雄心勃勃,你可以在DLR上实现自己的脚本语言,以充当你的命令解释器。

祝你好运。


4
投票

看看Console开源项目。它做了很多,而且做得很好。它为基于角色的任何内容提供统一的控制台。我在他们自己的选项卡中运行cmd,bash和python。

它是用C ++编写的,但它不会提供自己编写它的乐趣。


3
投票

我在RichTextBox上取得了巨大的成功。实际上,它可以完成您所需的一切:颜色自定义,有效渲染和滚动,剪贴板操作等。输入是通过拦截窗口的KeyPress事件来组织的。


3
投票

如果速度是最重要的,那么XNA是一种非常快速的方式(最小编码)来高速绘制文本。它可以在100的FPS下处理数千个精灵。使用SpriteBatch :: DrawString()和SpriteFont,您可以获得一个高速“控制台”,只需很少的编码工作。可以修改标准“游戏”类以按需重新绘制屏幕的子区域。注意事项包括不完美的字距调整,使文本外观模糊(您可以通过关闭消除锯齿并小心投影和精灵放置来解决此问题)。如果这是一个问题,那么也许Direct2D提供了更好的解决方案(或任何已经提到的解决方案)。


2
投票

作为第一个简单的方法,我会在多线模式下使用TextBox。观察TextChangedKeyPressedKeyUp事件并采取相应行动。稍后,您可以通过从简单的Panel控件派生一个来创建自己的控件。渲染通过覆盖OnPaint方法(WinForms)来实现。不需要循环,只需要调用InvalidateRefresh

使用字符串数组或List<string>LinkedList<string>作为行缓冲区或只使用文本框中存储的文本。

如果使用WinForms创建自己的控件,System.Windows.Forms.TextRenderer是渲染文本的不错选择。它将用于OnPaint

如果您创建自己的控件,滚动是一件棘手的事情。 System.Windows.Controls.Panel已经包含滚动支持,但是当文本发生变化时,您仍然必须告诉控件如何放置和调整滚动条按钮的大小。另一方面,当用户移动滚动条并相应地更新显示时,您可以移动文本。对于这种简单的控制,性能不应该是一个问题。


1
投票

github上的FastColoredTextBox项目有一个控制台示例。它是:

  • 高效快捷
  • 有色
  • 可在WPF和WinForm中使用
  • 在C#中易于阅读

我认为阅读代码会对你有所帮助。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.