UI자동화

&스피치

 

 

 

 

 

 

 

선문비트 21

김동영

 

 

 

 

 

 

 

===========================================================================

 

 

 

 

목 차

 

 

u UI Automation

 

u Text To Speech

 

u Speech To Text

 

 

 

 

 

 

 

 

 

 

 

===========================================================================

 

 


 

u UI Automation

 

Microsoft UI 자동화는 WPF를 지원하는 모든 운영 체제에서 사용할 수 있는 새로운 내게 필요한 옵션 프레임워크입니다.

UI 자동화를 통해 데스크톱에 있는 대부분의 UI(사용자 인터페이스) 요소에 프로그래밍 방식으로 엑세스할 수 있으므로 화면 판독기 등의 보조 기술 제품에서 최종 사용자에게 UI에 대한 정보를 제공할 수 있으며 표준 입력 이외의 방법으로 조작할 수 있습니다. 또한 자동화된 테스트 스크립트에서 UI 자동화를 통해 UI와 상호 작용할 수 있습니다. 

 

 

 

 

 

 

u UI 자동화 트리

 

1) 개요

현재 데스크톱을 나타내며 해당 자식 요소가 응용 프로그램 창을 나타내는 루트 요소(RootElement)가 있습니다. 이러한 각 자식 요소에는 메뉴, 단추, 도구 모음, 목록 상자 등의 UI 항목을 나타내는 요소가 포함될 수 있습니다. 포함된 각 요소도 목록 항목과 같은 요소를 포함할 수 있습니다.

UI 자동화 공급자는 대개 창에서 호스팅되는 루트와 하위 트리로 구성되는 조각의 항목 간에 탐색을 구현하여 UI 자동화 트리를 지원합니다. 그러나 공급자는 컨트롤 간의 탐색을 고려하지 않습니다. 이러한 탐색은 기본 창 공급자의 정보를 사용하여 UI 자동화 핵심에서 관리합니다.

 

2) 자동화 트리의 뷰

UI 자동화 트리를 필터링 하여 특정 클라이언트에 관련된 AutomationElement 개체만 포함하는 뷰를 만들 수 있습니다.

UI 자동화 공급자는 IsControlElementProperty IsContentElementProperty 속성을 비롯하여 요소에 대한 속성을 정의하여 필터링을 지원합니다.

UI 자동화에서는 세 가지 기본 뷰를 제공합니다. 이들 뷰는 수행되는 필터링 유형에 의해 정의되며 그 범위는 응용 프로그램에 의해 정의됩니다. 또한 응용 프로그램에서는 속성에 다른 필터를 적용할 수도 있는데, 예를 들어 컨트롤 뷰에 활성화된 컨트롤만 포함할 수도 있습니다.

 

 

 

 

u UI 자동화 컨트롤 패턴

 

1) 개요

UI 자동화는 컨트롤 패턴을 사용하여 많이 사용되는 컨트롤 동작을 나타냅니다. 예를 들어 단추와 같이 호출 가능한 컨트롤에는 Invoke 컨트롤 패턴을 사용하고, 목록상자, 목록 뷰 또는 콤보 상자와 같이 스크롤 막대가 있는 컨트롤에는 Scroll 컨트롤 패턴을 사용합니다.

 

2) UI 자동화 공급자 및 클라이언트

UI 자동화 공급자는 컨트롤 패턴을 구현하여 컨트롤이 지원하는 특정 기능에 대한 적절한 동작을 노출합니다.

UI 자동화 클라이언트는 UI 자동화 컨트롤 패턴 클래스의 메서드와 속성에 엑세스하고 이를 사용하여 UI에 대한 정보를 얻거나 UI를 조작합니다

 

InvokePattern invoke = ae.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;

//현재 AutomationElement 객체의 패턴이 InvokePattern인지 체크함

 

3) 컨트롤 패턴 클래스 및 인터페이스

 

컨트롤 패턴 클래스

공급자 인터페이스

설명

DockPattern

IDockProvider

도킹할 수 있는 컨트롤에 사용됨 예) 도구 모음

ExpandCollapsePattern

