프로그래밍 기술/소프트웨어 접근성, UI 자동화

[S/W 접근성] Range 값 제어기 실습

언제나휴일 2016. 4. 19. 15:29
반응형

Range 값 제어기 실습

 

Range 값 제어하기 솔루션(Visual Studio 2010).zip


 RangeValuePattern 개체를 이용하여 다른 프로세스를 제어하는 프로그램을 만들어 봅시다. 여기에선느 간단하게 데모 타겟 프로그램을 만든 후에 제어하는 프로그램을 만듭시다.


Range 값 제어기 실행 화면

[그림] 실행 화면

 

 먼저 데모 타겟은 단순히 메인 Form TrackBar 컨트롤을 배치하는 것이 끝입니다. 별도의 소스 코드를 편집하거나 설정할 필요는 없습니다.

 

 이제 Range 값 제어기를 만들기 위해 Windows Forms 응용 프로그램 프로젝트를 추가한 후 자식 컨트롤을 배치하세요.


컨트롤 배치

[그림] 컨트롤 배치

 

번호

컨트롤 타입

컨트롤 명

설명

1

Button

btn_target_start

타켓 프로그램 실행 버튼

2

Label

lb_msg

메시지 표시

3

Label

lb_countdown

대기 시간 표시

4

TrackBar

tbar_control

제어에 사용할 TrackBar

5

Timer

timer1

카운트 다운에 사용

[] Form1의 컨트롤 배치



UI 자동화 기술에 관한 .NET 어셈블리를 참조 추가하세요.(솔루션 탐색기의 프로젝트 참조 노드에서 오른쪽 마우스 버튼 클릭하여 컨텍스트 메뉴의 참조 

추가를 선택)

UI 자동화 기술 .NET 어셈블리 참조

[그림] UI 자동화 기술 .NET 어셈블리 참조

 

 멤버 필드로 데모 타겟 프로그램의 실행 파일명을 설정합니다.

string target = "Demo Range 값 제어대상.exe";

 데모 타겟 프로그램이 실행하여 Main 윈도우가 뜨고 난 후에 자동화 요소를 수집할 것입니다. 차후에는 자동화 이벤트를 이용하지만 여기에서는 의도적으로 10초간 대기하기로 할게요. 이를 위해 카운트 다운하기 위한 멤버 필드를 선언하고 10으로 초기화합니다.

int cd_value=10;

 

 타겟 프로그램의 프로세스 개체를 참조할 멤버 필드를 선언합니다.

Process process=null;

 제어할 컨트롤의 RangeValuePattern 개체를 참조할 멤버 필드를 선언합니다.

RangeValuePattern rvp=null;

 데모 타겟 프로그램 실행 버튼의 클릭 이벤트 핸들러를 추가합시다.

private void btn_target_start_Click(object sender, EventArgs e)

{

 타겟 프로세스를 시작합니다.

    process = Process.Start(target);

 그리고 카운트 다운 멤버 필드 값을 10으로 설정한 후 타이머를 가동합니다.

    cd_value = 10;

    timer1.Start();

 카운트 다운 시간과 대기 메시지를 설정하고 버튼을 비활성화합니다.

    lb_countdown.Text = cd_value.ToString();

    lb_msg.Text = "잠시 대기해 주세요.";

    btn_target_start.Enabled = false;

}

 타이머 이벤트 핸드러를 등록합니다.

private void timer1_Tick(object sender, EventArgs e)

{

 타이머 이벤트 핸들러에서는 카운트 다운을 감소하고 이를 표시하는 작업을 수행합니다.

    cd_value--;

    lb_countdown.Text = cd_value.ToString();

    if (cd_value == 0)

    {

 만약 카운트 다운 타밍이 만료하면 타이머를 멈추고 메시지를 빈 문자열로 설정합니다. 그리고 RangeValuePattern 의 자동화 요소를 탐색합니다. 탐색 부분은 메서드로 정의하여 사용합시다.

        timer1.Stop();

        lb_msg.Text = string.Empty;

        lb_countdown.Text = string.Empty;

        SearchRangeValuePattern();

    }

}

 

 RangeValuePattern을 탐색하는 메서드를 정의합시다.

private void SearchRangeValuePattern()

