At some point down the line this got fixed, so a console application today can have UI elements - for example, it can call MessageBox(). Despite the weirdness - I am sure HCI purists/Apple would never approve of it - it can actually come quite handy. I, for one, quite often find myself in need of a graphic in the middle of a simple application (sometimes to just visualize something as part of a debug code path) - which I don't want to convert to fully-fledged GUI.
Unfortunately, there is precious little information on how to do do mixed mode console/GUI programming on the Internet, so I figured I'd fill the void :-).
First add references to System.Windows.Forms and System.Drawing (only if you are going to be drawing of course) to your app, as well as the corresponding "using"s.
Then you can create a dialog box that derives from Form:
using System.Windows.Forms;
class MyForm : Form
{
}
...and display it as follows:
MyForm f = new MyForm();
f.ShowDialog();
ShowDialog function is blocking - your console thread will not get control until user closes the window. Of course, standard console functions all work, you can print to the screen like so:
class MyForm : Form
{
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Console.WriteLine("Paint called!");
}
}
As an example, here is a very simple application that allows a user to plot simple functions from Math library:
//-----------------------------------------------------------------------
// 
// Copyright (C) Sergey Solyanik.
//
// This file is subject to the terms and conditions of the Microsoft Public License (MS-PL).
// See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL for more details.
// 
//----------------------------------------------------------------------- 
using System;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
namespace Graph
{
    class Graph : Form
    {
        public delegate double Function(double x);
        public Function F;
        public double X1;
        public double X2;
        public double Y1;
        public double Y2;
        private double stretchX;
        private double stretchY;
        private int ToScreenX(double x)
        {
            return ClientRectangle.Left + (int)((x - X1) * stretchX);
        }
        private int ToScreenY(double y)
        {
            return ClientRectangle.Bottom + (int)((y - Y1) * stretchY);
        }
        private double ToPlaneX(int x)
        {
            return X1 + ((double)(x - ClientRectangle.Left)) / stretchX;
        }
        private double ToPlaneY(int y)
        {
            return Y1 + ((double)(y - ClientRectangle.Bottom)) / stretchY;
        }
        protected override void OnPaint(PaintEventArgs e)
        {
          base.OnPaint(e);
            stretchX = (double)(ClientRectangle.Right - ClientRectangle.Left) / 
                (X2 - X1);
            stretchY = (double)(ClientRectangle.Top - ClientRectangle.Bottom) /
                (Y2 - Y1);
            if (Math.Sign(X1) != Math.Sign(X2))
            {
                e.Graphics.DrawLine(
                    Pens.Black,
                    ToScreenX(0),
                    ClientRectangle.Bottom,
                    ToScreenX(0),
                    ClientRectangle.Top);
            }
            if (Math.Sign(Y1) != Math.Sign(Y2))
            {
                e.Graphics.DrawLine(
                    Pens.Black,
                    ClientRectangle.Left,
                    ToScreenY(0),
                    ClientRectangle.Right,
                    ToScreenY(0));
            }
            for (int x = ClientRectangle.Left; x < ClientRectangle.Right - 1; ++x)
            {
                e.Graphics.DrawLine(
                    Pens.Blue,
                    x,
                    ToScreenY(F(ToPlaneX(x))),
                    x + 1,
                    ToScreenY(F(ToPlaneX(x + 1))));
            }
        }
    }
    class Program
    {
        private static Graph.Function SelectFunction()
        {
            Console.WriteLine("Available functions:");
            Type t = typeof(Math);
            MethodInfo[] m = t.GetMethods();
            for (int i = 0; i < m.Length; ++i)
            {
                if (m[i].IsPublic && m[i].IsStatic && m[i].ReturnType == typeof(double))
                {
                    ParameterInfo[] p = m[i].GetParameters();
                    if (p.Length == 1 && p[0].ParameterType == typeof(double))
                        Console.WriteLine("    " + m[i].Name);
                }
            }
            while (true)
            {
                Console.Write("Select a function to plot: ");
                string response = Console.ReadLine();
                for (int i = 0; i < m.Length; ++i)
                {
                    if (m[i].IsPublic && m[i].IsStatic && m[i].ReturnType == typeof(double))
                    {
                        ParameterInfo[] p = m[i].GetParameters();
                        if (p.Length == 1 && p[0].ParameterType == typeof(double))
                        {
                            if (m[i].Name.Equals(response))
                            {
                                return (Graph.Function)
                                    Delegate.CreateDelegate(typeof(Graph.Function), m[i]);
                            }
                        }
                    }
                }
            }
        }
        private static double GetNumber(string prompt)
        {
            for (; ; )
            {
                Console.Write(prompt);
                string response = Console.ReadLine();
                double result;
                if (double.TryParse(response, out result))
                    return result;
            }
        }
        static void Main(string[] args)
        {
            Console.CancelKeyPress += delegate
            {
                Console.WriteLine("Cancelled!");
                Environment.Exit(1);
            };
            Console.WriteLine("Press Ctrl-C to quit.");
            Console.WriteLine();
            Graph g = new Graph();
            g.F = SelectFunction();
            g.X1 = GetNumber("Abscissa lower boundary: ");
            g.X2 = GetNumber("Abscissa upper boundary: ");
            g.Y1 = GetNumber("Ordinate lower boundary: ");
            g.Y2 = GetNumber("Ordinate upper boundary: ");
            g.ShowDialog();
        }
    }
}
 
 

1 comment:
It's good about Graphic in Cosole Process. It's best console related idea.
Post a Comment