7) AccEvalProject

접근성 평가 프로젝트의 자동화 요소를 조사하고 관리하는 AccEvalProject 클래스를 정의합시다. 이 부분이 전체 프로그램의 핵심적인 역할을 하는 부분입니다.

자동화 요소를 발견할 때 발견한 개수를 이벤트로 전달하기 위한 간단한 대리자를 정의합시다.

AccEvalProject에서는 자동화 요소의 계층 구조를 파악할 수 있어야 합니다. 이를 위해 사전 컬렉션을 멤버로 선언합시다.

평가가 끝났을 때 이를 구동하는 이벤트 핸들러를 등록하기 위한 이벤트를 선언합니다.

자동화 속성이 이동할 때 프로그램 방식의 하이라이트도 이동해야 합니다. 이를 위한 이벤트를 선언합니다.

자동화 속성 변경 이벤트 핸들러와 닫힐 때 처리를 위한 이벤트 핸들러 멤버를 선언합니다.

최상위 자동화 요소를 기억할 멤버를 선언합시다.

평가 프로젝트 제목을 속성으로 제공합시다.

 

 

자동화 요소 개수를 속성으로 제공합시다.

평가 테이블을 속성으로 제공합시다. 평가 테이블은 평가 내용을 XML로 저장하기 위한 개체로 XML로 기록하는 메서드를 제공하는 ADO.NET 기술의 클래스 DataTable 형식을 사용합시다.

평가 대상 프로세스도 속성으로 제공합니다.

평가 대상 프로세스의 메인 창의 윈도우 핸들도 속성으로 제공합시다.

계층화 구조의 루트 노드를 속성으로 제공합시다.

대상 프로세스의 메인 창의 이미지도 속성으로 제공합시다.

사전 개체에서 키로 트리 노드를 가져오기 할 수 있게 속성을 제공합시다.

생성자 메서드에서는 프로젝트 이름, 데이터 테이블, 평가 대상 프로세스 개체를 입력 인자로 받습니다.

생성자에서는 입력 인자로 속성을 설정합니다.

그리고 계층화 정보에 사용할 트리 노드 개체를 기억할 사전 개체를 생성합니다.

프로세스 모드를 초기화하는 메서드를 제공합시다. 이번 프로젝트는 프로세스 모드만 제공하지만 보다 효과적인 평가 도구로 만들려면 포커스 모드와 창 모드 등을 제공하는 것이 좋습니다.

프로세스의 메인 창의 자동화 요소를 찾습니다.

속성 변경 이벤트 핸들러를 생성합니다.

메인 창의 사각 영역 속성이 변하는 것을 알기 위해 이벤트 핸들러를 등록합니다. 이를 통해 창의 위치가 바뀌어도 프로그램 방식의 하이라이트가 유효한 위치에 표시할 수 있습니다.

 

창의 닫히는 시점을 알기 위해 이벤트 핸들러를 등록합시다. 여기에서는 평가 대상 프로젝트의 메인 창이 닫히면 프로젝트를 끝낼 것인지 메시지 창을 띄워 확인하는 구조로 만들 것입니다.

그리고 메인 창의 하위 자동화 요소들을 검색합니다. 이 부분은 별도의 메서드로 구현합시다.

첫번째 입력 인자로 받은 개체를 자동화 요소 형식으로 참조합니다.

이벤트 발생 이유가 사각 영역의 속성 변경이면 구독자에게 By Pass합니다.

윈도우 창 닫힘 이벤트 핸들러에서는 평가 프로젝트를 닫습니다.

계층 정보와 함께 자동화 요소를 검색하는 메서드를 구현합시다.

입력 인자로 받은 자동화 요소에 포커스를 부여하고 약간의 시간을 지연합니다. 시간을 지연하는 이유는 SetFocus 메서드를 호출하면 바로 포커스를 소유하는 것이 아니기 때문입니다.

하위 트리에서 키보드로 초점을 받을 수 있는 자동화 요소를 탐색합니다.

