5) EHAutoElem 클래스

EHAutoElem 클래스는 자동화 요소와 해당 요소에서 지원하는 컨트롤 패턴을 참조할 수 있는 클래스입니다. 그리고 요소의 화면을 캡쳐한 이미지를 멤버로 갖습니다.

public class EHAutoElem
{

자동화 요소에서 어떠한 컨트롤 유형을 지원하는지 조사한 것을 사전 개체로 기억합시다.

    Dictionary<ENUM_CONTROL, Object> pt_dic = new Dictionary<ENUM_CONTROL, object>();

그리고 자동화 요소의 속성을 문자열 목록으로 기억합시다.

    List<string> curval = new List<string>();

자동화 요소를 래핑합니다.

    public AutomationElement AE{    get;    private set;    }

개체와 매핑할 무언가가 있을 때 이를 기억하였다가 사용할 수 있는 속성을 제공합시다.

    public Object Tag{    get;    set;    }

자동화 요소를 캡쳐한 이미지를 기억하는 속성을 제공합시다.

    public Bitmap Image{    get;    private set;    }
    Bitmap gray_image = null;
    public Bitmap GrayImage
    {
        get
        {
            if (gray_image == null){    MakeGrayImage();    }
            return gray_image;
        }
    }

흑백 이미지로 변환하는 메서드를 구현합시다.

    private void MakeGrayImage()
    {

먼저 원본 이미지의 크기를 갖는 Bitmap 개체를 만듭니다.

        Bitmap gi = new Bitmap(Image.Width, Image.Height);
        Color color;
        int aver = 0;
        for (int x = 0; x < Image.Width; x++)
        {
            for (int y = 0; y < Image.Height; y++)
            {

원본 이미지의 x,y 좌표의 색 정보를 얻어와서 흑백으로 색을 변환합니다.

                color = Image.GetPixel(x,y);

흑백으로 변환하는 공식은 R*0.299 + G*0.587 + B *0.114입니다.

                 aver = (int)(color.R*0.299+color.G*0.587+color.B*0.114);

그리고 흑백으로 변환한 색 정보로 흑백 이미지에 설정합니다.

                gi.SetPixel(x, y, Color.FromArgb(aver, aver, aver));
            }
        }

모든 픽셀에 흑백 이미지를 설정한 비트맵 개체로 멤버 필드를 설정합니다.

        gray_image = gi;
    }

생성자 메소드는 자동화 요소를 입력 인자로 받습니다.

    public EHAutoElem(AutomationElement ae)
    {

입력 인자로 받은 자동화 요소를 속성에 설정합니다.

        AE = ae;
        try
        {

사각 영역정보를 구합니다. 자동화 요소의 사각 영역 정보는 Rect 형식이며 Windows Forms 응용에서는 Rectangle 형식을 사용하므로 이를 변환하는 것입니다. 이 부분은 별도의 메서드를 구현하여 사용합시다.

            Rectangle rect = GetBoundaryRect();

사각 영역 정보로 비트맵 개체를 생성합니다.

            Image = new Bitmap(rect.Width, rect.Height);

비트맵에 그릴 수 있는 Graphics 개체를 생성합니다. 비트맵에 그릴 수 있는 Graphics 개체를 생성할 때는 Graphics 클래스의 정적 메서드 FromImage 메서드를 사용합니다.

            Graphics g = Graphics.FromImage(Image);

화면에서 비트맵 이미지로 복사한 후 저장합니다.

            g.CopyFromScreen(rect.Location, new Point(0, 0), rect.Size);
            g.Save();
        }
        catch { }

Tag 속성은 null로 설정합니다. 이 부분은 사용하는 곳에서 대응할 것을 보관하였다가 사용하는 용도입니다.

        Tag = null;
        try
        {

현재 자동화 속성과 컨트롤 패턴을 분석하여 컬렉션에 보관합니다. 이 부분은 별도의 메서드를 구현하여 사용합시다.

            CurrentValueParsing();
            CurrentPatternParsing();
        }
        catch{ }
    }
    private void CurrentValueParsing()
    {

평가 내용을 입력할 부분은 빈 문자열로 제공합시다. 이번 접근성 평가 도우미에서는 이 부분을 사용하지 않지만 실제 평가 도구를 만들 때는 자동화 요소마다 평가 사항을 기재할 수 있는 필드를 제공하는 것이 효과적입니다.

        curval.Add(string.Empty);//평가 내용을 기재하기 위한 필드 - 현재 사용 안함

ENUM_UIProperty 열거형에 열거한 순서로 자동화 속성을 컬렉션에 추가합니다.

        curval.Add(AE.Current.AcceleratorKey);

…중략…

LabledBy 속성은 해당 컨트롤의 이름으로 설정하는데 null일 수 있으므로 예외 처리합니다.

        try{    curval.Add(AE.Current.LabeledBy.Current.Name);    }
        catch{    curval.Add(string.Empty);    }
        ...중략...
    }

컨트롤 패턴을 분석하는 메서드를 구현합시다.

