언어 자료구조 알고리즘/프로그래밍 실습

[C# 실습,설비 컨트롤 예광탄] 반도체 증착공정 및 Burn in 테스트 설비 시뮬레이션

언제나휴일 2020. 10. 8. 16:40
반응형

이전 게시글에는 반도체 증착 공정 및 Burn in 테스트 설비를 작성하기 위한 예광탄을 소개했어요.

이번 게시글은 설비를 화면에 시각화하고 제어하기 위한 설비 컨트롤을 만들기 위한 예광탄 만들기예요.

 

1. 앞에서 작성한 소스 코드를 이용하여 설비 라이브러리를 만드세요.

  - 클래스 라이브러리(.NET Framework) 프로젝트틀 생성하세요.

  - 기본으로 제공하는 Class1.cs 파일은 제거합니다.

  - 이전 게시글에 있는 소스 코드 중에 Program.cs를 제외한 나머지 소스 코드를 추가합니다.

  - 빌드

 

2. 설비 예광탄 프로젝트를 Windows Forms(.NET Framework)으로 생성하세요.

  - 1에서 만든 설비 라이브러리를 참조 추가합니다.

 

3. 설비 예광탄 프로젝트에 사용자 정의 컨트롤(DPMachineControl)을 추가합니다.

 

4. 추가한 DPMachineControl에 자식 컨트롤을 배치합니다.

  -lb로 시작하는 컨트롤은 Label

  -btn로 시작하는 컨트롤은 Button

  -nud로 시작하는 컨트롤은 NumericUnpdownControl

  -cb로 시작하는 컨트롤은 ComboBox

  -pb로 시작하는 컨트롤은 PictureBox

자식 컨트롤 배치

 각 버튼의 클릭 이벤트 핸들러를 추가합니다. 두 개의 콤보 박스의 선택항목 변경 이벤트 핸들러도 추가합니다.

DPMachineControl.Designer.cs

namespace DPMachineControl_예광탄
{
    partial class DPMachineControl
    {
        /// <summary> 
        /// 필수 디자이너 변수입니다.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// 사용 중인 모든 리소스를 정리합니다.
        /// </summary>
        /// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region 구성 요소 디자이너에서 생성한 코드

        /// <summary> 
        /// 디자이너 지원에 필요한 메서드입니다. 
        /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
        /// </summary>
        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.lb_type = new System.Windows.Forms.Label();
            this.lb_source = new System.Windows.Forms.Label();
            this.nud_source = new System.Windows.Forms.NumericUpDown();
            this.btn_add = new System.Windows.Forms.Button();
            this.btn_test = new System.Windows.Forms.Button();
            this.btn_start = new System.Windows.Forms.Button();
            this.btn_stop = new System.Windows.Forms.Button();
            this.label6 = new System.Windows.Forms.Label();
            this.lb_now = new System.Windows.Forms.Label();
            this.lb_proper = new System.Windows.Forms.Label();
            this.label9 = new System.Windows.Forms.Label();
            this.pb_now = new System.Windows.Forms.PictureBox();
            this.cb_result = new System.Windows.Forms.ComboBox();
            this.cb_product = new System.Windows.Forms.ComboBox();
            this.pb_product = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.nud_source)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pb_now)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pb_product)).BeginInit();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(93, 38);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(59, 21);
            this.label1.TabIndex = 0;
            this.label1.Text = "타입:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(23, 87);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(129, 21);
            this.label2.TabIndex = 1;
            this.label2.Text = "소스 페이지:";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(23, 134);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(129, 21);
            this.label3.TabIndex = 2;
            this.label3.Text = "페이지 추가:";
            // 
            // lb_type
            // 
            this.lb_type.AutoSize = true;
            this.lb_type.Location = new System.Drawing.Point(160, 38);
            this.lb_type.Name = "lb_type";
            this.lb_type.Size = new System.Drawing.Size(72, 21);
            this.lb_type.TabIndex = 3;
            this.lb_type.Text = "[타입]";
            // 
            // lb_source
            // 
            this.lb_source.AutoSize = true;
            this.lb_source.Location = new System.Drawing.Point(160, 87);
            this.lb_source.Name = "lb_source";
            this.lb_source.Size = new System.Drawing.Size(60, 21);
            this.lb_source.TabIndex = 4;
            this.lb_source.Text = "[No.]";
            // 
            // nud_source
            // 
            this.nud_source.Location = new System.Drawing.Point(158, 134);
            this.nud_source.Name = "nud_source";
            this.nud_source.Size = new System.Drawing.Size(94, 32);
            this.nud_source.TabIndex = 5;
            // 
            // btn_add
            // 
            this.btn_add.Enabled = false;
            this.btn_add.Location = new System.Drawing.Point(258, 133);
            this.btn_add.Name = "btn_add";
            this.btn_add.Size = new System.Drawing.Size(89, 32);
            this.btn_add.TabIndex = 6;
            this.btn_add.Text = "추가";
            this.btn_add.UseVisualStyleBackColor = true;
            this.btn_add.Click += new System.EventHandler(this.btn_add_Click);
            // 
            // btn_test
            // 
            this.btn_test.Enabled = false;
            this.btn_test.Location = new System.Drawing.Point(23, 474);
            this.btn_test.Name = "btn_test";
            this.btn_test.Size = new System.Drawing.Size(324, 32);
            this.btn_test.TabIndex = 8;
            this.btn_test.Text = "Burn In 테스트";
            this.btn_test.UseVisualStyleBackColor = true;
            this.btn_test.Click += new System.EventHandler(this.btn_test_Click);
            // 
            // btn_start
            // 
            this.btn_start.Enabled = false;
            this.btn_start.Location = new System.Drawing.Point(395, 29);
            this.btn_start.Name = "btn_start";
            this.btn_start.Size = new System.Drawing.Size(128, 30);
            this.btn_start.TabIndex = 9;
            this.btn_start.Text = "가동";
            this.btn_start.UseVisualStyleBackColor = true;
            this.btn_start.Click += new System.EventHandler(this.btn_start_Click);
            // 
            // btn_stop
            // 
            this.btn_stop.Enabled = false;
            this.btn_stop.Location = new System.Drawing.Point(551, 29);
            this.btn_stop.Name = "btn_stop";
            this.btn_stop.Size = new System.Drawing.Size(128, 30);
            this.btn_stop.TabIndex = 10;
            this.btn_stop.Text = "멈춤";
            this.btn_stop.UseVisualStyleBackColor = true;
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Location = new System.Drawing.Point(395, 87);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(178, 21);
            this.label6.TabIndex = 11;
            this.label6.Text = "가동 중인 페이퍼:";
            // 
            // lb_now
            // 
            this.lb_now.AutoSize = true;
            this.lb_now.Location = new System.Drawing.Point(579, 87);
            this.lb_now.Name = "lb_now";
            this.lb_now.Size = new System.Drawing.Size(60, 21);
            this.lb_now.TabIndex = 12;
            this.lb_now.Text = "[No.]";
            // 
            // lb_proper
            // 
            this.lb_proper.AutoSize = true;
            this.lb_proper.Location = new System.Drawing.Point(579, 134);
            this.lb_proper.Name = "lb_proper";
            this.lb_proper.Size = new System.Drawing.Size(60, 21);
            this.lb_proper.TabIndex = 14;
            this.lb_proper.Text = "[No.]";
            // 
            // label9
            // 
            this.label9.AutoSize = true;
            this.label9.Location = new System.Drawing.Point(493, 133);
            this.label9.Name = "label9";
            this.label9.Size = new System.Drawing.Size(80, 21);
            this.label9.TabIndex = 13;
            this.label9.Text = "진행률:";
            // 
            // pb_now
            // 
            this.pb_now.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pb_now.Location = new System.Drawing.Point(399, 190);
            this.pb_now.Name = "pb_now";
            this.pb_now.Size = new System.Drawing.Size(280, 248);
            this.pb_now.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
            this.pb_now.TabIndex = 15;
            this.pb_now.TabStop = false;
            // 
            // cb_result
            // 
            this.cb_result.FormattingEnabled = true;
            this.cb_result.Location = new System.Drawing.Point(399, 474);
            this.cb_result.Name = "cb_result";
            this.cb_result.Size = new System.Drawing.Size(280, 29);
            this.cb_result.TabIndex = 16;
            this.cb_result.SelectedIndexChanged += new System.EventHandler(this.cb_result_SelectedIndexChanged);
            // 
            // cb_product
            // 
            this.cb_product.FormattingEnabled = true;
            this.cb_product.Location = new System.Drawing.Point(27, 172);
            this.cb_product.Name = "cb_product";
            this.cb_product.Size = new System.Drawing.Size(280, 29);
            this.cb_product.TabIndex = 17;
            this.cb_product.SelectedIndexChanged += new System.EventHandler(this.cb_product_SelectedIndexChanged);
            // 
            // pb_product
            // 
            this.pb_product.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pb_product.Location = new System.Drawing.Point(27, 207);
            this.pb_product.Name = "pb_product";
            this.pb_product.Size = new System.Drawing.Size(280, 248);
            this.pb_product.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
            this.pb_product.TabIndex = 18;
            this.pb_product.TabStop = false;
            // 
            // DPMachineControl
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 21F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.pb_product);
            this.Controls.Add(this.cb_product);
            this.Controls.Add(this.cb_result);
            this.Controls.Add(this.pb_now);
            this.Controls.Add(this.lb_proper);
            this.Controls.Add(this.label9);
            this.Controls.Add(this.lb_now);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.btn_stop);
            this.Controls.Add(this.btn_start);
            this.Controls.Add(this.btn_test);
            this.Controls.Add(this.btn_add);
            this.Controls.Add(this.nud_source);
            this.Controls.Add(this.lb_source);
            this.Controls.Add(this.lb_type);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.DoubleBuffered = true;
            this.Font = new System.Drawing.Font("굴림", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
            this.Margin = new System.Windows.Forms.Padding(5);
            this.Name = "DPMachineControl";
            this.Size = new System.Drawing.Size(713, 509);
            ((System.ComponentModel.ISupportInitialize)(this.nud_source)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pb_now)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pb_product)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label lb_type;
        private System.Windows.Forms.Label lb_source;
        private System.Windows.Forms.NumericUpDown nud_source;
        private System.Windows.Forms.Button btn_add;
        private System.Windows.Forms.Button btn_test;
        private System.Windows.Forms.Button btn_start;
        private System.Windows.Forms.Button btn_stop;
        private System.Windows.Forms.Label label6;
        private System.Windows.Forms.Label lb_now;
        private System.Windows.Forms.Label lb_proper;
        private System.Windows.Forms.Label label9;
        private System.Windows.Forms.PictureBox pb_now;
        private System.Windows.Forms.ComboBox cb_result;
        private System.Windows.Forms.ComboBox cb_product;
        private System.Windows.Forms.PictureBox pb_product;
    }
}

 5. DPMachineControl에 각 이벤트 핸들러를 구현합니다.

