The Windows console interface (think cmd
window) is to the user a pretty simple GUI. The level of efficiency with which it handles rendering, user input, and scrolling is however very high. The methods used to create this interface are undoubtedly quite different to those of a traditional desktop GUI.
I am interested in creating my own custom console/terminal for Windows, preferably using C# and .NET-based technologies (e.g. managed GDI+ or WPF). As a starting point, I'd be quite keen simply to recreate the standard simple Windows shell. I could then expand things and add features from there.
I'm looking for general guidance on how to go about creating such a console UI, but some specific points include:
What sort of rendering model should I use? A render loop? Partial updates (like WPF)? The WinForms model (not sure how this works)?
What sort of caching is used in the rendering model?
How are fonts loaded and how are they rendered? Are they standard TrueType fonts, bitmap fonts, or something else?
How is scrolled performed so efficiently?
Anything else you think might be relevant!
Any explanation of how the inbuilt Windows console UI (or even the superior Linux terminal UI) do these things - and how I could emulate them - would be ideal, in fact.
Edit: To be clear, I really want to do this completely from scratch. Based on a graphical framework like GDI+ or WPF, but no more.
Windows Terminal is a modern host application for the command-line shells you already love, like Command Prompt, PowerShell, and bash (via Windows Subsystem for Linux (WSL)).
I once implemented a text output window from scratch - I wanted one that works like the Output window in Visual Studio. It turned out to be more complicated than I expected, and that was without any input capabilities.
Unfortunately the code is in C++ and belongs to a former employer, so I can't share it with you. But I can give you an idea of what to expect.
You need a way to store the lines of output that you can index quickly. If you're going to place a limit on the number of lines displayed it will also need to be easy to erase lines from the top. In C++ a deque<string>
was perfect, I don't know what the equivalent is (if any) in C#.
You'll need handlers for the following Windows messages, in no particular order.
As lines are added to the text buffer, adjust the range of the scrollbars. The vertical scrollbar range will be the total number of lines, and the horizontal scrollbar range will be the width of the widest line.
It is best to have a single font which is monospaced - it makes the calculations a lot easier. The specific font technology doesn't matter so much. You just need to be able to track the positions of the characters.
How is scrolled performed so efficiently? You track the top and bottom lines of the window as it scrolls, and when a paint message comes you only paint the lines that are currently visible. The others are still in the buffer but they don't get touched. It's possible to blit the contents of the window as it scrolls and only paint the parts that come in from the top or bottom, but with today's processors it's a wasted effort - the window will do a full repaint so quickly that you won't notice.
Edit: Coincidentally I came across this Microsoft guide to scroll bars which should be essential reading for this task. http://msdn.microsoft.com/en-us/library/windows/desktop/bb787527.aspx
If you want to create a beautiful .NET based command prompt replacement, then I suggest looking at http://poshconsole.codeplex.com/ It uses WPF for graphical elements and it implements a PowerShell script host. PowerShell is Microsoft's replacement for the venerable command prompt. PowerShell is installed by default with Windows 7, but you can download it for XP and Vista. PowerShell is highly extensible though scripting of using .NET objects directly. It can also be embedded in other programs.
WPF + PowerShell would be a great starting place for what you want to do. If you wanted you could then swap out PowerShell for your own command/scripting engine. If you were really ambitious you could take a whack at implementing your own scripting language on the DLR to act as your command interpreter.
Best of luck.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With