3) ProjectSelectForm

메인 폼에서 프로젝트 생성버튼을 눌렀을 때 뜨는 폼으로 현재 프로세스 목록을 보여주어 평가 대상 프로젝트를 선택할 수 있는 폼입니다. 프로젝트에 ProjectSelectForm을 추가하세요.

그리고 대상 프로젝트를 선택하였을 때 자동화 요소를 검색하는데 시간이 오래 걸릴 수 있다는 메시지와 함께 대기 시간을 카운터하고 검출한 UI 요소 개수를 표시하여 평가자에게 프로세스가 정상적으로 동작 중인 상태임을 알려줍니다.

[그림 10.11] ProjectSelectForm 자식 컨트롤 배치
[그림 10.11] ProjectSelectForm 자식 컨트롤 배치

모든 Label 컨트롤의 Visable속성과 btn_select 버튼 컨트롤의 Enabled 속성을 false로 설정하세요. 그리고 ListBox 컨트롤의 Dock 속성을 Fill로 하고 Timer의 Interval 속성을 1000으로 설정합니다.

번호컨트롤 형식컨트롤 이름번호컨트롤 형식컨트롤 이름
1Buttonbtn_refresh6Labellb_time_msg
2Buttonbtn_select7Labellb_time_cnt
3ListBoxlbox_process8Labellb_doing_msg
4Labellb_intro_msg9Labellb_elem_cnt
5Labellb_meta_msg10Timertm_search

[표 10.3] ProjectSelectForm 의 자식 컨트롤

먼저 생성자에 프로젝트 제목을 입력 인자로 설정하여 폼의 Text 속성을 설정합니다.

public ProcessSelectForm(string title)
{
    InitializeComponent();
    this.Text = title;
}

폼의 Load 이벤트 핸들러를 등록하여 프로세스 목록을 조사하여 표시합니다. 프로세스 목록을 조사하여 표시하는 부분은 ProcessList 메서드를 만들어서 사용할게요.

private void ProcessSelectForm_Load(object sender, EventArgs e)
{
    ProcessList();
}

새로 고침 버튼의 클릭 이벤트 핸들러를 조사하여 ProcessList 메서드를 호출합니다.

private void btn_refresh_Click(object sender, EventArgs e)
{
    ProcessList();
}
void ProcessList()
{

먼저 리스트 박스의 모든 항목을 지웁니다.

    lbox_process.Items.Clear();

모든 프로세스를 구합니다.

    Process[] processes = Process.GetProcesses();
    foreach (Process process in processes)
    {

프로세스 목록 중에 프로세스 ID가 자기 자신인 것은 필터링합니다.

        if (process.Id == Process.GetCurrentProcess().Id){    continue;    }

메인 윈도우 창이 있을 때 래핑한 EHProcess 개체를 생성하여 리스트 박스 목록에 추가합니다.

        if (process.MainWindowHandle != IntPtr.Zero)
        {
            EHProcess ep = new EHProcess(process);
            lbox_process.Items.Add(ep);
        }
    }
}

리스트 박스의 SelectedIndexChanged 이벤트 핸들러를 등록합니다.

private void lbox_process_SelectedIndexChanged(object sender, EventArgs e)
{

선택 버튼의 Enabled 속성을 선택 항목이 있는지 여부로 설정합니다.

    btn_select_process.Enabled = (lbox_process.SelectedIndex != -1);
}

선택 버튼의 클릭 이벤트 핸들러를 등록합니다.

private void btn_select_process_Click(object sender, EventArgs e)
{

선택 항목을 EHProcess 형식으로 참조합니다.

    EHProcess ehprocess = lbox_process.SelectedItem as EHProcess;

정보 표시 레이블 컨트롤을 시각화합니다. 이 부분은 SearchLablesShow 메서드를 만들어서 사용합시다.

    SearchLabelsShow();

타이머를 가동합니다.

    tm_search.Start();

평가 관리자 단일체를 구하여 정적 메서드 MakeProject를 호출하여 비동기적으로 평가 프로젝트를 생성합니다.

    EvalManager EM = EvalManager.Manager;
    EM.MakeProjectAsync(Text, ehprocess, EndMakeProject,
                         new AddFindElementDele(AddFindElement),null);
}

정보 표시 레이블들의 Visiblae 속성을 true로 설정합니다.