DPMachineControl.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using 증착_공정_및_Burn_in_테스트_설비_콘솔_예광탄;

namespace DPMachineControl_예광탄
{
    public partial class DPMachineControl : UserControl
    {
        public DPMachineControl()
        {
            InitializeComponent();
        }

        DepositionMachine dpmachine;
        public DepositionMachine DPMachine
        {
            get
            {
                return dpmachine;
            }
            set
            {
                if (value == null)
                {
                    return;
                }
                dpmachine = value;
                btn_start.Enabled = true;
                btn_stop.Enabled = false;
                btn_add.Enabled = true;
                btn_test.Enabled = true;
                SetProperty();

                dpmachine.OnDPCell += Dpmachine_OnDPCell;
                dpmachine.OnDPPaper += Dpmachine_OnDPPaper;
                dpmachine.OnEndJob += Dpmachine_OnEndJob;
                dpmachine.OnAddSource += Dpmachine_OnAddSource;
                dpmachine.OnStart += Dpmachine_OnStart;
            }
        }

        private void Dpmachine_OnStart(object sender, EventArgs e)
        {
            SetStartStop(false);
        }

        private void Dpmachine_OnAddSource(object sender, DPMachileLib.AddSourceEventArgs e)
        {
            lb_source.Text = e.TotalCount.ToString();
        }

