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

[C# 실습, 사용자 정의 컨트롤 제작 예광탄] 레코드 코팅

언제나휴일 2020. 10. 6. 15:07
반응형

1. 앞에서 작성하였던 RCMachine.cs와 CotingEventArgs.cs 파일로 구성한 클래스 라이브러리를 만듭니다.

2. Windows Forms 앱(.NET Framework) 프로젝트("RCManchine_공장_예광탄")를 생성합니다.

3. 생성한 프로젝트에 사용자 정의 컨트롤(Windows Forms)을 추가합니다. 파일명: RCMachineControl.cs

4. DPanel 클래스를 추가합니다.

   더블 버퍼링이 가능한 패널을 정의한 클래스입니다.

DPanel.cs

namespace RCManchine_공장_예광탄
{
    public class DPanel:System.Windows.Forms.Panel
    {
        public DPanel()
        {
            SetStyle(System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer | 
                System.Windows.Forms.ControlStyles.UserPaint | 
                System.Windows.Forms.ControlStyles.AllPaintingInWmPaint
                , true);
            UpdateStyles();
        }
    }
}

5. RCMachineControl에 자식 컨트롤을 배치합니다.

pn으로 시작하는 컨트롤은 Panel로 배치하세요.

RCMachineControl 자식 컨트롤 배치

6. RCMachineControlDesigner.cs 파일에 가서 InitializeComponent 메서드의 앞쪽 코드 중에 Panel 개체 생성 코드를 DPanel 생성 코드로 수정합니다.

 

RCMachineControlDesigner.cs

namespace RCManchine_공장_예광탄
{
    partial class RCMachineControl
    {
        /// <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.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.label6 = new System.Windows.Forms.Label();
            this.label7 = new System.Windows.Forms.Label();
            this.lb_liq = new System.Windows.Forms.Label();
            this.lb_avail = new System.Windows.Forms.Label();
            this.lb_source = new System.Windows.Forms.Label();
            this.lb_radius = new System.Windows.Forms.Label();
            this.lb_area = new System.Windows.Forms.Label();
            this.lb_speed = new System.Windows.Forms.Label();
            this.lb_product = new System.Windows.Forms.Label();
            this.pn_source = new DPanel();
            this.pn_record = new DPanel();
            this.pn_product = new DPanel();
            this.pn_liq = new DPanel();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(16, 23);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(80, 21);
            this.label1.TabIndex = 0;
            this.label1.Text = "코딩액:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(267, 23);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(80, 21);
            this.label2.TabIndex = 1;
            this.label2.Text = "남은양:";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(37, 85);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(59, 21);
            this.label3.TabIndex = 2;
            this.label3.Text = "소스:";
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(369, 76);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(129, 21);
            this.label4.TabIndex = 3;
            this.label4.Text = "투입구 반경:";
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(455, 165);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(59, 21);
            this.label5.TabIndex = 4;
            this.label5.Text = "면적:";
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Location = new System.Drawing.Point(271, 243);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(101, 21);
            this.label6.TabIndex = 5;
            this.label6.Text = "회전속도:";
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.Location = new System.Drawing.Point(20, 289);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(199, 21);
            this.label7.TabIndex = 6;
            this.label7.Text = "코팅한 레코드 개수:";
            // 
            // lb_liq
            // 
            this.lb_liq.AutoSize = true;
            this.lb_liq.Location = new System.Drawing.Point(102, 23);
            this.lb_liq.Name = "lb_liq";
            this.lb_liq.Size = new System.Drawing.Size(51, 21);
            this.lb_liq.TabIndex = 7;
            this.lb_liq.Text = "lb_liq";
            // 
            // lb_avail
            // 
            this.lb_avail.AutoSize = true;
            this.lb_avail.Location = new System.Drawing.Point(353, 23);
            this.lb_avail.Name = "lb_avail";
            this.lb_avail.Size = new System.Drawing.Size(70, 21);
            this.lb_avail.TabIndex = 8;
            this.lb_avail.Text = "lb_avail";
            // 
            // lb_source
            // 
            this.lb_source.AutoSize = true;
            this.lb_source.Location = new System.Drawing.Point(106, 85);
            this.lb_source.Name = "lb_source";
            this.lb_source.Size = new System.Drawing.Size(92, 21);
            this.lb_source.TabIndex = 9;
            this.lb_source.Text = "lb_source";
            // 
            // lb_radius
            // 
            this.lb_radius.AutoSize = true;
            this.lb_radius.Location = new System.Drawing.Point(504, 76);
            this.lb_radius.Name = "lb_radius";
            this.lb_radius.Size = new System.Drawing.Size(82, 21);
            this.lb_radius.TabIndex = 10;
            this.lb_radius.Text = "lb_radius";
            // 
            // lb_area
            // 
            this.lb_area.AutoSize = true;
            this.lb_area.Location = new System.Drawing.Point(520, 165);
            this.lb_area.Name = "lb_area";
            this.lb_area.Size = new System.Drawing.Size(70, 21);
            this.lb_area.TabIndex = 11;
            this.lb_area.Text = "lb_area";
            // 
            // lb_speed
            // 
            this.lb_speed.AutoSize = true;
            this.lb_speed.Location = new System.Drawing.Point(379, 243);
            this.lb_speed.Name = "lb_speed";
            this.lb_speed.Size = new System.Drawing.Size(87, 21);
            this.lb_speed.TabIndex = 12;
            this.lb_speed.Text = "lb_speed";
            // 
            // lb_product
            // 
            this.lb_product.AutoSize = true;
            this.lb_product.Location = new System.Drawing.Point(225, 289);
            this.lb_product.Name = "lb_product";
            this.lb_product.Size = new System.Drawing.Size(98, 21);
            this.lb_product.TabIndex = 13;
            this.lb_product.Text = "lb_product";
            // 
            // pn_source
            // 
            this.pn_source.BackColor = System.Drawing.Color.Maroon;
            this.pn_source.Location = new System.Drawing.Point(20, 121);
            this.pn_source.Name = "pn_source";
            this.pn_source.Size = new System.Drawing.Size(184, 143);
            this.pn_source.TabIndex = 14;
            this.pn_source.Paint += new System.Windows.Forms.PaintEventHandler(this.pn_source_Paint);
            // 
            // pn_record
            // 
            this.pn_record.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(255)))));
            this.pn_record.Location = new System.Drawing.Point(271, 111);
            this.pn_record.Name = "pn_record";
            this.pn_record.Size = new System.Drawing.Size(178, 129);
            this.pn_record.TabIndex = 15;
            this.pn_record.Paint += new System.Windows.Forms.PaintEventHandler(this.pn_record_Paint);
            // 
            // pn_product
            // 
            this.pn_product.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.pn_product.Location = new System.Drawing.Point(357, 289);
            this.pn_product.Name = "pn_product";
            this.pn_product.Size = new System.Drawing.Size(200, 151);
            this.pn_product.TabIndex = 16;
            this.pn_product.Paint += new System.Windows.Forms.PaintEventHandler(this.pn_product_Paint);
            // 
            // pn_liq
            // 
            this.pn_liq.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.pn_liq.Location = new System.Drawing.Point(339, 76);
            this.pn_liq.Name = "pn_liq";
            this.pn_liq.Size = new System.Drawing.Size(24, 24);
            this.pn_liq.TabIndex = 17;
            this.pn_liq.Paint += new System.Windows.Forms.PaintEventHandler(this.pn_liq_Paint);
            // 
            // RCMachineControl
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 21F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.pn_liq);
            this.Controls.Add(this.pn_product);
            this.Controls.Add(this.pn_record);
            this.Controls.Add(this.pn_source);
            this.Controls.Add(this.lb_product);
            this.Controls.Add(this.lb_speed);
            this.Controls.Add(this.lb_area);
            this.Controls.Add(this.lb_radius);
            this.Controls.Add(this.lb_source);
            this.Controls.Add(this.lb_avail);
            this.Controls.Add(this.lb_liq);
            this.Controls.Add(this.label7);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.label4);
            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 = "RCMachineControl";
            this.Size = new System.Drawing.Size(597, 456);
            this.Load += new System.EventHandler(this.RCMachineControl_Load);
            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 label4;
        private System.Windows.Forms.Label label5;
        private System.Windows.Forms.Label label6;
        private System.Windows.Forms.Label label7;
        private System.Windows.Forms.Label lb_liq;
        private System.Windows.Forms.Label lb_avail;
        private System.Windows.Forms.Label lb_source;
        private System.Windows.Forms.Label lb_radius;
        private System.Windows.Forms.Label lb_area;
        private System.Windows.Forms.Label lb_speed;
        private System.Windows.Forms.Label lb_product;
        private System.Windows.Forms.Panel pn_source;
        private System.Windows.Forms.Panel pn_record;
        private System.Windows.Forms.Panel pn_product;
        private System.Windows.Forms.Panel pn_liq;
    }
}

