Windows控制台界面(想想cmd
窗口)对用户来说是一个非常简单的GUI。然而,处理渲染,用户输入和滚动的效率水平非常高。用于创建此接口的方法无疑与传统桌面GUI完全不同。
我有兴趣为Windows创建自己的自定义控制台/终端,最好使用基于C#和.NET的技术(例如托管GDI +或WPF)。作为一个起点,我非常希望重新创建标准的简单Windows shell。然后我可以扩展内容并从那里添加功能。
我正在寻找有关如何创建此类控制台UI的一般指导,但一些具体要点包括:
我应该使用哪种渲染模型?渲染循环?部分更新(如WPF)? WinForms模型(不确定这是如何工作的)?
渲染模型中使用了哪种缓存?
如何加载字体以及如何呈现字体?它们是标准的TrueType字体,位图字体还是其他什么?
滚动如何有效地执行?
您认为其他任何可能相关的内容!
内置的Windows控制台UI(甚至是高级Linux终端用户界面)如何做这些事情 - 以及我如何模仿它们 - 的任何解释都是理想的事实。
编辑:要明确,我真的想从头开始完成这项工作。基于像GDI +或WPF这样的图形框架,但不多了。
答案 0 :(得分:19)
我曾经从头开始实现一个文本输出窗口 - 我想要一个像Visual Studio中的Output窗口一样工作的窗口。事实证明它比我想象的要复杂得多,而且没有任何输入功能。
不幸的是,代码是用C ++编写的,属于前雇主,因此我无法与您分享。但我可以让你知道会发生什么。
您需要一种方法来存储可以快速索引的输出行。如果您要对显示的行数进行限制,则还需要从顶部轻松擦除行。在C ++中,deque<string>
是完美的,我不知道C#中的等价物是什么(如果有的话)。
您需要处理以下Windows消息的处理程序,无需特别顺序。
当行添加到文本缓冲区时,请调整滚动条的范围。垂直滚动条范围将是总行数,水平滚动条范围将是最宽行的宽度。
最好有一个等宽字体 - 它使计算更容易。特定的字体技术并不重要。您只需要能够跟踪角色的位置。
滚动如何有效地执行?在滚动时跟踪窗口的顶部和底部线条,当出现绘制消息时,您只绘制当前可见的线条。其他人仍然在缓冲区,但他们没有被触及。可以在滚动窗口时将窗口内容加入blit,只绘制从顶部或底部进入的部分,但是使用今天的处理器会浪费精力 - 窗口会快速重新绘制,以至于您不会注意到
编辑:巧合的是,我遇到了这个微软滚动条指南,它应该是这项任务必不可少的阅读材料。 http://msdn.microsoft.com/en-us/library/windows/desktop/bb787527.aspx
答案 1 :(得分:8)
如果你想创建一个漂亮的基于.NET的命令提示符替换,那么我建议查看http://poshconsole.codeplex.com/它使用WPF作为图形元素,它实现了PowerShell脚本宿主。 PowerShell是Microsoft对古老的命令提示符的替代品。 PowerShell默认安装在Windows 7中,但您可以下载它用于XP和Vista。尽管直接使用.NET对象编写脚本,但PowerShell具有高度可扩展性。它也可以嵌入其他程序中。
WPF + PowerShell将是您想要做的一个很好的起点。如果您愿意,可以将PowerShell替换为您自己的命令/脚本引擎。如果你真的雄心勃勃,你可以在DLR上实现自己的脚本语言,以充当你的命令解释器。
祝你好运。
答案 2 :(得分:4)
查看Console开源项目。它做了很多,而且做得很好。它为基于角色的任何内容提供统一的控制台。我在他们自己的选项卡中运行cmd,bash和python。
它是在C ++中,但它不会提供自己编写它的乐趣。
答案 3 :(得分:3)
我在RichTextBox输出方面取得了巨大成功。实际上,它可以满足您的所有需求:颜色自定义,有效渲染和滚动,剪贴板操作等。输入是通过拦截窗口的KeyPress事件来组织的。
答案 4 :(得分:3)
如果速度是最重要的,那么XNA是一种非常快速的方式(最小编码)来高速绘制文本。它可以在100的FPS下处理数千个精灵。使用SpriteBatch :: DrawString()和SpriteFont,您可以获得一个高速“控制台”,只需很少的编码工作。可以修改标准“游戏”类以按需重新绘制屏幕的子区域。注意事项包括不完美的字距调整,使文本外观模糊(您可以通过关闭消除锯齿并小心投影和精灵放置来解决此问题)。如果这是一个问题,那么也许Direct2D提供了更好的解决方案(或任何已经提到的解决方案)。
答案 5 :(得分:2)
作为第一个简单的方法,我会在多行模式下使用TextBox
。观察TextChanged
或KeyPressed
或KeyUp
事件并采取相应措施。稍后,您可以通过从简单的Panel
控件派生一个来创建自己的控件。通过覆盖OnPaint
方法(WinForms)进行渲染。无需循环,只需拨打Invalidate
或Refresh
。
使用字符串数组或List<string>
或LinkedList<string>
作为行缓冲区,或者只使用文本框中存储的文本。
如果使用WinForms创建自己的控件,System.Windows.Forms.TextRenderer
是渲染文本的不错选择。它将在OnPaint
中使用。
如果您创建自己的控件,滚动是一件棘手的事情。 System.Windows.Controls.Panel
已经包含滚动支持,但是当文本发生变化时,您仍然必须告诉控件如何放置和调整滚动条按钮的大小。另一方面,当用户移动滚动条并相应地更新显示时,您可以移动文本。对于这种简单的控制,性能不应该是一个问题。
答案 6 :(得分:1)