        private void Dpmachine_OnEndJob(object sender, EndJobEventArgs e)
        {
            if (this.InvokeRequired)
            {
                EndJobEventHandler dele = Dpmachine_OnEndJob;
                object[] objs = new object[] { sender, e };
                this.Invoke(dele, objs);
            }
            else
            {
                SetStartStop(true);
            }
        }

        private void SetStartStop(bool sflag)
        {
            btn_stop.Enabled = !sflag;
            btn_start.Enabled = sflag;
            btn_test.Enabled = sflag;
        }

        List<Image> images = new List<Image>();//증착 완료한 이미지 컬렉션
        private void Dpmachine_OnDPPaper(object sender, EndPaperDPEventArgs e)
        {
            if (this.InvokeRequired)
            {
                EndPaperDPEventHandler dele = Dpmachine_OnDPPaper;
                object[] objs = new object[] { sender, e };
                this.Invoke(dele,objs);
            }
            else
            {
                images.Add(pb_now.Image);
                pb_now.Image = new Bitmap(100, 100);
                lb_now.Text = (e.PNum + 1).ToString();
                lb_proper.Text = "0";
                cb_product.Items.Add(e.PNum);
                cb_product.SelectedItem = e.PNum;
            }
        }


        private void Dpmachine_OnDPCell(object sender, EndCellDPEventArgs e)
        {
            if (this.InvokeRequired)
            {
                EndCellDPEventHandler dele = Dpmachine_OnDPCell;
                object[] objs = new object[] { sender, e };
                this.Invoke(dele, objs);
            }
            else
            {
                lb_proper.Text = e.CNum.ToString();
                int x = (e.CNum-1) % 10 * 10 + 2;
                int y = (e.CNum-1) / 10 * 10 + 2;
                Image image = pb_now.Image;
                Graphics graphics = Graphics.FromImage(image);
                Rectangle rect = new Rectangle(x, y, 6, 6);
                if (e.Quality)
                {
                    graphics.DrawRectangle(Pens.Red, rect);
                }
                else
                {
                    graphics.DrawRectangle(Pens.Blue, rect);
                }
                pb_now.Invalidate();
            }
        }


