Comment créer une console/terminal graphique personnalisé sur Windows?

l'interface Windows console (pensez cmd fenêtre) est pour l'utilisateur une interface graphique assez simple. Le niveau d'efficacité avec lequel il traite le rendu, l'entrée de l'utilisateur et le défilement est cependant très élevé. Les méthodes utilisées pour créer cette interface sont sans doute très différentes de celles d'une interface graphique traditionnelle.

je suis intéressé à créer ma propre console/terminal personnalisé pour Windows, de préférence en utilisant les technologies basées sur C# et .NET (par exemple GDI+ géré ou WPF). Départ point, je serais plutôt désireux de simplement recréer la coquille standard de fenêtres simples. Je pourrais alors étendre les choses et ajouter des fonctionnalités à partir de là.

je cherche des conseils généraux sur la façon de créer une telle interface, mais certains points spécifiques incluent:

  • quelle sorte de modèle de rendu devrais-je utiliser? Le rendu d'une boucle? Mises à jour partielles (comme WPF)? Le modèle WinForms (vous ne savez pas comment cela fonctionne)?

  • quel type de cache est utilisé dans le modèle de rendu?

  • Comment sont les polices chargées et comment sont-ils rendus? Sont-elles des polices TrueType standard, des polices bitmap, ou autre chose?

  • Comment est-ce que le scrolled est exécuté si efficacement?

  • Tout ce que vous pensez être pertinent!

