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