7. RCMachineControl.cs 에 코드를 작성합니다.

- RCMachine 형식 개체를 참조하는 멤버 필드와 이를 설정하고 가져오기할 속성을 정의합니다. 

- RCMachine 개에의 상태에 따라 컨트롤 속성을 변경할 수 있게 구현합니다.

RCMachineConrol.cs

using RCMachineControlLib;
using System.Drawing;
using System.Windows.Forms;
using 콘솔_예광탄;

namespace RCManchine_공장_예광탄
{
    public partial class RCMachineControl : UserControl
    {
        public event EndCotingEventHandler OnEnd;
        public RCMachineControl()
        {
            InitializeComponent();
        }
        RCMachine rcmachine;
        public RCMachine RCMachine
        {
            get
            {
                return rcmachine;
            }
            set
            {
                rcmachine = value;
                if(rcmachine != null)
                {
                    SetVisualProperty();
                    rcmachine.OnCoting += Rcmachine_OnCoting;
                    Invalidate();
                }
            }
        }

        int tobe;
        int acnt;
        private void Rcmachine_OnCoting(object sender, CotingEventArgs e)
        {
            SetVisualProperty();
            tobe = e.Tobe;
            acnt = e.AvailCnt;
            if((rcmachine.IsStart==false)&&(OnEnd!=null))
            {
                OnEnd(this, new EndCotingEventArgs(e.ProductCnt));
            }
        }