        private void SetProperty()
        {
            if(dpmachine==null)
            {
                return;
            }
            lb_type.Text = dpmachine.DT.ToString();
            lb_source.Text = dpmachine.PCnt.ToString();
            lb_now.Text = "1";
            lb_proper.Text = "0";
            pb_now.Image = new Bitmap(100, 100);
            images.Clear();
            cb_result.Items.Clear();
            cb_result.Text = string.Empty;
            cb_product.Items.Clear();
            cb_product.Text =string.Empty;
            pb_product.Image = new Bitmap(100, 100);
        }

        private void btn_start_Click(object sender, EventArgs e)
        {
            SetStartStop(false);
            dpmachine.Start();
        }

        private void btn_add_Click(object sender, EventArgs e)
        {
            int pcnt = (int)nud_source.Value;
            dpmachine.AddPaper(pcnt);
            lb_source.Text = dpmachine.PCnt.ToString();
            nud_source.Value = 0;
        }



        private void btn_test_Click(object sender, EventArgs e)
        {
            List<int> result =  dpmachine.BurnInTest();
            for(int i = cb_result.Items.Count;i<result.Count;i++)
            {
                cb_result.Items.Add(string.Format("{0}번 페이퍼 품질:{1}", i + 1, result[i]));
            }
        }

        private void btn_stop_Click(object sender, EventArgs e)
        {
            dpmachine.Stop();
            SetStartStop(true);
        }
        private void cb_product_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cb_product.SelectedIndex == -1)
            {
                return;
            }
            pb_product.Image = images[cb_product.SelectedIndex];
            if(cb_product.SelectedIndex<cb_result.Items.Count)
            {
                cb_result.SelectedIndex = cb_product.SelectedIndex;
            }
        }
        private void cb_result_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(cb_result.SelectedIndex==-1)
            {
                return;
            }
            cb_product.SelectedIndex = cb_result.SelectedIndex;
        }
    }
}

6. Form1에 자식 컨트롤을 배치합니다.