그리고 탐색한 개체에 포커스를 부여하고 지연합니다. 위에서 한 작업을 예외가 발생할 때 다시 하는 이유는 인터넷 익스플로어나 일부 응용 프로그램은 메인 창이 초점을 갖지 못할 때가 있습니다. 이러한 응용들을 위해 예외처리를 한 것입니다. 물론 이 책은 자동화 기술을 소개하는 것이 주 목적이며 상용 프로그램을 만드는 것이 아니어서 예외 처리를 최소화한 것입니다.

ImageCapture 정적 클래스의 CaptureFromRect 메서드를 이용하여 메인 창 이미지를 비트맵 개체로 만들어 속성에 설정합니다.

만약 탐색 대리자를 입력 인자로 받았다면 첫번째 항목을 발견하였음을 전달합니다.

그리고 EHAutoElem 개체를 생성합니다.

계층화 정보를 만들어 최상위 노드를 설정합니다. 계층화 정보를 만드는 부분은 별도의 메서드로 구현합시다.

입력 인자로 받은 요소의 ToString 메서드의 반환 문자열로 트리 노드를 생성합니다.

구분하기 위한 ID를 구합니다.

만약 사전 개체에 없다면 사전 개체에 등록합니다.

트리 노드의 Tag 속성에 EHAutoElem 개체를 설정하고 반대로 EHAutoElem 개체의 Tag 속성에 트리 노드를 설정합니다. 이를 통해 트리 뷰의 트리 노드를 선택하면 태그에 기억한 정보로 대응하는 자동화 요소를 확인하거나 그 역을 수행할 수 있습니다.

이미 사전 개체에 있다면 더 이상 진행하지 않고 메서드를 종료합니다.

이제 자식 요소를 탐색합니다.

탐색 대리자가 존재하면 탐색한 요소 개수를 인자로 전달합니다.

 

탐색한 자동화 요소 개체 항목마다 재귀적으로 MakeUIHierarchy 메서드를 호출합니다.

자동화 요소를 발견하였때 인자로 전달받은 EHAutoElem 개체를 참조합니다.

만약 테이블이 없으면 메서드를 종료합니다.

테이블의 NewRow 메서드를 호출하여 행 개체를 생성합니다.

자동화 속성 정보를 구하여 행 개체의 쉘에 설정합니다.

지원하는 컨트롤 패턴 정보도 마찬가지로 행 개체의 쉘에 설정합니다.

어느 자동화 요소 개체의 정보인지 설정합니다.

이렇게 설정한 행 개체를 테이블의 행 항목에 추가합니다.

평가 프로젝트가 종료하였는지 구독자가 있다면 이벤트를 게시합니다.

프로젝트 메인 창의 변화를 감지하기 위해 등록한 자동화 이벤트 핸들러를 해제합니다.

ToString 메서드를 재정의하여 평가 프로젝트 제목을 반환합니다.

저장하기 메서드를 제공합시다.

입력 인자로 받은 경로에 테이블 이름으로 폴더를 만들 것입니다.

만약 같은 디렉토리명이 존재하면 일련 번호를 부여하여 존재하지 않는 디렉토리 이름이 나올 때까지 반복합니다. 이와 같은 기능은 하나의 프로세스를 평가하기 위해 생성한 프로젝트를 같은 폴더에 번호를 부여하여 보관할 수 있게 하는 기능입니다.

디렉토리를 생성합니다.

그리고 평가 결과를 저장하고 모든 이미지를 저장합니다.

현재 디렉토리를 구하여 기억해 둡니다.

편의성을 위해 입력 인자로 들어온 경로를 현재 디렉토리로 설정합니다.

XML로 기록하기 위한 설정 개체를 생성합니다.

XML 선언부를 생략하지 않게 설정합니다.

문자 검사를 하지 않게 설정합니다.

자동 들여쓰기로 설정합니다.

