[.NET] C#을 이용한 PropertyGrid 사용법에 대한 Summary

이제 PropertyGrid 컨트롤의 프로퍼트에 이미지 컴보 리스트를 달아보자. 아래의 결과처럼 말이다.
먼저 PropertyGrid의 SelectedObject에 할당될 프로퍼티를 정의할 클래스를 만들어 주어야 한다. 즉 우리가 지금 정의할 클래스에는 위의 그림에서처럼 SourceType이라는 프로퍼티에 대한 정보를 담고 있을 것이다. 아래의 코드가 바로 그 클래스이다. 클래스 명은.. 딱히 지을만한게 없어 개똥이클래스라고 하려다가 그냥 얌전하게 MyProperty라고 이름 붙였다. (C#에서는 클래스명이나 변수명을 한글로 할 수 있다)

public class MyProperty {
    private MyType _type;

    [Editor(typeof(MyPropertyGridEditor), 
            typeof(System.Drawing.Design.UITypeEditor))]
    public MyType SourceType
    {
        get { return _type; }
        set { _type = value; }
    }
}

일단 MyType이라는 새로운 Type이 있는데, 이 Type은 아래와 같다.

public enum MyType { Left, Right, Up, Down };

실제로 PropertyGrid에 나타날 프로퍼티의 값으로 Left, Right, Up, Down이 나타날 것이다. 앞서 언급한 그림을 보기 바란다. 그리고 새롭게 등장한 Attribute 지시자로 Editor가 있는데, 이는 프러퍼티의 값을 변경할 UI Editor를 지정하기 위한 것이며, 인자로 2개를 받는다. 첫번째 인자는 UITypeEditor에서 상속받은, 곧 바로 우리가 새롭게 정의할 클래스명이고, 두번째 인자는 그냥 UITypeEditor 클래스명을 주면된다. 이렇게 Editor 특성자를 프로퍼티에 지정해주면 지정된 프로퍼티에 대한 값을 설정하기 위한 UI가 지정된다. 이 방법은 추후에 새롭게 살펴볼 프로퍼티의 값을 설정하기 위해 사용자 정의 UI를 붙이는 방법과 매우 유사하다.

이제 UITypeEditor에서 상속받아 새롭게 정의한 MyPropertyGridEditor에 대해서 살펴보도록하자.

public class MyPropertyGridEditor : UITypeEditor
{
    public override bool GetPaintValueSupported(
        ITypeDescriptorContext context) {
            return true;
        }

    public override void PaintValue(PaintValueEventArgs e) {
        string m = this.GetType().Module.Name;
        m = m.Substring(0, m.Length - 4);
        ResourceManager resourceManager =
            new ResourceManager(m + ".MyResource", 
                Assembly.GetExecutingAssembly());

        int i = (int)e.Value;
        string sourceName = "";
        switch (i) {
            case ((int)MyType.Left): sourceName = "left"; break;
            case ((int)MyType.Right): sourceName = "right"; break;
            case ((int)MyType.Up): sourceName = "up"; break;
            case ((int)MyType.Down): sourceName = "down"; break;
        }

        Bitmap newImage = (Bitmap)resourceManager.GetObject(sourceName);
        Rectangle destRect = e.Bounds;

        destRect.X = (e.Bounds.Width - newImage.Width) / 2;
        destRect.Y = e.Bounds.Y - 1;
        destRect.Width = newImage.Width;
        destRect.Height = newImage.Height;

        newImage.MakeTransparent();
        e.Graphics.DrawImage(newImage, destRect);
    }
}

제법 길다? -o-; ㅋ

먼저 이 클래스는 두개의 override된 매서드가 있다. 하나는 GetPaintValueSupported이며 또 하나는 PaintValue이다. 이 두개는 종속적인데 GetPaintValueSupported에서 true를 반환하면 PaintValue라는 매서드를 개발자가 override하겠다는 의미이다. 또한 바로 이 PaintValue 매서드에서 컴보 리스트에서 실제로 그림을 그려준다. 만약 GetPaintValueSupported가 false를 반환하면 그림이 없는 단순히 문자만 나타는 컴보 리스트의 형태로 나타난다. 아래의 그림처럼 말이다.
그렇다면 이제 PaintValue 매서드에 대해 집중해보자. 이 매서드는 내용은 이렇다. 먼저 IDE에서 추가한 리소스(MyResource.resx로 지정했음)에 접근할 수 있는 ResourceManager 클래스의 인스턴스를 얻는 코드의 부분이 있는데, 빨강색이 바로 그 코드이다. 아래의 그림을 참조하면 이해하기가 쉬울것이다.

그리고 이렇게 얻은 ResourceManager를 통해 현재 사용 컴보 리스트에 그려질 이미지를 얻어오는 코드가 초록색이다. 끝으로 빨강색 코드는 이렇게 얻어온 이미지를 화면상에 그린다. 그릴 영역은 PaintValue의 인자로 넘어온 PaintValueEventAgrs e를 통해서 얻을 수 있는데, 바로 e.Bounds이다.

음… 바로 지난번에 알아본 문자열에 대한 컴보 리스트 박스를 프로퍼티에 붙이는 것에 비하면 무척 쉽다고 생각한다.

pGIS(presentation GIS, pretty GIS)에 대한 생각

예전에 GIS는 단지 얼마나 빠르게 화면상에 도시하는냐가 관건이였다. 하지만 이제는 하드웨어 성능과 네트워크 대역폭의 개선으로 속도의 향상 부분에서 많은 향상을 얻을 수 있게 되었고, 이제는 얼마나 사용자의 시각을 흥분시키도록(Pretty) 화면상에 표현(Presentation)하게 할 것인지의 고민이 점차 커지고 있으며, 필자는 이를 pretty 또는 presentation GIS라는 의미로써 pGIS라는 코드로 한동안 고민을 해보려고 한다.

450
적절한 색상과 그에 어울리는 그라디언트 배경을 가진 2D pGIS

450
적절한 색상과 그에 어울리는 그라디언트 배경 그리고 그림자를 가진 가진 2D pGIS

393
적절한 색상과 그에 어울리는 그라디언트 배경을 가진 추상화된 3D pGIS

393
적절한 색상과 그에 어울리는 그라디언트 배경을 가진 추상화된 3D pGIS

pGIS라는 주제에 집중해서 위의 4개의 이미지를 통해 보다 Presentation하고 Pretty한 pGIS를 위한 요소로 뽑을 수 있는 것이 바로, 색(Color), 배경(Background) 그리고 그림자(Shadow)이다. 적절한 색상과 그 색상과 주제도에 어울리는 배경. 여기에 그림자..

참고로 위의 이미지들은 필자가 참여하고 있는 프로젝트의 실제 결과물을 이미지 편집 프로그램(직장 동료가 권해준 Paint.NET)을 이용해 그림자(Shadow)만을 추가한 것임을 밝힌다.