private void SearchLabelsShow()
{
    lb_intro_msg.Visible = true;
    lb_meta_msg.Visible = true;
    lb_time_msg.Visible = true;
    lb_time_cnt.Visible = true;
    lb_doing_msg.Visible = true;
    lb_elem_cnt.Visible = true;
}
void AddFindElement(int n)
{

크로스 스레드 문제를 해결하기 위해 컨트롤의 InvokeRequired 속성의 참인지 확인합니다.

    if (this.InvokeRequired)
    {

수행 스레드가 폼을 소유한 스레드가 아니면 폼의 Invoke 메서드를 호출하여 .NET 플렛폼에게 소유 스레드가 대리자에 위임한 작업을 수행할 수 있게 합니다.

        this.Invoke(new AddFindElementDele(AddFindElement), new object[]{n});
    }

이전까지 발견한 요소 개수와 새로 발견한 개수를 더한 값을 화면에 표시합니다.

    else
    {
        int cnt = int.Parse(lb_elem_cnt.Text);
        lb_elem_cnt.Text = (cnt + n).ToString();
    }
}

타이머의 Tick 이벤트 핸들러를 등록합니다.

private void tm_search_Tick(object sender, EventArgs e)
{

수행 시간을 1 증가한 값을 화면에 표시합니다.

    int tcnt = int.Parse(lb_time_cnt.Text);
    lb_time_cnt.Text = (tcnt + 1).ToString();
}
void EndMakeProject(IAsyncResult iar)
{

대리자의 위임한 행위가 끝날 때 수행하는 콜백 메서드인 EndMakeProject도 클로스 스레드 문제가 발생할 수 있습니다. 크로스 스레드 문제를 해결합니다.

    if (this.InvokeRequired)
    {
        this.Invoke(new AsyncCallback(EndMakeProject), new object[] { iar });
    }

폼을 닫습니다.

    else
    {
        Close();
    }
}
using System;
using System.Windows.Forms;
using System.Diagnostics;

namespace 접근성_평가_도우미
{
    public partial class ProcessSelectForm : Form
    {
        public ProcessSelectForm(string title)
        {
            InitializeComponent();
            this.Text = title;
        }

        private void ProcessSelectForm_Load(object sender, EventArgs e)
        {
            ProcessList();
        }
        private void btn_refresh_Click(object sender, EventArgs e)
        {
            ProcessList();
        }

        void ProcessList()
        {
            lbox_process.Items.Clear();
            Process[] processes = Process.GetProcesses();
            foreach (Process process in processes)
            {
                if (process.Id == Process.GetCurrentProcess().Id)
                {
                    continue;
                }
                if (process.MainWindowHandle != IntPtr.Zero)
                {
                    EHProcess ep = new EHProcess(process);
                    lbox_process.Items.Add(ep);
                }
            }
        }
        private void lbox_process_SelectedIndexChanged(object sender, EventArgs e)
        {
            btn_select_process.Enabled = (lbox_process.SelectedIndex != -1);
        }
        private void btn_select_process_Click(object sender, EventArgs e)
        {
            EHProcess ehprocess = lbox_process.SelectedItem as EHProcess;
            SearchLabelsShow();
            tm_search.Start();
            EvalManager EM = EvalManager.Manager;
            EM.MakeProjectAsync(Text, ehprocess, EndMakeProject,
                                 new AddFindElementDele(AddFindElement),null);            
        }
        private void SearchLabelsShow()
        {
            lb_intro_msg.Visible = true;
            lb_meta_msg.Visible = true;
            lb_time_msg.Visible = true;
            lb_time_cnt.Visible = true;
            lb_doing_msg.Visible = true;
            lb_elem_cnt.Visible = true;
        }
        void AddFindElement(int n)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new AddFindElementDele(AddFindElement), new object[]{n});
            }
            else
            {
                int cnt = int.Parse(lb_elem_cnt.Text);
                lb_elem_cnt.Text = (cnt + n).ToString();
            }
        }
        private void tm_search_Tick(object sender, EventArgs e)
        {
            int tcnt = int.Parse(lb_time_cnt.Text);
            lb_time_cnt.Text = (tcnt + 1).ToString();
        }
        void EndMakeProject(IAsyncResult iar)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new AsyncCallback(EndMakeProject), new object[] { iar });
            }
            else
            {
                Close();
            }
        }
    }
}

[소스 10.10] ProjectSelectForm.cs