¿Cómo debo crear una consola / terminal gráfica personalizada en Windows?


La interfaz de la consola de Windows (piense en la ventana cmd) es para el usuario una GUI bastante simple. Sin embargo, el nivel de eficiencia con el que maneja el renderizado, la entrada del usuario y el desplazamiento es muy alto. Los métodos utilizados para crear esta interfaz son, sin duda, muy diferentes a los de una interfaz gráfica de usuario de escritorio tradicional.

Estoy interesado en crear mi propia consola/terminal personalizada para Windows, preferiblemente utilizando tecnologías basadas en C# y.NET (por ejemplo, GDI+ administrado o WPF). Como punto de partida, sea muy entusiasta simplemente para recrear la cáscara simple estándar de Windows. Luego podría expandir las cosas y agregar características desde allí.

Estoy buscando una guía general sobre cómo crear una interfaz de usuario de consola, pero algunos puntos específicos incluyen:

  • ¿Qué tipo de modelo de renderizado debo usar? Un render bucle? Actualizaciones parciales (como WPF)? El modelo WinForms(no está seguro de cómo funciona)?

  • Qué tipo de almacenamiento en caché se utiliza en la representación modelo?

  • ¿Cómo se cargan las fuentes y cómo se representan? ¿Son fuentes TrueType estándar, fuentes de mapa de bits u otra cosa?

  • ¿Cómo se realiza scrolled de manera tan eficiente?

  • ¡Cualquier otra cosa que creas que pueda ser relevante!

Cualquier explicación de cómo la interfaz de usuario de la consola de Windows incorporada (o incluso la interfaz de usuario de terminal de Linux superior) hacer estas cosas - y cómo podría emularlas - sería ideal, de hecho.

Editar: Para ser claro, I realmente quiero hacer esto completamente desde cero. Basado en un framework gráfico como GDI + o WPF, pero no más.

Author: Noldorin, 2012-02-22

7 answers

Una vez implementé una ventana de salida de texto desde cero, quería una que funcionara como la ventana de salida en Visual Studio. Resultó ser más complicado de lo que esperaba, y eso fue sin ninguna capacidad de entrada.

Desafortunadamente, el código está en C++ y pertenece a un antiguo empleador, por lo que no puedo compartirlo con usted. Pero puedo darte una idea de qué esperar.

Necesita una forma de almacenar las líneas de salida que puede indexar rápidamente. Si vas a poner un límite en el número de líneas mostradas también tendrá que ser fácil de borrar las líneas de la parte superior. En C++, a deque<string> era perfecto, no se cuál es el equivalente (si lo hay) en C#.

Necesitará controladores para los siguientes mensajes de Windows, sin ningún orden en particular.

  • WM_LBUTTONDOWN - para iniciar una selección. Utilice SetCapture para rastrear el ratón mientras el botón está abajo.
  • WM_LBUTTONUP - para finalizar una selección.
  • WM_RBUTTONUP-traducir a WM_CONTEXTMENU.
  • WM_CONTEXTMENU - para mostrar un menú con Copiar/Cortar/Pegar y cualquier otra cosa que desee.
  • WM_KEYDOWN - para responder a las 4 teclas de cursor, Inicio/Fin, PageUp/PageDown. Ctrl-A Ctrl-C/Ctrl-X Ctrl-V/Ctrl-D.
  • WM_PAINT - para pintar el contenido de la ventana.
  • WM_SIZE - para actualizar las barras de desplazamiento cuando cambia el tamaño de la ventana.
  • WM_VSCROLL - para actualizar la parte visible de la ventana durante el desplazamiento vertical.
  • WM_HSCROLL-to actualice la parte visible de la ventana durante el desplazamiento horizontal.
  • WM_CREATE - para la inicialización cuando se crea la ventana.
  • WM_SETFOCUS - para crear un sistema de caret para mostrar la posición actual en la ventana.
  • WM_KILLFOCUS - para matar el caret ya que solo la ventana actualmente enfocada debería mostrar un caret.
  • WM_MOUSEMOVE - para realizar un seguimiento de los cambios en la selección con el botón izquierdo del ratón pulsado.
  • WM_CAPTURECHANGED-para terminar una selección.
  • WM_TIMER - para desplazarse automáticamente cuando el cursor sale de la ventana durante una selección.
  • WM_GETDLGCODE - para agregar DLGC_WANTARROWS para que las teclas de flecha lleguen.
  • WM_MOUSEWHEEL - para responder a la rueda del ratón para el desplazamiento.

A medida que se agregan líneas al búfer de texto, ajuste el rango de las barras de desplazamiento. El rango de la barra de desplazamiento vertical será el número total de líneas, y el rango de la barra de desplazamiento horizontal será el ancho del más ancho alinear.

Es mejor tener una sola fuente que esté monoespaciada - hace los cálculos mucho más fáciles. La tecnología específica de la fuente no importa tanto. Solo tienes que ser capaz de rastrear las posiciones de los personajes.