        public void SetArea(decimal value)
        {
            rcmachine.RArea = (int)value;
            lb_area.Text = value.ToString();
            pn_record.Invalidate();
        }

        public void SetSpeed(decimal value)
        {
            rcmachine.SpinSpeed = (int)value;
            lb_speed.Text = value.ToString();
        }

        public void AddSource(decimal value)
        {
            rcmachine.SourceCnt += (int)value;
            lb_source.Text = rcmachine.SourceCnt.ToString();
            pn_source.Invalidate();
        }

        public void AddLiq(decimal value)
        {
            rcmachine.CoatingLiq += (int)value;
            lb_liq.Text = rcmachine.CoatingLiq.ToString();
            pn_liq.Invalidate();
        }

        public void SetRadius(decimal value)
        {
            rcmachine.CRadius = (int)value;
            lb_radius.Text = value.ToString();
        }

        //크로스 스레드 문제가 발생한 메서드와 원형이 같은 대리자를 정의
        delegate void SetVisualPropertyDele();
        private void SetVisualProperty()
        {
            if (rcmachine == null)
            {
                return;
            }
            if (this.InvokeRequired)//크로스 스레드 문제가 발생했다면
            {
                //대리자 개체에 메소드 자신을 설정
                SetVisualPropertyDele dele = SetVisualProperty;
                //Form 컨트롤의 Invoke 메서드에 대리자를 전달
                // .NET 에서 Form을 소유한 스레드가 해당 메서드를 수행함을 보장
                this.Invoke(dele);
            }
            else
            {
                lb_area.Text = rcmachine.RArea.ToString();
                lb_avail.Text = "0";
                lb_source.Text = rcmachine.SourceCnt.ToString();
                lb_speed.Text = rcmachine.SpinSpeed.ToString();
                lb_liq.Text = rcmachine.CoatingLiq.ToString();
                lb_product.Text = rcmachine.ProductCnt.ToString();
                lb_radius.Text = rcmachine.CRadius.ToString();
                lb_avail.Text = acnt.ToString();
                Invalidate(true);
            }
        }


