닷넷프로그래밍정복 김상형저 가메출판사

이번 장은 완전히 실습장입니다.

 

닷넷의 기본적인 그리기 엔진은 Win32  GDI 모듈의 업그레이드 버전인 GDI+이다.  GDI+는 네이티브 C++라이브러리로 만들어졌고 닷넷은 GDI+를 외부호출로 구현한다.

 

GDI와 GDI+의 주요한 차이점 및 GDI+ 특징

  1.  GDI는 DC에 그리기 정보를 저장하고 그리기 함수들은 DC의 정보를 이용한다. DC에는 현재 그리기 상태에 대한 모든 정보가 저장되어 있고 함수들은 DC의 핸들을 받아 이 DC로부터 필요한 정보를 얻는다. 그래서 그리기 상태를 변경하려면 DC의 상태를 먼저 변경해야 한다. 예를 들어 파란색으로 선을 긋고 싶다면 파란색 펜을 만들어 DC에 선택한 후 LineTo함수를 호출해야 한다.반면에 GDI+는 별도의 상태를 유지하지 않으며 그리기에 필요한 모든 정보를 메서드를 일일이 전달한다. 파란색 선을 긋고 싶으면 파란색 펜 오브젝트를 만든 후  DrawLine메소드로 이 펜을 전달한다.
  2. 그리기에 사용되는 펜, 브러시, 폰트 같은 오브젝트들은 모두 클래스로 정의되어 있다. 따라서 별도의 파괴코드를 작성할 필요가 없다. C++에서는 파괴자가 자동으로 파괴하며 C#에서는 GC가 정리한다. 수동으로 선택 해제 및 삭제를 해야 하는 GDI에 비해 훨씬 편리해졌을뿐 아니라 실수나 예외에 의해 리소스가 제대로 해제되지 않던 골치 아픈 문제가 사라졌다
  3. GDI 의 그리기 함수들은 항상 외곽선을 그리고 내부를 채운다. 만약 둘 중 하나를 그리지 않으면 투명 오브젝트를 사용해야 한다. GDI+는 외곽선을 그리는 Draw 메소드와 내부를 채우는 Fill메소드가 철저하게 분리되어 있다. 그래서 한쪽만 그릴때는 편리하지만 외곽선과 내부를 모두 그리려면 Draw메소드와 Fill메소드를 순서대로 호출해야 한다.
  4. 모든 문자열은 유니코드이므로 안시문자열을 출력하려면 유니코드로 변환한 후 출력해야 한다. 출력하는 문자열뿐 아니라 파일의 경로도 반드시 유니코드로 써야 한다.

 

모든 그리기 함수들은 Graphics 클래스의 메소드로 존재한다. 그래서 화면이든 프린터든 그리기 를 하려면 먼저 Graphics객체를 얻어야 한다. Graphics 클래스는 생성자가 private이어서 직접 생성할수 없고 봉인클래스라 파생도 할수 없다. Graphics 객체를 얻는 방법은

  1.  그리기 전용 이벤트인 Paint의 인수로 전달된 PaintEventArgs 객체로 부터 얻는다. 직접 생성한 것이 아니므로 받아서 사용만 할뿐 별도의 정리가 필요없다. 대부분의 그리기는 이방식으로 사용된다.
  2. Paint 이외의 이벤트나 일반 메소드에서 그리기를 할때는 Control 클래스의 CreateGraphics 정적메소드를 호출하여 Graphics 객체를 생성한다. 직접 생성한 것이므로 사용한 후 Dispose 메소드를 호출하여 가급적이면 빨리 해제하는 것이 좋다.

 

 

색상.

GDI+에서는 색상도 객체이다. Color라는 구조체로 선언되어 있다. FromArgb 정적 메소드를 이용해서 원하는 색을 배합할수 있다. 색은 RGB값읆 각각 넣어주면 된다

ex

Color Red = Color.FromArgb(255, 0, 0);

Color Green - Color.FromArgb(0,255,0);

Color Yellow = Color.FromArgb(255,255,0);

FromArgb 메소드로 원하는 색상을 직접 만들어 쓰는 방법 말고 141 기 선언된 색상을 선택할수 있다. 140개는 HTML 표준색상이고 1개는 투명색이다.

GDI+색상이 GDI 색상보다 우수한 점이라면 색상요소에 알파채널이 포함되어 있어 반투명 효과를 지원한다는 점이다.

ex

 private int Alpha = 128;

        public JohnForm()
        {
            InitializeComponent();
        }

        private void JohnForm_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.FillEllipse(Brushes.Firebrick, 10, 10, 150, 100);
            SolidBrush s = new SolidBrush(Color.FromArgb(Alpha, 255, 0, 0));
            e.Graphics.FillRectangle(s, 50, 50, 150, 100);
            e.Graphics.DrawString("위 : 투명도 증가, 아래 : 투명도 감소", Font, Brushes.GhostWhite, 10, 160);
        }

        private void JohnForm_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                    Alpha = Math.Max(0, Alpha - 25);
                    Invalidate();
                    break;
                case Keys.Down:
                    Alpha = Math.Min(255, Alpha + 25);
                    Invalidate();
                    break;

            }
        }

투명효과는 게임에서 효과적이고 배경의 그림과 복잡한 논리 연산을 해야 하므로 속도는 느린편이다. 그러니까 꼭 필요하지 않은 곳에 어설프게 사용해서는 안 된다.

 

시스템 색상 - 운용체제가 바탕 화면과 왼도우의 각부분을 그리기 위해 사용하는 색상이다. Color 객체로 표현하는 색은 한번 정해지면 언제까지나 그 색상만 표현하는 절대색인데 비해 시스템 색상은 사용자가 선택할수 있는 가변색이다. 바탕화면의 등록정보 대화상자에서 시스템 색생을 선택하며 테마에 의해 정의되기도 한다.