¿Cómo se realiza el desplazamiento de manera tan eficiente? Realiza un seguimiento de las líneas superior e inferior de la ventana a medida que se desplaza, y cuando aparece un mensaje de pintura, solo pinta las líneas que están visibles actualmente. Los otros todavía están en el buffer pero no se tocan. Es posible borrar el contenido de la ventana a medida que se desplaza y solo pintar las partes que vienen desde la parte superior o inferior, pero con los procesadores de hoy es un esfuerzo desperdiciado - la ventana hará un repintado completo tan rápido que no te darás cuenta.

Editar: Casualmente me encontré con esta guía de Microsoft para barras de desplazamiento que debería ser lectura esencial para esta tarea. http://msdn.microsoft.com/en-us/library/windows/desktop/bb787527.aspx

 19
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-28 20:55:55

Si desea crear un hermoso reemplazo del símbolo del sistema basado en. NET, le sugiero que mire http://poshconsole.codeplex.com / Utiliza WPF para elementos gráficos e implementa un host de script de PowerShell. PowerShell es el reemplazo de Microsoft para el símbolo del sistema venerable. PowerShell se instala de forma predeterminada con Windows 7, pero se puede descargar para XP y Vista. PowerShell es altamente extensible a través de secuencias de comandos de usar objetos. NET directamente. También puede ser integrado en otros programas.

WPF + PowerShell sería un gran punto de partida para lo que quieres hacer. Si lo desea, puede intercambiar PowerShell por su propio motor de comandos/scripts. Si usted fuera realmente ambicioso, podría tomar un golpe en la implementación de su propio lenguaje de scripting en el DLR para actuar como su intérprete de comandos.

La mejor de las suertes.

 8
Author: Brad Campbell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-01 18:01:16

Echa un vistazo al proyecto de código abierto Console. Hace mucho, y lo hace muy bien. Proporciona una consola unificada para lo que sea basado en caracteres. Corro cmd, bash y python cada uno en su propia pestaña.

Está en C++ y no proporcionará la diversión de escribirlo usted mismo, sin embargo.

 4
Author: ixe013,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-28 21:03:38

Tuve un gran éxito con RichTextBox para la salida. En realidad, hace todo lo que pueda desear: personalización del color, renderizado y desplazamiento efectivos, operaciones de portapapeles, etc. La entrada se organizó interceptando los eventos de pulsación de teclas de la ventana.

 3
Author: ogggre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-27 22:24:00

Si la velocidad es primordial, entonces XNA es una forma muy rápida (codificación mínima) para dibujar su texto a alta velocidad. Puede manejar miles de sprites a 100 de FPS. Usando SpriteBatch:: DrawString() y SpriteFont puedes obtener una "consola" de alta velocidad con muy poco esfuerzo de codificación. La clase estándar de "Juego" se puede modificar para volver a dibujar solo subregiones de la pantalla bajo demanda. Las advertencias incluyen kerning imperfecto que le dará al texto un aspecto borroso (puede ser capaz de solucionar esto apagando anti-aliasing y tener cuidado con sus proyecciones y la colocación de sprites). Si esto es un problema, entonces tal vez Direct2D ofrece una mejor solución (o cualquiera de las soluciones ya mencionadas).

 3
Author: axon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-28 04:30:59

Como un primer y simple enfoque, usaría un TextBox en modo multilínea. Esté atento a los eventos TextChanged o KeyPressed o KeyUp y actúe en consecuencia. Más tarde, puede crear su propio control derivando uno de un simple control Panel por ejemplo. El renderizado se realiza sobreescribiendo el método OnPaint (WinForms). No se requiere un bucle, solo una llamada a Invalidate o Refresh.

Use una matriz de cadenas o un List<string> o un LinkedList<string> como búfer de línea o simplemente use el texto almacenado en el cuadro de texto.

Si crea su propio control con WinForms, System.Windows.Forms.TextRenderer es una buena opción para renderizar texto. Se utilizará en OnPaint.

El desplazamiento es algo complicado si creas tu propio control. System.Windows.Controls.Panel ya contiene soporte de desplazamiento, sin embargo, todavía tiene que decirle al control cómo colocar y dimensionar los botones de la barra de desplazamiento cuando el texto cambia. Por otro lado, tiene que mover su texto cuando el usuario mueve las barras de desplazamiento y actualizar la pantalla en consecuencia. El rendimiento no debe ser un problema para tal control simple.

 2
Author: Olivier Jacot-Descombes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-22 16:20:06

FastColoredTextBox el proyecto en github tiene un ejemplo Console. Es:

  • Eficiente y rápido
  • Coloreado
  • Disponible en WPF y WinForm
  • En C# y fácil de leer

Creo que leer el código te ayudará mucho.

 1
Author: samad montazeri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-01 09:35:33