IExpandCollapseProvider

확장하거나 축소할 수 있는 컨트롤에 사용됨 예) 파일 메뉴

GridPattern

IGridProvider

특정 셀로 이동 및 크기 조정 같은 표 기능을 지원하는 컨트롤

GridItemPattern

IGridItemProvider

표 안에 셀이 있는 컨트롤에 사용됨

InvokePattern

IInvokeProvider

호출할 수 있는 컨트롤에 사용됨 예) 단추

MultipleViewPattern

IMultipleViewProvider

같은 정보, 데이터 또는 자식 집합을 여러 표현 간에 전환할 수 있는 컨트롤에 사용됨

RangeVal!uePattern

IRangeVal!ueProvider

컨트롤에 적용할 수 있는 값의 범위가 있는 컨트롤에 사용됨

ScrollPattern

IScrollProvider

스크롤할 수 있는 컨트롤에 사용됨

ScrollItemPattern

IScrollItemProvider

스크롤되는 목록에 개별 항목이 있는 컨트롤에 사용됨 예) 콤보 상자

SelectionPattern

ISelectionProvider

선택 컨테이너 컨트롤에 사용됨 예) 목록 상자와 콤보 상자

SelectionItemPattern

ISelectionItemProvider

목록 상자 및 콤보 상자와 같은 선택 컨테이너 컨트롤에 있는 개별 항목에 사용됨

TablePattern

ITableProvider

표와 머리말 정보가 있는 컨트롤에 사용됨

TableItemPattern

ITableItemProvider

테이블의 항목에 사용됨

TextPattern

ITextProvider

텍스트 정보를 노출하는 문서 및 편집 컨트롤에 사용됨

TogglePattern

IToggleProvider

상태를 전환할 수 있는 컨트롤에 사용됨 예) 확인란

TransformPattern

ITransformProvider

크기, 이동, 회전할 수 있는 컨트롤에 사용됨

ValuePattern

IValueProvider

값 범위를 지원하지 않는 컨트롤에서 클라이언트가 값을 가져오거나 설정할 수 있음 예) 날짜 시간 선택 컨트롤

WindowPattern

IWindowProvider

MS O/S에 대한 기본 개념인 창에 관련된 정보를 노출

 

 

u 예제

 

private void ProcessStart()

        {           

            OpenFileDialog of = new OpenFileDialog();

            bool? check = of.ShowDialog();

            if (check == true)

            {

string filename = of.FileName;

                Process pro = Process.Start(filename);

                Thread.Sleep(2000);

 

SetEditElements(pro.MainWindowHandle);

                SetButtonElements(pro.MainWindowHandle);

}

        }

파일 대화상자를 이용해, 제어할 프로세스를 하나 선택, Process 클래스를 이용해 프로세스를 실행하고, 프로세스가 로딩되는 시간이 있으므로 2초 정도 대기합니다.   

EditBox Button 컨트롤을 제어 할 것 이므로 SetEditElements메소드와 SetButtonElements메소드에 시작한 프로세스의 메인 윈도우의 핸들값을 넘겨줍니다.

 

 

 

 

private void SetEditElements(IntPtr hWnd)

        {

            AutomationElement ae = AutomationElement.FromHandle(hWnd);

            System.Windows.Automation.Condition condition = new AndCondition(

                new PropertyCondition(AutomationElement.IsEnabledProperty, true),

                new PropertyCondition(AutomationElement.ControlTypeProperty,

ControlType.Edit));

 

            AutomationElementCollection aec = ae.FindAll(TreeScope.Children, condition);

 

            foreach (AutomationElement child_ae in aec)

            {

                ar.Add(new MyAE(child_ae));

            }           

        }

핸들 값으로 AutomationElement 개체를 얻어옵니다.