        private void pn_source_Paint(object sender, PaintEventArgs e)
        {
            if (rcmachine == null)
            {
                return;
            }
            Graphics graphics = e.Graphics;
            for (int i = 0; i < rcmachine.SourceCnt; i++)
            {
                Rectangle rect = new Rectangle(4, i * 10, pn_source.Width - 8, 9);
                graphics.DrawRectangle(Pens.White, rect);
            }
        }

        private void pn_record_Paint(object sender, PaintEventArgs e)
        {
            if (rcmachine == null)
            {
                return;
            }
            Graphics graphics = e.Graphics;

            for (int i = 0; i < rcmachine.RArea; i++)
            {

                Rectangle rect = new Rectangle((i/10)*10, (i%10) * 10, pn_record.Width/20, 9);
                if (i > rcmachine.RArea - tobe)
                {
                    graphics.DrawRectangle(Pens.White, rect);
                }
                else
                {
                    graphics.DrawRectangle(Pens.Gold, rect);
                }
            }
        }

        private void pn_liq_Paint(object sender, PaintEventArgs e)
        {
            if(rcmachine == null)
            {
                return;
            }
            
            Graphics graphics = e.Graphics;
            int i;
            for (i = 0; i < rcmachine.CoatingLiq; i++)
            {
                Rectangle rect = new Rectangle(0, i * 6, pn_liq.Width, 5);
                graphics.DrawRectangle(Pens.Red, rect);
                graphics.FillRectangle(Brushes.Gold, rect);
            }
            int awidth = (pn_liq.Width * acnt) / rcmachine.MAXACNT;

            Rectangle rect1 = new Rectangle(0, i * 6,  awidth, 5);
            graphics.DrawRectangle(Pens.Red, rect1);
            graphics.FillRectangle(Brushes.Gold, rect1);
            Rectangle rect2 = new Rectangle(awidth, i * 6,  pn_liq.Width- awidth, 5);
            graphics.DrawRectangle(Pens.Red, rect2);
        }

        private void pn_product_Paint(object sender, PaintEventArgs e)
        {
            if (rcmachine == null)
            {
                return;
            }
            Graphics graphics = e.Graphics;
            for(int i = 0; i<rcmachine.ProductCnt;i++)
            {
                Rectangle rect = new Rectangle(4, i * 10, pn_product.Width-8, 9);
                graphics.DrawRectangle(Pens.Gold, rect);
            }
        }

        private void RCMachineControl_Load(object sender, System.EventArgs e)
        {
          
        }
    }
}

8. Form1.cs 에 RCMachineControl을 배치하고 컨트롤 이름을 rccon이라 지정합니다.

 Form1에 Load이벤트 핸들러를 등록하여 RCMachine 개체 생성 및 rccon에 생성한 개체를 설정하는 코드를 추가합니다.

Form1.cs

using System;
using System.Windows.Forms;
using 콘솔_예광탄;

namespace RCManchine_공장_예광탄
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            RCMachine rc = new RCMachine();
            rc.RArea = 100;
            rc.CoatingLiq = 2;
            rc.CRadius = 3;
            rc.SpinSpeed = 100;
            rc.SourceCnt = 10;
            rccon.RCMachine = rc;
            rc.Start();
        }
    }
}
반응형