Form1 자식 컨트롤 배치

증착 방법을 설정하는 세 개의 버튼 클릭 이벤트 핸들러를 추가합니다.

Form1.Designer.cs

namespace DPMachineControl_예광탄
{
    partial class Form1
    {
        /// <summary>
        /// 필수 디자이너 변수입니다.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 사용 중인 모든 리소스를 정리합니다.
        /// </summary>
        /// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form 디자이너에서 생성한 코드

        /// <summary>
        /// 디자이너 지원에 필요한 메서드입니다. 
        /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
        /// </summary>
        private void InitializeComponent()
        {
            this.dpcon = new DPMachineControl_예광탄.DPMachineControl();
            this.btn_pvd = new System.Windows.Forms.Button();
            this.btn_cvd = new System.Windows.Forms.Button();
            this.btn_ald = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // dpcon
            // 
            this.dpcon.Font = new System.Drawing.Font("굴림", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
            this.dpcon.Location = new System.Drawing.Point(174, 14);
            this.dpcon.Margin = new System.Windows.Forms.Padding(5);
            this.dpcon.Name = "dpcon";
            this.dpcon.Size = new System.Drawing.Size(713, 509);
            this.dpcon.TabIndex = 0;
            // 
            // btn_pvd
            // 
            this.btn_pvd.Font = new System.Drawing.Font("굴림", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
            this.btn_pvd.Location = new System.Drawing.Point(13, 86);
            this.btn_pvd.Name = "btn_pvd";
            this.btn_pvd.Size = new System.Drawing.Size(114, 31);
            this.btn_pvd.TabIndex = 1;
            this.btn_pvd.Text = "PVD설정";
            this.btn_pvd.UseVisualStyleBackColor = true;
            this.btn_pvd.Click += new System.EventHandler(this.btn_pvd_Click);
            // 
            // btn_cvd
            // 
            this.btn_cvd.Font = new System.Drawing.Font("굴림", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
            this.btn_cvd.Location = new System.Drawing.Point(13, 146);
            this.btn_cvd.Name = "btn_cvd";
            this.btn_cvd.Size = new System.Drawing.Size(114, 31);
            this.btn_cvd.TabIndex = 2;
            this.btn_cvd.Text = "CVD설정";
            this.btn_cvd.UseVisualStyleBackColor = true;
            this.btn_cvd.Click += new System.EventHandler(this.btn_cvd_Click);
            // 
            // btn_ald
            // 
            this.btn_ald.Font = new System.Drawing.Font("굴림", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
            this.btn_ald.Location = new System.Drawing.Point(13, 195);
            this.btn_ald.Name = "btn_ald";
            this.btn_ald.Size = new System.Drawing.Size(114, 31);
            this.btn_ald.TabIndex = 3;
            this.btn_ald.Text = "ALD설정";
            this.btn_ald.UseVisualStyleBackColor = true;
            this.btn_ald.Click += new System.EventHandler(this.btn_ald_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(901, 532);
            this.Controls.Add(this.btn_ald);
            this.Controls.Add(this.btn_cvd);
            this.Controls.Add(this.btn_pvd);
            this.Controls.Add(this.dpcon);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        #endregion

        private DPMachineControl dpcon;
        private System.Windows.Forms.Button btn_pvd;
        private System.Windows.Forms.Button btn_cvd;
        private System.Windows.Forms.Button btn_ald;
    }
}

7. Form1에 추가한 이벤트 핸들러를 구현합니다.

Form1.cs

using System;
using System.Windows.Forms;
using 증착_공정_및_Burn_in_테스트_설비_콘솔_예광탄;

namespace DPMachineControl_예광탄
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btn_pvd_Click(object sender, EventArgs e)
        {
            SetDPMachine(DeposType.PVD);
        }

        private void SetDPMachine(DeposType dt)
        {
            dpcon.DPMachine = new DepositionMachine(dt);
        }

        private void btn_cvd_Click(object sender, EventArgs e)
        {
            SetDPMachine(DeposType.CVD);
        }

        private void btn_ald_Click(object sender, EventArgs e)
        {
            SetDPMachine(DeposType.ALD);
        }
    }
}
반응형