Condition 클래스는 UI 자동화 요소 검색에 사용할 수 있는 대부분의 방법에서 검색하려는 요소를 정의하는 조건의 집합입니다. IsEnabledProperty true이며 ControlTypeProperty Edit인 요소를 얻어 올 것이므로 AndCondition을 사용 하였습니다. 한 개는 Condition, 한 개만 만족해도 얻어 오려면 OrCondition을 사용 하시면 됩니다.

 FindFirst 또는 FindAll을 사용하여 수행하는 검색에는 시작 지점과 범위가 있어야 합니다. 시작 지점에는 요소 자체와 형제 요소, 부모 요소, 상위 요소, 바로 아래 자식 요소 및 하위 요소가 포함 될 수 있습니다. 시작 지점을 자식 요소, 바로 위에서 생성한 condition 개체를 인자로 넘겨 줍니다.

 얻어온 요소들을 ArrayList에 보관 하였습니다.

 

 

 

 

private void SetButtonElements(IntPtr hWnd)

        {

            AutomationElement ae = AutomationElement.FromHandle(hWnd);

            System.Windows.Automation.Condition condition = new AndCondition(

                new PropertyCondition(AutomationElement.IsEnabledProperty, true),

                new PropertyCondition(AutomationElement.ControlTypeProperty,

 ControlType.Button));

            AutomationElementCollection aec = ae.FindAll(TreeScope.Children, condition);

 

                          

            foreach (AutomationElement child_ae in aec)

            {  

                ar.Add(new MyAE(child_ae));         

            }           

        }

Condition ControlType.Button을 제외하곤 동일합니다.

 

 

 

 

 

 

 

void it_InputTextEventHandler(string text)

        {           

            MyAE mae = listView1.SelectedItem as MyAE;

            AutomationElement ae = mae.AE;

            object obj;

            try

            {

                if (ae.TryGetCurrentPattern(ValuePattern.Pattern, out obj))

                {

                    ValuePattern valp = obj as ValuePattern;

                    valp.SetValue(text);

                }

 

            }

            catch

            {

 

            }

        }

선택한 요소의 타입이 Edit 일 경우의 처리입니다. 요소의 TryGetCurrentPattern 메소드는 컨트롤 패턴을 구현하는 개체를 검색합니다.

컨트롤 별 패턴은 http://msdn.microsoft.com/ko-kr/library/ms750574 을 참조하시길 바랍니다. 요소가 Value 패턴을 지원하는지 검색 하고, Value 패턴을 지원 한다면 True return 하고 ValuePattern 개체를 얻습니다. 이 개체를 통해 공급자의 EditBox에 접근 할 수 있습니다.

 

 

 

 

 

 

 

MyAE ate = ar[index] as MyAE;

 

                    object obj;

                    try

                    {

                        if (ate.AE.TryGetCurrentPattern(InvokePattern.Pattern, out obj))

                        {

                            InvokePattern invp = obj as InvokePattern;

                            invp.Invoke();

                        }

                    }

                    catch

                    {

 

                    }

버튼도 비슷합니다. InvokePattern을 지원 하는지 검색하여 InvokePattern 패턴이라면 Invoke해주고 있습니다.

 

 

 

 

 

 

 

===========================================================================

 

 

u Text To Speech

WPF에서는 시각적으로 불편한 사람들을 위하여 텍스트를 읽어주는 기능, Speech 기능을 지원하고 있습니다. 우선 Speech 기능을 사용하기 위해선 참조추가를 해줘야 하는데, System.Speech 항목을 추가하여야만 사용이 가능합니다. SpeechSDK51를 설치해야 System.Speech가 설치 됩니다. 아래의 경로로 이동하여 SpeechSDK51.exe 를 다운 받으시면 됩니다.

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=5e86ec97-40a7-453f-b0ee-6583171b4530

 

 

 

SpeechSynthesizer synthesizer = new SpeechSynthesizer();

synthesizer.Speak("I love you");

 

SpeechSynthesizer 클래스를 이용해 간단하게 원하는 영어 단어를 읽어줍니다. 아직 한글 지원은 하지 않습니다. 비동기적으로 이용하시려면 SpeckAsync메소드를 이용하시면 됩니다. 

 

읽어주는 속도를 변경하고자 하면 Rate 속성을 -10~10 사이의 값을 이용해 변경 해주시고,  볼륨을 조절 할 때는 Volume 속성의 값을 0~100 사이의 값을 이용해 변경해 주시면 됩니다.

 