인코딩은 디폴트로 설정할게요.

레포트를 기록할 XmlWriter 개체를 생성합니다.

“Report”가 XML 문서의 루트 요소로 할 것입니다. 자식 요소로 결과를 기록합니다.

모든 정보를 기록하였으면 XmlWriter 개체를 닫고 기억해 두었던 원래 디렉토리를 현재 디레토리로 설정합니다.

이름이 없는 자동화 요소의 개수를 가져오기 할 수 있는 속성을 제공합시다. 접근성 평가에서 가장 기본적인 절차가 UI 요소를 구분할 수 있는 이름이 적절한지 확인하는 것입니다.

테이블의 행 목록에서 이름 정보가 빈 것을 카운팅하여 반환합니다.

Access 키 정보를 기록하는 메서드입니다.

먼저 Access 키를 갖고 있는 목록을 구합니다. 이 부분은 GetAccessKeyItemList 메서드로 구현합시다. GetAccessItemList 메서드에서는 키와 쌍을 원소로 하는 문자열 배열을 목록화한 컬렉션을 반환하게 구현할 것입니다.

각 목록의 키와 값을 기록합니다. 주의할 점은 요소 이름으로 (나 )와 같은 기호들은 사용할 수 없습니다. 따라서 문자열을 필터링해야 하는데 이 부분도 ConvertString 메서드를 별도로 정의하기로 할게요.

먼저 반환할 키와 값을 원소로 하는 문자열 배열 개체을 목록화할 컬렉션 개체를 생성합니다.

테이블에 기록한 정보를 이용할 것입니다.

테이블의 행 항목마다 반복적인 작업을 수행합니다.

EHAutoElem 쉘의 개체를 참조합니다.

만약 개체의 AccessKey가 빈 문자열이 아니면 키와 값을 문자열 배열에 설정하여 컬렉션에 추가합니다.

특수 기호를 필터링하는 메서드를 구현합시다.

먼저 문자열 길이를 구합니다.

반복해서 알파벳과 숫자 문자가 아닌 것을 발견하면 해당 요소를 제거합니다.

변환한 문자열을 반환합니다.

Accelerator 키의 정보를 기록하는 메서드도 Access 키를 기록하는 메서드와 원리가 같습니다.

Accelerator 키 항목을 구하는 메서드도 Access 키 항목을 구하는 메서드와 논리가 같습니다.

 

컨트롤 유형 별 개수를 기록하는 메서드에서는 컨트롤 패턴 별로 개수를 구한 후에 이를 기록합니다.

컨트롤 패턴 별 개수를 세기위한 변수를 선언합니다.

테이블의 행에서 NULL이 아닌 개체의 수를 구하여 반환합니다.

모든 UI 요소 정보를 기록하는 메서드에서는 테이블의 행 의 각 UI 요소 정보를 기록합니다.

UI 요소 정보를 기록하는 메서드는 별도로 작성합시다.

속성 열거형의 마지막 열거값까지 반복하여 UI 요소의 속성 정보를 기록합니다. 앞에서 열거형을 정의한 이유가 이와 같은 기능을 간결하게 표현하기 위함입니다.

모든 이미지를 저장하는 메서드에서는 원본 이미지들을 저장하는 메서드와 흑백 이미지들을 저장하는 메서드를 호출합니다.

현재 디렉토리를 기억해 두고 입력 인자로 받은 디렉토리로 현재 디렉토리를 설정합니다.

이미지 디렉토리를 생성합시다.

이미지 파일 이름은 일련 번호를 부여합시다.

사전 개체의 각 트리 노드마다 다음을 반복합니다. 트리 노드의 Tag에는 EHAutoElem 개체를 설정해 두었습니다.

EHAutoElem 개체의 이미지를 저장합니다.

기억해 두었던 디렉토리로 현재 디렉토리를 설정합니다.

흑백 이미지를 저장하는 원리도 같습니다.

 

 

[소스 10.7] AccEvalProject.cs