    private void CurrentPatternParsing()
    {

자동화 요소의 TryGetCurretnPattern 메서드를 이용하여 특정 컨트롤 패턴을 지원하는지 확인하여 지원할 때만 컬렉션에 추가합니다.

        Object obj;
        if (AE.TryGetCurrentPattern(DockPattern.Pattern, out obj))
        {
            pt_dic[ENUM_CONTROL.DOCK] = obj as DockPattern;
       }
       ...중략...
    }

컬렉션에 추가한 자동화 속성 정보를 인덱스로 검색하는 기능을 제공합시다.

    public string GetAEPropertyByIndex(int index)
    {
        return curval[index];
    }

UI 속성 열거형으로 자동화 속성 정로블 검색하는 기능도 제공합시다.

    public string GetAEProperty(ENUM_UIProperty eupropery)
    {
        return GetAEPropertyByIndex((int)eupropery);
    }

컨트롤 열거형을 인자로 사전 컬렉션에 추가한 개체를 검색하는 기능도 제공합시다.

    public object GetPattern(ENUM_CONTROL dptype)
    {
        if (pt_dic.ContainsKey(dptype))
        {
            return pt_dic[dptype];
        }
        return null;
    }

ToString 메서드를 재정의하여 Name 속성과 Class 이름 속성을 하나의 문자열로 형성하여 반환합니다.

    public override string ToString()
    {
        try
        {
            return string.Format("{0}:{1}", AE.Current.Name, AE.Current.ClassName);
        }
        catch{    }
        return string.Empty;
    }

다음은 자동화 요소 속성의 rect 정보를 Rectangle 형식으로 변환하여 반환하는 메서드입니다.

    internal Rectangle GetBoundaryRect()
    {
        System.Windows.Rect wrect = AE.Current.BoundingRectangle;
        return new Rectangle((int)wrect.Left, (int)wrect.Top, (int)wrect.Width, (int)wrect.Height);
    }

평가에 사용할 자동화 요소들을 구분하기 위한 ID를 만드는 메서드를 제공합시다.

    internal string GetEHID()
    {

이름과 자동화 ID, 지역화 컨트롤 이름, 클래스 이름의 조합으로 구분합시다.

        return AE.Current.Name + AE.Current.AutomationId + AE.Current.LocalizedControlType +
              AE.Current.ClassName;
    }
}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Automation;
namespace 접근성_평가_도우미
{
    public class EHAutoElem
    {
        Dictionary<ENUM_CONTROL, Object> pt_dic = 
                 new Dictionary<ENUM_CONTROL, object>();
        List<string> curval = new List<string>();
        public AutomationElement AE{    get;    private set;    }
        public Object Tag{    get;    set;    }
        public Bitmap Image{    get;    private set;    }
        Bitmap gray_image = null;
        public Bitmap GrayImage
        {
            get
            {
                if (gray_image == null){    MakeGrayImage();    }
                return gray_image;
            }
        }
        private void MakeGrayImage()
        {
            Bitmap gi = new Bitmap(Image.Width, Image.Height);
            Color color;
            int aver = 0;
            for (int x = 0; x < Image.Width; x++)
            {
                for (int y = 0; y < Image.Height; y++)
                { 
                    color = Image.GetPixel(x,y);
                    aver = (int)(color.R*0.299+color.G*0.587+color.B*0.114);
                    gi.SetPixel(x, y, Color.FromArgb(aver, aver, aver));
                }
            }
            gray_image = gi;
        }
        public EHAutoElem(AutomationElement ae)
        {
            AE = ae;
            try
            {
                Rectangle rect = GetBoundaryRect();
                Image = new Bitmap(rect.Width, rect.Height);
                Graphics g = Graphics.FromImage(Image);
                g.CopyFromScreen(rect.Location, new Point(0, 0), rect.Size);
                g.Save();
            }
            catch { }
            Tag = null;
            try
            {
                CurrentValueParsing();
                CurrentPatternParsing();
            }
            catch{ }
        }

