퇴근5분전

위와 같이 

일자 및 시간을  보여주는 컨트롤을 만들었다. 

설비에서 데이타 입력하는 터치에서 화상키보드 열어서 년 월일을 입력하고 있는 걸 보고... 

와우... 이런 컨트롤이 있으면 그냥 넣을 수 있을 듯 해서... 잠깐 만들어봤다. 

UP, DN 버튼은 눌러도 되고, 화면을 밀어서 올리고 내리고...

 

설정할 수 있는 속성은 위와 같다. 

 

표시 갯수설정.

값이 계속 이어서 돌려서 보여줄지 말지

몇개씩 건너뛸지...

현재 선택된 값...

값 표시 포맷...

박스세로 간격...

 

컨트롤을 만들면서 직접 그려야 하는 부분이 있는데

영역내에 그려야 하는 박스 갯수에 따라 중심에서 그려져야 할때의 계산... 

 

5개 짜리
1개짜리
4개짜리

top 0 

중심 250 box H=100 

높이 500
//중심점을 기준으로 display되는 갯수로 높이값을 빼주면 시작지점이 된다. 
//중심이 절반이니까 = display / 2

1개면  250 - ( 100 * 1/2 ) = 250 -  50 box 1개 : 200-300
2개면  250 - ( 100 * 2/2 ) = 250 - 100 box 2개 : 150-250, 250-350
3개면  250 - ( 100 * 3/2 ) = 250 - 150 box 3개 : 100-200, 200-300, 300-400
...

간격값을 주면? 10씩 넣으면
offset = 10 // 중간에 display -1 개씩 끼워넣어지므로...

1개면  250 - ( 100 * 1/2 ) - (10 * (1-1/2)) = 250 -  50 -  0 box 1개 : 200-300
2개면  250 - ( 100 * 2/2 ) - (10 * (2-1/2)) = 250 - 100 -  5 box 2개 : 145-245,+10, 255-355
3개면  250 - ( 100 * 3/2 ) - (10 * (3-1/2)) = 250 - 150 - 10 box 3개 : 90-190, +10, 200-300, +10, 310-410

 

구현..

 


        int offset = 15;

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
 
    // 시작 지점 = 박스 높이 *  디스플레이 카운트 / 2 - (간격 * (디스플레이 카운트 - 1) /2 );
    int top = this.Height/2 - (BoxHeight * DisplayCount / 2 ) - (offset * (DisplayCount-1) / 2);
    e.Graphics.DrawLine(Pens.Black, 0, this.Height / 2f, this.Width, this.Height / 2f);
    for (int loop = 0; loop < DisplayCount; loop++)
    {
        e.Graphics.DrawRectangle(Pens.Red, 10, top, BoxWidth, BoxHeight);
        top += BoxHeight + offset; 
    }
}

## 플로우

    + 조건 중첩된 컨트롤 만들기 ...

단순 코딩으로 만드는건 쉬웠는데...

UI로 구현하려니 골때리넹.. 머리아퍼...

[Variable 조건변수] 을 [변수] 또는 [컨디션 조건] 등에 드랍을 하면 코딩으로 하던 구조대로 변경해준다.

버튼으로 만들어준 파서로 변환하면서 확인.  드디어 완성이다.

300라인 내외로 파일 몇개인데 겁나 오래 걸렸네.

원노트에 모두 옮겨놨고, 내일 아침에 옮길 시간이 되려나...?

종일 코딩했는데... 느릿 느릿...? 졸려서 ... 혼났네!

 

 

 간간히 보이기에...

폰트 파일 https://www.barcodesinc.com/free-barcode-font/

 

 

 

 

 

  배틀 그라운드 자기장 ... 구현해보기.

C#으로 만들어보니... 어거지로 만들어봤음.  종일 걸리네...

 > 이미지로 스샷 찍고...

 > 그걸 GIF로 만드는 소스를 구해서 이미지를 만들었음.

스샷으로 일정 시간별로 스샷을 찍어서 끊겨보이는데... 실제 돌리면 스르륵... 이동함.

>> 모바일에서 보면 줄다 말다 하네...

( 소스 숨김 ) 

 

 트리의 노드 선택 <-- 시 하이라이트 < 처리가 되는데.

트리에서 포커스가 빠지면 하이라이트가 안되고 사라진다.

이걸 포커스가 없어도 선택된 노드에 하이라이트 표시를 유지 하기 위해.

# 주에에 포커스가 있지만 트리에는 제대로 표시가 됨.

# 해당 소스임. ( 회의록 관리 프로그램에 있는 코드. )

 

 

 

닷넷 카페에 질문글이 올라왔는데...

답변을 하려니 ... 전에 만들어 두었던 것들을 찾기 쉽지 않아서...

