5) InvokePattern, 6) 실습: InvokePattern 요소 제어하기

5) InvokePattern

InvokePattern은 버튼처럼 작업을 수행하도록 명령을 내릴 수 있는 컨트롤의 패턴입니다.

 

System.Object
System.Windows.Automation.BasePattern
System.Windows.Automation.InvokePattern

네임스페이스:  System.Windows.Automation
어셈블리:  UIAutomationClient(UIAutomationClient.dll)

 

InvokePattern 클래스에는 작업을 수행하게 명령하는 Invoke 메서드를 제공합니다. 그리고 정적 멤버 필드로 InvokedEvent를 제공하여 InvokePattern 컨트롤에 의해 작업을 수행하거나 활성화할 때 발생하는 이벤트를 식별할 수 있습니다.

 

6) 실습: InvokePattern 요소 제어하기

이번에는 InvokePattern 개체를 이용하여 다른 프로세스를 간단하게 제어하는 프로그램을 만들어 봅시다.

 

[그림 5.1] Invoke 요소 제어기
[그림 5.1] Invoke 요소 제어기

이번에 작성할 Invoke 요소 제어기는 Windows Forms 응용 프로그램입니다. 프로세스 목록 새로고침 버튼을 클릭하면 메인 창이 있는 프로세스 목록이 리스트 상자에 표시합니다. 그리고 프로세스 리스트 상자에서 항목을 선택하면 해당 프로세스의 메인 창의 자식 요소 중에 InvokePatten 을 지원하는 자동화 요소를 조사하여 가운데 리스트 상자에 표시합니다. 그리고 가운데 상자의 항목을 선택하면 선택한 항목과 매핑하는 컨트롤을 Invoke 합니다. 이는 다른 프로세스의 버튼을 클릭한 것과 같은 효과를 가져옵니다. 그리고 선택한 프로세스의 Main 창의 자식 컨트롤에 의해 Invoke 이벤트를 감지하면 마지막 리스트 상자에 표시하는 프로그램입니다.

 

앞으로 많은 곳에서 Process를 래핑하거나 자동화 요소를 래핑하는 등의 작업은 중복해서 발생합니다. 매 번 같은 작업을 하는 것은 효과적이지 않아 클래스 라이브러리를 만들어서 사용하기로 할게요. 앞으로 이 라이브러리는 추가 및 변경할 때에만 언급하기로 할게요.

 

먼저 WrapLib 이름으로 클래스 라이브러리를 추가하세요.

[그림 5.2] 클래스 라이브러리 생성
[그림 5.2] 클래스 라이브러리 생성

기본으로 제공하는 Class1.cs 파일의 속성을 WrapProcess로 변경하세요. WrapProcess 클래스는 앞에서 작성한 것과 차이가 없습니다. Visual Studio의 인텔리센스 기능을 활용하기 위해 세 줄 주석만 추가할게요.

[소스 5.1] WrapProcess.cs

여기에서는 InvokePattern 을 조사하여 사용할 것입니다. WrapLib 프로젝트에 WrapInvoke 클래스를 추가하세요.

 

WrapInvoke 클래스에는 자동화 요소를 래핑할 것이며 이를 참조할 수 있는 속성을 제공합시다.

그리고 자동화 요소의 이름을 가져오기 할 수 있게 속성을 제공합시다.

 

자동화 요소의 지역화 컨트롤 타입명도 가져오기 할 수 있게 속성을 제공합시다.

 

생성자는 입력 인자로 래핑할 자동화 요소를 전달받습니다. 그리고 전달받은 자동화 요소를 AE 속성에 설정합니다.

 

InvokePattern의 Invoke 메서드를 래핑한 메서드를 제공합시다. 메서드 내부에서는 래핑한 자동화 요소 개체가 InvokePattern 개체로 참조한 후에 Invoke 메서드를 호출합니다.

ToString 메서드도 재정의합시다.

 

[소스 5.2] WrapInvoke.cs

작성한 클래스 라이브러리를 참조 추가할 때는 솔루션 창의 프로젝트의 참조에서 컨텍스트 메뉴를 통해 참조 추가할 수 있습니다.

[그림 5.3] 어셈블리 참조 추가
[그림 5.3] 어셈블리 참조 추가

이제 Invoke 요소 제어기를 작성합니다. 먼저 프로젝트 추가를 통해 Windows Forms 응용 프로그램을 선택하세요.

 

물론 WrapLib를 참조 추가 및 UI 자동화 기술에 관한 어셈블리도 참조 추가해야 합니다.

 

이제 메인 폼의 컨트롤을 배치합시다.

 

[그림 5.4] Main 폼 컨트롤 배치
[그림 5.4] Main 폼 컨트롤 배치

Main 폼에는 버튼 1개와 ListBox 3개를 배치합니다.

번호 컨트롤 타입 컨트롤 명 설명
1 Button btn_refresh 프로세스 목록 새로고침
2 ListBox lbox_process 프로세스 목록을 보여주는 리스트 상자
3 ListBox lbox_inv_elem 선택한 프로세스의 InvokePattern 자동화 요소 목록을 보여주는 리스트 상자
4 ListBox lbox_history 선택한 프로세스의 InvokeEvent를 보여주는 리스트 상자

[표 5.8] Form1의 컨트롤

 

먼저 프로세스 목록 새로고침 버튼의 클릭 이벤트 핸드러를 추가합니다.

 

프로세스 리스트 상자의 선택 항목 변경 이벤트 핸들러를 추가합니다.

 

 

 

리스트 상자에 추가하는 메서드를 정의합시다. 그런데 Invoke 관련 이벤트를 감지하여 전달하는 스레드와 리스트 상자를 소유하는 스레드가 다르기 때문에 크로스 스레드 문제가 발생합니다. 이를 위해 AddEvent 메서드와 반환 형식과 입력 인자 리스트가 같은 대리자를 정의합시다.

 

InvokePattern 개체를 항목으로 표시한 리스트 상자의 선택 변경 이벤트 핸들러를 추가하세요.

 

이제 프로그램을 빌드하여 테스트를 해 보세요.

[소스 5.3] Form1.cs