응용 프로그램에서 윈도의 각 부분을 직접 그려야 한다면 절대색을 사용하지 말고 반드시 시스템 색을 써야 한다. ex,Form 예제에서 배경색은 Control, ForeColor는 ControlText로 정해짐.

 

펜은 선을 긋는데 사용되는 그래픽 오브젝트이다. Graphics의 메소드 중 Draw로 시작하는 메소드들은 공통적으로 선을 그리는데 필요한 펜을 인수로 요구한다. 생성자는 다음과 같다.

public Pen(Color color, [.float width]) //Color 객체로 색상을 바로 지정.

public Pen(Brush brush, [.float width]) //Brush 객체로 무늬까지 같이 지정.

그리기와 관련된 대부분의 클래스들은 System.Drawing 네임스페이스에 포함되어 있어서 따로 참초추가할필요가 없다.

 

교점처리 및 정렬

ex

 Pen P = new Pen(Color.DodgerBlue, 15);
            P.Alignment = PenAlignment.Center;
            P.LineJoin = LineJoin.Miter;
            e.Graphics.DrawRectangle(P, 10, 10, 80, 80);

            P.Alignment = PenAlignment.Inset;
            P.LineJoin = LineJoin.MiterClipped;
            e.Graphics.DrawRectangle(P, 120, 10, 80, 80);

            P.Alignment = PenAlignment.Outset;
            P.LineJoin = LineJoin.Bevel;
            e.Graphics.DrawRectangle(P, 10, 120, 80, 80);

            P.Alignment = PenAlignment.Left;
            P.LineJoin = LineJoin.Round;
            e.Graphics.DrawRectangle(P, 120, 120, 80, 80);

            e.Graphics.DrawRectangle(Pens.Black, 10, 10, 80, 80);
            e.Graphics.DrawRectangle(Pens.Black, 120, 10, 80, 80);
            e.Graphics.DrawRectangle(Pens.Black, 10, 120, 80, 80);
            e.Graphics.DrawRectangle(Pens.Black, 120, 120, 80, 80);

 

 

브러쉬 - 면을 채우는 그래픽 오브젝트이다. Graphics 클래스의 Fill 로 시작되는 메소드들은 면적을 채우기 위한 브러쉬를 인수로 요구한다. 텏스트 출력문이나 펜 생성자도 브러쉬를 사용하는데 면적이 있는 모든 출력문에 브러쉬가 사용된다. 최상위의 Brush는 추상클래스이므로 객체를 생성할수 없으며 그리기와 관련된 특별한 메소드나 프로퍼티도 없다. 다만 대표타입으로서 브러쉬 전체를 칭하는 용도로만 사용된다.

 

그래디언트브러쉬 - 색상이 점점 변하는 브러쉬이다.

 

텍스처 브러쉬 - 이미지를 반복적으로 타일링하는 브러쉬이다. 이미지의 크기나 색상수에 특별한 제약이 없으므로 얼마든지 자유로운 모양의 브러쉬를 만들수 있다. 텍스트 브러쉬의 원점을 조정하려면 Matrix 객체를 생성하여 평행이동하는 좌표변환을 해야 한다.

 

 

그리기 메소드.

직선

 

면 - 타원과 사각형을 그리는 메소드

 

곡선 

 

텍스트 출력

DrawString - 씨로 치면 printf, win32에선 TextOut 해당하는 기본적인 출력문이다.

 

폰트 - 문자열의 모양을 정의하는 그래픽 오브젝트이며 Font 클래스로 표현한다. DrawSTring 메소드를 글꼴을 정의하는 Font  객체를 인수로 전달받는데 통상 폼의 Font 프로퍼티를 그대로 전달하여 디폴트로 사용한다.

폰트패밀리는 비슷한 특성을 가지는 폰트의 그룹이다. 폰트 패밀리에 크기와 스타일이 더해지면 실제출력에 사용할수 있는 폰트오브젝트가 된다.

사용자가 지정한 폰트가 없을 경우에 대체폰트를 찾게 된다. Win32는 글꼴이 발견되지 않을 경우를 대비해서 피치특성, 문자셋, 패밀리, 여러가지 정확도 등을 지정하며 지정한 폰트가 아니더라도 최대한 비슷한 폰트를 생성하도록 폰트맴핑 알고리즘이 정교하다. 반면에 닷넷은 고작 폰트의 이름밖에 지정하지 않으므로 어떤 폰트가 선택될지 예측하기 어렵다.

ex. 현재 시스템이 가지고 있는 폰트 리스트만들기

FontFamily[] Fms = FontFamily.Families;
            int x = 10, y = 10;

            foreach (FontFamily fm in Fms)
            {
                try
                {
                    Font F = new Font(fm, 15);
                    e.Graphics.DrawString(fm.Name, F, Brushes.Black, x, y);
                    y += 20;
                    if (y > ClientSize.Height - 20)
                    {
                        x += 300;
                        y = 10;
                    }

                }
                catch
                {
                }

            }

 

안티알리아싱

점단위로 그래픽을 출력하는 디지털 장비의 특성상 흰 바탕에 검정색으로 출력하면 계단 현상이 생긴다. 계단현상은 늘 있으나 얼마만큼 우리가 보기에 잘보이느냐의 문제이다. 그래서 색상차가 큰 경계부근에 중간 색상을 적당히 삽입하여 계단이 잘 안보이도록 하는 것이 안티알리아싱이다.

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 9. 1. 14:55