그냥 새로 간단하게 만들어 올림.

 

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        PointF origin = new PointF(200f, 200f);
        float angle = 45f; // 각도
        float r = 100; // 반지름
        float startOffset = 10;

        Pen linePen = new Pen(Color.Black, 1f);
        Pen ellipsePen = new Pen(Color.Blue, 1f);

        Brush degree_0_dotBrush = new SolidBrush(Color.Red);
        Brush degree_90_dotBrush = new SolidBrush(Color.Yellow);
        Brush degree_180_dotBrush = new SolidBrush(Color.DarkBlue);
        Brush degree_270_dotBrush = new SolidBrush(Color.Green);

        Brush degree_result_dotBrush = new SolidBrush(Color.BlueViolet);

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            //외곽선 그리기
            e.Graphics.DrawRectangle(linePen, startOffset, startOffset, origin.X * 2, origin.Y * 2);
            //x축 그리기
            e.Graphics.DrawLine(linePen, new PointF(startOffset, origin.Y + startOffset), new PointF( origin.X * 2 + startOffset, origin.Y + startOffset));
            //y축 그리기
            e.Graphics.DrawLine(linePen, new PointF(origin.X + startOffset, startOffset), new PointF(origin.X + startOffset, origin.Y * 2 + startOffset));

            // 원그리기
            e.Graphics.DrawEllipse(ellipsePen, startOffset + origin.X-r, startOffset + origin.Y-r, 2*r, 2*r);

            // 0도
            float x = r * (float)Math.Cos(ConvertRadian(0d));
            float y = r * (float)Math.Sin(ConvertRadian(0d));
            e.Graphics.FillEllipse(degree_0_dotBrush, startOffset + origin.X + x - 5f, startOffset + origin.Y + y - 5f, 10f, 10f);
            // 90도
            x = r * (float)Math.Cos(ConvertRadian(90d));
            y = r * (float)Math.Sin(ConvertRadian(90d));
            e.Graphics.FillEllipse(degree_90_dotBrush, startOffset + origin.X + x - 5f, startOffset + origin.Y + y - 5f, 10f, 10f);

            // 180도
            x = r * (float)Math.Cos(ConvertRadian(180d));
            y = r * (float)Math.Sin(ConvertRadian(180d));
            e.Graphics.FillEllipse(degree_180_dotBrush, startOffset + origin.X + x - 5f, startOffset + origin.Y + y - 5f, 10f, 10f);

            // 270도
            x = r * (float)Math.Cos(ConvertRadian(270d));
            y = r * (float)Math.Sin(ConvertRadian(270d));
            e.Graphics.FillEllipse(degree_270_dotBrush, startOffset + origin.X + x - 5f, startOffset + origin.Y + y - 5f, 10f, 10f);

            // 실제 구하는 좌표 값
            x = (r + 10 ) * (float)Math.Cos(ConvertRadian(90d + 45d));
            y = (r + 10) * (float)Math.Sin(ConvertRadian(90d + 45d));
            e.Graphics.FillEllipse(degree_result_dotBrush, startOffset + origin.X + x - 5f, startOffset + origin.Y + y - 5f, 10f, 10f);

        }

        private double ConvertRadian(double angle)
        {
            return angle * Math.PI / 180d;
        }
    }

 

모델을 만들고 이걸 컨트롤을 디자인 해서 띄웠더니 구분되는 로직마다 폼이 떠서 창을 세번이나 띄워야 하기에 뭔가 좋은 방법이 없을까 하고

 

만들어봤다. 새로운 작업이력관리 프로그램에 적용도 해보았다.

 

<form>

 

 

< 이전 : x, 다음 : 아래 페이지로 이동 >

< 이전 : 위페이지로, 001 다음 : 아래 페이지로, 002 는 아래 아래 페이지로 >

< 이전 : 위 페이지, 다음 : x >

< 이전 : 위 위 페이지, 다음 : X >

 

 

소스이다.

 

        protected override void OnLoad(EventArgs e)
        {
            uC0011.Next("001", uC001UC0011);
            uC001UC0011.Next("001", uC001UC001UC0011);
            uC001UC0011.Next("002", uC001UC001UC0021);
            base.OnLoad(e);

            uC0011.GoToNext += UC0011_GoToNext;
            uC0011.BackToPrev += UC0011_BackToPrev;

            uC001UC0011.GoToNext += UC001UC0011_GoToNext;
            uC001UC0011.BackToPrev += UC001UC0011_BackToPrev;

            uC001UC001UC0011.BackToPrev += UC001UC001UC0011_BackToPrev;
            uC001UC001UC0021.BackToPrev += UC001UC001UC0021_BackToPrev;

            uC0011.Dock = DockStyle.Fill;
            uC001UC0011.Dock = DockStyle.Fill;
            uC001UC001UC0011.Dock = DockStyle.Fill;
            uC001UC001UC0021.Dock = DockStyle.Fill;

            uC0011.BringToFront();
        }

        private void UC001UC001UC0021_BackToPrev(Control prev)
        {
            prev.BringToFront();
        }

        private void UC001UC001UC0011_BackToPrev(Control prev)
        {
            prev.BringToFront();
        }

        private void UC001UC0011_BackToPrev(Control prev)
        {
            prev.BringToFront();
        }

        private void UC001UC0011_GoToNext(string next, object[] prms)
        {
            switch (next) {
                case "001":
                    uC001UC001UC0011.BringToFront();
                    if (prms != null && 0 < prms.Length)
                    {
                      //  uC001UC001UC0011.SetData("" + prms[0]);
                    }
                    break;
                case "002":
                    uC001UC001UC0021.BringToFront();
                    if (prms != null && 0 < prms.Length)
                    {
                      //  uC001UC001UC0021.SetData("" + prms[0]);
                    }
                    break;

            }
        }

        private void UC0011_BackToPrev(Control prev)
        {
            prev.BringToFront();
        }

        private void UC0011_GoToNext(string next, object[] prms)
        {
            uC001UC0011.BringToFront();
            // prms는 uC001UC0011 에 필요한 정보를 고정된 순서로 전달되며 필요한 데이타 타입으로 캐스팅 해서 사용.

            if (prms != null && 0 < prms.Length)
            {
                uC001UC0011.SetData("" + prms[0]);
            }
        }

 

 

