첨부 소스 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
다운로드

▶ MainForm.cs

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Delegate
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 상태 추가하기 대리자 - AddStatusDelegate(text)

        /// <summary>
        /// 상태 추가하기 대리자
        /// </summary>
        /// <param name="text">텍스트</param>
        private delegate void AddStatusDelegate(string text);

        #endregion
        #region 값 그리기 대리자 - PlotValueDelegate(previousY, newY)

        /// <summary>
        /// 값 그리기 대리자
        /// </summary>
        /// <param name="previousY">이전 Y 값</param>
        /// <param name="newY">신규 Y 값</param>
        private delegate void PlotValueDelegate(int previousY, int newY);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 그리드 단계
        /// </summary>
        private const int GRID_STEP = 40;

        /// <summary>
        /// Y 중간값
        /// </summary>
        private int yMiddle;

        /// <summary>
        /// Y 값
        /// </summary>
        private int yValue;

        /// <summary>
        /// 그래프 스레드
        /// </summary>
        private Thread graphThread;

        /// <summary>
        /// 난수 발생기
        /// </summary>
        private Random random = new Random();

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            #region 이벤트를 설정한다.

            Load                   += Form_Load;
            this.graphButton.Click += graphButton_Click;
            this.timer.Tick        += timer_Tick;

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

        /// <summary>
        /// 폼 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_Load(object sender, EventArgs e)
        {
            this.yMiddle = this.graphPictureBox.ClientSize.Height / 2;

            this.yValue = this.yMiddle;

            int bitmapWidth  = this.graphPictureBox.ClientSize.Width;
            int bitmapHeight = this.graphPictureBox.ClientSize.Height;

            Bitmap bitmap = new Bitmap(bitmapWidth, bitmapHeight);

            Graphics graphics = Graphics.FromImage(bitmap);

            graphics.Clear(Color.Blue);

            for(int i = this.yMiddle; i <= this.graphPictureBox.ClientSize.Height; i += GRID_STEP)
            {
                graphics.DrawLine(Pens.LightBlue, 0, i, bitmapWidth - 1, i);
            }

            for(int i = this.yMiddle; i >= 0; i -= GRID_STEP)
            {
                graphics.DrawLine(Pens.LightBlue, 0, i, bitmapWidth - 1, i);
            }

            this.graphPictureBox.Image = bitmap;
        }

        #endregion
        #region 그래프 버튼 클릭시 처리하기 - graphButton_Click(sender, e)

        /// <summary>
        /// 그래프 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void graphButton_Click(object sender, EventArgs e)
        {
            if(this.graphThread == null)
            {
                AddStatus("스레드를 시작합니다.");

                this.graphThread = new Thread(DrawGraph);

                this.graphThread.Priority     = ThreadPriority.BelowNormal;
                this.graphThread.IsBackground = true;

                this.graphThread.Start();

                AddStatus("스레드가 시작되었습니다.");

                this.graphButton.Text = "중단";
            }
            else
            {
                AddStatus("스레드를 중단합니다.");

                this.graphThread.Abort();

                this.graphThread = null;

                AddStatus("스레드가 중단되었습니다.");

                this.graphButton.Text = "그래프";
            }
        }

        #endregion
        #region 타이머 틱 처리하기 - timer_Tick(sender, e)

        /// <summary>
        /// 타이머 틱 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void timer_Tick(object sender, EventArgs e)
        {
            this.timeLabel.Text = DateTime.Now.ToString("T");
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 상태 추가하기 - AddStatus(text)

        /// <summary>
        /// 상태 추가하기
        /// </summary>
        /// <param name="text">텍스트</param>
        private void AddStatus(string text)
        {
            if(InvokeRequired)
            {
                object[] argumentArray = new object[] { text };

                AddStatusDelegate addStatusDelegate = AddStatus;

                Invoke(addStatusDelegate, argumentArray);

                return;
            }

            this.statusTextBox.AppendText("\r\n" + text);

            this.statusTextBox.Select(statusTextBox.Text.Length, 0);

            this.statusTextBox.ScrollToCaret();
        }

        #endregion
        #region Y 값 설정하기 - SetYValue()

        /// <summary>
        /// Y 값 설정하기
        /// </summary>
        private void SetYValue()
        {
            DateTime stopTime = DateTime.Now.AddMilliseconds(20);

            while(DateTime.Now < stopTime)
            {
            }

            this.yValue += this.random.Next(-4, 5);

            if(this.yValue < 0)
            {
                this.yValue = 0;
            }

            if(this.yValue >= this.graphPictureBox.ClientSize.Height - 1)
            {
                this.yValue = graphPictureBox.ClientSize.Height - 1;
            }
        }

        #endregion
        #region 값 그리기 - PlotValue(previousY, newY)

        /// <summary>
        /// 값 그리기
        /// </summary>
        /// <param name="previousY">이전 Y 값</param>
        /// <param name="newY">신규 Y 값</param>
        private void PlotValue(int previousY, int newY)
        {
            if(InvokeRequired)
            {
                object[] argumentArray = new object[] { previousY, newY };

                PlotValueDelegate plotValueDelegate = PlotValue;

                Invoke(plotValueDelegate, argumentArray);

                return;
            }

            int bitmapWidth  = this.graphPictureBox.ClientSize.Width;
            int bitmapHeight = this.graphPictureBox.ClientSize.Height;

            Bitmap bitmap = new Bitmap(bitmapWidth, bitmapHeight);

            Graphics graphics = Graphics.FromImage(bitmap);

            graphics.DrawImage(this.graphPictureBox.Image, -1, 0);

            graphics.DrawLine(Pens.Blue, bitmapWidth - 1, 0, bitmapWidth - 1, bitmapHeight - 1);

            for(int i = this.yMiddle; i <= graphPictureBox.ClientSize.Height; i += GRID_STEP)
            {
                graphics.DrawLine(Pens.LightBlue, bitmapWidth - 2, i, bitmapWidth - 1, i);
            }

            for(int i = this.yMiddle; i >= 0; i -= GRID_STEP)
            {
                graphics.DrawLine(Pens.LightBlue, bitmapWidth - 2, i, bitmapWidth - 1, i);
            }

            graphics.DrawLine(Pens.White, bitmapWidth - 2, previousY, bitmapWidth - 1, newY);

            this.graphPictureBox.Image = bitmap;

            this.graphPictureBox.Refresh();

            graphics.Dispose();
        }

        #endregion
        #region 그래프 그리기 - DrawGraph()

        /// <summary>
        /// 그래프 그리기
        /// </summary>
        private void DrawGraph()
        {
            try
            {
                int y = this.yValue;

                for(;;)
                {
                    SetYValue();

                    PlotValue(y, this.yValue);

                    y = this.yValue;
                }
            }
            catch(Exception exception)
            {
                AddStatus("[스레드] " + exception.Message);
            }
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요