        private void CurrentValueParsing()
        {
            curval.Add(string.Empty);//평가 내용을 기재하기 위한 필드 - 현재 사용 안함
            curval.Add(AE.Current.AcceleratorKey);
            curval.Add(AE.Current.AccessKey);
            curval.Add(AE.Current.AutomationId);
            curval.Add(AE.Current.BoundingRectangle.ToString());
            curval.Add(AE.Current.ClassName);
            curval.Add(AE.Current.ControlType.ProgrammaticName);
            curval.Add(AE.Current.FrameworkId);
            curval.Add(AE.Current.HasKeyboardFocus.ToString());
            curval.Add(AE.Current.HelpText);
            curval.Add(AE.Current.IsContentElement.ToString());
            curval.Add(AE.Current.IsControlElement.ToString());
            curval.Add(AE.Current.IsEnabled.ToString());
            curval.Add(AE.Current.IsKeyboardFocusable.ToString());
            curval.Add(AE.Current.IsOffscreen.ToString());
            curval.Add(AE.Current.IsPassword.ToString());
            curval.Add(AE.Current.IsRequiredForForm.ToString());
            curval.Add(AE.Current.ItemStatus);
            curval.Add(AE.Current.ItemType);
            try{    curval.Add(AE.Current.LabeledBy.Current.Name);    }
            catch{    curval.Add(string.Empty);    }
            curval.Add(AE.Current.LocalizedControlType);
            curval.Add(AE.Current.Name);
            curval.Add(AE.Current.NativeWindowHandle.ToString());
            curval.Add(AE.Current.Orientation.ToString());
            curval.Add(AE.Current.ProcessId.ToString());
        }

        private void CurrentPatternParsing()
        {
            Object obj;
            if (AE.TryGetCurrentPattern(DockPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.DOCK] = obj as DockPattern;
            }
            if (AE.TryGetCurrentPattern(ExpandCollapsePattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.EXPANDCOLLAPSE] = obj as ExpandCollapsePattern;
            }
            if (AE.TryGetCurrentPattern(GridPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.GRID] = obj as GridPattern;
            }
            if (AE.TryGetCurrentPattern(GridItemPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.GRIDITEM] = obj as GridItemPattern;
            }
            if (AE.TryGetCurrentPattern(InvokePattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.INVOKE] = obj as InvokePattern;
            }
            if (AE.TryGetCurrentPattern(MultipleViewPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.MULTIPLEVIEW] = obj as MultipleViewPattern;
            }
            if (AE.TryGetCurrentPattern(RangeValuePattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.RANGEVALUE] = obj as RangeValuePattern;
            }
            if (AE.TryGetCurrentPattern(ScrollPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.SCROLL] = obj as ScrollPattern;
            }
            if (AE.TryGetCurrentPattern(ScrollItemPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.SCROLLITEM] = obj as ScrollItemPattern;
            }
            if (AE.TryGetCurrentPattern(SelectionPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.SELECTION] = obj as SelectionPattern;
            }
            if (AE.TryGetCurrentPattern(SelectionItemPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.SELECTIONITEM] = obj as SelectionItemPattern;
            }
            if (AE.TryGetCurrentPattern(TablePattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.TABLE] = obj as TablePattern;
            }
            if (AE.TryGetCurrentPattern(TableItemPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.TABLEITEM] = obj as TableItemPattern;
            }
            if (AE.TryGetCurrentPattern(TextPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.TEXT] = obj as TextPattern;
            }
            if (AE.TryGetCurrentPattern(TogglePattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.TOGGLE] = obj as TogglePattern;
            }
            if (AE.TryGetCurrentPattern(TransformPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.TRANSFORM] = obj as TransformPattern;
            }
            if (AE.TryGetCurrentPattern(ValuePattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.VALUE] = obj as ValuePattern;
            }
            if (AE.TryGetCurrentPattern(WindowPattern.Pattern, out obj))
            {
                pt_dic[ENUM_CONTROL.WINDOW] = obj as WindowPattern;
            }
        }
        public string GetAEPropertyByIndex(int index)
        {
            return curval[index];
        }
        public string GetAEProperty(ENUM_UIProperty eupropery)
        {
            return GetAEPropertyByIndex((int)eupropery);
        }
        public object GetPattern(ENUM_CONTROL dptype)
        {
            if (pt_dic.ContainsKey(dptype)){    return pt_dic[dptype];    }
            return null;
        }
        public override string ToString()
        {
            try{    return string.Format("{0}:{1}", AE.Current.Name, AE.Current.ClassName);    }
            catch{    }
            return string.Empty;
        }
        internal Rectangle GetBoundaryRect()
        {
            System.Windows.Rect wrect = AE.Current.BoundingRectangle;
            return new Rectangle((int)wrect.Left,(int)wrect.Top,(int)wrect.Width,(int)wrect.Height);
        }
        internal string GetEHID()
        {
            return AE.Current.Name + AE.Current.AutomationId + 
                  AE.Current.LocalizedControlType + AE.Current.ClassName;
        }
    }
}

[소스 10.5] EHAutoElem.cs