{

 만약 프로세스 개체가 null이거나 Main 창의 Handle Zero일 때는 제대로 프로세스를 동작하지 않거나 아직 메인 창이 뜨지 않을 때입니다. 이 때는 오류 메시지를 메시지 창을 통해 사용자에게 알려줍시다.

    if ( (process == null)||(process.MainWindowHandle == IntPtr.Zero) )

    {

        MessageBox.Show("죄송합니다. 다시 실행해 주세요.");

        btn_target_start.Enabled =false;

        return;

    }

 이제 프로세스의 Main Handle을 인다로 자동화 요소를 참조합니다. 이를 위해 자동화 기술에서는 AutomationElement 형식에 정적 메서드 FromHandle을 제공하고 있습니다.

    AutomationElement ae = AutomationElement.FromHandle(process.MainWindowHandle);

 탐색 조건 개체를 생성합니다. 여기에서는 RangeValuePattern을 찾아야 합니다. 자동화 기술에서는 AutomationElement의 정적 속성 IsRangeValuePatternAvailableProperty를 제공하여 조건 개체를 만들 때 인자로 사용할 수 있습니다.

    Condition cond = new PropertyCondition(

              AutomationElement.IsRangeValuePatternAvailableProperty, true);

 자동화 요소의 FindAll 멤버 메서드에 탐색 범위를 서브 트리로 지정하고 앞에서 생성한 조건 개체를 전달합니다. FindAll 멤버 메서드에서는 조건에 맞는 개체들을 찾아 컬렉션을 반환합니다.

     AutomationElementCollection aec = ae.FindAll(TreeScope.Subtree, cond); 

    try

    {

 이번 실습에서는 타겟 프로그램에 의도적으로 RangeValuePattern인 컨트롤을 하나 추가하였습니다. 컬렉션에 있는 개체를 전수 조사하지 않고 인덱스 0에 있는 개체에 직접 접근하기로 할게요.

 탐색 결과로 받은 자동화 요소 컬렉션의 인덱스 0에 있는 개체가 RangePattern으로 참조합니다. 이를 위해 자동화 요소 개체에서는 GetCurrentPattern 메서드를 통해 컨트롤 패턴 개체를 참조할 수 있게 기능을 제공합니다. 이 때 원하는 패턴을 접근하기 위해 RangeValuePattern의 정적 속성인 Pattern을 입력 인자로 사용합니다. 그리고 실제 자동화 요소 개체가 요청한 컨트롤 패턴이 아닐 수 있기 때문에 as 연산을 통해 참조합니다.

        rvp = aec[0].GetCurrentPattern(RangeValuePattern.Pattern) as RangeValuePattern;

 그리고 트랙바 컨트롤을 활성화 상태로 설정하고 자동화 요소의 Current 속성의 Minimum 속성과 Maximum 속성과 Value 속성을 참조하여 트랙바의 속성을 설정합니다.

        tbar_control.Enabled = true;

        tbar_control.Minimum = (int)rvp.Current.Minimum;

        tbar_control.Maximum = (int)rvp.Current.Maximum;

        tbar_control.Value = (int)rvp.Current.Value;

    }

    catch { }

}

 트랙바의 스크롤 이벤트 핸들러를 등록하여 Value 속성으로 RanageValuePattern 개체의 값을 설정합니다.

private void tbar_control_Scroll(object sender, EventArgs e)

{

    rvp.SetValue(tbar_control.Value);

}

 빌드한 후 타겟 응용 프로그램을 제어기 실행 파일과 같은 위치로 옮긴 후 테스트 하세요.



using System;

using System.Windows.Forms;

using System.Diagnostics;

using System.Windows.Automation;

 

namespace Range__제어하기

{

    public partial class Form1 : Form

    {

        string target = "Demo Range 값 제어대상.exe";

        int cd_value=10;

        Process process=null;

        RangeValuePattern rvp=null;

        public Form1()

        {

            InitializeComponent();

        }

        private void btn_target_start_Click(object sender, EventArgs e)

        {

            process = Process.Start(target);

            cd_value = 10;

            timer1.Start();

            lb_countdown.Text = cd_value.ToString();

            lb_msg.Text = "잠시 대기해 주세요.";

            btn_target_start.Enabled = false;

        }

        private void timer1_Tick(object sender, EventArgs e)

        {

            cd_value--;

            lb_countdown.Text = cd_value.ToString();

            if (cd_value == 0)

            {

                timer1.Stop();

                lb_msg.Text = string.Empty;

                lb_countdown.Text = string.Empty;

                SearchRangeValuePattern();

            }

        }

 

        private void SearchRangeValuePattern()

        {

            if ( (process == null)||(process.MainWindowHandle == IntPtr.Zero) )

            {

                MessageBox.Show("죄송합니다. 다시 실행해 주세요.");

                btn_target_start.Enabled =false;

                return;

            }

            AutomationElement ae = AutomationElement.FromHandle(

                                        process.MainWindowHandle);

 

            Condition cond = new PropertyCondition(

                     AutomationElement.IsRangeValuePatternAvailableProperty, true);

            AutomationElementCollection aec = ae.FindAll(TreeScope.Subtree, cond);

 

            try

            {

                rvp = aec[0].GetCurrentPattern(RangeValuePattern.Pattern)

                          as RangeValuePattern;

                tbar_control.Enabled = true;

                tbar_control.Minimum = (int)rvp.Current.Minimum;

                tbar_control.Maximum = (int)rvp.Current.Maximum;

                tbar_control.Value = (int)rvp.Current.Value;

               

            }

            catch { }

        }

        private void tbar_control_Scroll(object sender, EventArgs e)

        {

            rvp.SetValue(tbar_control.Value);

        }

    }

}

[소스] Form1.cs


반응형