다양한 음성이 설치 되어 있다면 SelectVoice메소드를 이용하시면 되고, SelectVoiceByHints 메소드를 이용해 원하는 목소리와 연령대도 선택 할 수 있습니다.

 

 

 

 

 

 

 

 

 

 

 ===========================================================================

 

 

u Speech To Text

Speech To Text는 곧 음성 인식입니다. SpeechSDK51를 설치 하면 Speech.dll을 이용하여

음성인식을 간단하게 사용 하실 수 있습니다. 저는 SpeechToText Class를 정의 하였습니다.

 

SpeechToText Class

namespace SupportSpeech

{

    class SpeechToText

    {

        SpeechRecognizer sr = null;

        public SpeechToText()

        {

           

        }

        public SpeechRecognizer ListenStart(string[] key)

        {

            sr = new SpeechRecognizer();

            SrgsDocument doc = new SrgsDocument();

 

            CultureInfo info = CultureInfo.GetCultureInfo("en-US");

            doc.Culture = info;

 

            SrgsRule command = new SrgsRule("command");

                       

            command.Add(new SrgsOneOf(key));

            doc.Rules.Add(command);

            doc.Root = command;

            Grammar grammer = new Grammar(doc);

            sr.LoadGrammar(grammer);

            return sr;

        }

       

        public void DisposeSpeechRecognizer()

        {

            sr.Dispose();

        }       

    }

}

SpeechRecognizer는 음성 인식에 관련된 클래스 입니다.  ListenStart 메소드는 인자로 인식할 keyword들을 받아 등록 시키는 메소드 입니다.

SpeechRecognizer 개체를 하나 생성 합니다. SrgsDocument 클래스를 사용하면 xml을 이용하여 입력 규칙을 등록 할 수 있습니다. 위의 예제에서는 xml을 이용하지 않고 바로 등록 하고 있습니다.

 

 

CultureInfo 클래스를 사용한 이유는 컴퓨터의 언어가 기본적으로 한국어로 되어 있는 컴퓨터의 경우 아래의 같은 에러가 발생합니다.

 

'SupportSpeech, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 어셈블리에 정의된 'Window1'의 인스턴스를 만들 수 없습니다.

 

문화권을 en-US로 변경하여 줍니다. SrgsRule 개체를 하나 생성 하였는데 인자로는 id 값입니다. 이 개체를 이용해 입력 규칙을 저장 한 후, LoadGrammer 메소드를 이용해 SpeechRecognizer 개체에 입력 규칙을 추가합니다.

 

 

 

 

SpeechRecognizer sr = st.ListenStart(temp);

sr.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(sr_SpeechRecognized);

이제 추가한 입력 규칙에 해당하는 음성이 발생을 시켜야 하는데, 그러려면 SpeechRecognizer 개체의 SpeechRecognized 이벤트 핸들러를 등록 합니다.

 

 

 

 

[DllImport!("user32.dll")]

public static extern void keybd_event(byte vk, byte scan, int flags, ref int extrainfo);

 

        void sr_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)

        {

            if (e.Result.Text == "tab")

            {

Activate();

                byte TabKey = 9;

                int info = 0;

                keybd_event(TabKey, 0, 0, ref info);

            }           

            else if (e.Result.Text == "enter")

            {

                byte enter = 0x0D;

                int result = 0;

                keybd_event(enter, 0, 0, ref result);

            }           

           

        }

입력 규칙에 해당하는 단어나 문자가 사용자의 음성에 의해 입력되게 되면 두번째 인자인 SpeechRecognizedEventArgs 개체가 넘어옵니다. Result.Text 속성이 입력된 단어이므로 조건문을 이용하여 처리합니다. 키보드 이벤트를 발생 시키게 하기 위하여 마이그레이션 하였습니다.

 

 

 

 

 

참고자료

1. http://msdn.microsoft.com/ko-kr/library/ms753388.aspx

2. 선문비트 19 4 RUSIA 천정민씨 ,김동현씨 기술문서

3. 애덤 네이선의 WPF 언리쉬드

+ Recent posts