n'importe quelle explication de la façon dont L'interface utilisateur intégrée de la console Windows (ou même l'interface utilisateur supérieure du terminal Linux) fait ces choses - et comment je pourrais les émuler - l'idéal serait, en fait.

Edit: pour être clair, je veux vraiment le faire complètement à partir de zéro. Basé sur un cadre graphique comme GDI+ ou WPF, mais pas plus.

27
demandé sur Noldorin 2012-02-22 19:56:53

7 réponses

j'ai une fois implémenté une fenêtre de sortie de texte à partir de zéro - j'en voulais une qui fonctionne comme la fenêtre de sortie dans Visual Studio. Il s'est avéré être plus compliqué que je m'y attendais, et c'était sans aucune capacité d'entrée.

malheureusement le code est en C++ et appartient à un ancien employeur, donc je ne peux pas le partager avec vous. Mais je peux vous donner une idée de ce à quoi s'attendre.

Vous avez besoin d'un moyen de stocker les lignes de sortie que vous pouvez indexer rapidement. Si vous allez à placer une limite sur le nombre de lignes affichées, il faudra également être facile à effacer les lignes du haut. En C++ a deque<string> a été parfait, je ne sais pas ce que l'équivalent est (le cas échéant) en C#.

Vous aurez besoin de gestionnaires pour les messages Windows suivants, sans ordre particulier.

  • WM_LBUTTONDOWN-pour lancer une sélection. Utilisez SetCapture pour suivre la souris pendant que le bouton est en bas.
  • WM_LBUTTONUP-mettre fin à une sélection.
  • WM_RBUTTONUP - traduire en WM_CONTEXTMENU.
  • WM_CONTEXTMENU-pour afficher un menu avec Copier/Couper/Coller et tout ce que vous voulez.
  • WM_KEYDOWN à répondre aux 4 touches curseur, début/Fin, PageUp/PageDown. Ctrl-A/Ctrl-C/Ctrl-X/Ctrl-V/Ctrl-D.
  • WM_PAINT-peindre le contenu de la fenêtre.
  • WM_SIZE - pour mettre à jour les barres de défilement lorsque la taille de la fenêtre change.
  • WM_VSCROLL - pour mettre à jour la partie visible de la fenêtre pendant la verticale défiler.
  • WM_HSCROLL - pour mettre à jour la partie visible de la fenêtre lors du défilement horizontal.
  • WM_CREATE - pour l'initialisation lorsque la fenêtre est créée.
  • WM_SETFOCUS - pour créer un système caret pour afficher la position actuelle dans la fenêtre.
  • WM_KILLFOCUS - pour tuer le caret puisque seule la fenêtre actuellement focalisée devrait afficher un caret.
  • WM_MOUSEMOVE - pour suivre les modifications à la sélection pendant que la souris gauche bouton est enfoncé.
  • WM_CAPTURECHANGED-to end a selection.
  • WM_TIMER-faire défiler automatiquement lorsque le curseur quitte la fenêtre lors d'une sélection.
  • WM_GETDLGCODE-ajouter DLGC_WANTARROWS pour que les touches fléchées passent.
  • WM_MOUSEWHEEL - pour répondre à la molette de la souris pour faire défiler.

comme des lignes sont ajoutées au tampon de texte, ajustez la portée des barres de défilement. La portée du scrollbar vertical sera le total nombre de lignes, et la portée horizontale scrollbar sera la largeur de la ligne la plus large.

il est préférable d'avoir une police unique qui est mono - placée-cela rend les calculs beaucoup plus faciles. La technologie de la fonte n'a pas tellement d'importance. Vous avez juste besoin d'être en mesure de suivre la position des personnages.

Comment est-ce que le scrolled est exécuté si efficacement? Vous suivez les lignes du haut et du bas de la fenêtre pendant qu'elle défile, et quand un message de peinture vient vous peignez seulement le les lignes qui sont actuellement visibles. Les autres sont toujours dans le tampon, mais ils ne sont pas touchés. Il est possible de blifier le contenu de la fenêtre pendant qu'elle défile et de peindre seulement les parties qui viennent du haut ou du bas, mais avec les processeurs d'aujourd'hui c'est un effort gaspillé - la fenêtre fera un repaint complet si rapidement que vous ne le remarquerez pas.

Modifier: par coïncidence je suis tombé sur ce guide de Microsoft pour faire défiler les barres qui devraient être la lecture essentielle pour cette tâche. http://msdn.microsoft.com/en-us/library/windows/desktop/bb787527.aspx

19
répondu Mark Ransom 2012-02-28 20:55:55

si vous voulez créer un beau remplacement d'invite de commande basé sur .NET, alors je suggère de regarder http://poshconsole.codeplex.com/ il utilise WPF pour les éléments graphiques et implémente un hôte de script PowerShell. PowerShell est le remplacement de Microsoft pour l'invite de commande vénérable. PowerShell est installé par défaut avec Windows 7, mais vous pouvez le TÉLÉCHARGER pour XP et Vista. PowerShell est très extensible bien que le script de l'utilisation d'objets .NET directement. Il peut également être intégrés dans d'autres programmes.

WPF + PowerShell serait un excellent point de départ pour ce que vous voulez faire. Si vous le souhaitez, vous pouvez alors remplacer PowerShell pour votre propre commande/moteur de script. Si vous étiez vraiment ambitieux, vous pourriez prendre un coup à mettre en œuvre votre propre langage de script sur le DLR pour agir comme votre interprète de commande.

bonne chance.

8
répondu Brad Campbell 2012-03-01 18:01:16

regardez Console projet open source. Il fait beaucoup, et le fait très bien. Il fournit une console unifiée pour tout ce qui est basé sur les caractères. J'exécute cmd, bash et python chacun dans leur propre onglet.

C'est en C++ et il ne fournit pas le plaisir de l'écrire vous-même, cependant.

4
répondu ixe013 2012-02-28 21:03:38

J'ai eu un grand succès avec RichTextBox pour la sortie. En fait, il fait tout ce que vous pouvez souhaiter: la personnalisation des couleurs, le rendu et le défilement efficaces, les opérations de bloc-notes, etc. L'entrée a été organisée en interceptant les événements de pression de la fenêtre.

3
répondu ogggre 2012-02-27 22:24:00

si la vitesse est primordiale, alors XNA est un moyen très rapide (codage minimal) pour dessiner votre texte à haute vitesse. Il peut supporter des milliers de sprites à des centaines de FPS. En utilisant le SpriteBatch:: DrawString () et SpriteFont vous pouvez obtenir une "console" à grande vitesse avec très peu d'effort de codage. La classe "Game" standard peut être modifiée pour ne dessiner que des sous-régions de l'écran à la demande. Mises en garde inclure imparfaite crénage qui donne au texte une apparence floue (vous pouvez peut-être résoudre ce problème en désactivant l'anti-aliasing et en étant prudent avec vos projections et sprite de placement). Si C'est un problème, alors peut-être Direct2D offre une meilleure solution (ou l'une des solutions déjà mentionnées).

3
répondu axon 2012-02-28 04:30:59

comme première et simple approche, j'utiliserais un TextBox en mode multi-ligne. Montre pour l' TextChanged ou KeyPressed ou KeyUp événements et d'agir en conséquence. Plus tard, vous pouvez créer votre propre contrôle en dérivant un d'un simple Panel par exemple. Le rendu se fait en écrasant le OnPaint méthode (WinForms). Aucune boucle n'est nécessaire, juste un appel à Invalidate ou Refresh.

utilisez un tableau string ou un List<string> et LinkedList<string> comme tampon de ligne ou utilisez simplement le texte stocké dans le zone de texte.

si vous créez votre propre contrôle avec WinForms,System.Windows.Forms.TextRenderer est un bon choix pour rendre le texte. Il sera utilisé dans OnPaint.

le Scrolling est une chose délicate si vous créez votre propre contrôle. System.Windows.Controls.Panel contient déjà le support de scrolling, mais vous devez toujours indiquer au contrôle comment placer et dimensionner les boutons de la barre de défilement lorsque le texte change. D'autre part, vous devez déplacer votre texte lorsque l'utilisateur déplace les barres de défilement et de mettre à jour l'affichage conséquent. La Performance ne devrait pas être un problème pour un simple contrôle.

2
répondu Olivier Jacot-Descombes 2012-02-22 16:20:06