이렇게 form에서는 네비게이터 이동처리만 하고 실제 모듈에 대한 처리는 판넬 내부에서 직접처리하게 만들었다.

 

 

  화면에 컨트롤을 여러개 뿌려져있을때

이를 마우스 드래그로 여러개를 선택하고자 할때 점선으로 박스를 그리고 싶을때 사용하면 됨.

 

기본 form에 버튼 몇개를 마구잡이로 배치하고 아래와 같이 구현하면

 

마우스 down시작점에서 마우스 up끝점까지 박스를 그려준다.

 

시작점에서 끝지점이 w+, h+일때는 크게 문제가 안되지만.

끝지점이 w- 또는 h-일 경우  Rectangle GetBox(Rectangle rct) 메서드 내에 있는 것처럼

박스위치와 크기를 고쳐줘야 한다.

 

전에 모니터링 만들땐 좀 복잡하게 했던것 같은뎅... 어째꺼나.. 아래처럼 쉽게 되었다.

 

 

어느 방향으로든 마우스로 끌어도 사각형이 제대로 그려진다.

 

 

 

 

List<Button> SelectButtonList = new List<Button>();

        bool IsMDown = false;
        Rectangle rect = new Rectangle();
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            ClearSelectedButtonList();

            IsMDown = e.Button == System.Windows.Forms.MouseButtons.Left;
            rect.Location = e.Location;
            rect.Width = 0;
            rect.Height = 0;
            Invalidate();
        }

        private void ClearSelectedButtonList()
        {
            foreach (var btn in SelectButtonList)
            {
                btn.ForeColor = Color.Black;
            }
            SelectButtonList.Clear();
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (IsMDown)
            {
                rect.Width = e.Location.X - rect.X;
                rect.Height = e.Location.Y - rect.Y;
                Invalidate();
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            IsMDown = false;

            Rectangle box = GetBox(rect);

            foreach (Control ctrl in Controls)
            {
                if (box.Contains(ctrl.Bounds) && ctrl is Button)
                {
                    SelectButtonList.Add(ctrl as Button);
                    ctrl.ForeColor = Color.Red;
                }
            }

            rect.Location = e.Location;
            rect.Width = 0;
            rect.Height = 0;

            Invalidate();
        }

 

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
             Rectangle box = GetBox(rect);
             ControlPaint.DrawBorder(e.Graphics, box, Color.Red, ButtonBorderStyle.Dotted);
        }

 

        private Rectangle GetBox(Rectangle rct)
        {
            Rectangle box = rct;

            if (box.Width < 0)
            {
                box.X = box.X + box.Width;
                box.Width *= -1;
            }

            if (box.Height < 0)
            {
                box.Y = box.Y + box.Height;
                box.Height *= -1;
            }
            return box;
        }

 

 Mockup Designer 에서 판넬에 스크롤을 넣을 수가 없어서 이걸 비스므리 하게...

 

트랙바를 이용해서 구현했다.

 

 

아래처럼 하면 내부 컨텐츠 컨트롤이 뷰 판넬보다 크게 만들어놓고

테스트 하면 트랙바가 움직일때 내부 컨트롤들을 이동시켜주므로

스크롤 되는 것 처럼 보인다.

 

        int prev = 0;

 

        public Init()
        {             
            trackBar1.Maximum = ( {내부 컨텐츠 컨트롤}.Height - {뷰 판넬}.Height + 2 );
            trackBar1.Value = trackBar1.Maximum;
            prev = trackBar1.Maximum - trackBar1.Value;
        }


        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            foreach (Control ctrl in {뷰 판넬}.Controls)
            {

                ctrl.Top += (prev - (trackBar1.Maximum - trackBar1.Value));
            }

            prev = trackBar1.Maximum - trackBar1.Value;
        }

 

 

 

## 기존 버그...

Mockup Designer에서 스크롤을 적용하면 ...

 

컨트롤을 드래그해서 올리거나 또는 끌어다가 이동시키면 스크롤이 미친듯이 움직여서 .... 제어가 안된다.

 

그래서 없이 썼는데, 모니터가 작으니 큰 화면 디자인이 안되었다.

 

편법으로 위와 같이...

 

 

오늘도 12시가 넘어버렸넹...

 

집에서 코딩 그만해야되는데!!!!! 쭙~